From 22a60518ca90cf1065076d4d061352ff83ced8ed Mon Sep 17 00:00:00 2001 From: Phil Kuang Date: Mon, 7 Jun 2021 19:01:17 -0400 Subject: [PATCH 001/204] feat(GithubMultiOrgReaderProcessor): implement processor to handle multi-org ingestion Signed-off-by: Phil Kuang --- .changeset/orange-news-sparkle.md | 46 +++++ packages/integration/api-report.md | 10 + .../github/GithubCredentialsProvider.test.ts | 27 +-- .../src/github/GithubCredentialsProvider.ts | 38 ++-- packages/integration/src/github/index.ts | 5 +- plugins/catalog-backend/config.d.ts | 21 ++ .../GithubMultiOrgReaderProcessor.ts | 181 ++++++++++++++++++ .../processors/github/config.test.ts | 33 +++- .../src/ingestion/processors/github/config.ts | 24 +++ .../processors/github/github.test.ts | 40 +++- .../src/ingestion/processors/github/github.ts | 8 +- .../src/ingestion/processors/github/index.ts | 4 +- .../src/ingestion/processors/index.ts | 1 + 13 files changed, 397 insertions(+), 41 deletions(-) create mode 100644 .changeset/orange-news-sparkle.md create mode 100644 plugins/catalog-backend/src/ingestion/processors/GithubMultiOrgReaderProcessor.ts diff --git a/.changeset/orange-news-sparkle.md b/.changeset/orange-news-sparkle.md new file mode 100644 index 0000000000..d3a0292d52 --- /dev/null +++ b/.changeset/orange-news-sparkle.md @@ -0,0 +1,46 @@ +--- +'@backstage/integration': patch +'@backstage/plugin-catalog-backend': patch +--- + +Support ingesting multiple GitHub organizations via a new `GithubMultiOrgReaderProcessor`. + +This new processor handles namespacing created groups according to the org of the associated GitHub team to prevent potential name clashes between organizations. Be aware that this processor is considered alpha and may not be compatible with future org structures in the catalog. + +NOTE: This processor only fully supports auth via GitHub Apps + +To install this processor, import and add it as follows: + +```typescript +// Typically in packages/backend/src/plugins/catalog.ts +import { GithubMultiOrgReaderProcessor } from '@backstage/plugin-catalog-backend'; +// ... +export default async function createPlugin(env: PluginEnvironment) { + const builder = new CatalogBuilder(env); + builder.addProcessor( + GithubMultiOrgReaderProcessor.fromConfig(env.config, { + logger: env.logger, + }), + ); + // ... +} +``` + +Configure in your `app-config.yaml` by pointing to your GitHub instance and optionally list which GitHub organizations you wish to import. You can also configure what namespace you want to set for teams from each org. If unspecified, the org name will be used as the namespace. If no organizations are listed, by default this processor will import from all organizations accessible by all configured GitHub Apps: + +```yaml +catalog: + locations: + - type: github-multi-org + target: https://github.myorg.com + + processors: + githubMultiOrg: + orgs: + - name: fooOrg + groupNamespace: foo + - name: barOrg + groupNamespace: bar + - name: awesomeOrg + - name: anotherOrg +``` diff --git a/packages/integration/api-report.md b/packages/integration/api-report.md index 31cbc8b5d8..afd048cb13 100644 --- a/packages/integration/api-report.md +++ b/packages/integration/api-report.md @@ -5,6 +5,7 @@ ```ts import { Config } from '@backstage/config'; +import { RestEndpointMethodTypes } from '@octokit/rest'; // @public (undocumented) export class AzureIntegration implements ScmIntegration { @@ -106,6 +107,15 @@ export function getGitLabFileFetchUrl(url: string, config: GitLabIntegrationConf // @public export function getGitLabRequestOptions(config: GitLabIntegrationConfig): RequestInit; +// @public (undocumented) +export class GithubAppCredentialsMux { + constructor(config: GitHubIntegrationConfig); + // (undocumented) + getAllInstallations(): Promise; + // (undocumented) + getAppToken(owner: string, repo?: string): Promise; +} + // @public (undocumented) export class GithubCredentialsProvider { // (undocumented) diff --git a/packages/integration/src/github/GithubCredentialsProvider.test.ts b/packages/integration/src/github/GithubCredentialsProvider.test.ts index 271d4b9920..6b70109a26 100644 --- a/packages/integration/src/github/GithubCredentialsProvider.test.ts +++ b/packages/integration/src/github/GithubCredentialsProvider.test.ts @@ -15,6 +15,7 @@ */ const octokit = { + paginate: async (fn: any) => (await fn()).data, apps: { listInstallations: jest.fn(), createInstallationAccessToken: jest.fn(), @@ -53,7 +54,7 @@ describe('GithubCredentialsProvider tests', () => { jest.resetAllMocks(); }); it('create repository specific tokens', async () => { - octokit.apps.listInstallations.mockResolvedValueOnce({ + octokit.apps.listInstallations.mockResolvedValue({ headers: { etag: '123', }, @@ -72,7 +73,6 @@ describe('GithubCredentialsProvider tests', () => { }, ], } as RestEndpointMethodTypes['apps']['listInstallations']['response']); - octokit.apps.listInstallations.mockRejectedValue({ status: 304 }); octokit.apps.createInstallationAccessToken.mockResolvedValueOnce({ data: { @@ -84,12 +84,8 @@ describe('GithubCredentialsProvider tests', () => { const { token, headers, type } = await github.getCredentials({ url: 'https://github.com/backstage/foobar', }); - const { token: accessToken2 } = await github.getCredentials({ - url: 'https://github.com/backstage/foobar', - }); expect(type).toEqual('app'); expect(token).toEqual('secret_token'); - expect(token).toEqual(accessToken2); expect(headers).toEqual({ Authorization: 'Bearer secret_token' }); // fallback to the configured token if no application is matching @@ -107,7 +103,7 @@ describe('GithubCredentialsProvider tests', () => { }); it('creates tokens for an organization', async () => { - octokit.apps.listInstallations.mockResolvedValueOnce({ + octokit.apps.listInstallations.mockResolvedValue({ headers: { etag: '123', }, @@ -121,7 +117,6 @@ describe('GithubCredentialsProvider tests', () => { }, ], } as RestEndpointMethodTypes['apps']['listInstallations']['response']); - octokit.apps.listInstallations.mockRejectedValue({ status: 304 }); octokit.apps.createInstallationAccessToken.mockResolvedValueOnce({ data: { @@ -133,17 +128,13 @@ describe('GithubCredentialsProvider tests', () => { const { token, headers } = await github.getCredentials({ url: 'https://github.com/backstage', }); - const { token: accessToken2 } = await github.getCredentials({ - url: 'https://github.com/backstage', - }); expect(headers).toEqual({ Authorization: 'Bearer secret_token' }); expect(token).toEqual('secret_token'); - expect(token).toEqual(accessToken2); }); it('should fail to issue tokens for an organization when the app is installed for a single repo', async () => { - octokit.apps.listInstallations.mockResolvedValueOnce({ + octokit.apps.listInstallations.mockResolvedValue({ headers: { etag: '123', }, @@ -157,7 +148,6 @@ describe('GithubCredentialsProvider tests', () => { }, ], } as RestEndpointMethodTypes['apps']['listInstallations']['response']); - octokit.apps.listInstallations.mockRejectedValue({ status: 304 }); octokit.apps.createInstallationAccessToken.mockResolvedValueOnce({ data: { @@ -176,7 +166,7 @@ describe('GithubCredentialsProvider tests', () => { }); it('should throw if the app is suspended', async () => { - octokit.apps.listInstallations.mockResolvedValueOnce({ + octokit.apps.listInstallations.mockResolvedValue({ headers: { etag: '123', }, @@ -193,7 +183,6 @@ describe('GithubCredentialsProvider tests', () => { }, ], } as RestEndpointMethodTypes['apps']['listInstallations']['response']); - octokit.apps.listInstallations.mockRejectedValue({ status: 304 }); await expect( github.getCredentials({ @@ -229,7 +218,7 @@ describe('GithubCredentialsProvider tests', () => { ).resolves.toEqual(expect.objectContaining({ token: 'fallback_token' })); }); - it('should return the configured token if listing installations throws', async () => { + it('should return the configured token if there are no installations', async () => { const githubProvider = GithubCredentialsProvider.create({ host: 'github.com', apps: [ @@ -243,7 +232,9 @@ describe('GithubCredentialsProvider tests', () => { ], token: 'hardcoded_token', }); - octokit.apps.listInstallations.mockRejectedValue({ status: 304 }); + octokit.apps.listInstallations.mockResolvedValue(({ + data: [], + } as unknown) as RestEndpointMethodTypes['apps']['listInstallations']['response']); await expect( githubProvider.getCredentials({ diff --git a/packages/integration/src/github/GithubCredentialsProvider.ts b/packages/integration/src/github/GithubCredentialsProvider.ts index 9bc09deab3..e0517bdff4 100644 --- a/packages/integration/src/github/GithubCredentialsProvider.ts +++ b/packages/integration/src/github/GithubCredentialsProvider.ts @@ -66,7 +66,6 @@ const HEADERS = { class GithubAppManager { private readonly appClient: Octokit; private readonly baseAuthConfig: { appId: number; privateKey: string }; - private installations?: RestEndpointMethodTypes['apps']['listInstallations']['response']; private readonly cache = new Cache(); constructor(config: GithubAppConfig, baseUrl?: string) { @@ -121,22 +120,15 @@ class GithubAppManager { }); } + getInstallations(): Promise< + RestEndpointMethodTypes['apps']['listInstallations']['response']['data'] + > { + return this.appClient.paginate(this.appClient.apps.listInstallations); + } + private async getInstallationData(owner: string): Promise { - // List all installations using the last used etag. - // Return cached InstallationData if error with status 304 is thrown. - try { - this.installations = await this.appClient.apps.listInstallations({ - headers: { - 'If-None-Match': this.installations?.headers.etag, - Accept: HEADERS.Accept, - }, - }); - } catch (error) { - if (error.status !== 304) { - throw error; - } - } - const installation = this.installations?.data.find( + const allInstallations = await this.getInstallations(); + const installation = allInstallations.find( inst => inst.account?.login === owner, ); if (installation) { @@ -163,6 +155,20 @@ export class GithubAppCredentialsMux { config.apps?.map(ac => new GithubAppManager(ac, config.apiBaseUrl)) ?? []; } + async getAllInstallations(): Promise< + RestEndpointMethodTypes['apps']['listInstallations']['response']['data'] + > { + if (!this.apps.length) { + return []; + } + + const installs = await Promise.all( + this.apps.map(app => app.getInstallations()), + ); + + return installs.flat(); + } + async getAppToken(owner: string, repo?: string): Promise { if (this.apps.length === 0) { return undefined; diff --git a/packages/integration/src/github/index.ts b/packages/integration/src/github/index.ts index ee92b7d934..b987a06bb1 100644 --- a/packages/integration/src/github/index.ts +++ b/packages/integration/src/github/index.ts @@ -20,6 +20,9 @@ export { } from './config'; export type { GitHubIntegrationConfig } from './config'; export { getGitHubFileFetchUrl, getGitHubRequestOptions } from './core'; -export { GithubCredentialsProvider } from './GithubCredentialsProvider'; +export { + GithubAppCredentialsMux, + GithubCredentialsProvider, +} from './GithubCredentialsProvider'; export type { GithubCredentialType } from './GithubCredentialsProvider'; export { GitHubIntegration } from './GitHubIntegration'; diff --git a/plugins/catalog-backend/config.d.ts b/plugins/catalog-backend/config.d.ts index 20fcd975cf..a4cfdf95aa 100644 --- a/plugins/catalog-backend/config.d.ts +++ b/plugins/catalog-backend/config.d.ts @@ -145,6 +145,27 @@ export interface Config { }>; }; + /** + * GithubMultiOrgReaderProcessor configuration + */ + githubMultiOrg?: { + /** + * The configuration parameters for each GitHub org to process. + */ + orgs: Array<{ + /** + * The name of the GitHub org to process. + */ + name: string; + /** + * The namespace of the group created for this org. + * + * Defaults to org name if omitted. + */ + groupNamespace?: string; + }>; + }; + /** * LdapOrgReaderProcessor configuration */ diff --git a/plugins/catalog-backend/src/ingestion/processors/GithubMultiOrgReaderProcessor.ts b/plugins/catalog-backend/src/ingestion/processors/GithubMultiOrgReaderProcessor.ts new file mode 100644 index 0000000000..5223acba4a --- /dev/null +++ b/plugins/catalog-backend/src/ingestion/processors/GithubMultiOrgReaderProcessor.ts @@ -0,0 +1,181 @@ +/* + * Copyright 2021 Spotify AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { LocationSpec } from '@backstage/catalog-model'; +import { Config } from '@backstage/config'; +import { + GithubAppCredentialsMux, + GithubCredentialsProvider, + GitHubIntegrationConfig, + ScmIntegrations, +} from '@backstage/integration'; +import { graphql } from '@octokit/graphql'; +import { Logger } from 'winston'; +import { + getOrganizationTeams, + getOrganizationUsers, + GithubMultiOrgConfig, + readGithubMultiOrgConfig, +} from './github'; +import * as results from './results'; +import { CatalogProcessor, CatalogProcessorEmit } from './types'; +import { buildOrgHierarchy } from './util/org'; + +/** + * @alpha + * Extracts teams and users out of a multiple GitHub orgs namespaced per org. + * + * Be aware that this processor may not be compatible with future org structures in the catalog. + */ +export class GithubMultiOrgReaderProcessor implements CatalogProcessor { + private readonly integrations: ScmIntegrations; + private readonly orgs: GithubMultiOrgConfig; + private readonly logger: Logger; + + static fromConfig(config: Config, options: { logger: Logger }) { + const c = config.getOptionalConfig('catalog.processors.githubMultiOrg'); + const integrations = ScmIntegrations.fromConfig(config); + + return new GithubMultiOrgReaderProcessor({ + ...options, + integrations, + orgs: c ? readGithubMultiOrgConfig(c) : [], + }); + } + + constructor(options: { + integrations: ScmIntegrations; + logger: Logger; + orgs: GithubMultiOrgConfig; + }) { + this.integrations = options.integrations; + this.logger = options.logger; + this.orgs = options.orgs; + } + + async readLocation( + location: LocationSpec, + _optional: boolean, + emit: CatalogProcessorEmit, + ): Promise { + if (location.type !== 'github-multi-org') { + return false; + } + + const gitHubConfig = this.integrations.github.byUrl(location.target) + ?.config; + if (!gitHubConfig) { + throw new Error( + `There is no GitHub integration that matches ${location.target}. Please add a configuration entry for it under integrations.github`, + ); + } + + const allUsersMap = new Map(); + const baseUrl = new URL(location.target).origin; + const credentialsProvider = GithubCredentialsProvider.create(gitHubConfig); + + const orgsToProcess = this.orgs.length + ? this.orgs + : await this.getAllOrgs(gitHubConfig); + + for (const orgConfig of orgsToProcess) { + try { + const { + headers, + type: tokenType, + } = await credentialsProvider.getCredentials({ + url: `${baseUrl}/${orgConfig.name}`, + }); + const client = graphql.defaults({ + baseUrl: gitHubConfig.apiBaseUrl, + headers, + }); + + const startTimestamp = Date.now(); + this.logger.info( + `Reading GitHub users and teams for org: ${orgConfig.name}`, + ); + const { users } = await getOrganizationUsers( + client, + orgConfig.name, + tokenType, + ); + const { groups, groupMemberUsers } = await getOrganizationTeams( + client, + orgConfig.name, + orgConfig.groupNamespace, + ); + + const duration = ((Date.now() - startTimestamp) / 1000).toFixed(1); + this.logger.debug( + `Read ${users.length} GitHub users and ${groups.length} GitHub teams from ${orgConfig.name} in ${duration} seconds`, + ); + + users.forEach(u => { + if (!allUsersMap.has(u.metadata.name)) { + allUsersMap.set(u.metadata.name, u); + } + }); + + for (const [groupName, userNames] of groupMemberUsers.entries()) { + for (const userName of userNames) { + const user = allUsersMap.get(userName); + if (user && !user.spec.memberOf.includes(groupName)) { + user.spec.memberOf.push(groupName); + } + } + } + buildOrgHierarchy(groups); + + for (const group of groups) { + emit(results.entity(location, group)); + } + } catch (e) { + this.logger.error( + `Failed to read GitHub org data for ${orgConfig.name}: ${e}`, + ); + } + } + + const allUsers = Array.from(allUsersMap.values()); + for (const user of allUsers) { + emit(results.entity(location, user)); + } + + return true; + } + + // Note: Does not support usage of PATs + private async getAllOrgs( + gitHubConfig: GitHubIntegrationConfig, + ): Promise { + const githubAppMux = new GithubAppCredentialsMux(gitHubConfig); + const installs = await githubAppMux.getAllInstallations(); + + return installs + .map(install => + install.target_type === 'Organization' && + install.account && + install.account.login + ? { + name: install.account.login, + groupNamespace: install.account.login.toLowerCase(), + } + : undefined, + ) + .filter(Boolean) as GithubMultiOrgConfig; + } +} diff --git a/plugins/catalog-backend/src/ingestion/processors/github/config.test.ts b/plugins/catalog-backend/src/ingestion/processors/github/config.test.ts index 14f3caa42c..560a916f09 100644 --- a/plugins/catalog-backend/src/ingestion/processors/github/config.test.ts +++ b/plugins/catalog-backend/src/ingestion/processors/github/config.test.ts @@ -15,7 +15,7 @@ */ import { ConfigReader } from '@backstage/config'; -import { readGithubConfig } from './config'; +import { readGithubConfig, readGithubMultiOrgConfig } from './config'; describe('config', () => { describe('readGithubConfig', () => { @@ -76,4 +76,35 @@ describe('config', () => { ).toThrow(/token/); }); }); + + describe('readGithubMultiOrgConfig', () => { + function config(orgs: { name: string; groupNamespace?: string }[]) { + return new ConfigReader({ orgs }); + } + + it('reads org configs', () => { + const output = readGithubMultiOrgConfig( + config([ + { name: 'foo', groupNamespace: 'apple' }, + { name: 'bar', groupNamespace: 'Orange' }, + ]), + ); + + expect(output).toEqual([ + { name: 'foo', groupNamespace: 'apple' }, + { name: 'bar', groupNamespace: 'orange' }, + ]); + }); + + it('defaults groupNamespace to org name if undefined', () => { + const output = readGithubMultiOrgConfig( + config([{ name: 'foo' }, { name: 'bar' }]), + ); + + expect(output).toEqual([ + { name: 'foo', groupNamespace: 'foo' }, + { name: 'bar', groupNamespace: 'bar' }, + ]); + }); + }); }); diff --git a/plugins/catalog-backend/src/ingestion/processors/github/config.ts b/plugins/catalog-backend/src/ingestion/processors/github/config.ts index 88f2f96218..6a177f7be0 100644 --- a/plugins/catalog-backend/src/ingestion/processors/github/config.ts +++ b/plugins/catalog-backend/src/ingestion/processors/github/config.ts @@ -82,3 +82,27 @@ export function readGithubConfig(config: Config): ProviderConfig[] { return providers; } + +/** + * The configuration parameters for a multi-org GitHub processor. + */ +export type GithubMultiOrgConfig = Array<{ + /** + * The name of the GitHub org to process. + */ + name: string; + /** + * The namespace of the group created for this org. + */ + groupNamespace: string; +}>; + +export function readGithubMultiOrgConfig(config: Config): GithubMultiOrgConfig { + const orgConfigs = config.getOptionalConfigArray('orgs') ?? []; + return orgConfigs.map(c => ({ + name: c.getString('name'), + groupNamespace: ( + c.getOptionalString('groupNamespace') ?? c.getString('name') + ).toLowerCase(), + })); +} diff --git a/plugins/catalog-backend/src/ingestion/processors/github/github.test.ts b/plugins/catalog-backend/src/ingestion/processors/github/github.test.ts index c5094230f8..b9da8e735e 100644 --- a/plugins/catalog-backend/src/ingestion/processors/github/github.test.ts +++ b/plugins/catalog-backend/src/ingestion/processors/github/github.test.ts @@ -72,8 +72,10 @@ describe('github', () => { }); describe('getOrganizationTeams', () => { - it('reads teams', async () => { - const input: QueryResponse = { + let input: QueryResponse; + + beforeEach(() => { + input = { organization: { teams: { pageInfo: { hasNextPage: false }, @@ -98,7 +100,9 @@ describe('github', () => { }, }, }; + }); + it('reads teams', async () => { const output = { groups: [ expect.objectContaining({ @@ -126,6 +130,38 @@ describe('github', () => { await expect(getOrganizationTeams(graphql, 'a')).resolves.toEqual(output); }); + + it('applies namespaces', async () => { + const output = { + groups: [ + expect.objectContaining({ + metadata: expect.objectContaining({ + name: 'team', + namespace: 'foo', + description: 'The one and only team', + }), + spec: { + type: 'team', + profile: { + displayName: 'Team', + picture: 'http://example.com/team.jpeg', + }, + parent: 'parent', + children: [], + }, + }), + ], + groupMemberUsers: new Map([['foo/team', ['user']]]), + }; + + server.use( + graphqlMsw.query('teams', (_req, res, ctx) => res(ctx.data(input))), + ); + + await expect(getOrganizationTeams(graphql, 'a', 'foo')).resolves.toEqual( + output, + ); + }); }); describe('getTeamMembers', () => { diff --git a/plugins/catalog-backend/src/ingestion/processors/github/github.ts b/plugins/catalog-backend/src/ingestion/processors/github/github.ts index 2cc97d2ec5..093012544a 100644 --- a/plugins/catalog-backend/src/ingestion/processors/github/github.ts +++ b/plugins/catalog-backend/src/ingestion/processors/github/github.ts @@ -144,6 +144,7 @@ export async function getOrganizationUsers( export async function getOrganizationTeams( client: typeof graphql, org: string, + orgNamespace?: string, ): Promise<{ groups: GroupEntity[]; groupMemberUsers: Map; @@ -189,6 +190,10 @@ export async function getOrganizationTeams( }, }; + if (orgNamespace) { + entity.metadata.namespace = orgNamespace; + } + if (team.description) { entity.metadata.description = team.description; } @@ -203,7 +208,8 @@ export async function getOrganizationTeams( } const memberNames: string[] = []; - groupMemberUsers.set(team.slug, memberNames); + const groupKey = orgNamespace ? `${orgNamespace}/${team.slug}` : team.slug; + groupMemberUsers.set(groupKey, memberNames); if (!team.members.pageInfo.hasNextPage) { // We got all the members in one go, run the fast path diff --git a/plugins/catalog-backend/src/ingestion/processors/github/index.ts b/plugins/catalog-backend/src/ingestion/processors/github/index.ts index 2063e8c1b2..6feeea2e15 100644 --- a/plugins/catalog-backend/src/ingestion/processors/github/index.ts +++ b/plugins/catalog-backend/src/ingestion/processors/github/index.ts @@ -14,8 +14,8 @@ * limitations under the License. */ -export { readGithubConfig } from './config'; -export type { ProviderConfig } from './config'; +export { readGithubConfig, readGithubMultiOrgConfig } from './config'; +export type { GithubMultiOrgConfig, ProviderConfig } from './config'; export { getOrganizationTeams, getOrganizationUsers, diff --git a/plugins/catalog-backend/src/ingestion/processors/index.ts b/plugins/catalog-backend/src/ingestion/processors/index.ts index a92cc9ed3b..9cd851d471 100644 --- a/plugins/catalog-backend/src/ingestion/processors/index.ts +++ b/plugins/catalog-backend/src/ingestion/processors/index.ts @@ -25,6 +25,7 @@ export { CodeOwnersProcessor } from './CodeOwnersProcessor'; export { FileReaderProcessor } from './FileReaderProcessor'; export { GithubDiscoveryProcessor } from './GithubDiscoveryProcessor'; export { GithubOrgReaderProcessor } from './GithubOrgReaderProcessor'; +export { GithubMultiOrgReaderProcessor } from './GithubMultiOrgReaderProcessor'; export { LdapOrgReaderProcessor } from './LdapOrgReaderProcessor'; export { LocationEntityProcessor } from './LocationEntityProcessor'; export { MicrosoftGraphOrgReaderProcessor } from './MicrosoftGraphOrgReaderProcessor'; From 6f47e3ec16caa243c3c35ff987c3793e649b4b6f Mon Sep 17 00:00:00 2001 From: Joe Porpeglia Date: Fri, 25 Jun 2021 11:34:05 -0400 Subject: [PATCH 002/204] Set up dev instance for plugin Signed-off-by: Joe Porpeglia --- .../github-actions/dev/getWorkflowRun.json | 176 ++++++++++++++++++ plugins/github-actions/dev/index.tsx | 62 +++++- .../dev/listJobsForWorkflowRun.json | 102 ++++++++++ 3 files changed, 338 insertions(+), 2 deletions(-) create mode 100644 plugins/github-actions/dev/getWorkflowRun.json create mode 100644 plugins/github-actions/dev/listJobsForWorkflowRun.json diff --git a/plugins/github-actions/dev/getWorkflowRun.json b/plugins/github-actions/dev/getWorkflowRun.json new file mode 100644 index 0000000000..5527b356f1 --- /dev/null +++ b/plugins/github-actions/dev/getWorkflowRun.json @@ -0,0 +1,176 @@ +{ + "id": 30433642, + "name": "Build", + "node_id": "MDEyOldvcmtmbG93IFJ1bjI2OTI4OQ==", + "check_suite_id": 42, + "check_suite_node_id": "MDEwOkNoZWNrU3VpdGU0Mg==", + "head_branch": "master", + "head_sha": "acb5820ced9479c074f688cc328bf03f341a511d", + "run_number": 562, + "event": "push", + "status": "queued", + "conclusion": null, + "workflow_id": 159038, + "url": "https://api.github.com/repos/octo-org/octo-repo/actions/runs/30433642", + "html_url": "https://github.com/octo-org/octo-repo/actions/runs/30433642", + "pull_requests": [], + "created_at": "2020-01-22T19:33:08Z", + "updated_at": "2020-01-22T19:33:08Z", + "jobs_url": "https://api.github.com/repos/octo-org/octo-repo/actions/runs/30433642/jobs", + "logs_url": "https://api.github.com/repos/octo-org/octo-repo/actions/runs/30433642/logs", + "check_suite_url": "https://api.github.com/repos/octo-org/octo-repo/check-suites/414944374", + "artifacts_url": "https://api.github.com/repos/octo-org/octo-repo/actions/runs/30433642/artifacts", + "cancel_url": "https://api.github.com/repos/octo-org/octo-repo/actions/runs/30433642/cancel", + "rerun_url": "https://api.github.com/repos/octo-org/octo-repo/actions/runs/30433642/rerun", + "workflow_url": "https://api.github.com/repos/octo-org/octo-repo/actions/workflows/159038", + "head_commit": { + "id": "acb5820ced9479c074f688cc328bf03f341a511d", + "tree_id": "d23f6eedb1e1b9610bbc754ddb5197bfe7271223", + "message": "Create linter.yaml", + "timestamp": "2020-01-22T19:33:05Z", + "author": { + "name": "Octo Cat", + "email": "octocat@github.com" + }, + "committer": { + "name": "GitHub", + "email": "noreply@github.com" + } + }, + "repository": { + "id": 1296269, + "node_id": "MDEwOlJlcG9zaXRvcnkxMjk2MjY5", + "name": "Hello-World", + "full_name": "octocat/Hello-World", + "owner": { + "login": "octocat", + "id": 1, + "node_id": "MDQ6VXNlcjE=", + "avatar_url": "https://github.com/images/error/octocat_happy.gif", + "gravatar_id": "", + "url": "https://api.github.com/users/octocat", + "html_url": "https://github.com/octocat", + "followers_url": "https://api.github.com/users/octocat/followers", + "following_url": "https://api.github.com/users/octocat/following{/other_user}", + "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}", + "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/octocat/subscriptions", + "organizations_url": "https://api.github.com/users/octocat/orgs", + "repos_url": "https://api.github.com/users/octocat/repos", + "events_url": "https://api.github.com/users/octocat/events{/privacy}", + "received_events_url": "https://api.github.com/users/octocat/received_events", + "type": "User", + "site_admin": false + }, + "private": false, + "html_url": "https://github.com/octocat/Hello-World", + "description": "This your first repo!", + "fork": false, + "url": "https://api.github.com/repos/octocat/Hello-World", + "archive_url": "https://api.github.com/repos/octocat/Hello-World/{archive_format}{/ref}", + "assignees_url": "https://api.github.com/repos/octocat/Hello-World/assignees{/user}", + "blobs_url": "https://api.github.com/repos/octocat/Hello-World/git/blobs{/sha}", + "branches_url": "https://api.github.com/repos/octocat/Hello-World/branches{/branch}", + "collaborators_url": "https://api.github.com/repos/octocat/Hello-World/collaborators{/collaborator}", + "comments_url": "https://api.github.com/repos/octocat/Hello-World/comments{/number}", + "commits_url": "https://api.github.com/repos/octocat/Hello-World/commits{/sha}", + "compare_url": "https://api.github.com/repos/octocat/Hello-World/compare/{base}...{head}", + "contents_url": "https://api.github.com/repos/octocat/Hello-World/contents/{+path}", + "contributors_url": "https://api.github.com/repos/octocat/Hello-World/contributors", + "deployments_url": "https://api.github.com/repos/octocat/Hello-World/deployments", + "downloads_url": "https://api.github.com/repos/octocat/Hello-World/downloads", + "events_url": "https://api.github.com/repos/octocat/Hello-World/events", + "forks_url": "https://api.github.com/repos/octocat/Hello-World/forks", + "git_commits_url": "https://api.github.com/repos/octocat/Hello-World/git/commits{/sha}", + "git_refs_url": "https://api.github.com/repos/octocat/Hello-World/git/refs{/sha}", + "git_tags_url": "https://api.github.com/repos/octocat/Hello-World/git/tags{/sha}", + "git_url": "git:github.com/octocat/Hello-World.git", + "issue_comment_url": "https://api.github.com/repos/octocat/Hello-World/issues/comments{/number}", + "issue_events_url": "https://api.github.com/repos/octocat/Hello-World/issues/events{/number}", + "issues_url": "https://api.github.com/repos/octocat/Hello-World/issues{/number}", + "keys_url": "https://api.github.com/repos/octocat/Hello-World/keys{/key_id}", + "labels_url": "https://api.github.com/repos/octocat/Hello-World/labels{/name}", + "languages_url": "https://api.github.com/repos/octocat/Hello-World/languages", + "merges_url": "https://api.github.com/repos/octocat/Hello-World/merges", + "milestones_url": "https://api.github.com/repos/octocat/Hello-World/milestones{/number}", + "notifications_url": "https://api.github.com/repos/octocat/Hello-World/notifications{?since,all,participating}", + "pulls_url": "https://api.github.com/repos/octocat/Hello-World/pulls{/number}", + "releases_url": "https://api.github.com/repos/octocat/Hello-World/releases{/id}", + "ssh_url": "git@github.com:octocat/Hello-World.git", + "stargazers_url": "https://api.github.com/repos/octocat/Hello-World/stargazers", + "statuses_url": "https://api.github.com/repos/octocat/Hello-World/statuses/{sha}", + "subscribers_url": "https://api.github.com/repos/octocat/Hello-World/subscribers", + "subscription_url": "https://api.github.com/repos/octocat/Hello-World/subscription", + "tags_url": "https://api.github.com/repos/octocat/Hello-World/tags", + "teams_url": "https://api.github.com/repos/octocat/Hello-World/teams", + "trees_url": "https://api.github.com/repos/octocat/Hello-World/git/trees{/sha}", + "hooks_url": "http://api.github.com/repos/octocat/Hello-World/hooks" + }, + "head_repository": { + "id": 217723378, + "node_id": "MDEwOlJlcG9zaXRvcnkyMTc3MjMzNzg=", + "name": "octo-repo", + "full_name": "octo-org/octo-repo", + "private": true, + "owner": { + "login": "octocat", + "id": 1, + "node_id": "MDQ6VXNlcjE=", + "avatar_url": "https://github.com/images/error/octocat_happy.gif", + "gravatar_id": "", + "url": "https://api.github.com/users/octocat", + "html_url": "https://github.com/octocat", + "followers_url": "https://api.github.com/users/octocat/followers", + "following_url": "https://api.github.com/users/octocat/following{/other_user}", + "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}", + "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/octocat/subscriptions", + "organizations_url": "https://api.github.com/users/octocat/orgs", + "repos_url": "https://api.github.com/users/octocat/repos", + "events_url": "https://api.github.com/users/octocat/events{/privacy}", + "received_events_url": "https://api.github.com/users/octocat/received_events", + "type": "User", + "site_admin": false + }, + "html_url": "https://github.com/octo-org/octo-repo", + "description": null, + "fork": false, + "url": "https://api.github.com/repos/octo-org/octo-repo", + "forks_url": "https://api.github.com/repos/octo-org/octo-repo/forks", + "keys_url": "https://api.github.com/repos/octo-org/octo-repo/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/octo-org/octo-repo/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/octo-org/octo-repo/teams", + "hooks_url": "https://api.github.com/repos/octo-org/octo-repo/hooks", + "issue_events_url": "https://api.github.com/repos/octo-org/octo-repo/issues/events{/number}", + "events_url": "https://api.github.com/repos/octo-org/octo-repo/events", + "assignees_url": "https://api.github.com/repos/octo-org/octo-repo/assignees{/user}", + "branches_url": "https://api.github.com/repos/octo-org/octo-repo/branches{/branch}", + "tags_url": "https://api.github.com/repos/octo-org/octo-repo/tags", + "blobs_url": "https://api.github.com/repos/octo-org/octo-repo/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/octo-org/octo-repo/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/octo-org/octo-repo/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/octo-org/octo-repo/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/octo-org/octo-repo/statuses/{sha}", + "languages_url": "https://api.github.com/repos/octo-org/octo-repo/languages", + "stargazers_url": "https://api.github.com/repos/octo-org/octo-repo/stargazers", + "contributors_url": "https://api.github.com/repos/octo-org/octo-repo/contributors", + "subscribers_url": "https://api.github.com/repos/octo-org/octo-repo/subscribers", + "subscription_url": "https://api.github.com/repos/octo-org/octo-repo/subscription", + "commits_url": "https://api.github.com/repos/octo-org/octo-repo/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/octo-org/octo-repo/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/octo-org/octo-repo/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/octo-org/octo-repo/issues/comments{/number}", + "contents_url": "https://api.github.com/repos/octo-org/octo-repo/contents/{+path}", + "compare_url": "https://api.github.com/repos/octo-org/octo-repo/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/octo-org/octo-repo/merges", + "archive_url": "https://api.github.com/repos/octo-org/octo-repo/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/octo-org/octo-repo/downloads", + "issues_url": "https://api.github.com/repos/octo-org/octo-repo/issues{/number}", + "pulls_url": "https://api.github.com/repos/octo-org/octo-repo/pulls{/number}", + "milestones_url": "https://api.github.com/repos/octo-org/octo-repo/milestones{/number}", + "notifications_url": "https://api.github.com/repos/octo-org/octo-repo/notifications{?since,all,participating}", + "labels_url": "https://api.github.com/repos/octo-org/octo-repo/labels{/name}", + "releases_url": "https://api.github.com/repos/octo-org/octo-repo/releases{/id}", + "deployments_url": "https://api.github.com/repos/octo-org/octo-repo/deployments" + } +} diff --git a/plugins/github-actions/dev/index.tsx b/plugins/github-actions/dev/index.tsx index dfda83909b..e105bf9294 100644 --- a/plugins/github-actions/dev/index.tsx +++ b/plugins/github-actions/dev/index.tsx @@ -14,7 +14,65 @@ * limitations under the License. */ +import React from 'react'; import { createDevApp } from '@backstage/dev-utils'; -import { githubActionsPlugin } from '../src/plugin'; +import { EntityGithubActionsContent, githubActionsPlugin } from '../src/plugin'; +import { EntityProvider } from '@backstage/plugin-catalog-react'; +import { Entity } from '@backstage/catalog-model'; +import { GithubActionsApi, githubActionsApiRef } from '../src'; +import getWorkflowRunResponse from './getWorkflowRun.json'; +import listJobsForWorkflowRunResponse from './listJobsForWorkflowRun.json'; -createDevApp().registerPlugin(githubActionsPlugin).render(); +const mockEntity: Entity = { + apiVersion: 'backstage.io/v1alpha1', + kind: 'Component', + metadata: { + name: 'backstage', + description: 'backstage.io', + annotations: { + 'github.com/project-slug': 'backstage/backstage', + }, + }, + spec: { + lifecycle: 'production', + type: 'website', + owner: 'user:guest', + }, +}; + +const mockGithubActionsApi: GithubActionsApi = { + async downloadJobLogsForWorkflowRun() {}, + async getWorkflow() { + return {} as any; + }, + async getWorkflowRun() { + return getWorkflowRunResponse; + }, + async listJobsForWorkflowRun() { + return listJobsForWorkflowRunResponse as any; + }, + async listWorkflowRuns() { + return {} as any; + }, + async reRunWorkflow() { + return {} as any; + }, +}; + +createDevApp() + .registerApi({ + api: githubActionsApiRef, + deps: {}, + factory: () => mockGithubActionsApi, + }) + .registerPlugin(githubActionsPlugin) + .addPage({ + path: '/github-actions', + title: 'Github Actions', + element: ( + + + + ), + }) + .render(); diff --git a/plugins/github-actions/dev/listJobsForWorkflowRun.json b/plugins/github-actions/dev/listJobsForWorkflowRun.json new file mode 100644 index 0000000000..1c3837baa1 --- /dev/null +++ b/plugins/github-actions/dev/listJobsForWorkflowRun.json @@ -0,0 +1,102 @@ +{ + "total_count": 1, + "jobs": [ + { + "id": 399444496, + "run_id": 29679449, + "run_url": "https://api.github.com/repos/octo-org/octo-repo/actions/runs/29679449", + "node_id": "MDEyOldvcmtmbG93IEpvYjM5OTQ0NDQ5Ng==", + "head_sha": "f83a356604ae3c5d03e1b46ef4d1ca77d64a90b0", + "url": "https://api.github.com/repos/octo-org/octo-repo/actions/jobs/399444496", + "html_url": "https://github.com/octo-org/octo-repo/runs/399444496", + "status": "completed", + "conclusion": "success", + "started_at": "2020-01-20T17:42:40Z", + "completed_at": "2020-01-20T17:44:39Z", + "name": "build", + "steps": [ + { + "name": "Set up job", + "status": "completed", + "conclusion": "success", + "number": 1, + "started_at": "2020-01-20T09:42:40.000-08:00", + "completed_at": "2020-01-20T09:42:41.000-08:00" + }, + { + "name": "Run actions/checkout@v2", + "status": "completed", + "conclusion": "success", + "number": 2, + "started_at": "2020-01-20T09:42:41.000-08:00", + "completed_at": "2020-01-20T09:42:45.000-08:00" + }, + { + "name": "Set up Ruby", + "status": "completed", + "conclusion": "success", + "number": 3, + "started_at": "2020-01-20T09:42:45.000-08:00", + "completed_at": "2020-01-20T09:42:45.000-08:00" + }, + { + "name": "Run actions/cache@v2", + "status": "completed", + "conclusion": "success", + "number": 4, + "started_at": "2020-01-20T09:42:45.000-08:00", + "completed_at": "2020-01-20T09:42:48.000-08:00" + }, + { + "name": "Install Bundler", + "status": "completed", + "conclusion": "success", + "number": 5, + "started_at": "2020-01-20T09:42:48.000-08:00", + "completed_at": "2020-01-20T09:42:52.000-08:00" + }, + { + "name": "Install Gems", + "status": "completed", + "conclusion": "success", + "number": 6, + "started_at": "2020-01-20T09:42:52.000-08:00", + "completed_at": "2020-01-20T09:42:53.000-08:00" + }, + { + "name": "Run Tests", + "status": "completed", + "conclusion": "success", + "number": 7, + "started_at": "2020-01-20T09:42:53.000-08:00", + "completed_at": "2020-01-20T09:42:59.000-08:00" + }, + { + "name": "Deploy to Heroku", + "status": "completed", + "conclusion": "success", + "number": 8, + "started_at": "2020-01-20T09:42:59.000-08:00", + "completed_at": "2020-01-20T09:44:39.000-08:00" + }, + { + "name": "Post actions/cache@v2", + "status": "completed", + "conclusion": "success", + "number": 16, + "started_at": "2020-01-20T09:44:39.000-08:00", + "completed_at": "2020-01-20T09:44:39.000-08:00" + }, + { + "name": "Complete job", + "status": "completed", + "conclusion": "success", + "number": 17, + "started_at": "2020-01-20T09:44:39.000-08:00", + "completed_at": "2020-01-20T09:44:39.000-08:00" + } + ], + "check_run_url": "https://api.github.com/repos/octo-org/octo-repo/check-runs/399444496" + } + ] +} From d000f29ee5cde22384bde9e806c9e6408398bba6 Mon Sep 17 00:00:00 2001 From: Joe Porpeglia Date: Fri, 25 Jun 2021 11:34:35 -0400 Subject: [PATCH 003/204] Replace moment with luxon Signed-off-by: Joe Porpeglia --- plugins/github-actions/package.json | 2 +- .../components/WorkflowRunDetails/WorkflowRunDetails.tsx | 8 +++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/plugins/github-actions/package.json b/plugins/github-actions/package.json index 1948b8babe..b1d3a3dd1b 100644 --- a/plugins/github-actions/package.json +++ b/plugins/github-actions/package.json @@ -42,7 +42,7 @@ "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.45", "@octokit/rest": "^18.5.3", - "moment": "^2.27.0", + "luxon": "^1.27.0", "react": "^16.13.1", "react-dom": "^16.13.1", "react-lazylog": "^4.5.3", diff --git a/plugins/github-actions/src/components/WorkflowRunDetails/WorkflowRunDetails.tsx b/plugins/github-actions/src/components/WorkflowRunDetails/WorkflowRunDetails.tsx index 4b5da51ce8..aebf7dfa01 100644 --- a/plugins/github-actions/src/components/WorkflowRunDetails/WorkflowRunDetails.tsx +++ b/plugins/github-actions/src/components/WorkflowRunDetails/WorkflowRunDetails.tsx @@ -36,7 +36,7 @@ import { } from '@material-ui/core'; import ExpandMoreIcon from '@material-ui/icons/ExpandMore'; import ExternalLinkIcon from '@material-ui/icons/Launch'; -import moment from 'moment'; +import { DateTime } from 'luxon'; import React from 'react'; import { Job, Jobs, Step } from '../../api'; import { useProjectName } from '../useProjectName'; @@ -74,8 +74,10 @@ const useStyles = makeStyles(theme => ({ })); const getElapsedTime = (start: string, end: string) => { - const diff = moment(moment(end || moment()).diff(moment(start))); - const timeElapsed = diff.format('m [minutes] s [seconds]'); + const startDate = DateTime.fromISO(start); + const endDate = end ? DateTime.fromISO(end) : DateTime.now(); + const diff = endDate.diff(startDate); + const timeElapsed = diff.toFormat(`m 'minutes' s 'seconds'`); return timeElapsed; }; From 316530684f15dc02ec7b23aec2e5c58650e1efc9 Mon Sep 17 00:00:00 2001 From: Joe Porpeglia Date: Fri, 25 Jun 2021 12:00:03 -0400 Subject: [PATCH 004/204] Add changeset Signed-off-by: Joe Porpeglia --- .changeset/slow-jobs-doubt.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/slow-jobs-doubt.md diff --git a/.changeset/slow-jobs-doubt.md b/.changeset/slow-jobs-doubt.md new file mode 100644 index 0000000000..0cc4ff20e8 --- /dev/null +++ b/.changeset/slow-jobs-doubt.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-github-actions': patch +--- + +Migrate from Moment to Luxon From 4c75f2f0e29262e4cd432dd689ce07c632db6e37 Mon Sep 17 00:00:00 2001 From: Johan Haals Date: Wed, 23 Jun 2021 14:16:33 +0200 Subject: [PATCH 005/204] Catalog: Add location key to handle duplicate entities Signed-off-by: Johan Haals --- .../20210302150147_refresh_state.js | 2 + ...210622104022_refresh_state_location_key.js | 35 +++++++++++++++++ .../src/next/ConfigLocationEntityProvider.ts | 5 ++- .../next/DefaultCatalogProcessingEngine.ts | 9 +++-- .../src/next/DefaultLocationStore.ts | 12 +++--- .../database/DefaultProcessingDatabase.ts | 39 ++++++++++++------- .../src/next/database/tables.ts | 1 + .../src/next/database/types.ts | 13 ++++--- .../DefaultCatalogProcessingOrchestrator.ts | 1 - .../processing/ProcessorOutputCollector.ts | 21 +++++++--- .../src/next/processing/types.ts | 7 +++- plugins/catalog-backend/src/next/types.ts | 5 ++- 12 files changed, 110 insertions(+), 40 deletions(-) create mode 100644 plugins/catalog-backend/migrations/20210622104022_refresh_state_location_key.js diff --git a/plugins/catalog-backend/migrations/20210302150147_refresh_state.js b/plugins/catalog-backend/migrations/20210302150147_refresh_state.js index db66b46305..2752ab0176 100644 --- a/plugins/catalog-backend/migrations/20210302150147_refresh_state.js +++ b/plugins/catalog-backend/migrations/20210302150147_refresh_state.js @@ -65,6 +65,8 @@ exports.up = async function up(knex) { .dateTime('last_discovery_at') // TODO: timezone or change to epoch-millis or similar .notNullable() .comment('The last timestamp of which this entity was discovered'); + // TODO: get migrations to work for this field instead. should be removed before merge. + table.text('location_key').nullable().comment('Location key'); table.unique(['entity_ref'], 'refresh_state_entity_ref_uniq'); table.index('entity_id', 'refresh_state_entity_id_idx'); table.index('entity_ref', 'refresh_state_entity_ref_idx'); diff --git a/plugins/catalog-backend/migrations/20210622104022_refresh_state_location_key.js b/plugins/catalog-backend/migrations/20210622104022_refresh_state_location_key.js new file mode 100644 index 0000000000..b77ff8961c --- /dev/null +++ b/plugins/catalog-backend/migrations/20210622104022_refresh_state_location_key.js @@ -0,0 +1,35 @@ +/* + * Copyright 2020 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// @ts-check + +/** + * @param {import('knex').Knex} knex + */ +exports.up = async function up(knex) { + await knex.schema.alterTable('refresh_state', table => { + table.text('location_key').nullable().comment('').alter(); + }); +}; + +/** + * @param {import('knex').Knex} knex + */ +exports.down = async function down(knex) { + await knex.schema.alterTable('refresh_state', table => { + table.dropColumn('location_key'); + }); +}; diff --git a/plugins/catalog-backend/src/next/ConfigLocationEntityProvider.ts b/plugins/catalog-backend/src/next/ConfigLocationEntityProvider.ts index 9218a9c0e1..5e343b0f23 100644 --- a/plugins/catalog-backend/src/next/ConfigLocationEntityProvider.ts +++ b/plugins/catalog-backend/src/next/ConfigLocationEntityProvider.ts @@ -16,6 +16,7 @@ import { Config } from '@backstage/config'; import path from 'path'; +import { getEntityLocationRef } from './processing/util'; import { EntityProvider, EntityProviderConnection } from './types'; import { locationSpecToLocationEntity } from './util'; @@ -37,10 +38,12 @@ export class ConfigLocationEntityProvider implements EntityProvider { const entities = locationConfigs.map(location => { const type = location.getString('type'); const target = location.getString('target'); - return locationSpecToLocationEntity({ + const entity = locationSpecToLocationEntity({ type, target: type === 'file' ? path.resolve(target) : target, }); + const emitKey = getEntityLocationRef(entity); + return { entity, emitKey }; }); await this.connection.applyMutation({ diff --git a/plugins/catalog-backend/src/next/DefaultCatalogProcessingEngine.ts b/plugins/catalog-backend/src/next/DefaultCatalogProcessingEngine.ts index a504de0bf3..e3828bdfd8 100644 --- a/plugins/catalog-backend/src/next/DefaultCatalogProcessingEngine.ts +++ b/plugins/catalog-backend/src/next/DefaultCatalogProcessingEngine.ts @@ -46,7 +46,7 @@ class Connection implements EntityProviderConnection { const db = this.config.processingDatabase; if (mutation.type === 'full') { - this.check(mutation.entities); + this.check(mutation.entities.map(e => e.entity)); await db.transaction(async tx => { await db.replaceUnprocessedEntities(tx, { sourceKey: this.config.id, @@ -57,8 +57,8 @@ class Connection implements EntityProviderConnection { return; } - this.check(mutation.added); - this.check(mutation.removed); + this.check(mutation.added.map(e => e.entity)); + this.check(mutation.removed.map(e => e.entity)); await db.transaction(async tx => { await db.replaceUnprocessedEntities(tx, { sourceKey: this.config.id, @@ -125,7 +125,7 @@ export class DefaultCatalogProcessingEngine implements CatalogProcessingEngine { }, processTask: async item => { try { - const { id, state, unprocessedEntity, entityRef } = item; + const { id, state, unprocessedEntity, entityRef, emitKey } = item; const result = await this.orchestrator.process({ entity: unprocessedEntity, state, @@ -171,6 +171,7 @@ export class DefaultCatalogProcessingEngine implements CatalogProcessingEngine { errors: errorsString, relations: result.relations, deferredEntities: result.deferredEntities, + emitKey, }); }); diff --git a/plugins/catalog-backend/src/next/DefaultLocationStore.ts b/plugins/catalog-backend/src/next/DefaultLocationStore.ts index 09de77e49f..5c3cefbaf7 100644 --- a/plugins/catalog-backend/src/next/DefaultLocationStore.ts +++ b/plugins/catalog-backend/src/next/DefaultLocationStore.ts @@ -19,6 +19,7 @@ import { ConflictError, NotFoundError } from '@backstage/errors'; import { Knex } from 'knex'; import { v4 as uuid } from 'uuid'; import { DbLocationsRow } from './database/tables'; +import { getEntityLocationRef } from './processing/util'; import { EntityProvider, EntityProviderConnection, @@ -60,10 +61,10 @@ export class DefaultLocationStore implements LocationStore, EntityProvider { return inner; }); - + const entity = locationSpecToLocationEntity(location); await this.connection.applyMutation({ type: 'delta', - added: [locationSpecToLocationEntity(location)], + added: [{ entity, emitKey: getEntityLocationRef(entity) }], removed: [], }); @@ -102,11 +103,11 @@ export class DefaultLocationStore implements LocationStore, EntityProvider { await tx('locations').where({ id }).del(); return location; }); - + const entity = locationSpecToLocationEntity(deleted); await this.connection.applyMutation({ type: 'delta', added: [], - removed: [locationSpecToLocationEntity(deleted)], + removed: [{ entity, emitKey: getEntityLocationRef(entity) }], }); } @@ -124,7 +125,8 @@ export class DefaultLocationStore implements LocationStore, EntityProvider { const locations = await this.locations(); const entities = locations.map(location => { - return locationSpecToLocationEntity(location); + const entity = locationSpecToLocationEntity(location); + return { entity, emitKey: getEntityLocationRef(entity) }; }); await this.connection.applyMutation({ diff --git a/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.ts b/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.ts index 79daee13e6..5bdde1fe78 100644 --- a/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.ts +++ b/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.ts @@ -22,6 +22,7 @@ import lodash from 'lodash'; import { v4 as uuid } from 'uuid'; import type { Logger } from 'winston'; import { Transaction } from '../../database'; +import { DeferredEntity } from '../processing/types'; import { DbRefreshStateReferencesRow, DbRefreshStateRow, @@ -63,15 +64,18 @@ export class DefaultProcessingDatabase implements ProcessingDatabase { errors, relations, deferredEntities, + emitKey, } = options; - const refreshResult = await tx('refresh_state') .update({ processed_entity: JSON.stringify(processedEntity), cache: JSON.stringify(state), errors, + emit_key: emitKey, }) - .where('entity_id', id); + .where('entity_id', id) + .andWhere('emit_key', emitKey) + .orWhere('emit_key', ''); if (refreshResult === 0) { throw new NotFoundError(`Processing state not found for ${id}`); } @@ -129,11 +133,11 @@ export class DefaultProcessingDatabase implements ProcessingDatabase { private async createDelta( tx: Knex.Transaction, options: ReplaceUnprocessedEntitiesOptions, - ): Promise<{ toAdd: Entity[]; toRemove: string[] }> { + ): Promise<{ toAdd: DeferredEntity[]; toRemove: string[] }> { if (options.type === 'delta') { return { toAdd: options.added, - toRemove: options.removed.map(e => stringifyEntityRef(e)), + toRemove: options.removed.map(e => stringifyEntityRef(e.entity)), }; } @@ -146,7 +150,7 @@ export class DefaultProcessingDatabase implements ProcessingDatabase { const items = options.items.map(entity => ({ entity, - ref: stringifyEntityRef(entity), + ref: stringifyEntityRef(entity.entity), })); const oldRefsSet = new Set(oldRefs); @@ -281,19 +285,22 @@ export class DefaultProcessingDatabase implements ProcessingDatabase { } if (toAdd.length) { - const state: Knex.DbRecord[] = toAdd.map(entity => ({ - entity_id: uuid(), - entity_ref: stringifyEntityRef(entity), - unprocessed_entity: JSON.stringify(entity), - errors: '', - next_update_at: tx.fn.now(), - last_discovery_at: tx.fn.now(), - })); + const state: Knex.DbRecord[] = toAdd.map( + ({ entity, emitKey }) => ({ + entity_id: uuid(), + entity_ref: stringifyEntityRef(entity), + unprocessed_entity: JSON.stringify(entity), + emit_key: emitKey, + errors: '', + next_update_at: tx.fn.now(), + last_discovery_at: tx.fn.now(), + }), + ); const stateReferences: DbRefreshStateReferencesRow[] = toAdd.map( entity => ({ source_key: options.sourceKey, - target_entity_ref: stringifyEntityRef(entity), + target_entity_ref: stringifyEntityRef(entity.entity), }), ); // TODO(freben): Concurrency? If we did these one by one, a .onConflict().merge would have made sense @@ -313,12 +320,13 @@ export class DefaultProcessingDatabase implements ProcessingDatabase { const tx = txOpaque as Knex.Transaction; const stateRows = options.entities.map( - entity => + ({ entity, emitKey }) => ({ entity_id: uuid(), entity_ref: stringifyEntityRef(entity), unprocessed_entity: JSON.stringify(entity), errors: '', + emit_key: emitKey, next_update_at: tx.fn.now(), last_discovery_at: tx.fn.now(), } as Knex.DbRecord), @@ -406,6 +414,7 @@ export class DefaultProcessingDatabase implements ProcessingDatabase { ? JSON.parse(i.cache) : new Map(), errors: i.errors, + emitKey: i.emit_key, } as RefreshStateItem), ), }; diff --git a/plugins/catalog-backend/src/next/database/tables.ts b/plugins/catalog-backend/src/next/database/tables.ts index 93453ba914..a298c37022 100644 --- a/plugins/catalog-backend/src/next/database/tables.ts +++ b/plugins/catalog-backend/src/next/database/tables.ts @@ -29,6 +29,7 @@ export type DbRefreshStateRow = { next_update_at: string; last_discovery_at: string; // remove? errors?: string; + emit_key: string; }; export type DbRefreshStateReferencesRow = { diff --git a/plugins/catalog-backend/src/next/database/types.ts b/plugins/catalog-backend/src/next/database/types.ts index dd342126c4..5e4d0becd3 100644 --- a/plugins/catalog-backend/src/next/database/types.ts +++ b/plugins/catalog-backend/src/next/database/types.ts @@ -17,10 +17,11 @@ import { Entity, EntityRelationSpec } from '@backstage/catalog-model'; import { JsonObject } from '@backstage/config'; import { Transaction } from '../../database/types'; +import { DeferredEntity } from '../processing/types'; export type AddUnprocessedEntitiesOptions = { entityRef: string; - entities: Entity[]; + entities: DeferredEntity[]; }; export type AddUnprocessedEntitiesResult = {}; @@ -31,7 +32,8 @@ export type UpdateProcessedEntityOptions = { state?: Map; errors?: string; relations: EntityRelationSpec[]; - deferredEntities: Entity[]; + deferredEntities: DeferredEntity[]; + emitKey: string; }; export type UpdateProcessedEntityErrorsOptions = { @@ -48,6 +50,7 @@ export type RefreshStateItem = { lastDiscoveryAt: string; // remove? state: Map; errors?: string; + emitKey: string; }; export type GetProcessableEntitiesResult = { @@ -57,13 +60,13 @@ export type GetProcessableEntitiesResult = { export type ReplaceUnprocessedEntitiesOptions = | { sourceKey: string; - items: Entity[]; + items: DeferredEntity[]; type: 'full'; } | { sourceKey: string; - added: Entity[]; - removed: Entity[]; + added: DeferredEntity[]; + removed: DeferredEntity[]; type: 'delta'; }; diff --git a/plugins/catalog-backend/src/next/processing/DefaultCatalogProcessingOrchestrator.ts b/plugins/catalog-backend/src/next/processing/DefaultCatalogProcessingOrchestrator.ts index 48a40a2f6e..bb23b6afb3 100644 --- a/plugins/catalog-backend/src/next/processing/DefaultCatalogProcessingOrchestrator.ts +++ b/plugins/catalog-backend/src/next/processing/DefaultCatalogProcessingOrchestrator.ts @@ -68,7 +68,6 @@ export class DefaultCatalogProcessingOrchestrator async process( request: EntityProcessingRequest, ): Promise { - // TODO: implement dryRun/eager return this.processSingleEntity(request.entity); } diff --git a/plugins/catalog-backend/src/next/processing/ProcessorOutputCollector.ts b/plugins/catalog-backend/src/next/processing/ProcessorOutputCollector.ts index 3f8594bd48..fbb2744668 100644 --- a/plugins/catalog-backend/src/next/processing/ProcessorOutputCollector.ts +++ b/plugins/catalog-backend/src/next/processing/ProcessorOutputCollector.ts @@ -24,7 +24,12 @@ import { import { Logger } from 'winston'; import { CatalogProcessorResult } from '../../ingestion'; import { locationSpecToLocationEntity } from '../util'; -import { getEntityOriginLocationRef, validateEntityEnvelope } from './util'; +import { DeferredEntity } from './types'; +import { + getEntityLocationRef, + getEntityOriginLocationRef, + validateEntityEnvelope, +} from './util'; /** * Helper class for aggregating all of the emitted data from processors. @@ -32,7 +37,7 @@ import { getEntityOriginLocationRef, validateEntityEnvelope } from './util'; export class ProcessorOutputCollector { private readonly errors = new Array(); private readonly relations = new Array(); - private readonly deferredEntities = new Array(); + private readonly deferredEntities = new Array(); private done = false; constructor( @@ -73,6 +78,8 @@ export class ProcessorOutputCollector { return; } + const location = stringifyLocationReference(i.location); + // Note that at this point, we have only validated the envelope part of // the entity data. Annotations are not part of that, so we have to be // defensive. If the annotations were malformed (e.g. were not a valid @@ -81,7 +88,6 @@ export class ProcessorOutputCollector { const annotations = entity.metadata.annotations || {}; if (typeof annotations === 'object' && !Array.isArray(annotations)) { const originLocation = getEntityOriginLocationRef(this.parentEntity); - const location = stringifyLocationReference(i.location); entity = { ...entity, metadata: { @@ -95,11 +101,14 @@ export class ProcessorOutputCollector { }; } - this.deferredEntities.push(entity); + this.deferredEntities.push({ entity, emitKey: location }); } else if (i.type === 'location') { - this.deferredEntities.push( - locationSpecToLocationEntity(i.location, this.parentEntity), + const entity = locationSpecToLocationEntity( + i.location, + this.parentEntity, ); + const emitKey = getEntityLocationRef(entity); + this.deferredEntities.push({ entity, emitKey }); } else if (i.type === 'relation') { this.relations.push(i.relation); } else if (i.type === 'error') { diff --git a/plugins/catalog-backend/src/next/processing/types.ts b/plugins/catalog-backend/src/next/processing/types.ts index e76e789e54..b2a627943b 100644 --- a/plugins/catalog-backend/src/next/processing/types.ts +++ b/plugins/catalog-backend/src/next/processing/types.ts @@ -27,7 +27,7 @@ export type EntityProcessingResult = ok: true; state: Map; completedEntity: Entity; - deferredEntities: Entity[]; + deferredEntities: DeferredEntity[]; relations: EntityRelationSpec[]; errors: Error[]; } @@ -39,3 +39,8 @@ export type EntityProcessingResult = export interface CatalogProcessingOrchestrator { process(request: EntityProcessingRequest): Promise; } + +export type DeferredEntity = { + entity: Entity; + emitKey: string; +}; diff --git a/plugins/catalog-backend/src/next/types.ts b/plugins/catalog-backend/src/next/types.ts index c689f288aa..3b27dd7d10 100644 --- a/plugins/catalog-backend/src/next/types.ts +++ b/plugins/catalog-backend/src/next/types.ts @@ -15,6 +15,7 @@ */ import { Entity, Location, LocationSpec } from '@backstage/catalog-model'; +import { DeferredEntity } from './processing/types'; export interface LocationService { createLocation( @@ -39,8 +40,8 @@ export interface CatalogProcessingEngine { } export type EntityProviderMutation = - | { type: 'full'; entities: Entity[] } - | { type: 'delta'; added: Entity[]; removed: Entity[] }; + | { type: 'full'; entities: DeferredEntity[] } + | { type: 'delta'; added: DeferredEntity[]; removed: DeferredEntity[] }; export interface EntityProviderConnection { applyMutation(mutation: EntityProviderMutation): Promise; From ffaedfb702d2f21168fa0e19013f9c65aadc1528 Mon Sep 17 00:00:00 2001 From: Johan Haals Date: Mon, 28 Jun 2021 10:37:38 +0200 Subject: [PATCH 006/204] Rename to locationKey, make it optional Signed-off-by: Johan Haals --- .../src/next/DefaultCatalogProcessingEngine.ts | 4 ++-- .../src/next/DefaultLocationService.ts | 12 +++++++++--- .../src/next/DefaultLocationStore.ts | 6 +++--- .../next/database/DefaultProcessingDatabase.ts | 18 +++++++++--------- .../src/next/database/tables.ts | 2 +- .../catalog-backend/src/next/database/types.ts | 4 ++-- .../processing/ProcessorOutputCollector.ts | 6 +++--- .../src/next/processing/types.ts | 2 +- 8 files changed, 30 insertions(+), 24 deletions(-) diff --git a/plugins/catalog-backend/src/next/DefaultCatalogProcessingEngine.ts b/plugins/catalog-backend/src/next/DefaultCatalogProcessingEngine.ts index e3828bdfd8..0ae20c94b1 100644 --- a/plugins/catalog-backend/src/next/DefaultCatalogProcessingEngine.ts +++ b/plugins/catalog-backend/src/next/DefaultCatalogProcessingEngine.ts @@ -125,7 +125,7 @@ export class DefaultCatalogProcessingEngine implements CatalogProcessingEngine { }, processTask: async item => { try { - const { id, state, unprocessedEntity, entityRef, emitKey } = item; + const { id, state, unprocessedEntity, entityRef, locationKey } = item; const result = await this.orchestrator.process({ entity: unprocessedEntity, state, @@ -171,7 +171,7 @@ export class DefaultCatalogProcessingEngine implements CatalogProcessingEngine { errors: errorsString, relations: result.relations, deferredEntities: result.deferredEntities, - emitKey, + locationKey, }); }); diff --git a/plugins/catalog-backend/src/next/DefaultLocationService.ts b/plugins/catalog-backend/src/next/DefaultLocationService.ts index ceb51a952e..70679a3bd6 100644 --- a/plugins/catalog-backend/src/next/DefaultLocationService.ts +++ b/plugins/catalog-backend/src/next/DefaultLocationService.ts @@ -20,7 +20,10 @@ import { LOCATION_ANNOTATION, ORIGIN_LOCATION_ANNOTATION, } from '@backstage/catalog-model'; -import { CatalogProcessingOrchestrator } from './processing/types'; +import { + CatalogProcessingOrchestrator, + DeferredEntity, +} from './processing/types'; import { LocationService, LocationStore } from './types'; import { locationSpecToMetadataName } from './util'; @@ -73,7 +76,9 @@ export class DefaultLocationService implements LocationService { target: spec.target, }, }; - const unprocessedEntities: Entity[] = [entity]; + const unprocessedEntities: DeferredEntity[] = [ + { entity, locationKey: `${spec.type}:${spec.target}` }, + ]; const entities: Entity[] = []; const state = new Map(); // ignored while (unprocessedEntities.length) { @@ -82,11 +87,12 @@ export class DefaultLocationService implements LocationService { continue; } const processed = await this.orchestrator.process({ - entity: currentEntity, + entity: currentEntity.entity, state, }); if (processed.ok) { + // todo unprocessedEntities.push(...processed.deferredEntities); entities.push(processed.completedEntity); } else { diff --git a/plugins/catalog-backend/src/next/DefaultLocationStore.ts b/plugins/catalog-backend/src/next/DefaultLocationStore.ts index 5c3cefbaf7..c9ffe9a682 100644 --- a/plugins/catalog-backend/src/next/DefaultLocationStore.ts +++ b/plugins/catalog-backend/src/next/DefaultLocationStore.ts @@ -64,7 +64,7 @@ export class DefaultLocationStore implements LocationStore, EntityProvider { const entity = locationSpecToLocationEntity(location); await this.connection.applyMutation({ type: 'delta', - added: [{ entity, emitKey: getEntityLocationRef(entity) }], + added: [{ entity, locationKey: getEntityLocationRef(entity) }], removed: [], }); @@ -107,7 +107,7 @@ export class DefaultLocationStore implements LocationStore, EntityProvider { await this.connection.applyMutation({ type: 'delta', added: [], - removed: [{ entity, emitKey: getEntityLocationRef(entity) }], + removed: [{ entity, locationKey: getEntityLocationRef(entity) }], }); } @@ -126,7 +126,7 @@ export class DefaultLocationStore implements LocationStore, EntityProvider { const entities = locations.map(location => { const entity = locationSpecToLocationEntity(location); - return { entity, emitKey: getEntityLocationRef(entity) }; + return { entity, locationKey: getEntityLocationRef(entity) }; }); await this.connection.applyMutation({ diff --git a/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.ts b/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.ts index 5bdde1fe78..c2bfb4f633 100644 --- a/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.ts +++ b/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.ts @@ -64,18 +64,18 @@ export class DefaultProcessingDatabase implements ProcessingDatabase { errors, relations, deferredEntities, - emitKey, + locationKey, } = options; const refreshResult = await tx('refresh_state') .update({ processed_entity: JSON.stringify(processedEntity), cache: JSON.stringify(state), errors, - emit_key: emitKey, + location_key: locationKey, }) .where('entity_id', id) - .andWhere('emit_key', emitKey) - .orWhere('emit_key', ''); + .andWhere('location_key', locationKey) + .orWhere('location_key', ''); if (refreshResult === 0) { throw new NotFoundError(`Processing state not found for ${id}`); } @@ -286,11 +286,11 @@ export class DefaultProcessingDatabase implements ProcessingDatabase { if (toAdd.length) { const state: Knex.DbRecord[] = toAdd.map( - ({ entity, emitKey }) => ({ + ({ entity, locationKey }) => ({ entity_id: uuid(), entity_ref: stringifyEntityRef(entity), unprocessed_entity: JSON.stringify(entity), - emit_key: emitKey, + location_key: locationKey, errors: '', next_update_at: tx.fn.now(), last_discovery_at: tx.fn.now(), @@ -320,13 +320,13 @@ export class DefaultProcessingDatabase implements ProcessingDatabase { const tx = txOpaque as Knex.Transaction; const stateRows = options.entities.map( - ({ entity, emitKey }) => + ({ entity, locationKey }) => ({ entity_id: uuid(), entity_ref: stringifyEntityRef(entity), unprocessed_entity: JSON.stringify(entity), errors: '', - emit_key: emitKey, + location_key: locationKey, next_update_at: tx.fn.now(), last_discovery_at: tx.fn.now(), } as Knex.DbRecord), @@ -414,7 +414,7 @@ export class DefaultProcessingDatabase implements ProcessingDatabase { ? JSON.parse(i.cache) : new Map(), errors: i.errors, - emitKey: i.emit_key, + locationKey: i.location_key, } as RefreshStateItem), ), }; diff --git a/plugins/catalog-backend/src/next/database/tables.ts b/plugins/catalog-backend/src/next/database/tables.ts index a298c37022..395694131d 100644 --- a/plugins/catalog-backend/src/next/database/tables.ts +++ b/plugins/catalog-backend/src/next/database/tables.ts @@ -29,7 +29,7 @@ export type DbRefreshStateRow = { next_update_at: string; last_discovery_at: string; // remove? errors?: string; - emit_key: string; + location_key?: string; }; export type DbRefreshStateReferencesRow = { diff --git a/plugins/catalog-backend/src/next/database/types.ts b/plugins/catalog-backend/src/next/database/types.ts index 5e4d0becd3..cd5d2a362d 100644 --- a/plugins/catalog-backend/src/next/database/types.ts +++ b/plugins/catalog-backend/src/next/database/types.ts @@ -33,7 +33,7 @@ export type UpdateProcessedEntityOptions = { errors?: string; relations: EntityRelationSpec[]; deferredEntities: DeferredEntity[]; - emitKey: string; + locationKey?: string; }; export type UpdateProcessedEntityErrorsOptions = { @@ -50,7 +50,7 @@ export type RefreshStateItem = { lastDiscoveryAt: string; // remove? state: Map; errors?: string; - emitKey: string; + locationKey?: string; }; export type GetProcessableEntitiesResult = { diff --git a/plugins/catalog-backend/src/next/processing/ProcessorOutputCollector.ts b/plugins/catalog-backend/src/next/processing/ProcessorOutputCollector.ts index fbb2744668..507def964a 100644 --- a/plugins/catalog-backend/src/next/processing/ProcessorOutputCollector.ts +++ b/plugins/catalog-backend/src/next/processing/ProcessorOutputCollector.ts @@ -101,14 +101,14 @@ export class ProcessorOutputCollector { }; } - this.deferredEntities.push({ entity, emitKey: location }); + this.deferredEntities.push({ entity, locationKey: location }); } else if (i.type === 'location') { const entity = locationSpecToLocationEntity( i.location, this.parentEntity, ); - const emitKey = getEntityLocationRef(entity); - this.deferredEntities.push({ entity, emitKey }); + const locationKey = getEntityLocationRef(entity); + this.deferredEntities.push({ entity, locationKey }); } else if (i.type === 'relation') { this.relations.push(i.relation); } else if (i.type === 'error') { diff --git a/plugins/catalog-backend/src/next/processing/types.ts b/plugins/catalog-backend/src/next/processing/types.ts index b2a627943b..9e30d07404 100644 --- a/plugins/catalog-backend/src/next/processing/types.ts +++ b/plugins/catalog-backend/src/next/processing/types.ts @@ -42,5 +42,5 @@ export interface CatalogProcessingOrchestrator { export type DeferredEntity = { entity: Entity; - emitKey: string; + locationKey?: string; }; From 683308ecf805e786b26ba751f484e5383a9399e6 Mon Sep 17 00:00:00 2001 From: Flavien Chantelot Date: Mon, 28 Jun 2021 11:24:28 +0200 Subject: [PATCH 007/204] fix: remove utf8 encoding on openstack publisher The utf8 encoding, which was not setted for other cloud storage providers, broke all images and other binary files. The files uploaded were unreadable except plain text files. So in a standard documentation, all images were broken Signed-off-by: Flavien Chantelot --- .changeset/gorgeous-timers-cover.md | 5 +++++ .../techdocs-common/src/stages/publish/openStackSwift.ts | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 .changeset/gorgeous-timers-cover.md diff --git a/.changeset/gorgeous-timers-cover.md b/.changeset/gorgeous-timers-cover.md new file mode 100644 index 0000000000..de71d740c0 --- /dev/null +++ b/.changeset/gorgeous-timers-cover.md @@ -0,0 +1,5 @@ +--- +'@backstage/techdocs-common': patch +--- + +Fix openStack swift publisher encoding issue. Remove utf8 forced encoding on binary files diff --git a/packages/techdocs-common/src/stages/publish/openStackSwift.ts b/packages/techdocs-common/src/stages/publish/openStackSwift.ts index 18944b5605..6be8539aa9 100644 --- a/packages/techdocs-common/src/stages/publish/openStackSwift.ts +++ b/packages/techdocs-common/src/stages/publish/openStackSwift.ts @@ -156,7 +156,7 @@ export class OpenStackSwiftPublish implements PublisherBase { const uploadFile = limiter( () => new Promise((res, rej) => { - const readStream = fs.createReadStream(filePath, 'utf8'); + const readStream = fs.createReadStream(filePath); const writeStream = this.storageClient.upload(params); From 846168da2cfbc5a224f35493fdfebe097e64392b Mon Sep 17 00:00:00 2001 From: Andrew Shirley Date: Mon, 28 Jun 2021 13:51:33 +0100 Subject: [PATCH 008/204] Add an optional id prop and pass to load API Signed-off-by: Andrew Shirley --- .changeset/many-melons-hang.md | 5 ++++ plugins/tech-radar/README.md | 8 +++++- plugins/tech-radar/api-report.md | 11 ++++---- plugins/tech-radar/src/api.ts | 14 +++++++---- .../src/components/RadarComponent.tsx | 11 ++++---- .../src/components/RadarPage.test.tsx | 25 +++++++++++++++++++ 6 files changed, 58 insertions(+), 16 deletions(-) create mode 100644 .changeset/many-melons-hang.md diff --git a/.changeset/many-melons-hang.md b/.changeset/many-melons-hang.md new file mode 100644 index 0000000000..02fb8316b7 --- /dev/null +++ b/.changeset/many-melons-hang.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-tech-radar': patch +--- + +Add optional id prop passing it to the load API diff --git a/plugins/tech-radar/README.md b/plugins/tech-radar/README.md index 35c510ddd3..469a12e8e4 100644 --- a/plugins/tech-radar/README.md +++ b/plugins/tech-radar/README.md @@ -82,7 +82,9 @@ import { } from '@backstage/plugin-tech-radar'; class MyOwnClient implements TechRadarApi { - async load(): Promise { + async load(id: string | undefined): Promise { + // if needed id prop can be used to fetch the correct data + const data = await fetch('https://mydata.json').then(res => res.json()); // maybe you'll need to do some data transformation here to make it look like TechRadarLoaderResponse @@ -120,3 +122,7 @@ You can use the `svgProps` option to pass custom React props to the `` elem // const { getByTestId } = render(...); // expect(getByTestId('tech-radar-svg')).toBeInTheDocument(); ``` + +### How do I support multiple radars + +The `TechRadarPage` and `TechRadarComponent` components both take an optional `id` prop which is subsequently passed to the `load` method of the API to distinguish which radar's data to load. diff --git a/plugins/tech-radar/api-report.md b/plugins/tech-radar/api-report.md index f8bcc84d3a..8b98f1e494 100644 --- a/plugins/tech-radar/api-report.md +++ b/plugins/tech-radar/api-report.md @@ -46,7 +46,7 @@ export interface RadarQuadrant { name: string; } -// @public +// @public (undocumented) export interface RadarRing { // (undocumented) color: string; @@ -68,8 +68,7 @@ export const Router: { // @public (undocumented) export interface TechRadarApi { - // (undocumented) - load: () => Promise; + load: (id: string | undefined) => Promise; } // @public (undocumented) @@ -78,17 +77,19 @@ export const techRadarApiRef: ApiRef; // @public (undocumented) export const TechRadarComponent: (props: TechRadarComponentProps) => JSX.Element; -// @public +// @public (undocumented) export interface TechRadarComponentProps { // (undocumented) height: number; // (undocumented) + id?: string; + // (undocumented) svgProps?: object; // (undocumented) width: number; } -// @public +// @public (undocumented) export interface TechRadarLoaderResponse { // (undocumented) entries: RadarEntry[]; diff --git a/plugins/tech-radar/src/api.ts b/plugins/tech-radar/src/api.ts index fe574fcfd1..34307a1697 100644 --- a/plugins/tech-radar/src/api.ts +++ b/plugins/tech-radar/src/api.ts @@ -23,11 +23,14 @@ export const techRadarApiRef = createApiRef({ }); export interface TechRadarApi { - // Loads the TechRadar response data to pass through to the TechRadar component - load: () => Promise; + /** + * Loads the TechRadar response data to pass through to the TechRadar component. + * Takes the id prop of the TechRadarComponent or TechRadarPage to distinguish between multiple radars if needed + */ + load: (id: string | undefined) => Promise; } -/** +/* * Types related to the Radar's visualization. */ @@ -59,7 +62,7 @@ export interface RadarEntrySnapshot { moved?: MovedState; } -/** +/* * Types related to data collection for the Radar. */ @@ -69,11 +72,12 @@ export interface TechRadarLoaderResponse { entries: RadarEntry[]; } -/** +/* * Set up the Radar as a Backstage component. */ export interface TechRadarComponentProps { + id?: string; width: number; height: number; svgProps?: object; diff --git a/plugins/tech-radar/src/components/RadarComponent.tsx b/plugins/tech-radar/src/components/RadarComponent.tsx index fe42ad8e78..faa2763f17 100644 --- a/plugins/tech-radar/src/components/RadarComponent.tsx +++ b/plugins/tech-radar/src/components/RadarComponent.tsx @@ -27,13 +27,14 @@ import { Entry } from '../utils/types'; import { Progress } from '@backstage/core-components'; import { useApi, errorApiRef } from '@backstage/core-plugin-api'; -const useTechRadarLoader = () => { +const useTechRadarLoader = (id: string | undefined) => { const errorApi = useApi(errorApiRef); const techRadarApi = useApi(techRadarApiRef); - const { error, value, loading } = useAsync(async () => techRadarApi.load(), [ - techRadarApi, - ]); + const { error, value, loading } = useAsync( + async () => techRadarApi.load(id), + [techRadarApi], + ); useEffect(() => { if (error) { @@ -45,7 +46,7 @@ const useTechRadarLoader = () => { }; const RadarComponent = (props: TechRadarComponentProps): JSX.Element => { - const { loading, error, value: data } = useTechRadarLoader(); + const { loading, error, value: data } = useTechRadarLoader(props.id); const mapToEntries = ( loaderResponse: TechRadarLoaderResponse | undefined, diff --git a/plugins/tech-radar/src/components/RadarPage.test.tsx b/plugins/tech-radar/src/components/RadarPage.test.tsx index f4b768d369..7215fc40df 100644 --- a/plugins/tech-radar/src/components/RadarPage.test.tsx +++ b/plugins/tech-radar/src/components/RadarPage.test.tsx @@ -85,6 +85,7 @@ describe('RadarPage', () => { height: 800, svgProps: { 'data-testid': 'tech-radar-svg' }, }; + jest.spyOn(mockClient, 'load'); const { getByText, getByTestId } = await renderInTestApp( @@ -100,6 +101,30 @@ describe('RadarPage', () => { getByText('Pick the recommended technologies for your projects'), ).toBeInTheDocument(); expect(getByTestId('tech-radar-svg')).toBeInTheDocument(); + expect(mockClient.load).toBeCalledWith(undefined); + }); + + it('should call load with id', async () => { + const techRadarProps = { + width: 1200, + height: 800, + svgProps: { 'data-testid': 'tech-radar-svg' }, + id: 'myId', + }; + jest.spyOn(mockClient, 'load'); + + const { getByTestId } = await renderInTestApp( + + + + + , + ); + + await waitForElement(() => getByTestId('tech-radar-svg')); + + expect(getByTestId('tech-radar-svg')).toBeInTheDocument(); + expect(mockClient.load).toBeCalledWith('myId'); }); it('should call the errorApi if load fails', async () => { From 4742508f06b99e62df0312f64543f53740ee090d Mon Sep 17 00:00:00 2001 From: Deepak Bhardwaj <62239457+deepak-bhardwaj-ps@users.noreply.github.com> Date: Fri, 25 Jun 2021 21:21:11 +0530 Subject: [PATCH 009/204] fix: Sys Diagram clipped if wider than container Signed-off-by: Deepak Bhardwaj Signed-off-by: Deepak Bhardwaj <62239457+deepak-bhardwaj-ps@users.noreply.github.com> Signed-off-by: Deepak Bhardwaj --- .../src/components/DependencyGraph/DependencyGraph.tsx | 2 +- .../src/components/SystemDiagramCard/SystemDiagramCard.tsx | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/core-components/src/components/DependencyGraph/DependencyGraph.tsx b/packages/core-components/src/components/DependencyGraph/DependencyGraph.tsx index 5c0442f906..89f7421d2a 100644 --- a/packages/core-components/src/components/DependencyGraph/DependencyGraph.tsx +++ b/packages/core-components/src/components/DependencyGraph/DependencyGraph.tsx @@ -262,7 +262,7 @@ export function DependencyGraph({ diff --git a/plugins/catalog/src/components/SystemDiagramCard/SystemDiagramCard.tsx b/plugins/catalog/src/components/SystemDiagramCard/SystemDiagramCard.tsx index 5af4755bcb..a56d101d34 100644 --- a/plugins/catalog/src/components/SystemDiagramCard/SystemDiagramCard.tsx +++ b/plugins/catalog/src/components/SystemDiagramCard/SystemDiagramCard.tsx @@ -262,6 +262,8 @@ export function SystemDiagramCard() { nodeMargin={10} direction={DependencyGraphTypes.Direction.BOTTOM_TOP} renderNode={RenderNode} + paddingX={50} + paddingY={50} /> Date: Fri, 25 Jun 2021 21:55:01 +0530 Subject: [PATCH 010/204] Updated changeset Signed-off-by: Deepak Bhardwaj --- .changeset/grumpy-sloths-check.md | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 .changeset/grumpy-sloths-check.md diff --git a/.changeset/grumpy-sloths-check.md b/.changeset/grumpy-sloths-check.md new file mode 100644 index 0000000000..124898b7fd --- /dev/null +++ b/.changeset/grumpy-sloths-check.md @@ -0,0 +1,6 @@ +--- +'@backstage/core-components': patch +'@backstage/plugin-catalog': patch +--- + +System Diagram was getting clipped when it was wider than the container. From 496ff9be1748e57a24dfc6272aa885e3c9f3070f Mon Sep 17 00:00:00 2001 From: Deepak Bhardwaj Date: Sat, 26 Jun 2021 09:52:01 +0530 Subject: [PATCH 011/204] Used theme spacing Signed-off-by: Deepak Bhardwaj --- .../src/components/SystemDiagramCard/SystemDiagramCard.tsx | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/plugins/catalog/src/components/SystemDiagramCard/SystemDiagramCard.tsx b/plugins/catalog/src/components/SystemDiagramCard/SystemDiagramCard.tsx index a56d101d34..272ad8a6d6 100644 --- a/plugins/catalog/src/components/SystemDiagramCard/SystemDiagramCard.tsx +++ b/plugins/catalog/src/components/SystemDiagramCard/SystemDiagramCard.tsx @@ -29,7 +29,7 @@ import { getEntityRelations, useEntity, } from '@backstage/plugin-catalog-react'; -import { Box, makeStyles, Typography } from '@material-ui/core'; +import { Box, makeStyles, Typography, useTheme } from '@material-ui/core'; import ZoomOutMap from '@material-ui/icons/ZoomOutMap'; import React from 'react'; import { useAsync } from 'react-use'; @@ -151,6 +151,7 @@ function RenderNode(props: DependencyGraphTypes.RenderNodeProps) { */ export function SystemDiagramCard() { const { entity } = useEntity(); + const theme = useTheme(); const currentSystemName = entity.metadata.name; const currentSystemNode = stringifyEntityRef(entity); const systemNodes = new Array<{ id: string; kind: string; name: string }>(); @@ -262,8 +263,8 @@ export function SystemDiagramCard() { nodeMargin={10} direction={DependencyGraphTypes.Direction.BOTTOM_TOP} renderNode={RenderNode} - paddingX={50} - paddingY={50} + paddingX={theme.spacing(4)} + paddingY={theme.spacing(4)} /> Date: Sat, 26 Jun 2021 10:10:31 +0530 Subject: [PATCH 012/204] Updated changeset description Signed-off-by: Deepak Bhardwaj --- .changeset/grumpy-sloths-check.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/grumpy-sloths-check.md b/.changeset/grumpy-sloths-check.md index 124898b7fd..e2c2483c00 100644 --- a/.changeset/grumpy-sloths-check.md +++ b/.changeset/grumpy-sloths-check.md @@ -3,4 +3,4 @@ '@backstage/plugin-catalog': patch --- -System Diagram was getting clipped when it was wider than the container. +Fixed sizing of the System diagram when the rendered graph was wider than the container. From f11e50ea712e939039a3dc5ccd0b50b4a903f9f8 Mon Sep 17 00:00:00 2001 From: Deepak Bhardwaj Date: Mon, 28 Jun 2021 21:05:11 +0530 Subject: [PATCH 013/204] feat: open external tools in new tab Signed-off-by: Deepak Bhardwaj --- .changeset/fair-falcons-scream.md | 5 +++++ plugins/explore/src/components/ToolCard/ToolCard.tsx | 8 +++++++- 2 files changed, 12 insertions(+), 1 deletion(-) create mode 100644 .changeset/fair-falcons-scream.md diff --git a/.changeset/fair-falcons-scream.md b/.changeset/fair-falcons-scream.md new file mode 100644 index 0000000000..5ce4b40265 --- /dev/null +++ b/.changeset/fair-falcons-scream.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-explore': patch +--- + +Enhanced tools card to open external tools in new tab diff --git a/plugins/explore/src/components/ToolCard/ToolCard.tsx b/plugins/explore/src/components/ToolCard/ToolCard.tsx index 2baa0cffda..00c9851865 100644 --- a/plugins/explore/src/components/ToolCard/ToolCard.tsx +++ b/plugins/explore/src/components/ToolCard/ToolCard.tsx @@ -63,6 +63,7 @@ export const ToolCard = ({ card, objectFit }: Props) => { const classes = useStyles(); const { title, description, url, image, lifecycle, tags } = card; + const isExternalUrl = url.startsWith('https://') || url.startsWith('http://'); return ( @@ -97,7 +98,12 @@ export const ToolCard = ({ card, objectFit }: Props) => { )} - From 4389ceefea0dfe89dfb84df10e943de3eb7e97c4 Mon Sep 17 00:00:00 2001 From: Philipp Hugenroth Date: Mon, 28 Jun 2021 18:09:52 +0200 Subject: [PATCH 014/204] Don't open sidebar on click for smaller screens Signed-off-by: Philipp Hugenroth --- packages/core-components/src/layout/Sidebar/Bar.tsx | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/packages/core-components/src/layout/Sidebar/Bar.tsx b/packages/core-components/src/layout/Sidebar/Bar.tsx index f6edac81b7..65da4d2d75 100644 --- a/packages/core-components/src/layout/Sidebar/Bar.tsx +++ b/packages/core-components/src/layout/Sidebar/Bar.tsx @@ -14,7 +14,7 @@ * limitations under the License. */ -import { makeStyles } from '@material-ui/core'; +import { makeStyles, useMediaQuery } from '@material-ui/core'; import clsx from 'clsx'; import React, { useRef, useState, useContext, PropsWithChildren } from 'react'; import { sidebarConfig, SidebarContext } from './config'; @@ -82,6 +82,9 @@ export const Sidebar = ({ children, }: PropsWithChildren) => { const classes = useStyles(); + const isSmallScreen = useMediaQuery(theme => + theme.breakpoints.down('md'), + ); const [state, setState] = useState(State.Closed); const hoverTimerRef = useRef(); const { isPinned } = useContext(SidebarPinStateContext); @@ -94,7 +97,7 @@ export const Sidebar = ({ clearTimeout(hoverTimerRef.current); hoverTimerRef.current = undefined; } - if (state !== State.Open) { + if (state !== State.Open && !isSmallScreen) { hoverTimerRef.current = window.setTimeout(() => { hoverTimerRef.current = undefined; setState(State.Open); @@ -122,6 +125,8 @@ export const Sidebar = ({ } }; + const isOpen = (state === State.Open && !isSmallScreen) || isPinned; + return (
{children} From ca080cab8b2775fb451fd47f5e5ee9fb413a363e Mon Sep 17 00:00:00 2001 From: Dominik Henneke Date: Mon, 28 Jun 2021 18:16:26 +0200 Subject: [PATCH 015/204] Don't crash if the entities response doesn't include the entities name and kind Signed-off-by: Dominik Henneke --- .changeset/sour-cherries-occur.md | 5 +++++ .../catalog-client/src/CatalogClient.test.ts | 20 +++++++++++++++++++ packages/catalog-client/src/CatalogClient.ts | 10 ++++++++++ 3 files changed, 35 insertions(+) create mode 100644 .changeset/sour-cherries-occur.md diff --git a/.changeset/sour-cherries-occur.md b/.changeset/sour-cherries-occur.md new file mode 100644 index 0000000000..a8837749d3 --- /dev/null +++ b/.changeset/sour-cherries-occur.md @@ -0,0 +1,5 @@ +--- +'@backstage/catalog-client': patch +--- + +Don't crash if the entities response doesn't include the entities name and kind diff --git a/packages/catalog-client/src/CatalogClient.test.ts b/packages/catalog-client/src/CatalogClient.test.ts index 6d43af85ed..4e3d95f99f 100644 --- a/packages/catalog-client/src/CatalogClient.test.ts +++ b/packages/catalog-client/src/CatalogClient.test.ts @@ -151,6 +151,26 @@ describe('CatalogClient', () => { expect(response.items).toEqual([]); }); + + it('handles field filtered entities', async () => { + server.use( + rest.get(`${mockBaseUrl}/entities`, (_req, res, ctx) => { + return res(ctx.json([{ apiVersion: '1' }, { apiVersion: '2' }])); + }), + ); + + const response = await client.getEntities( + { + fields: ['apiVersion'], + }, + { token }, + ); + + expect(response.items).toEqual([ + { apiVersion: '1' }, + { apiVersion: '2' }, + ]); + }); }); describe('getLocationById', () => { diff --git a/packages/catalog-client/src/CatalogClient.ts b/packages/catalog-client/src/CatalogClient.ts index 10c282f786..35b8045d27 100644 --- a/packages/catalog-client/src/CatalogClient.ts +++ b/packages/catalog-client/src/CatalogClient.ts @@ -92,6 +92,16 @@ export class CatalogClient implements CatalogApi { ); const refCompare = (a: Entity, b: Entity) => { + // in case field filtering is used, these fields might not be part of the response + if ( + a.metadata?.name === undefined || + a.metadata?.kind === undefined || + b.metadata?.name === undefined || + b.metadata?.kind === undefined + ) { + return 0; + } + const aRef = stringifyEntityRef(a); const bRef = stringifyEntityRef(b); if (aRef < bRef) { From d408af872a72f48404f18b5587d604700454a6ed Mon Sep 17 00:00:00 2001 From: Dominik Henneke Date: Mon, 28 Jun 2021 18:42:30 +0200 Subject: [PATCH 016/204] Only return the selected fields from the new catalog Signed-off-by: Dominik Henneke --- .changeset/small-kings-repair.md | 5 +++++ plugins/catalog-backend/src/next/NextEntitiesCatalog.ts | 8 +++++++- 2 files changed, 12 insertions(+), 1 deletion(-) create mode 100644 .changeset/small-kings-repair.md diff --git a/.changeset/small-kings-repair.md b/.changeset/small-kings-repair.md new file mode 100644 index 0000000000..498126d8e6 --- /dev/null +++ b/.changeset/small-kings-repair.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-backend': patch +--- + +Only return the selected fields from the new catalog. diff --git a/plugins/catalog-backend/src/next/NextEntitiesCatalog.ts b/plugins/catalog-backend/src/next/NextEntitiesCatalog.ts index a7be2aef10..f3921602e2 100644 --- a/plugins/catalog-backend/src/next/NextEntitiesCatalog.ts +++ b/plugins/catalog-backend/src/next/NextEntitiesCatalog.ts @@ -133,8 +133,14 @@ export class NextEntitiesCatalog implements EntitiesCatalog { }; } + const dbResponse = rows.map(e => JSON.parse(e.final_entity!)); + + const entities = dbResponse.map(e => + request?.fields ? request.fields(e) : e, + ); + return { - entities: rows.map(e => JSON.parse(e.final_entity!)), + entities, pageInfo, }; } From 874dfd6fcf68e1f88a0b10ce71373e71b0cacedd Mon Sep 17 00:00:00 2001 From: Dominik Henneke Date: Mon, 28 Jun 2021 18:44:26 +0200 Subject: [PATCH 017/204] Check for the correct fields Signed-off-by: Dominik Henneke --- packages/catalog-client/src/CatalogClient.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/catalog-client/src/CatalogClient.ts b/packages/catalog-client/src/CatalogClient.ts index 35b8045d27..5dfcddde0c 100644 --- a/packages/catalog-client/src/CatalogClient.ts +++ b/packages/catalog-client/src/CatalogClient.ts @@ -95,9 +95,9 @@ export class CatalogClient implements CatalogApi { // in case field filtering is used, these fields might not be part of the response if ( a.metadata?.name === undefined || - a.metadata?.kind === undefined || + a.kind === undefined || b.metadata?.name === undefined || - b.metadata?.kind === undefined + b.kind === undefined ) { return 0; } From 0941139cf48678df0acf20ccc1816942728d9db5 Mon Sep 17 00:00:00 2001 From: Dominik Henneke Date: Mon, 28 Jun 2021 18:50:51 +0200 Subject: [PATCH 018/204] Update msw in @backstage/plugin-catalog-backend-module-ldap Signed-off-by: Dominik Henneke --- plugins/catalog-backend-module-ldap/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/catalog-backend-module-ldap/package.json b/plugins/catalog-backend-module-ldap/package.json index d8a5545368..17f87898e1 100644 --- a/plugins/catalog-backend-module-ldap/package.json +++ b/plugins/catalog-backend-module-ldap/package.json @@ -40,7 +40,7 @@ "@backstage/cli": "^0.7.1", "@backstage/test-utils": "^0.1.13", "@types/lodash": "^4.14.151", - "msw": "^0.21.2" + "msw": "^0.29.0" }, "files": [ "dist", From 58e19478ef07a3a946205036958e894226e0b4d8 Mon Sep 17 00:00:00 2001 From: Joe Porpeglia Date: Mon, 28 Jun 2021 13:26:45 -0400 Subject: [PATCH 019/204] Use __fixtures__ for static json test data Signed-off-by: Joe Porpeglia --- plugins/github-actions/dev/index.tsx | 4 ++-- .../__fixtures__/get-workflow-run.json} | 0 .../__fixtures__/list-jobs-for-workflow-run.json} | 0 3 files changed, 2 insertions(+), 2 deletions(-) rename plugins/github-actions/{dev/getWorkflowRun.json => src/__fixtures__/get-workflow-run.json} (100%) rename plugins/github-actions/{dev/listJobsForWorkflowRun.json => src/__fixtures__/list-jobs-for-workflow-run.json} (100%) diff --git a/plugins/github-actions/dev/index.tsx b/plugins/github-actions/dev/index.tsx index e105bf9294..ee761b3504 100644 --- a/plugins/github-actions/dev/index.tsx +++ b/plugins/github-actions/dev/index.tsx @@ -20,8 +20,8 @@ import { EntityGithubActionsContent, githubActionsPlugin } from '../src/plugin'; import { EntityProvider } from '@backstage/plugin-catalog-react'; import { Entity } from '@backstage/catalog-model'; import { GithubActionsApi, githubActionsApiRef } from '../src'; -import getWorkflowRunResponse from './getWorkflowRun.json'; -import listJobsForWorkflowRunResponse from './listJobsForWorkflowRun.json'; +import getWorkflowRunResponse from '../src/__fixtures__/get-workflow-run.json'; +import listJobsForWorkflowRunResponse from '../src/__fixtures__/list-jobs-for-workflow-run.json'; const mockEntity: Entity = { apiVersion: 'backstage.io/v1alpha1', diff --git a/plugins/github-actions/dev/getWorkflowRun.json b/plugins/github-actions/src/__fixtures__/get-workflow-run.json similarity index 100% rename from plugins/github-actions/dev/getWorkflowRun.json rename to plugins/github-actions/src/__fixtures__/get-workflow-run.json diff --git a/plugins/github-actions/dev/listJobsForWorkflowRun.json b/plugins/github-actions/src/__fixtures__/list-jobs-for-workflow-run.json similarity index 100% rename from plugins/github-actions/dev/listJobsForWorkflowRun.json rename to plugins/github-actions/src/__fixtures__/list-jobs-for-workflow-run.json From ab5cc376fac968c0643d1b624fb37d3117d399de Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Thu, 24 Jun 2021 17:27:05 +0200 Subject: [PATCH 020/204] backend-common,cli-common: new utilites for safely resolving child paths Signed-off-by: Patrik Oldsberg --- .changeset/loud-pets-hang.md | 6 ++ .changeset/many-penguins-clap.md | 5 ++ .changeset/silent-avocados-beam.md | 5 ++ .changeset/six-weeks-shop.md | 5 ++ packages/backend-common/api-report.md | 6 ++ packages/backend-common/src/paths.ts | 26 +++++++ packages/cli-common/api-report.md | 3 + packages/cli-common/src/index.ts | 1 + packages/cli-common/src/isChildPath.test.ts | 74 +++++++++++++++++++ packages/cli-common/src/isChildPath.ts | 33 +++++++++ .../lib/bundler/LinkedPackageResolvePlugin.ts | 2 +- packages/cli/src/lib/bundler/config.ts | 3 +- packages/cli/src/lib/bundler/paths.ts | 17 ----- .../src/stages/generate/helpers.ts | 7 +- .../builtin/fetch/cookiecutter.test.ts | 2 +- .../actions/builtin/fetch/cookiecutter.ts | 9 +-- .../actions/builtin/fetch/plain.test.ts | 2 +- .../scaffolder/actions/builtin/fetch/plain.ts | 11 +-- 18 files changed, 175 insertions(+), 42 deletions(-) create mode 100644 .changeset/loud-pets-hang.md create mode 100644 .changeset/many-penguins-clap.md create mode 100644 .changeset/silent-avocados-beam.md create mode 100644 .changeset/six-weeks-shop.md create mode 100644 packages/cli-common/src/isChildPath.test.ts create mode 100644 packages/cli-common/src/isChildPath.ts diff --git a/.changeset/loud-pets-hang.md b/.changeset/loud-pets-hang.md new file mode 100644 index 0000000000..52e5c8a7dd --- /dev/null +++ b/.changeset/loud-pets-hang.md @@ -0,0 +1,6 @@ +--- +'@backstage/techdocs-common': patch +'@backstage/plugin-scaffolder-backend': patch +--- + +Use new utilities from `@backstage/backend-common` for safely resolving child paths diff --git a/.changeset/many-penguins-clap.md b/.changeset/many-penguins-clap.md new file mode 100644 index 0000000000..be88536af6 --- /dev/null +++ b/.changeset/many-penguins-clap.md @@ -0,0 +1,5 @@ +--- +'@backstage/cli-common': patch +--- + +Add new `isChildPath` export diff --git a/.changeset/silent-avocados-beam.md b/.changeset/silent-avocados-beam.md new file mode 100644 index 0000000000..b3f2796b86 --- /dev/null +++ b/.changeset/silent-avocados-beam.md @@ -0,0 +1,5 @@ +--- +'@backstage/cli': patch +--- + +Use new `isChildPath` export from `@backstage/cli-common` diff --git a/.changeset/six-weeks-shop.md b/.changeset/six-weeks-shop.md new file mode 100644 index 0000000000..3adb37d144 --- /dev/null +++ b/.changeset/six-weeks-shop.md @@ -0,0 +1,5 @@ +--- +'@backstage/backend-common': patch +--- + +Add new `isChildPath` and `resolveSafeChildPath` exports diff --git a/packages/backend-common/api-report.md b/packages/backend-common/api-report.md index fcddb8dda5..6b9e7bbbe0 100644 --- a/packages/backend-common/api-report.md +++ b/packages/backend-common/api-report.md @@ -16,6 +16,7 @@ import { GithubCredentialsProvider } from '@backstage/integration'; import { GitHubIntegration } from '@backstage/integration'; import { GitLabIntegration } from '@backstage/integration'; import * as http from 'http'; +import { isChildPath } from '@backstage/cli-common'; import { JsonValue } from '@backstage/config'; import { Knex } from 'knex'; import { Logger } from 'winston'; @@ -252,6 +253,8 @@ export class GitlabUrlReader implements UrlReader { toString(): string; } +export { isChildPath } + // @public export function loadBackendConfig(options: Options): Promise; @@ -294,6 +297,9 @@ export function requestLoggingHandler(logger?: Logger): RequestHandler; // @public export function resolvePackagePath(name: string, ...paths: string[]): string; +// @public +export function resolveSafeChildPath(base: string, path: string): string; + // @public (undocumented) export type RunContainerOptions = { imageName: string; diff --git a/packages/backend-common/src/paths.ts b/packages/backend-common/src/paths.ts index efe8e027c8..ffe99fe762 100644 --- a/packages/backend-common/src/paths.ts +++ b/packages/backend-common/src/paths.ts @@ -14,6 +14,8 @@ * limitations under the License. */ +import { isChildPath } from '@backstage/cli-common'; +import { NotAllowedError } from '@backstage/errors'; import { resolve as resolvePath } from 'path'; /** @@ -32,3 +34,27 @@ export function resolvePackagePath(name: string, ...paths: string[]) { return resolvePath(req.resolve(`${name}/package.json`), '..', ...paths); } + +/** + * Resolves a target path from a base path while guaranteeing that the result is + * a path that point to or within the base path. This is useful for resolving + * paths from user input, as it otherwise opens up for vulnerabilities. + * + * @param base The base directory to resolve the path from. + * @param path The target path, relative or absolute + * @returns A path that is guaranteed to point to or within the base path. + */ +export function resolveSafeChildPath(base: string, path: string): string { + const targetPath = resolvePath(base, path); + + if (!isChildPath(base, targetPath)) { + throw new NotAllowedError( + 'Relative path is not allowed to refer to a directory outside its parent', + ); + } + + return targetPath; +} + +// Re-export isChildPath so that backend packages don't need to depend on cli-common +export { isChildPath }; diff --git a/packages/cli-common/api-report.md b/packages/cli-common/api-report.md index bcdc023c22..7141d27f3a 100644 --- a/packages/cli-common/api-report.md +++ b/packages/cli-common/api-report.md @@ -7,6 +7,9 @@ // @public export function findPaths(searchDir: string): Paths; +// @public +export function isChildPath(base: string, path: string): boolean; + // @public (undocumented) export type Paths = { ownDir: string; diff --git a/packages/cli-common/src/index.ts b/packages/cli-common/src/index.ts index d36314ba35..1f4f17fe9f 100644 --- a/packages/cli-common/src/index.ts +++ b/packages/cli-common/src/index.ts @@ -15,4 +15,5 @@ */ export { findPaths } from './paths'; +export { isChildPath } from './isChildPath'; export type { Paths } from './paths'; diff --git a/packages/cli-common/src/isChildPath.test.ts b/packages/cli-common/src/isChildPath.test.ts new file mode 100644 index 0000000000..4c0d94f07c --- /dev/null +++ b/packages/cli-common/src/isChildPath.test.ts @@ -0,0 +1,74 @@ +/* + * Copyright 2021 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { posix, win32 } from 'path'; + +describe('isChildPath', () => { + it('should check child posix paths', () => { + jest.isolateModules(() => { + jest.setMock('path', posix); + const { isChildPath } = require('./isChildPath'); + + expect(isChildPath('/', '/')).toBe(true); + expect(isChildPath('/x', '/x')).toBe(true); + expect(isChildPath('/x', '/x/y')).toBe(true); + expect(isChildPath('/x', '/x/x')).toBe(true); + expect(isChildPath('/x', '/x/y/z')).toBe(true); + expect(isChildPath('/x/y', '/x/y/z')).toBe(true); + expect(isChildPath('/x/y/z', '/x/y/z')).toBe(true); + expect(isChildPath('/x/a b c/z', '/x/a b c/z')).toBe(true); + expect(isChildPath('/', '/ yz')).toBe(true); + + expect(isChildPath('/x', '/y')).toBe(false); + expect(isChildPath('/x', '/')).toBe(false); + expect(isChildPath('/x', '/x y')).toBe(false); + expect(isChildPath('/x y', '/x yz')).toBe(false); + expect(isChildPath('/ yz', '/')).toBe(false); + expect(isChildPath('/x', '/')).toBe(false); + + jest.dontMock('path'); + }); + }); + + it('should check child win32 paths', () => { + jest.isolateModules(() => { + jest.setMock('path', win32); + const { isChildPath } = require('./isChildPath'); + + expect(isChildPath('/x', '/x')).toBe(true); + expect(isChildPath('/x', '/x/y')).toBe(true); + expect(isChildPath('/x', '/x/x')).toBe(true); + expect(isChildPath('/x', '/x/y/z')).toBe(true); + expect(isChildPath('/x/y', '/x/y/z')).toBe(true); + expect(isChildPath('/x/y/z', '/x/y/z')).toBe(true); + expect(isChildPath('Z:', 'Z:')).toBe(true); + expect(isChildPath('C:/', 'c:/')).toBe(true); + expect(isChildPath('C:/x', 'C:/x')).toBe(true); + expect(isChildPath('C:/x', 'c:/x')).toBe(true); + expect(isChildPath('C:/x', 'C:/x/y')).toBe(true); + expect(isChildPath('d:/x', 'D:/x/y')).toBe(true); + + expect(isChildPath('/x', '/y')).toBe(false); + expect(isChildPath('/x', '/')).toBe(false); + expect(isChildPath('C:/', 'D:/')).toBe(false); + expect(isChildPath('C:/x', 'D:/x')).toBe(false); + expect(isChildPath('D:/x', 'CD:/x')).toBe(false); + expect(isChildPath('D:/x', 'D:/y')).toBe(false); + + jest.dontMock('path'); + }); + }); +}); diff --git a/packages/cli-common/src/isChildPath.ts b/packages/cli-common/src/isChildPath.ts new file mode 100644 index 0000000000..f48c92db32 --- /dev/null +++ b/packages/cli-common/src/isChildPath.ts @@ -0,0 +1,33 @@ +/* + * Copyright 2021 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { relative, isAbsolute } from 'path'; + +/** + * Checks if path is the same as or a child path of base. + */ +export function isChildPath(base: string, path: string): boolean { + const relativePath = relative(base, path); + if (relativePath === '') { + // The same directory + return true; + } + + const outsideBase = relativePath.startsWith('..'); // not outside base + const differentDrive = isAbsolute(relativePath); // on Windows, this means dir is on a different drive from base. + + return !outsideBase && !differentDrive; +} diff --git a/packages/cli/src/lib/bundler/LinkedPackageResolvePlugin.ts b/packages/cli/src/lib/bundler/LinkedPackageResolvePlugin.ts index 2360078a18..aa6a6b4e2e 100644 --- a/packages/cli/src/lib/bundler/LinkedPackageResolvePlugin.ts +++ b/packages/cli/src/lib/bundler/LinkedPackageResolvePlugin.ts @@ -16,7 +16,7 @@ import { resolve as resolvePath } from 'path'; import { ResolvePlugin } from 'webpack'; -import { isChildPath } from './paths'; +import { isChildPath } from '@backstage/cli-common'; import { LernaPackage } from './types'; // Enables proper resolution of packages when linking in external packages. diff --git a/packages/cli/src/lib/bundler/config.ts b/packages/cli/src/lib/bundler/config.ts index 89f677109d..75e94af716 100644 --- a/packages/cli/src/lib/bundler/config.ts +++ b/packages/cli/src/lib/bundler/config.ts @@ -22,9 +22,10 @@ import ModuleScopePlugin from 'react-dev-utils/ModuleScopePlugin'; import StartServerPlugin from 'start-server-webpack-plugin'; import webpack from 'webpack'; import nodeExternals from 'webpack-node-externals'; +import { isChildPath } from '@backstage/cli-common'; import { optimization } from './optimization'; import { Config } from '@backstage/config'; -import { BundlingPaths, isChildPath } from './paths'; +import { BundlingPaths } from './paths'; import { transforms } from './transforms'; import { LinkedPackageResolvePlugin } from './LinkedPackageResolvePlugin'; import { BundlingOptions, BackendBundlingOptions, LernaPackage } from './types'; diff --git a/packages/cli/src/lib/bundler/paths.ts b/packages/cli/src/lib/bundler/paths.ts index 01fdcdefe5..d465b3010f 100644 --- a/packages/cli/src/lib/bundler/paths.ts +++ b/packages/cli/src/lib/bundler/paths.ts @@ -15,25 +15,8 @@ */ import fs from 'fs-extra'; -import path from 'path'; import { paths } from '../paths'; -/** - * Checks if dir is the same as or a child of base. - */ -export function isChildPath(base: string, dir: string): boolean { - const relativePath = path.relative(base, dir); - if (relativePath === '') { - // The same directory - return true; - } - - const outsideBase = relativePath.startsWith('..'); // not outside base - const differentDrive = path.isAbsolute(relativePath); // on Windows, this means dir is on a different drive from base. - - return !outsideBase && !differentDrive; -} - export type BundlingPathsOptions = { // bundle entrypoint, e.g. 'src/index' entry: string; diff --git a/packages/techdocs-common/src/stages/generate/helpers.ts b/packages/techdocs-common/src/stages/generate/helpers.ts index 718ee9f924..086377b4ef 100644 --- a/packages/techdocs-common/src/stages/generate/helpers.ts +++ b/packages/techdocs-common/src/stages/generate/helpers.ts @@ -15,6 +15,7 @@ */ import { Entity } from '@backstage/catalog-model'; +import { isChildPath } from '@backstage/backend-common'; import { spawn } from 'child_process'; import fs from 'fs-extra'; import yaml, { DEFAULT_SCHEMA, Type } from 'js-yaml'; @@ -23,7 +24,6 @@ import { Logger } from 'winston'; import { ParsedLocationAnnotation } from '../../helpers'; import { RemoteProtocol } from '../prepare/types'; import { SupportedGeneratorKey } from './types'; -import { resolve as resolvePath } from 'path'; // TODO: Implement proper support for more generators. export function getGeneratorKey(entity: Entity): SupportedGeneratorKey { @@ -178,10 +178,7 @@ export const validateMkdocsYaml = async ( schema: MKDOCS_SCHEMA, }); - if ( - mkdocsYml.docs_dir && - !resolvePath(inputDir, mkdocsYml.docs_dir).startsWith(inputDir) - ) { + if (mkdocsYml.docs_dir && !isChildPath(inputDir, mkdocsYml.docs_dir)) { throw new Error( `docs_dir configuration value in mkdocs can't be an absolute directory or start with ../ for security reasons. Use relative paths instead which are resolved relative to your mkdocs.yml file location.`, diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/cookiecutter.test.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/cookiecutter.test.ts index 123f5e0ebb..3ce3052956 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/cookiecutter.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/cookiecutter.test.ts @@ -180,7 +180,7 @@ describe('fetch:cookiecutter', () => { }, }), ).rejects.toThrow( - /targetPath may not specify a path outside the working directory/, + /Relative path is not allowed to refer to a directory outside its parent/, ); }); }); diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/cookiecutter.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/cookiecutter.ts index 9679adffa8..62dfc20125 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/cookiecutter.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/cookiecutter.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { UrlReader } from '@backstage/backend-common'; +import { UrlReader, resolveSafeChildPath } from '@backstage/backend-common'; import { JsonObject } from '@backstage/config'; import { InputError } from '@backstage/errors'; import { ScmIntegrations } from '@backstage/integration'; @@ -138,12 +138,7 @@ export function createFetchCookiecutterAction(options: { // Finally move the template result into the task workspace const targetPath = ctx.input.targetPath ?? './'; - const outputPath = resolvePath(ctx.workspacePath, targetPath); - if (!outputPath.startsWith(ctx.workspacePath)) { - throw new InputError( - `Fetch action targetPath may not specify a path outside the working directory`, - ); - } + const outputPath = resolveSafeChildPath(ctx.workspacePath, targetPath); await fs.copy(resultDir, outputPath); }, }); diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/plain.test.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/plain.test.ts index 2f6caf8c97..1a4428e3f0 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/plain.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/plain.test.ts @@ -62,7 +62,7 @@ describe('fetch:plain', () => { }, }), ).rejects.toThrow( - /Fetch action targetPath may not specify a path outside the working directory/, + /Relative path is not allowed to refer to a directory outside its parent/, ); }); diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/plain.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/plain.ts index 8f7eefb657..9cac6d5ab8 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/plain.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/plain.ts @@ -14,9 +14,7 @@ * limitations under the License. */ -import path from 'path'; -import { UrlReader } from '@backstage/backend-common'; -import { InputError } from '@backstage/errors'; +import { UrlReader, resolveSafeChildPath } from '@backstage/backend-common'; import { ScmIntegrations } from '@backstage/integration'; import { fetchContents } from './helpers'; import { createTemplateAction } from '../../createTemplateAction'; @@ -56,12 +54,7 @@ export function createFetchPlainAction(options: { // Finally move the template result into the task workspace const targetPath = ctx.input.targetPath ?? './'; - const outputPath = path.resolve(ctx.workspacePath, targetPath); - if (!outputPath.startsWith(ctx.workspacePath)) { - throw new InputError( - `Fetch action targetPath may not specify a path outside the working directory`, - ); - } + const outputPath = resolveSafeChildPath(ctx.workspacePath, targetPath); await fetchContents({ reader, From 88d742eb83e002943c79e254941118e6392aa63a Mon Sep 17 00:00:00 2001 From: Jingchao Zhang Date: Mon, 28 Jun 2021 17:33:24 -0400 Subject: [PATCH 021/204] Download tar.gz archives for Gitlab Signed-off-by: Jingchao Zhang --- .changeset/gold-avocados-thank.md | 5 +++++ .../src/reading/GitlabUrlReader.test.ts | 16 ++++++++-------- .../src/reading/GitlabUrlReader.ts | 4 ++-- .../reading/__fixtures__/gitlab-archive.tar.gz | Bin 0 -> 257 bytes 4 files changed, 15 insertions(+), 10 deletions(-) create mode 100644 .changeset/gold-avocados-thank.md create mode 100644 packages/backend-common/src/reading/__fixtures__/gitlab-archive.tar.gz diff --git a/.changeset/gold-avocados-thank.md b/.changeset/gold-avocados-thank.md new file mode 100644 index 0000000000..bd97499629 --- /dev/null +++ b/.changeset/gold-avocados-thank.md @@ -0,0 +1,5 @@ +--- +'@backstage/backend-common': patch +--- + +Download archives as compressed tar files for Gitlab to fix the readtree bug in TODO Plugin. diff --git a/packages/backend-common/src/reading/GitlabUrlReader.test.ts b/packages/backend-common/src/reading/GitlabUrlReader.test.ts index a76b898aaf..5ed151c5c2 100644 --- a/packages/backend-common/src/reading/GitlabUrlReader.test.ts +++ b/packages/backend-common/src/reading/GitlabUrlReader.test.ts @@ -182,7 +182,7 @@ describe('GitlabUrlReader', () => { describe('readTree', () => { const archiveBuffer = fs.readFileSync( - path.resolve('src', 'reading', '__fixtures__', 'gitlab-archive.zip'), + path.resolve('src', 'reading', '__fixtures__', 'gitlab-archive.tar.gz'), ); const projectGitlabApiResponse = { @@ -205,7 +205,7 @@ describe('GitlabUrlReader', () => { beforeEach(() => { worker.use( rest.get( - 'https://gitlab.com/api/v4/projects/backstage%2Fmock/repository/archive.zip?sha=main', + 'https://gitlab.com/api/v4/projects/backstage%2Fmock/repository/archive?sha=main', (_, res, ctx) => res( ctx.status(200), @@ -283,7 +283,7 @@ describe('GitlabUrlReader', () => { }, ), rest.get( - 'https://gitlab.mycompany.com/api/v4/projects/backstage%2Fmock/repository/archive.zip?sha=main', + 'https://gitlab.mycompany.com/api/v4/projects/backstage%2Fmock/repository/archive?sha=main', (_, res, ctx) => res( ctx.status(200), @@ -306,8 +306,8 @@ describe('GitlabUrlReader', () => { const files = await response.files(); expect(files.length).toBe(2); - const mkDocsFile = await files[0].content(); - const indexMarkdownFile = await files[1].content(); + const indexMarkdownFile = await files[0].content(); + const mkDocsFile = await files[1].content(); expect(mkDocsFile.toString()).toBe('site_name: Test\n'); expect(indexMarkdownFile.toString()).toBe('# Test\n'); @@ -331,7 +331,7 @@ describe('GitlabUrlReader', () => { it('returns the wanted files from hosted gitlab', async () => { worker.use( rest.get( - 'https://gitlab.mycompany.com/backstage/mock/-/archive/main.zip', + 'https://gitlab.mycompany.com/backstage/mock/-/archive/main.tar.gz', (_, res, ctx) => res( ctx.status(200), @@ -454,7 +454,7 @@ describe('GitlabUrlReader', () => { describe('search', () => { const archiveBuffer = fs.readFileSync( - path.resolve('src', 'reading', '__fixtures__', 'gitlab-archive.zip'), + path.resolve('src', 'reading', '__fixtures__', 'gitlab-archive.tar.gz'), ); const projectGitlabApiResponse = { @@ -471,7 +471,7 @@ describe('GitlabUrlReader', () => { beforeEach(() => { worker.use( rest.get( - 'https://gitlab.com/api/v4/projects/backstage%2Fmock/repository/archive.zip?sha=main', + 'https://gitlab.com/api/v4/projects/backstage%2Fmock/repository/archive?sha=main', (_, res, ctx) => res( ctx.status(200), diff --git a/packages/backend-common/src/reading/GitlabUrlReader.ts b/packages/backend-common/src/reading/GitlabUrlReader.ts index 13764a5312..aa215aee47 100644 --- a/packages/backend-common/src/reading/GitlabUrlReader.ts +++ b/packages/backend-common/src/reading/GitlabUrlReader.ts @@ -139,7 +139,7 @@ export class GitlabUrlReader implements UrlReader { const archiveGitLabResponse = await fetch( `${this.integration.config.apiBaseUrl}/projects/${encodeURIComponent( full_name, - )}/repository/archive.zip?sha=${branch}`, + )}/repository/archive?sha=${branch}`, getGitLabRequestOptions(this.integration.config), ); if (!archiveGitLabResponse.ok) { @@ -150,7 +150,7 @@ export class GitlabUrlReader implements UrlReader { throw new Error(message); } - return await this.deps.treeResponseFactory.fromZipArchive({ + return await this.deps.treeResponseFactory.fromTarArchive({ stream: (archiveGitLabResponse.body as unknown) as Readable, subpath: filepath, etag: commitSha, diff --git a/packages/backend-common/src/reading/__fixtures__/gitlab-archive.tar.gz b/packages/backend-common/src/reading/__fixtures__/gitlab-archive.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..c078e07e7e1255d7b6da4abe961aa8a79ac63781 GIT binary patch literal 257 zcmV+c0sj6UiwFP!000001MSt(YQiuS#_?SH6a}x>otSeH*mLY&VjJ3Qwu0@3?&+6` z2orG(YTelPqZg$&3H*DKD)wu?dhpw#j_=`7-2x>}M2Qi0)+#2_={bBqQkuzHCdaZ+ zq>U^{Wpb0R?O$$+ZuFnvNBy;={><#qe+rlS z$F>Z+yeY?8V+d@Suk?3H8^<=~H$tg@dQ1IjtPNcA&->4_=g{@Ddv62om> H04M+e6!wJ_ literal 0 HcmV?d00001 From a93e60fdc32c3c747b2f9d9bd96a7e859ad01192 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 29 Jun 2021 04:09:49 +0000 Subject: [PATCH 022/204] chore(deps): bump css-loader from 3.6.0 to 5.2.6 Bumps [css-loader](https://github.com/webpack-contrib/css-loader) from 3.6.0 to 5.2.6. - [Release notes](https://github.com/webpack-contrib/css-loader/releases) - [Changelog](https://github.com/webpack-contrib/css-loader/blob/master/CHANGELOG.md) - [Commits](https://github.com/webpack-contrib/css-loader/compare/v3.6.0...v5.2.6) --- updated-dependencies: - dependency-name: css-loader dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .changeset/curly-eggs-destroy.md | 5 ++++ packages/cli/package.json | 2 +- yarn.lock | 50 +++++++++++++++++++++----------- 3 files changed, 39 insertions(+), 18 deletions(-) create mode 100644 .changeset/curly-eggs-destroy.md diff --git a/.changeset/curly-eggs-destroy.md b/.changeset/curly-eggs-destroy.md new file mode 100644 index 0000000000..9441f3aeb7 --- /dev/null +++ b/.changeset/curly-eggs-destroy.md @@ -0,0 +1,5 @@ +--- +'@backstage/cli': patch +--- + +Updated dependencies diff --git a/packages/cli/package.json b/packages/cli/package.json index b0e6b021cc..07fcd07404 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -61,7 +61,7 @@ "chalk": "^4.0.0", "chokidar": "^3.3.1", "commander": "^6.1.0", - "css-loader": "^3.5.3", + "css-loader": "^5.2.6", "dashify": "^2.0.0", "diff": "^5.0.0", "esbuild": "^0.8.56", diff --git a/yarn.lock b/yarn.lock index 2a6827419c..7c0d4b3bfb 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9240,12 +9240,7 @@ camelcase@^5.0.0, camelcase@^5.3.1: resolved "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== -camelcase@^6.0.0: - version "6.0.0" - resolved "https://registry.npmjs.org/camelcase/-/camelcase-6.0.0.tgz#5259f7c30e35e278f1bdc2a4d91230b37cad981e" - integrity sha512-8KMDF1Vz2gzOq54ONPJS65IvTUaB1cHJ2DMM7MbPmLZljDH1qpzzLsWdiN9pHh6qvkRVDTi/07+eNGch/oLU4w== - -camelcase@^6.2.0: +camelcase@^6.0.0, camelcase@^6.2.0: version "6.2.0" resolved "https://registry.npmjs.org/camelcase/-/camelcase-6.2.0.tgz#924af881c9d525ac9d87f40d964e5cea982a1809" integrity sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg== @@ -10579,6 +10574,22 @@ css-loader@^3.5.3: schema-utils "^2.7.0" semver "^6.3.0" +css-loader@^5.2.6: + version "5.2.6" + resolved "https://registry.npmjs.org/css-loader/-/css-loader-5.2.6.tgz#c3c82ab77fea1f360e587d871a6811f4450cc8d1" + integrity sha512-0wyN5vXMQZu6BvjbrPdUJvkCzGEO24HC7IS7nW4llc6BBFC+zwR9CKtYGv63Puzsg10L/o12inMY5/2ByzfD6w== + dependencies: + icss-utils "^5.1.0" + loader-utils "^2.0.0" + postcss "^8.2.15" + postcss-modules-extract-imports "^3.0.0" + postcss-modules-local-by-default "^4.0.0" + postcss-modules-scope "^3.0.0" + postcss-modules-values "^4.0.0" + postcss-value-parser "^4.1.0" + schema-utils "^3.0.0" + semver "^7.3.5" + css-select-base-adapter@^0.1.1: version "0.1.1" resolved "https://registry.npmjs.org/css-select-base-adapter/-/css-select-base-adapter-0.1.1.tgz#3b2ff4972cc362ab88561507a95408a1432135d7" @@ -15030,7 +15041,7 @@ icss-utils@^4.0.0, icss-utils@^4.1.1: dependencies: postcss "^7.0.14" -icss-utils@^5.0.0: +icss-utils@^5.0.0, icss-utils@^5.1.0: version "5.1.0" resolved "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz#c6be6858abd013d768e98366ae47e25d5887b1ae" integrity sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA== @@ -19029,10 +19040,10 @@ nanoid@^2.1.0: resolved "https://registry.npmjs.org/nanoid/-/nanoid-2.1.11.tgz#ec24b8a758d591561531b4176a01e3ab4f0f0280" integrity sha512-s/snB+WGm6uwi0WjsZdaVcuf3KJXlfGl2LcxgwkEwJF0D/BWzVWAZW/XY4bFaiR7s0Jk3FPvlnepg1H1b1UwlA== -nanoid@^3.1.22: - version "3.1.22" - resolved "https://registry.npmjs.org/nanoid/-/nanoid-3.1.22.tgz#b35f8fb7d151990a8aebd5aa5015c03cf726f844" - integrity sha512-/2ZUaJX2ANuLtTvqTlgqBQNJoQO398KyJgZloL0PZkC0dpysjncRUPsFe3DUPzz/y3h+u7C46np8RMuvF3jsSQ== +nanoid@^3.1.23: + version "3.1.23" + resolved "https://registry.npmjs.org/nanoid/-/nanoid-3.1.23.tgz#f744086ce7c2bc47ee0a8472574d5c78e4183a81" + integrity sha512-FiB0kzdP0FFVGDKlRLEQ1BgDzU87dy5NnzjeW9YZNt+/c3+q82EQDUwniSAUxp/F0gFNI1ZhKU1FqYsMuqZVnw== nanomatch@^1.2.9: version "1.2.13" @@ -21217,14 +21228,14 @@ postcss-value-parser@^4.0.0, postcss-value-parser@^4.0.2, postcss-value-parser@^ source-map "^0.6.1" supports-color "^6.1.0" -postcss@^8.0.2, postcss@^8.1.0: - version "8.2.13" - resolved "https://registry.npmjs.org/postcss/-/postcss-8.2.13.tgz#dbe043e26e3c068e45113b1ed6375d2d37e2129f" - integrity sha512-FCE5xLH+hjbzRdpbRb1IMCvPv9yZx2QnDarBEYSN0N0HYk+TcXsEhwdFcFb+SRWOKzKGErhIEbBK2ogyLdTtfQ== +postcss@^8.0.2, postcss@^8.1.0, postcss@^8.2.15: + version "8.3.5" + resolved "https://registry.npmjs.org/postcss/-/postcss-8.3.5.tgz#982216b113412bc20a86289e91eb994952a5b709" + integrity sha512-NxTuJocUhYGsMiMFHDUkmjSKT3EdH4/WbGF6GCi1NDGk+vbcUTun4fpbOqaPtD8IIsztA2ilZm2DhYCuyN58gA== dependencies: colorette "^1.2.2" - nanoid "^3.1.22" - source-map "^0.6.1" + nanoid "^3.1.23" + source-map-js "^0.6.2" postgres-array@~1.0.0: version "1.0.3" @@ -23963,6 +23974,11 @@ source-list-map@^2.0.0: resolved "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz#3993bd873bfc48479cca9ea3a547835c7c154b34" integrity sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw== +source-map-js@^0.6.2: + version "0.6.2" + resolved "https://registry.npmjs.org/source-map-js/-/source-map-js-0.6.2.tgz#0bb5de631b41cfbda6cfba8bd05a80efdfd2385e" + integrity sha512-/3GptzWzu0+0MBQFrDKzw/DvvMTUORvgY6k6jd/VS6iCR4RDTKWH6v6WPwQoUO8667uQEf9Oe38DxAYWY5F/Ug== + source-map-resolve@^0.5.0: version "0.5.3" resolved "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz#190866bece7553e1f8f267a2ee82c606b5509a1a" From b19a5da0cf5a304d676593ae99ba17ac7b7ede12 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 24 Jun 2021 15:48:22 +0000 Subject: [PATCH 023/204] chore(deps): bump apollo-server-express from 2.21.0 to 2.25.2 Bumps [apollo-server-express](https://github.com/apollographql/apollo-server/tree/HEAD/packages/apollo-server-express) from 2.21.0 to 2.25.2. - [Release notes](https://github.com/apollographql/apollo-server/releases) - [Changelog](https://github.com/apollographql/apollo-server/blob/main/CHANGELOG.md) - [Commits](https://github.com/apollographql/apollo-server/commits/apollo-server-express@2.25.2/packages/apollo-server-express) --- updated-dependencies: - dependency-name: apollo-server-express dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- yarn.lock | 330 +++++++++++++++++++++++++----------------------------- 1 file changed, 150 insertions(+), 180 deletions(-) diff --git a/yarn.lock b/yarn.lock index 7885e5f724..8585ca504a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -11,10 +11,10 @@ call-me-maybe "^1.0.1" js-yaml "^3.13.1" -"@apollo/protobufjs@^1.0.3": - version "1.0.4" - resolved "https://registry.npmjs.org/@apollo/protobufjs/-/protobufjs-1.0.4.tgz#cf01747a55359066341f31b5ce8db17df44244e0" - integrity sha512-EE3zx+/D/wur/JiLp6VCiw1iYdyy1lCJMf8CGPkLeDt5QJrN4N8tKFx33Ah4V30AUQzMk7Uz4IXKZ1LOj124gA== +"@apollo/protobufjs@1.2.2": + version "1.2.2" + resolved "https://registry.npmjs.org/@apollo/protobufjs/-/protobufjs-1.2.2.tgz#4bd92cd7701ccaef6d517cdb75af2755f049f87c" + integrity sha512-vF+zxhPiLtkwxONs6YanSt1EpwpGilThpneExUN5K3tCymuxNnVq2yojTvnpRjv2QfsEIt/n7ozPIIzBLwGIDQ== dependencies: "@protobufjs/aspromise" "^1.1.2" "@protobufjs/base64" "^1.1.2" @@ -30,19 +30,17 @@ "@types/node" "^10.1.0" long "^4.0.0" -"@apollographql/apollo-tools@^0.4.3": - version "0.4.8" - resolved "https://registry.npmjs.org/@apollographql/apollo-tools/-/apollo-tools-0.4.8.tgz#d81da89ee880c2345eb86bddb92b35291f6135ed" - integrity sha512-W2+HB8Y7ifowcf3YyPHgDI05izyRtOeZ4MqIr7LbTArtmJ0ZHULWpn84SGMW7NAvTV1tFExpHlveHhnXuJfuGA== - dependencies: - apollo-env "^0.6.5" +"@apollographql/apollo-tools@^0.5.0": + version "0.5.1" + resolved "https://registry.npmjs.org/@apollographql/apollo-tools/-/apollo-tools-0.5.1.tgz#f0baef739ff7e2fafcb8b98ad29f6ac817e53e32" + integrity sha512-ZII+/xUFfb9ezDU2gad114+zScxVFMVlZ91f8fGApMzlS1kkqoyLnC4AJaQ1Ya/X+b63I20B4Gd+eCL8QuB4sA== -"@apollographql/graphql-playground-html@1.6.26": - version "1.6.26" - resolved "https://registry.npmjs.org/@apollographql/graphql-playground-html/-/graphql-playground-html-1.6.26.tgz#2f7b610392e2a872722912fc342b43cf8d641cb3" - integrity sha512-XAwXOIab51QyhBxnxySdK3nuMEUohhDsHQ5Rbco/V1vjlP75zZ0ZLHD9dTpXTN8uxKxopb2lUvJTq+M4g2Q0HQ== +"@apollographql/graphql-playground-html@1.6.27": + version "1.6.27" + resolved "https://registry.npmjs.org/@apollographql/graphql-playground-html/-/graphql-playground-html-1.6.27.tgz#bc9ab60e9445aa2a8813b4e94f152fa72b756335" + integrity sha512-tea2LweZvn6y6xFV11K0KC8ETjmm52mQrW+ezgB2O/aTQf8JGyFmMcRPFgUaQZeHbWdm8iisDC6EjOKsXu0nfw== dependencies: - xss "^1.0.6" + xss "^1.0.8" "@apollographql/graphql-upload-8-fork@^8.1.3": version "8.1.3" @@ -2754,6 +2752,11 @@ "@types/yargs" "^15.0.0" chalk "^4.0.0" +"@josephg/resolvable@^1.0.0": + version "1.0.1" + resolved "https://registry.npmjs.org/@josephg/resolvable/-/resolvable-1.0.1.tgz#69bc4db754d79e1a2f17a650d3466e038d94a5eb" + integrity sha512-CtzORUwWTTOTqfVtHaKRJ0I1kNQd1bpn3sUh8I3nJDVY+5/M/Oe1DnEWzPQvqq/xPIIkzzzIP7mfCoAjFRvDhg== + "@jsdevtools/ono@^7.1.3": version "7.1.3" resolved "https://registry.npmjs.org/@jsdevtools/ono/-/ono-7.1.3.tgz#9df03bbd7c696a5c58885c34aa06da41c8543796" @@ -5629,14 +5632,7 @@ resolved "https://registry.npmjs.org/@types/core-js/-/core-js-2.5.4.tgz#fc42ebde7d9cfa7c5f2668f117449b02348e41fd" integrity sha512-Xwy8o12ak+iYgFr/KCVaVK5Sy+jFMiiPAID3+ObvMlBzy26XQJw5xu+a6rlHsrJENXj/AwJOGsJpVohUjAzSKQ== -"@types/cors@2.8.8": - version "2.8.8" - resolved "https://registry.npmjs.org/@types/cors/-/cors-2.8.8.tgz#317a8d8561995c60e35b9e0fcaa8d36660c98092" - integrity sha512-fO3gf3DxU2Trcbr75O7obVndW/X5k8rJNZkLXlQWStTHhP71PkRqjwPIEI0yMnJdg9R9OasjU+Bsr+Hr1xy/0w== - dependencies: - "@types/express" "*" - -"@types/cors@^2.8.6": +"@types/cors@2.8.10", "@types/cors@^2.8.6": version "2.8.10" resolved "https://registry.npmjs.org/@types/cors/-/cors-2.8.10.tgz#61cc8469849e5bcdd0c7044122265c39cec10cf4" integrity sha512-C7srjHiVG3Ey1nR6d511dtDkCEjxuN9W1HWAEjGq8kpcwmNM6JJkpC0xvabM7BXTG2wDq8Eu33iH9aQKa7IvLQ== @@ -5732,19 +5728,10 @@ resolved "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz#e177e699ee1b8c22d23174caaa7422644389509f" integrity sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw== -"@types/express-serve-static-core@*", "@types/express-serve-static-core@^4.17.5": - version "4.17.19" - resolved "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.19.tgz#00acfc1632e729acac4f1530e9e16f6dd1508a1d" - integrity sha512-DJOSHzX7pCiSElWaGR8kCprwibCB/3yW6vcT8VG3P0SJjnv19gnWG/AZMfM60Xj/YJIp/YCaDHyvzsFVeniARA== - dependencies: - "@types/node" "*" - "@types/qs" "*" - "@types/range-parser" "*" - -"@types/express-serve-static-core@4.17.18": - version "4.17.18" - resolved "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.18.tgz#8371e260f40e0e1ca0c116a9afcd9426fa094c40" - integrity sha512-m4JTwx5RUBNZvky/JJ8swEJPKFd8si08pPF2PfizYjGZOKr/svUWPcoUmLow6MmPzhasphB7gSTINY67xn3JNA== +"@types/express-serve-static-core@*", "@types/express-serve-static-core@^4.17.18", "@types/express-serve-static-core@^4.17.21", "@types/express-serve-static-core@^4.17.5": + version "4.17.21" + resolved "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.21.tgz#a427278e106bca77b83ad85221eae709a3414d42" + integrity sha512-gwCiEZqW6f7EoR8TTEfalyEhb1zA5jQJnRngr97+3pzMaO1RKoI1w2bw07TK72renMUVWcWS5mLI6rk1NqN0nA== dependencies: "@types/node" "*" "@types/qs" "*" @@ -5765,13 +5752,13 @@ "@types/express" "*" "@types/xml2js" "*" -"@types/express@*", "@types/express@4.17.7", "@types/express@^4.17.6", "@types/express@^4.17.7": - version "4.17.7" - resolved "https://registry.npmjs.org/@types/express/-/express-4.17.7.tgz#42045be6475636d9801369cd4418ef65cdb0dd59" - integrity sha512-dCOT5lcmV/uC2J9k0rPafATeeyz+99xTt54ReX11/LObZgfzJqZNcW27zGhYyX+9iSEGXGt5qLPwRSvBZcLvtQ== +"@types/express@*", "@types/express@^4.17.12", "@types/express@^4.17.6", "@types/express@^4.17.7": + version "4.17.12" + resolved "https://registry.npmjs.org/@types/express/-/express-4.17.12.tgz#4bc1bf3cd0cfe6d3f6f2853648b40db7d54de350" + integrity sha512-pTYas6FrP15B1Oa0bkN5tQMNqOcVXa9j4FTFtO8DWI9kppKib+6NJtfTOOLcwxuuYvcX2+dVG6et1SxW/Kc17Q== dependencies: "@types/body-parser" "*" - "@types/express-serve-static-core" "*" + "@types/express-serve-static-core" "^4.17.18" "@types/qs" "*" "@types/serve-static" "*" @@ -6130,10 +6117,10 @@ resolved "https://registry.npmjs.org/@types/mime-types/-/mime-types-2.1.0.tgz#9ca52cda363f699c69466c2a6ccdaad913ea7a73" integrity sha1-nKUs2jY/aZxpRmwqbM2q2RPqenM= -"@types/mime@*": - version "2.0.1" - resolved "https://registry.npmjs.org/@types/mime/-/mime-2.0.1.tgz#dc488842312a7f075149312905b5e3c0b054c79d" - integrity sha512-FwI9gX75FgVBJ7ywgnq/P7tw+/o1GUbtP0KzbtusLigAOgIgNISRK0ZPl4qertvXSIE8YbsVJueQ90cDt9YYyw== +"@types/mime@^1": + version "1.3.2" + resolved "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz#93e25bf9ee75fe0fd80b594bc4feb0e862111b5a" + integrity sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw== "@types/mini-css-extract-plugin@^1.2.2": version "1.2.2" @@ -6180,14 +6167,6 @@ dependencies: "@types/node" "*" -"@types/node-fetch@2.5.7": - version "2.5.7" - resolved "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.5.7.tgz#20a2afffa882ab04d44ca786449a276f9f6bbf3c" - integrity sha512-o2WVNf5UhWRkxlf6eq+jMZDu7kjgpgJfl4xVNlvryc95O/6F2ld8ztKX+qu+Rjyet93WAWm5LjeX9H5FGkODvw== - dependencies: - "@types/node" "*" - form-data "^3.0.0" - "@types/node-fetch@^2.5.0", "@types/node-fetch@^2.5.4", "@types/node-fetch@^2.5.7": version "2.5.8" resolved "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.5.8.tgz#e199c835d234c7eb0846f6618012e558544ee2fb" @@ -6575,12 +6554,12 @@ integrity sha512-+beqKQOh9PYxuHvijhVl+tIHvT6tuwOrE9m14zd+MT2A38KoKZhh7pYJ0SNleLtwDsiIxHDsIk9bv01oOxvSvA== "@types/serve-static@*": - version "1.13.3" - resolved "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.3.tgz#eb7e1c41c4468272557e897e9171ded5e2ded9d1" - integrity sha512-oprSwp094zOglVrXdlo/4bAHtKTAxX6VT8FOZlBKrmyLbNvE1zxZyJ6yikMVtHIvwP45+ZQGJn+FdXGKTozq0g== + version "1.13.9" + resolved "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.9.tgz#aacf28a85a05ee29a11fb7c3ead935ac56f33e4e" + integrity sha512-ZFqF6qa48XsPdjXV5Gsz0Zqmux2PerNd3a/ktL45mHpa19cuMi/cL8tcxdAx497yRh+QtYPuofjT9oWw9P7nkA== dependencies: - "@types/express-serve-static-core" "*" - "@types/mime" "*" + "@types/mime" "^1" + "@types/node" "*" "@types/set-cookie-parser@^2.4.0": version "2.4.0" @@ -7455,49 +7434,30 @@ anymatch@^3.0.3, anymatch@~3.1.1: normalize-path "^3.0.0" picomatch "^2.0.4" -apollo-cache-control@^0.11.6: - version "0.11.6" - resolved "https://registry.npmjs.org/apollo-cache-control/-/apollo-cache-control-0.11.6.tgz#f7bdf924272af47ac474cf3f3f35cfc038cc9485" - integrity sha512-YZ+uuIG+fPy+mkpBS2qKF0v1qlzZ3PW6xZVaDukeK3ed3iAs4L/2YnkTqau3OmoF/VPzX2FmSkocX/OVd59YSw== +apollo-cache-control@^0.14.0: + version "0.14.0" + resolved "https://registry.npmjs.org/apollo-cache-control/-/apollo-cache-control-0.14.0.tgz#95f20c3e03e7994e0d1bd48c59aeaeb575ed0ce7" + integrity sha512-qN4BCq90egQrgNnTRMUHikLZZAprf3gbm8rC5Vwmc6ZdLolQ7bFsa769Hqi6Tq/lS31KLsXBLTOsRbfPHph12w== dependencies: - apollo-server-env "^3.0.0" - apollo-server-plugin-base "^0.10.4" + apollo-server-env "^3.1.0" + apollo-server-plugin-base "^0.13.0" -apollo-datasource@^0.7.3: - version "0.7.3" - resolved "https://registry.npmjs.org/apollo-datasource/-/apollo-datasource-0.7.3.tgz#c824eb1457bdee5a3173ced0e35e594547e687a0" - integrity sha512-PE0ucdZYjHjUyXrFWRwT02yLcx2DACsZ0jm1Mp/0m/I9nZu/fEkvJxfsryXB6JndpmQO77gQHixf/xGCN976kA== +apollo-datasource@^0.9.0: + version "0.9.0" + resolved "https://registry.npmjs.org/apollo-datasource/-/apollo-datasource-0.9.0.tgz#b0b2913257a6103a5f4c03cb56d78a30e9d850db" + integrity sha512-y8H99NExU1Sk4TvcaUxTdzfq2SZo6uSj5dyh75XSQvbpH6gdAXIW9MaBcvlNC7n0cVPsidHmOcHOWxJ/pTXGjA== dependencies: - apollo-server-caching "^0.5.3" - apollo-server-env "^3.0.0" + apollo-server-caching "^0.7.0" + apollo-server-env "^3.1.0" -apollo-env@^0.6.5: - version "0.6.5" - resolved "https://registry.npmjs.org/apollo-env/-/apollo-env-0.6.5.tgz#5a36e699d39e2356381f7203493187260fded9f3" - integrity sha512-jeBUVsGymeTHYWp3me0R2CZRZrFeuSZeICZHCeRflHTfnQtlmbSXdy5E0pOyRM9CU4JfQkKDC98S1YglQj7Bzg== +apollo-graphql@^0.9.0: + version "0.9.3" + resolved "https://registry.npmjs.org/apollo-graphql/-/apollo-graphql-0.9.3.tgz#1ca6f625322ae10a66f57a39642849a07a7a5dc9" + integrity sha512-rcAl2E841Iko4kSzj4Pt3PRBitmyq1MvoEmpl04TQSpGnoVgl1E/ZXuLBYxMTSnEAm7umn2IsoY+c6Ll9U/10A== dependencies: - "@types/node-fetch" "2.5.7" - core-js "^3.0.1" - node-fetch "^2.2.0" - sha.js "^2.4.11" - -apollo-env@^0.6.6: - version "0.6.6" - resolved "https://registry.npmjs.org/apollo-env/-/apollo-env-0.6.6.tgz#d7880805c4e96ee3d4142900a405176a04779438" - integrity sha512-hXI9PjJtzmD34XviBU+4sPMOxnifYrHVmxpjykqI/dUD2G3yTiuRaiQqwRwB2RCdwC1Ug/jBfoQ/NHDTnnjndQ== - dependencies: - "@types/node-fetch" "2.5.7" - core-js "^3.0.1" - node-fetch "^2.2.0" - sha.js "^2.4.11" - -apollo-graphql@^0.6.0: - version "0.6.1" - resolved "https://registry.npmjs.org/apollo-graphql/-/apollo-graphql-0.6.1.tgz#d0bf0aff76f445de3da10e08f6974f1bf65f5753" - integrity sha512-ZRXAV+k+hboCVS+FW86FW/QgnDR7gm/xMUwJPGXEbV53OLGuQQdIT0NCYK7AzzVkCfsbb7NJ3mmEclkZY9uuxQ== - dependencies: - apollo-env "^0.6.6" + core-js-pure "^3.10.2" lodash.sortby "^4.7.0" + sha.js "^2.4.11" apollo-link-http-common@^0.2.14: version "0.2.16" @@ -7518,12 +7478,12 @@ apollo-link@^1.2.12, apollo-link@^1.2.14: tslib "^1.9.3" zen-observable-ts "^0.8.21" -apollo-reporting-protobuf@^0.6.2: - version "0.6.2" - resolved "https://registry.npmjs.org/apollo-reporting-protobuf/-/apollo-reporting-protobuf-0.6.2.tgz#5572866be9b77f133916532b10e15fbaa4158304" - integrity sha512-WJTJxLM+MRHNUxt1RTl4zD0HrLdH44F2mDzMweBj1yHL0kSt8I1WwoiF/wiGVSpnG48LZrBegCaOJeuVbJTbtw== +apollo-reporting-protobuf@^0.8.0: + version "0.8.0" + resolved "https://registry.npmjs.org/apollo-reporting-protobuf/-/apollo-reporting-protobuf-0.8.0.tgz#ae9d967934d3d8ed816fc85a0d8068ef45c371b9" + integrity sha512-B3XmnkH6Y458iV6OsA7AhfwvTgeZnFq9nPVjbxmLKnvfkEl8hYADtz724uPa0WeBiD7DSFcnLtqg9yGmCkBohg== dependencies: - "@apollo/protobufjs" "^1.0.3" + "@apollo/protobufjs" "1.2.2" apollo-server-caching@0.5.1: version "0.5.1" @@ -7532,95 +7492,95 @@ apollo-server-caching@0.5.1: dependencies: lru-cache "^5.0.0" -apollo-server-caching@^0.5.3: - version "0.5.3" - resolved "https://registry.npmjs.org/apollo-server-caching/-/apollo-server-caching-0.5.3.tgz#cf42a77ad09a46290a246810075eaa029b5305e1" - integrity sha512-iMi3087iphDAI0U2iSBE9qtx9kQoMMEWr6w+LwXruBD95ek9DWyj7OeC2U/ngLjRsXM43DoBDXlu7R+uMjahrQ== +apollo-server-caching@^0.7.0: + version "0.7.0" + resolved "https://registry.npmjs.org/apollo-server-caching/-/apollo-server-caching-0.7.0.tgz#e6d1e68e3bb571cba63a61f60b434fb771c6ff39" + integrity sha512-MsVCuf/2FxuTFVhGLK13B+TZH9tBd2qkyoXKKILIiGcZ5CDUEBO14vIV63aNkMkS1xxvK2U4wBcuuNj/VH2Mkw== dependencies: lru-cache "^6.0.0" -apollo-server-core@^2.21.0: - version "2.21.0" - resolved "https://registry.npmjs.org/apollo-server-core/-/apollo-server-core-2.21.0.tgz#12ee11aee61fa124f11b1d73cae2e068112a3a53" - integrity sha512-GtIiq2F0dVDLzzIuO5+dK/pGq/sGxYlKCqAuQQqzYg0fvZ7fukyluXtcTe0tMI+FJZjU0j0WnKgiLsboCoAlPQ== +apollo-server-core@^2.21.0, apollo-server-core@^2.25.2: + version "2.25.2" + resolved "https://registry.npmjs.org/apollo-server-core/-/apollo-server-core-2.25.2.tgz#ff65da5e512d9b5ca54c8e5e8c78ee28b5987247" + integrity sha512-lrohEjde2TmmDTO7FlOs8x5QQbAS0Sd3/t0TaK2TWaodfzi92QAvIsq321Mol6p6oEqmjm8POIDHW1EuJd7XMA== dependencies: - "@apollographql/apollo-tools" "^0.4.3" - "@apollographql/graphql-playground-html" "1.6.26" + "@apollographql/apollo-tools" "^0.5.0" + "@apollographql/graphql-playground-html" "1.6.27" "@apollographql/graphql-upload-8-fork" "^8.1.3" + "@josephg/resolvable" "^1.0.0" "@types/ws" "^7.0.0" - apollo-cache-control "^0.11.6" - apollo-datasource "^0.7.3" - apollo-graphql "^0.6.0" - apollo-reporting-protobuf "^0.6.2" - apollo-server-caching "^0.5.3" - apollo-server-env "^3.0.0" - apollo-server-errors "^2.4.2" - apollo-server-plugin-base "^0.10.4" - apollo-server-types "^0.6.3" - apollo-tracing "^0.12.2" + apollo-cache-control "^0.14.0" + apollo-datasource "^0.9.0" + apollo-graphql "^0.9.0" + apollo-reporting-protobuf "^0.8.0" + apollo-server-caching "^0.7.0" + apollo-server-env "^3.1.0" + apollo-server-errors "^2.5.0" + apollo-server-plugin-base "^0.13.0" + apollo-server-types "^0.9.0" + apollo-tracing "^0.15.0" async-retry "^1.2.1" fast-json-stable-stringify "^2.0.0" - graphql-extensions "^0.12.8" + graphql-extensions "^0.15.0" graphql-tag "^2.11.0" graphql-tools "^4.0.8" loglevel "^1.6.7" lru-cache "^6.0.0" sha.js "^2.4.11" - subscriptions-transport-ws "^0.9.11" + subscriptions-transport-ws "^0.9.19" uuid "^8.0.0" - ws "^6.0.0" -apollo-server-env@^3.0.0: - version "3.0.0" - resolved "https://registry.npmjs.org/apollo-server-env/-/apollo-server-env-3.0.0.tgz#0157c51f52b63aee39af190760acf789ffc744d9" - integrity sha512-tPSN+VttnPsoQAl/SBVUpGbLA97MXG990XIwq6YUnJyAixrrsjW1xYG7RlaOqetxm80y5mBZKLrRDiiSsW/vog== +apollo-server-env@^3.1.0: + version "3.1.0" + resolved "https://registry.npmjs.org/apollo-server-env/-/apollo-server-env-3.1.0.tgz#0733c2ef50aea596cc90cf40a53f6ea2ad402cd0" + integrity sha512-iGdZgEOAuVop3vb0F2J3+kaBVi4caMoxefHosxmgzAbbSpvWehB8Y1QiSyyMeouYC38XNVk5wnZl+jdGSsWsIQ== dependencies: - node-fetch "^2.1.2" + node-fetch "^2.6.1" util.promisify "^1.0.0" -apollo-server-errors@^2.4.2: - version "2.4.2" - resolved "https://registry.npmjs.org/apollo-server-errors/-/apollo-server-errors-2.4.2.tgz#1128738a1d14da989f58420896d70524784eabe5" - integrity sha512-FeGxW3Batn6sUtX3OVVUm7o56EgjxDlmgpTLNyWcLb0j6P8mw9oLNyAm3B+deHA4KNdNHO5BmHS2g1SJYjqPCQ== +apollo-server-errors@^2.5.0: + version "2.5.0" + resolved "https://registry.npmjs.org/apollo-server-errors/-/apollo-server-errors-2.5.0.tgz#5d1024117c7496a2979e3e34908b5685fe112b68" + integrity sha512-lO5oTjgiC3vlVg2RKr3RiXIIQ5pGXBFxYGGUkKDhTud3jMIhs+gel8L8zsEjKaKxkjHhCQAA/bcEfYiKkGQIvA== apollo-server-express@^2.16.1, apollo-server-express@^2.21.0: - version "2.21.0" - resolved "https://registry.npmjs.org/apollo-server-express/-/apollo-server-express-2.21.0.tgz#29bd4ec728e1992da240c5956c3ce6d95c1d252e" - integrity sha512-zbOSNGuxUjlOFZnRrbMpga3pKDEroitF4NAqoVxgBivx7v2hGsE7rljct3PucTx2cMN90AyYe3cU4oA8jBxZIQ== + version "2.25.2" + resolved "https://registry.npmjs.org/apollo-server-express/-/apollo-server-express-2.25.2.tgz#58cd819694ff4c2dec6945a95c5dff6aa2719ef6" + integrity sha512-A2gF2e85vvDugPlajbhr0A14cDFDIGX0mteNOJ8P3Z3cIM0D4hwrWxJidI+SzobefDIyIHu1dynFedJVhV0euQ== dependencies: - "@apollographql/graphql-playground-html" "1.6.26" + "@apollographql/graphql-playground-html" "1.6.27" "@types/accepts" "^1.3.5" "@types/body-parser" "1.19.0" - "@types/cors" "2.8.8" - "@types/express" "4.17.7" - "@types/express-serve-static-core" "4.17.18" + "@types/cors" "2.8.10" + "@types/express" "^4.17.12" + "@types/express-serve-static-core" "^4.17.21" accepts "^1.3.5" - apollo-server-core "^2.21.0" - apollo-server-types "^0.6.3" + apollo-server-core "^2.25.2" + apollo-server-types "^0.9.0" body-parser "^1.18.3" - cors "^2.8.4" + cors "^2.8.5" express "^4.17.1" graphql-subscriptions "^1.0.0" graphql-tools "^4.0.8" parseurl "^1.3.2" - subscriptions-transport-ws "^0.9.16" + subscriptions-transport-ws "^0.9.19" type-is "^1.6.16" -apollo-server-plugin-base@^0.10.4: - version "0.10.4" - resolved "https://registry.npmjs.org/apollo-server-plugin-base/-/apollo-server-plugin-base-0.10.4.tgz#fbf73f64f95537ca9f9639dd7c535eb5eeb95dcd" - integrity sha512-HRhbyHgHFTLP0ImubQObYhSgpmVH4Rk1BinnceZmwudIVLKrqayIVOELdyext/QnSmmzg5W7vF3NLGBcVGMqDg== +apollo-server-plugin-base@^0.13.0: + version "0.13.0" + resolved "https://registry.npmjs.org/apollo-server-plugin-base/-/apollo-server-plugin-base-0.13.0.tgz#3f85751a420d3c4625355b6cb3fbdd2acbe71f13" + integrity sha512-L3TMmq2YE6BU6I4Tmgygmd0W55L+6XfD9137k+cWEBFu50vRY4Re+d+fL5WuPkk5xSPKd/PIaqzidu5V/zz8Kg== dependencies: - apollo-server-types "^0.6.3" + apollo-server-types "^0.9.0" -apollo-server-types@^0.6.3: - version "0.6.3" - resolved "https://registry.npmjs.org/apollo-server-types/-/apollo-server-types-0.6.3.tgz#f7aa25ff7157863264d01a77d7934aa6e13399e8" - integrity sha512-aVR7SlSGGY41E1f11YYz5bvwA89uGmkVUtzMiklDhZ7IgRJhysT5Dflt5IuwDxp+NdQkIhVCErUXakopocFLAg== +apollo-server-types@^0.9.0: + version "0.9.0" + resolved "https://registry.npmjs.org/apollo-server-types/-/apollo-server-types-0.9.0.tgz#ccf550b33b07c48c72f104fbe2876232b404848b" + integrity sha512-qk9tg4Imwpk732JJHBkhW0jzfG0nFsLqK2DY6UhvJf7jLnRePYsPxWfPiNkxni27pLE2tiNlCwoDFSeWqpZyBg== dependencies: - apollo-reporting-protobuf "^0.6.2" - apollo-server-caching "^0.5.3" - apollo-server-env "^3.0.0" + apollo-reporting-protobuf "^0.8.0" + apollo-server-caching "^0.7.0" + apollo-server-env "^3.1.0" apollo-server@^2.16.1: version "2.21.0" @@ -7634,13 +7594,13 @@ apollo-server@^2.16.1: graphql-tools "^4.0.8" stoppable "^1.1.0" -apollo-tracing@^0.12.2: - version "0.12.2" - resolved "https://registry.npmjs.org/apollo-tracing/-/apollo-tracing-0.12.2.tgz#a261c3970bb421b6dadf50cd85d75b2567a7e52c" - integrity sha512-SYN4o0C0wR1fyS3+P0FthyvsQVHFopdmN3IU64IaspR/RZScPxZ3Ae8uu++fTvkQflAkglnFM0aX6DkZERBp6w== +apollo-tracing@^0.15.0: + version "0.15.0" + resolved "https://registry.npmjs.org/apollo-tracing/-/apollo-tracing-0.15.0.tgz#237fbbbf669aee4370b7e9081b685eabaa8ce84a" + integrity sha512-UP0fztFvaZPHDhIB/J+qGuy6hWO4If069MGC98qVs0I8FICIGu4/8ykpX3X3K6RtaQ56EDAWKykCxFv4ScxMeA== dependencies: - apollo-server-env "^3.0.0" - apollo-server-plugin-base "^0.10.4" + apollo-server-env "^3.1.0" + apollo-server-plugin-base "^0.13.0" apollo-upload-client@^13.0.0: version "13.0.0" @@ -10236,6 +10196,11 @@ core-js-pure@^3.0.0, core-js-pure@^3.0.1: resolved "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.6.4.tgz#4bf1ba866e25814f149d4e9aaa08c36173506e3a" integrity sha512-epIhRLkXdgv32xIUFaaAry2wdxZYBi6bgM7cB136dzzXXa+dFyRLTZeLUJxnd8ShrmyVXBub63n2NHo2JAt8Cw== +core-js-pure@^3.10.2: + version "3.15.1" + resolved "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.15.1.tgz#8356f6576fa2aa8e54ca6fe02620968ff010eed7" + integrity sha512-OZuWHDlYcIda8sJLY4Ec6nWq2hRjlyCqCZ+jCflyleMkVt3tPedDVErvHslyS2nbO+SlBFMSBJYvtLMwxnrzjA== + core-js@3, core-js@^3.0.1, core-js@^3.0.4, core-js@^3.5.0, core-js@^3.6.0, core-js@^3.6.5, core-js@^3.8.2: version "3.15.0" resolved "https://registry.npmjs.org/core-js/-/core-js-3.15.0.tgz#db9554ebce0b6fd90dc9b1f2465c841d2d055044" @@ -10251,7 +10216,7 @@ core-util-is@1.0.2, core-util-is@~1.0.0: resolved "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= -cors@^2.8.4, cors@^2.8.5: +cors@^2.8.5: version "2.8.5" resolved "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz#eac11da51592dd86b9f06f6e7ac293b3df875d29" integrity sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g== @@ -14245,14 +14210,14 @@ graphql-config@^3.0.2, graphql-config@^3.3.0: minimatch "3.0.4" string-env-interpolation "1.0.1" -graphql-extensions@^0.12.8: - version "0.12.8" - resolved "https://registry.npmjs.org/graphql-extensions/-/graphql-extensions-0.12.8.tgz#9cdc2c43d8fe5e0f6c3177a004ac011da2a8aa0f" - integrity sha512-xjsSaB6yKt9jarFNNdivl2VOx52WySYhxPgf8Y16g6GKZyAzBoIFiwyGw5PJDlOSUa6cpmzn6o7z8fVMbSAbkg== +graphql-extensions@^0.15.0: + version "0.15.0" + resolved "https://registry.npmjs.org/graphql-extensions/-/graphql-extensions-0.15.0.tgz#3f291f9274876b0c289fa4061909a12678bd9817" + integrity sha512-bVddVO8YFJPwuACn+3pgmrEg6I8iBuYLuwvxiE+lcQQ7POotVZxm2rgGw0PvVYmWWf3DT7nTVDZ5ROh/ALp8mA== dependencies: - "@apollographql/apollo-tools" "^0.4.3" - apollo-server-env "^3.0.0" - apollo-server-types "^0.6.3" + "@apollographql/apollo-tools" "^0.5.0" + apollo-server-env "^3.1.0" + apollo-server-types "^0.9.0" graphql-language-service-interface@2.8.2, graphql-language-service-interface@^2.8.2: version "2.8.2" @@ -19124,7 +19089,7 @@ node-dir@^0.1.10, node-dir@^0.1.17: dependencies: minimatch "^3.0.2" -node-fetch@2.6.1, node-fetch@^2.1.2, node-fetch@^2.2.0, node-fetch@^2.3.0, node-fetch@^2.6.0, node-fetch@^2.6.1: +node-fetch@2.6.1, node-fetch@^2.2.0, node-fetch@^2.3.0, node-fetch@^2.6.0, node-fetch@^2.6.1: version "2.6.1" resolved "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052" integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw== @@ -24658,16 +24623,16 @@ stylis@^4.0.6: resolved "https://registry.npmjs.org/stylis/-/stylis-4.0.7.tgz#412a90c28079417f3d27c028035095e4232d2904" integrity sha512-OFFeUXFgwnGOKvEXaSv0D0KQ5ADP0n6g3SVONx6I/85JzNZ3u50FRwB3lVIk1QO2HNdI75tbVzc4Z66Gdp9voA== -subscriptions-transport-ws@^0.9.11, subscriptions-transport-ws@^0.9.16, subscriptions-transport-ws@^0.9.18: - version "0.9.18" - resolved "https://registry.npmjs.org/subscriptions-transport-ws/-/subscriptions-transport-ws-0.9.18.tgz#bcf02320c911fbadb054f7f928e51c6041a37b97" - integrity sha512-tztzcBTNoEbuErsVQpTN2xUNN/efAZXyCyL5m3x4t6SKrEiTL2N8SaKWBFWM4u56pL79ULif3zjyeq+oV+nOaA== +subscriptions-transport-ws@^0.9.18, subscriptions-transport-ws@^0.9.19: + version "0.9.19" + resolved "https://registry.npmjs.org/subscriptions-transport-ws/-/subscriptions-transport-ws-0.9.19.tgz#10ca32f7e291d5ee8eb728b9c02e43c52606cdcf" + integrity sha512-dxdemxFFB0ppCLg10FTtRqH/31FNRL1y1BQv8209MK5I4CwALb7iihQg+7p65lFcIl8MHatINWBLOqpgU4Kyyw== dependencies: backo2 "^1.0.2" eventemitter3 "^3.1.0" iterall "^1.2.1" symbol-observable "^1.0.4" - ws "^5.2.0" + ws "^5.2.0 || ^6.0.0 || ^7.0.0" sucrase@^3.18.0, sucrase@^3.18.2: version "3.18.2" @@ -26905,7 +26870,12 @@ ws@^5.2.0: dependencies: async-limiter "~1.0.0" -ws@^6.0.0, ws@^6.1.2, ws@^6.2.1: +"ws@^5.2.0 || ^6.0.0 || ^7.0.0": + version "7.5.0" + resolved "https://registry.npmjs.org/ws/-/ws-7.5.0.tgz#0033bafea031fb9df041b2026fc72a571ca44691" + integrity sha512-6ezXvzOZupqKj4jUqbQ9tXuJNo+BR2gU8fFRk3XCP3e0G6WT414u5ELe6Y0vtp7kmSJ3F7YWObSNr1ESsgi4vw== + +ws@^6.1.2, ws@^6.2.1: version "6.2.1" resolved "https://registry.npmjs.org/ws/-/ws-6.2.1.tgz#442fdf0a47ed64f59b6a5d8ff130f4748ed524fb" integrity sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA== @@ -27023,10 +26993,10 @@ xpath@0.0.27: resolved "https://registry.npmjs.org/xpath/-/xpath-0.0.27.tgz#dd3421fbdcc5646ac32c48531b4d7e9d0c2cfa92" integrity sha512-fg03WRxtkCV6ohClePNAECYsmpKKTv5L8y/X3Dn1hQrec3POx2jHZ/0P2qQ6HvsrU1BmeqXcof3NGGueG6LxwQ== -xss@^1.0.6: - version "1.0.7" - resolved "https://registry.npmjs.org/xss/-/xss-1.0.7.tgz#a554cbd5e909324bd6893fb47fff441ad54e2a95" - integrity sha512-A9v7tblGvxu8TWXQC9rlpW96a+LN1lyw6wyhpTmmGW+FwRMactchBR3ROKSi33UPCUcUHSu8s9YP6F+K3Mw//w== +xss@^1.0.8: + version "1.0.9" + resolved "https://registry.npmjs.org/xss/-/xss-1.0.9.tgz#3ffd565571ff60d2e40db7f3b80b4677bec770d2" + integrity sha512-2t7FahYnGJys6DpHLhajusId7R0Pm2yTmuL0GV9+mV0ZlaLSnb2toBmppATfg5sWIhZQGlsTLoecSzya+l4EAQ== dependencies: commander "^2.20.3" cssfilter "0.0.10" From 115473c085083bf1d3b2f20280960ac05900296b Mon Sep 17 00:00:00 2001 From: Mustansar Anwar ul Samad Date: Wed, 23 Jun 2021 18:12:01 +1200 Subject: [PATCH 024/204] Handle error gracefully on msgraph api photo load Signed-off-by: Mustansar Anwar ul Samad --- .changeset/fair-dolphins-relate.md | 5 +++++ .../package.json | 1 + .../src/microsoftGraph/read.test.ts | 3 ++- .../src/microsoftGraph/read.ts | 22 +++++++++++++------ .../MicrosoftGraphOrgReaderProcessor.ts | 1 + 5 files changed, 24 insertions(+), 8 deletions(-) create mode 100644 .changeset/fair-dolphins-relate.md diff --git a/.changeset/fair-dolphins-relate.md b/.changeset/fair-dolphins-relate.md new file mode 100644 index 0000000000..dcc14cd17f --- /dev/null +++ b/.changeset/fair-dolphins-relate.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-backend-module-msgraph': patch +--- + +Handle error gracefully if failure occurs while loading photos using Microsoft Graph API diff --git a/plugins/catalog-backend-module-msgraph/package.json b/plugins/catalog-backend-module-msgraph/package.json index f37b954706..4d60949b22 100644 --- a/plugins/catalog-backend-module-msgraph/package.json +++ b/plugins/catalog-backend-module-msgraph/package.json @@ -29,6 +29,7 @@ }, "dependencies": { "@azure/msal-node": "^1.1.0", + "@backstage/backend-common": "^0.8.3", "@backstage/catalog-model": "^0.8.4", "@backstage/config": "^0.1.5", "@backstage/plugin-catalog-backend": "^0.10.4", diff --git a/plugins/catalog-backend-module-msgraph/src/microsoftGraph/read.test.ts b/plugins/catalog-backend-module-msgraph/src/microsoftGraph/read.test.ts index b1179c20df..a7f24b41ad 100644 --- a/plugins/catalog-backend-module-msgraph/src/microsoftGraph/read.test.ts +++ b/plugins/catalog-backend-module-msgraph/src/microsoftGraph/read.test.ts @@ -23,6 +23,7 @@ import { readMicrosoftGraphUsers, resolveRelations, } from './read'; +import { getVoidLogger } from '@backstage/backend-common'; function user(data: Partial): UserEntity { return merge( @@ -82,7 +83,7 @@ describe('read microsoft graph', () => { 'data:image/jpeg;base64,...', ); - const { users } = await readMicrosoftGraphUsers(client, { + const { users } = await readMicrosoftGraphUsers(getVoidLogger(), client, { userFilter: 'accountEnabled eq true', }); diff --git a/plugins/catalog-backend-module-msgraph/src/microsoftGraph/read.ts b/plugins/catalog-backend-module-msgraph/src/microsoftGraph/read.ts index 70c403d0b7..8af15605e7 100644 --- a/plugins/catalog-backend-module-msgraph/src/microsoftGraph/read.ts +++ b/plugins/catalog-backend-module-msgraph/src/microsoftGraph/read.ts @@ -33,6 +33,7 @@ import { OrganizationTransformer, UserTransformer, } from './types'; +import { Logger } from 'winston'; export async function defaultUserTransformer( user: MicrosoftGraph.User, @@ -74,6 +75,7 @@ export async function defaultUserTransformer( } export async function readMicrosoftGraphUsers( + logger: Logger, client: MicrosoftGraphClient, options?: { userFilter?: string; transformer?: UserTransformer }, ): Promise<{ @@ -91,12 +93,17 @@ export async function readMicrosoftGraphUsers( // Process all users in parallel, otherwise it can take quite some time promises.push( limiter(async () => { - const userPhoto = await client.getUserPhotoWithSizeLimit( - user.id!, - // We are limiting the photo size, as users with full resolution photos - // can make the Backstage API slow - 120, - ); + let userPhoto; + try { + userPhoto = await client.getUserPhotoWithSizeLimit( + user.id!, + // We are limiting the photo size, as users with full resolution photos + // can make the Backstage API slow + 120, + ); + } catch (e) { + logger.warn(`Unable to load photo for ${user.id}`); + } const entity = await transformer(user, userPhoto); @@ -369,6 +376,7 @@ export function resolveRelations( } export async function readMicrosoftGraphOrg( + logger: Logger, client: MicrosoftGraphClient, tenantId: string, options?: { @@ -377,7 +385,7 @@ export async function readMicrosoftGraphOrg( groupTransformer?: GroupTransformer; }, ): Promise<{ users: UserEntity[]; groups: GroupEntity[] }> { - const { users } = await readMicrosoftGraphUsers(client, { + const { users } = await readMicrosoftGraphUsers(logger, client, { userFilter: options?.userFilter, }); const { diff --git a/plugins/catalog-backend-module-msgraph/src/processors/MicrosoftGraphOrgReaderProcessor.ts b/plugins/catalog-backend-module-msgraph/src/processors/MicrosoftGraphOrgReaderProcessor.ts index d86584a9fd..3e5203d3a5 100644 --- a/plugins/catalog-backend-module-msgraph/src/processors/MicrosoftGraphOrgReaderProcessor.ts +++ b/plugins/catalog-backend-module-msgraph/src/processors/MicrosoftGraphOrgReaderProcessor.ts @@ -84,6 +84,7 @@ export class MicrosoftGraphOrgReaderProcessor implements CatalogProcessor { // We create a client each time as we need one that matches the specific provider const client = MicrosoftGraphClient.create(provider); const { users, groups } = await readMicrosoftGraphOrg( + this.logger, client, provider.tenantId, { From 32bbf51a1d9c0f3ac681886078a277dc7b1c61ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?= Date: Tue, 29 Jun 2021 08:25:33 +0200 Subject: [PATCH 025/204] fix api-report, move logger to options MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fredrik Adelöw --- .changeset/fair-dolphins-relate.md | 6 ++++-- .../api-report.md | 3 ++- .../package.json | 2 +- .../src/microsoftGraph/read.test.ts | 3 ++- .../src/microsoftGraph/read.ts | 20 +++++++++++-------- .../MicrosoftGraphOrgReaderProcessor.ts | 2 +- 6 files changed, 22 insertions(+), 14 deletions(-) diff --git a/.changeset/fair-dolphins-relate.md b/.changeset/fair-dolphins-relate.md index dcc14cd17f..85bc517a8d 100644 --- a/.changeset/fair-dolphins-relate.md +++ b/.changeset/fair-dolphins-relate.md @@ -1,5 +1,7 @@ --- -'@backstage/plugin-catalog-backend-module-msgraph': patch +'@backstage/plugin-catalog-backend-module-msgraph': minor --- -Handle error gracefully if failure occurs while loading photos using Microsoft Graph API +Handle error gracefully if failure occurs while loading photos using Microsoft Graph API. + +This includes a breaking change: you now have to pass the `options` object to `readMicrosoftGraphUsers` and `readMicrosoftGraphOrg`. diff --git a/plugins/catalog-backend-module-msgraph/api-report.md b/plugins/catalog-backend-module-msgraph/api-report.md index 702601b469..f1e7e22c35 100644 --- a/plugins/catalog-backend-module-msgraph/api-report.md +++ b/plugins/catalog-backend-module-msgraph/api-report.md @@ -103,10 +103,11 @@ export type OrganizationTransformer = (organization: MicrosoftGraph.Organization export function readMicrosoftGraphConfig(config: Config): MicrosoftGraphProviderConfig[]; // @public (undocumented) -export function readMicrosoftGraphOrg(client: MicrosoftGraphClient, tenantId: string, options?: { +export function readMicrosoftGraphOrg(client: MicrosoftGraphClient, tenantId: string, options: { userFilter?: string; groupFilter?: string; groupTransformer?: GroupTransformer; + logger: Logger; }): Promise<{ users: UserEntity[]; groups: GroupEntity[]; diff --git a/plugins/catalog-backend-module-msgraph/package.json b/plugins/catalog-backend-module-msgraph/package.json index 4d60949b22..417ef90c6e 100644 --- a/plugins/catalog-backend-module-msgraph/package.json +++ b/plugins/catalog-backend-module-msgraph/package.json @@ -29,7 +29,6 @@ }, "dependencies": { "@azure/msal-node": "^1.1.0", - "@backstage/backend-common": "^0.8.3", "@backstage/catalog-model": "^0.8.4", "@backstage/config": "^0.1.5", "@backstage/plugin-catalog-backend": "^0.10.4", @@ -41,6 +40,7 @@ "qs": "^6.9.4" }, "devDependencies": { + "@backstage/backend-common": "^0.8.3", "@backstage/cli": "^0.7.2", "@backstage/test-utils": "^0.1.14", "@types/lodash": "^4.14.151", diff --git a/plugins/catalog-backend-module-msgraph/src/microsoftGraph/read.test.ts b/plugins/catalog-backend-module-msgraph/src/microsoftGraph/read.test.ts index a7f24b41ad..929d01e128 100644 --- a/plugins/catalog-backend-module-msgraph/src/microsoftGraph/read.test.ts +++ b/plugins/catalog-backend-module-msgraph/src/microsoftGraph/read.test.ts @@ -83,8 +83,9 @@ describe('read microsoft graph', () => { 'data:image/jpeg;base64,...', ); - const { users } = await readMicrosoftGraphUsers(getVoidLogger(), client, { + const { users } = await readMicrosoftGraphUsers(client, { userFilter: 'accountEnabled eq true', + logger: getVoidLogger(), }); expect(users).toEqual([ diff --git a/plugins/catalog-backend-module-msgraph/src/microsoftGraph/read.ts b/plugins/catalog-backend-module-msgraph/src/microsoftGraph/read.ts index 8af15605e7..a9e2465ad7 100644 --- a/plugins/catalog-backend-module-msgraph/src/microsoftGraph/read.ts +++ b/plugins/catalog-backend-module-msgraph/src/microsoftGraph/read.ts @@ -75,9 +75,12 @@ export async function defaultUserTransformer( } export async function readMicrosoftGraphUsers( - logger: Logger, client: MicrosoftGraphClient, - options?: { userFilter?: string; transformer?: UserTransformer }, + options: { + userFilter?: string; + transformer?: UserTransformer; + logger: Logger; + }, ): Promise<{ users: UserEntity[]; // With all relations empty }> { @@ -88,7 +91,7 @@ export async function readMicrosoftGraphUsers( const promises: Promise[] = []; for await (const user of client.getUsers({ - filter: options?.userFilter, + filter: options.userFilter, })) { // Process all users in parallel, otherwise it can take quite some time promises.push( @@ -102,7 +105,7 @@ export async function readMicrosoftGraphUsers( 120, ); } catch (e) { - logger.warn(`Unable to load photo for ${user.id}`); + options.logger.warn(`Unable to load photo for ${user.id}`); } const entity = await transformer(user, userPhoto); @@ -376,17 +379,18 @@ export function resolveRelations( } export async function readMicrosoftGraphOrg( - logger: Logger, client: MicrosoftGraphClient, tenantId: string, - options?: { + options: { userFilter?: string; groupFilter?: string; groupTransformer?: GroupTransformer; + logger: Logger; }, ): Promise<{ users: UserEntity[]; groups: GroupEntity[] }> { - const { users } = await readMicrosoftGraphUsers(logger, client, { - userFilter: options?.userFilter, + const { users } = await readMicrosoftGraphUsers(client, { + userFilter: options.userFilter, + logger: options.logger, }); const { groups, diff --git a/plugins/catalog-backend-module-msgraph/src/processors/MicrosoftGraphOrgReaderProcessor.ts b/plugins/catalog-backend-module-msgraph/src/processors/MicrosoftGraphOrgReaderProcessor.ts index 3e5203d3a5..88240db618 100644 --- a/plugins/catalog-backend-module-msgraph/src/processors/MicrosoftGraphOrgReaderProcessor.ts +++ b/plugins/catalog-backend-module-msgraph/src/processors/MicrosoftGraphOrgReaderProcessor.ts @@ -84,13 +84,13 @@ export class MicrosoftGraphOrgReaderProcessor implements CatalogProcessor { // We create a client each time as we need one that matches the specific provider const client = MicrosoftGraphClient.create(provider); const { users, groups } = await readMicrosoftGraphOrg( - this.logger, client, provider.tenantId, { userFilter: provider.userFilter, groupFilter: provider.groupFilter, groupTransformer: this.groupTransformer, + logger: this.logger, }, ); From 9e60a728ecd28f86e0b44aebbec5b3f2c5b721d7 Mon Sep 17 00:00:00 2001 From: Oliver Sand Date: Tue, 29 Jun 2021 09:47:43 +0200 Subject: [PATCH 026/204] Upgrade rjsf to 3.0.0 [Release notes](https://github.com/rjsf-team/react-jsonschema-form/releases/tag/v3.0.0) Resolves #5833 Signed-off-by: Oliver Sand --- .changeset/early-buckets-type.md | 5 +++ plugins/scaffolder/package.json | 4 +- yarn.lock | 75 ++++++++------------------------ 3 files changed, 24 insertions(+), 60 deletions(-) create mode 100644 .changeset/early-buckets-type.md diff --git a/.changeset/early-buckets-type.md b/.changeset/early-buckets-type.md new file mode 100644 index 0000000000..376408dcae --- /dev/null +++ b/.changeset/early-buckets-type.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder': patch +--- + +Upgrade `rjsf` to 3.0.0. diff --git a/plugins/scaffolder/package.json b/plugins/scaffolder/package.json index 88845b402b..6e2827cbe5 100644 --- a/plugins/scaffolder/package.json +++ b/plugins/scaffolder/package.json @@ -43,8 +43,8 @@ "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.45", - "@rjsf/core": "^2.4.0", - "@rjsf/material-ui": "^2.4.0", + "@rjsf/core": "^3.0.0", + "@rjsf/material-ui": "^3.0.0", "@types/react": "^16.9", "classnames": "^2.2.6", "git-url-parse": "^11.4.4", diff --git a/yarn.lock b/yarn.lock index d1a605c186..54d2647694 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1283,14 +1283,6 @@ pirates "^4.0.0" source-map-support "^0.5.16" -"@babel/runtime-corejs2@^7.8.7": - version "7.14.0" - resolved "https://registry.npmjs.org/@babel/runtime-corejs2/-/runtime-corejs2-7.14.0.tgz#5519b92ccc819bd3d0a1ecb25ab3cb5a775485f8" - integrity sha512-btR4E8JiGlmmDI5YgirlG9z3T91rBdxnVh2YuEStrHDcekffaaIeK+CE0S4IaYUyYhMa7rFDfF2GEO79XNbLEA== - dependencies: - core-js "^2.6.5" - regenerator-runtime "^0.13.4" - "@babel/runtime-corejs3@^7.10.2", "@babel/runtime-corejs3@^7.11.2", "@babel/runtime-corejs3@^7.13.17": version "7.14.0" resolved "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.14.0.tgz#6bf5fbc0b961f8e3202888cb2cd0fb7a0a9a3f66" @@ -4119,27 +4111,25 @@ prop-types "^15.6.1" react-lifecycles-compat "^3.0.4" -"@rjsf/core@^2.4.0": - version "2.5.1" - resolved "https://registry.npmjs.org/@rjsf/core/-/core-2.5.1.tgz#95a842d22bab5f83929662fcd73739108e9f5cbb" - integrity sha512-km8NYScXNONaL5BiSLS6wyDj49pOLZtn0iXg7Zxlm921uuf3o2AAX5SuZS5kB4Zj2zlrVMrXESexfX6bxdDYHw== +"@rjsf/core@^3.0.0": + version "3.0.0" + resolved "https://registry.npmjs.org/@rjsf/core/-/core-3.0.0.tgz#7f79b0635c969e3fbfe0aaa4773d844fbee68a63" + integrity sha512-QSvyVMDiwd7neVnIMOte4tZUvtDWgLDYKOsq1tgCsIFh+RXskd3AEBf6IsK8w6Wg36Om7YalDqqrtXbk9z+rLw== dependencies: - "@babel/runtime-corejs2" "^7.8.7" - "@types/json-schema" "^7.0.4" + "@types/json-schema" "^7.0.7" ajv "^6.7.0" - core-js "^2.5.7" + core-js-pure "^3.6.5" json-schema-merge-allof "^0.6.0" jsonpointer "^4.0.1" lodash "^4.17.15" + nanoid "^3.1.23" prop-types "^15.7.2" - react-app-polyfill "^1.0.4" react-is "^16.9.0" - shortid "^2.2.14" -"@rjsf/material-ui@^2.4.0": - version "2.5.1" - resolved "https://registry.npmjs.org/@rjsf/material-ui/-/material-ui-2.5.1.tgz#b93ac9f1f4a909e2aae729616859c2d72557e53e" - integrity sha512-ooKxQJO12+i1xCGtknMZDxWSbVlSEgQ5U1I7lJ+uI/MvwAg3Rz9wb2cTEF3ErBczT7EEW+j1lR19rxBjFd78MA== +"@rjsf/material-ui@^3.0.0": + version "3.0.0" + resolved "https://registry.npmjs.org/@rjsf/material-ui/-/material-ui-3.0.0.tgz#69ece2cb549f0e860b5f89898db90edcc95b15ba" + integrity sha512-T2B8QnrDQphbFNxDz7baAa0zTd5TXJmO9soHBPTKKdniRbMEOQ19AJBbZkA3ED2XZa/xrUY/6XjERQLpNACddw== "@roadiehq/backstage-plugin-buildkite@^1.0.3": version "1.0.3" @@ -7859,7 +7849,7 @@ arrify@^2.0.0, arrify@^2.0.1: resolved "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz#c9655e9331e0abcd588d2a7cad7e9956f66701fa" integrity sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug== -asap@^2.0.0, asap@~2.0.3, asap@~2.0.6: +asap@^2.0.0, asap@~2.0.3: version "2.0.6" resolved "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" integrity sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY= @@ -10230,17 +10220,17 @@ core-js-pure@^3.0.0, core-js-pure@^3.0.1: resolved "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.6.4.tgz#4bf1ba866e25814f149d4e9aaa08c36173506e3a" integrity sha512-epIhRLkXdgv32xIUFaaAry2wdxZYBi6bgM7cB136dzzXXa+dFyRLTZeLUJxnd8ShrmyVXBub63n2NHo2JAt8Cw== -core-js-pure@^3.10.2: +core-js-pure@^3.10.2, core-js-pure@^3.6.5: version "3.15.1" resolved "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.15.1.tgz#8356f6576fa2aa8e54ca6fe02620968ff010eed7" integrity sha512-OZuWHDlYcIda8sJLY4Ec6nWq2hRjlyCqCZ+jCflyleMkVt3tPedDVErvHslyS2nbO+SlBFMSBJYvtLMwxnrzjA== -core-js@3, core-js@^3.0.1, core-js@^3.0.4, core-js@^3.5.0, core-js@^3.6.0, core-js@^3.6.5, core-js@^3.8.2: +core-js@3, core-js@^3.0.1, core-js@^3.0.4, core-js@^3.6.0, core-js@^3.6.5, core-js@^3.8.2: version "3.15.0" resolved "https://registry.npmjs.org/core-js/-/core-js-3.15.0.tgz#db9554ebce0b6fd90dc9b1f2465c841d2d055044" integrity sha512-GUbtPllXMYRzIgHNZ4dTYTcUemls2cni83Q4Q/TrFONHfhcg9oEGOtaGHfb0cpzec60P96UKPvMkjX1jET8rUw== -core-js@^2.4.0, core-js@^2.5.7, core-js@^2.6.10, core-js@^2.6.5: +core-js@^2.4.0, core-js@^2.6.10: version "2.6.11" resolved "https://registry.npmjs.org/core-js/-/core-js-2.6.11.tgz#38831469f9922bded8ee21c9dc46985e0399308c" integrity sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg== @@ -19000,11 +18990,6 @@ nano-css@^5.1.0, nano-css@^5.2.1, nano-css@^5.3.1: stacktrace-js "^2.0.2" stylis "^4.0.6" -nanoid@^2.1.0: - version "2.1.11" - resolved "https://registry.npmjs.org/nanoid/-/nanoid-2.1.11.tgz#ec24b8a758d591561531b4176a01e3ab4f0f0280" - integrity sha512-s/snB+WGm6uwi0WjsZdaVcuf3KJXlfGl2LcxgwkEwJF0D/BWzVWAZW/XY4bFaiR7s0Jk3FPvlnepg1H1b1UwlA== - nanoid@^3.1.23: version "3.1.23" resolved "https://registry.npmjs.org/nanoid/-/nanoid-3.1.23.tgz#f744086ce7c2bc47ee0a8472574d5c78e4183a81" @@ -21410,13 +21395,6 @@ promise@^7.1.1: dependencies: asap "~2.0.3" -promise@^8.0.3: - version "8.1.0" - resolved "https://registry.npmjs.org/promise/-/promise-8.1.0.tgz#697c25c3dfe7435dd79fcd58c38a135888eaf05e" - integrity sha512-W04AqnILOL/sPRXziNicCjSNRruLAuIHEOVBazepu0545DDNGYHz7ar9ZgZ1fMU8/MA4mVxp5rkBWRi6OXIy3Q== - dependencies: - asap "~2.0.6" - prompts@2.4.0, prompts@^2.0.1: version "2.4.0" resolved "https://registry.npmjs.org/prompts/-/prompts-2.4.0.tgz#4aa5de0723a231d1ee9121c40fdf663df73f61d7" @@ -21782,18 +21760,6 @@ rc@^1.2.7, rc@^1.2.8: minimist "^1.2.0" strip-json-comments "~2.0.1" -react-app-polyfill@^1.0.4: - version "1.0.6" - resolved "https://registry.npmjs.org/react-app-polyfill/-/react-app-polyfill-1.0.6.tgz#890f8d7f2842ce6073f030b117de9130a5f385f0" - integrity sha512-OfBnObtnGgLGfweORmdZbyEz+3dgVePQBb3zipiaDsMHV1NpWm0rDFYIVXFV/AK+x4VIIfWHhrdMIeoTLyRr2g== - dependencies: - core-js "^3.5.0" - object-assign "^4.1.1" - promise "^8.0.3" - raf "^3.4.1" - regenerator-runtime "^0.13.3" - whatwg-fetch "^3.0.0" - react-beautiful-dnd@^13.0.0: version "13.0.0" resolved "https://registry.npmjs.org/react-beautiful-dnd/-/react-beautiful-dnd-13.0.0.tgz#f70cc8ff82b84bc718f8af157c9f95757a6c3b40" @@ -22717,7 +22683,7 @@ regenerator-runtime@^0.11.0: resolved "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9" integrity sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg== -regenerator-runtime@^0.13.3, regenerator-runtime@^0.13.4, regenerator-runtime@^0.13.7: +regenerator-runtime@^0.13.4, regenerator-runtime@^0.13.7: version "0.13.7" resolved "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz#cac2dacc8a1ea675feaabaeb8ae833898ae46f55" integrity sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew== @@ -23700,13 +23666,6 @@ shellwords@^0.1.1: resolved "https://registry.npmjs.org/shellwords/-/shellwords-0.1.1.tgz#d6b9181c1a48d397324c84871efbcfc73fc0654b" integrity sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww== -shortid@^2.2.14: - version "2.2.15" - resolved "https://registry.npmjs.org/shortid/-/shortid-2.2.15.tgz#2b902eaa93a69b11120373cd42a1f1fe4437c122" - integrity sha512-5EaCy2mx2Jgc/Fdn9uuDuNIIfWBpzY4XIlhoqtXF6qsf+/+SGZ+FxDdX/ZsMZiWupIWNqAEmiNY4RC+LSmCeOw== - dependencies: - nanoid "^2.1.0" - shx@^0.3.2: version "0.3.3" resolved "https://registry.npmjs.org/shx/-/shx-0.3.3.tgz#681a88c7c10db15abe18525349ed474f0f1e7b9f" @@ -26647,7 +26606,7 @@ whatwg-fetch@^2.0.4: resolved "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-2.0.4.tgz#dde6a5df315f9d39991aa17621853d720b85566f" integrity sha512-dcQ1GWpOD/eEQ97k66aiEVpNnapVj90/+R+SXTPYGHpYBBypfKJEQjLrvMZ7YXbKm21gXd4NcuxUTjiv1YtLng== -whatwg-fetch@^3.0.0, whatwg-fetch@^3.4.1: +whatwg-fetch@^3.4.1: version "3.4.1" resolved "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.4.1.tgz#e5f871572d6879663fa5674c8f833f15a8425ab3" integrity sha512-sofZVzE1wKwO+EYPbWfiwzaKovWiZXf4coEzjGP9b2GBVgQRLQUZ2QcuPpQExGDAW5GItpEm6Tl4OU5mywnAoQ== From 640220b2fad32b4a9f565482c6726b1312e5fb09 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 28 Jun 2021 04:10:17 +0000 Subject: [PATCH 027/204] chore(deps-dev): bump prettier from 2.3.1 to 2.3.2 in /microsite Bumps [prettier](https://github.com/prettier/prettier) from 2.3.1 to 2.3.2. - [Release notes](https://github.com/prettier/prettier/releases) - [Changelog](https://github.com/prettier/prettier/blob/main/CHANGELOG.md) - [Commits](https://github.com/prettier/prettier/compare/2.3.1...2.3.2) --- updated-dependencies: - dependency-name: prettier dependency-type: direct:development update-type: version-update:semver-patch ... 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 1894e37d84..eee549fb70 100644 --- a/microsite/package.json +++ b/microsite/package.json @@ -19,7 +19,7 @@ "@spotify/prettier-config": "^10.0.0", "docusaurus": "^2.0.0-alpha.70", "js-yaml": "^4.1.0", - "prettier": "^2.3.1", + "prettier": "^2.3.2", "yarn-lock-check": "^1.0.5" }, "prettier": "@spotify/prettier-config" diff --git a/microsite/yarn.lock b/microsite/yarn.lock index a89235bf98..1da9288808 100644 --- a/microsite/yarn.lock +++ b/microsite/yarn.lock @@ -5207,10 +5207,10 @@ prepend-http@^2.0.0: resolved "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz#e92434bfa5ea8c19f41cdfd401d741a3c819d897" integrity sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc= -prettier@^2.3.1: - version "2.3.1" - resolved "https://registry.npmjs.org/prettier/-/prettier-2.3.1.tgz#76903c3f8c4449bc9ac597acefa24dc5ad4cbea6" - integrity sha512-p+vNbgpLjif/+D+DwAZAbndtRrR0md0MwfmOVN9N+2RgyACMT+7tfaRnT+WDPkqnuVwleyuBIG2XBxKDme3hPA== +prettier@^2.3.2: + version "2.3.2" + resolved "https://registry.npmjs.org/prettier/-/prettier-2.3.2.tgz#ef280a05ec253712e486233db5c6f23441e7342d" + integrity sha512-lnJzDfJ66zkMy58OL5/NY5zp70S7Nz6KqcKkXYzn2tMVrNxvbqaBpg7H3qHaLxCJ5lNMsGuM8+ohS7cZrthdLQ== prismjs@^1.22.0: version "1.23.0" From b2b169acaf472f56993bdd4e27ce2e7cc9553929 Mon Sep 17 00:00:00 2001 From: Roy Jacobs Date: Sat, 26 Jun 2021 14:36:39 +0200 Subject: [PATCH 028/204] Update ADOPTERS.md to reflect changed username MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit My username changed and this is causing a 404 in ADOPTERS.md. Signed-off-by: Fredrik Adelöw --- ADOPTERS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ADOPTERS.md b/ADOPTERS.md index 94a470e1a7..70a6cbc3f4 100644 --- a/ADOPTERS.md +++ b/ADOPTERS.md @@ -1,7 +1,7 @@ | Organization | Contact | Description of Use | | ------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | [Spotify](https://www.spotify.com) | [@leemills83](https://github.com/leemills83) | Main interface towards all of Spotify's infrastructure and technical documentation. | -| [bol.com](https://www.bol.com) | [@RoyJacobs](https://github.com/RoyJacobs) | Initial work being done to unify platform tooling. | +| [bol.com](https://www.bol.com) | [@sagacity](https://github.com/sagacity) | Initial work being done to unify platform tooling. | | [DFDS](https://www.dfds.com) | [@carlsendk](https://github.com/carlsendk) | V2 self-service platform. | | [Roadie](https://roadie.io) | [@dtuite](https://github.com/dtuite) | Hosted, managed Backstage with easy set-up | | [Roku](https://www.roku.com) | [@timurista](https://github.com/timurista) | Initial work on Cloud engineering service platform. | From 55f49fcc78388006f6ce86018cc0192dc45d4799 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 25 Jun 2021 04:40:48 +0000 Subject: [PATCH 029/204] chore(deps): bump @rollup/plugin-yaml from 2.1.1 to 3.0.0 Bumps [@rollup/plugin-yaml](https://github.com/rollup/plugins) from 2.1.1 to 3.0.0. - [Release notes](https://github.com/rollup/plugins/releases) - [Commits](https://github.com/rollup/plugins/compare/yaml-v2.1.1...wasm-v3.0.0) --- updated-dependencies: - dependency-name: "@rollup/plugin-yaml" dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .changeset/nasty-games-share.md | 5 +++++ packages/cli/package.json | 2 +- yarn.lock | 14 +++++++------- 3 files changed, 13 insertions(+), 8 deletions(-) create mode 100644 .changeset/nasty-games-share.md diff --git a/.changeset/nasty-games-share.md b/.changeset/nasty-games-share.md new file mode 100644 index 0000000000..f154817634 --- /dev/null +++ b/.changeset/nasty-games-share.md @@ -0,0 +1,5 @@ +--- +'@backstage/cli': patch +--- + +Update dependencies diff --git a/packages/cli/package.json b/packages/cli/package.json index b0e6b021cc..8a4b71d9c6 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -40,7 +40,7 @@ "@rollup/plugin-commonjs": "^17.1.0", "@rollup/plugin-json": "^4.0.2", "@rollup/plugin-node-resolve": "^13.0.0", - "@rollup/plugin-yaml": "^2.1.1", + "@rollup/plugin-yaml": "^3.0.0", "@spotify/eslint-config-base": "^9.0.0", "@spotify/eslint-config-react": "^10.0.0", "@spotify/eslint-config-typescript": "^10.0.0", diff --git a/yarn.lock b/yarn.lock index 7885e5f724..28012b8af1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4232,16 +4232,16 @@ is-module "^1.0.0" resolve "^1.19.0" -"@rollup/plugin-yaml@^2.1.1": - version "2.1.1" - resolved "https://registry.npmjs.org/@rollup/plugin-yaml/-/plugin-yaml-2.1.1.tgz#6c864adee22004eb325d53bc4ee5553828e056d8" - integrity sha512-CnGD3dbDhP+JeKFX7kJuaBOa7jVzXpl3G8lXp1hasB87cDYOz7qNWd4cFPmYbxMsT/8OCVsceIpRtQ+cj9uxBw== +"@rollup/plugin-yaml@^3.0.0": + version "3.0.0" + resolved "https://registry.npmjs.org/@rollup/plugin-yaml/-/plugin-yaml-3.0.0.tgz#632af397a6faaea10c885680c575ae01f4556c1d" + integrity sha512-nXYI3WsfG7Oq5K5k7evGQ1ZABGCPhHxMaMX4T3GRSDi9VyhkaU1+8R1RzTRFXITFJHx0QEGn8jR+P9pux5FuBQ== dependencies: - "@rollup/pluginutils" "^3.0.1" - js-yaml "^3.13.1" + "@rollup/pluginutils" "^3.1.0" + js-yaml "^3.14.0" tosource "^1.0.0" -"@rollup/pluginutils@^3.0.1", "@rollup/pluginutils@^3.0.8", "@rollup/pluginutils@^3.1.0": +"@rollup/pluginutils@^3.0.8", "@rollup/pluginutils@^3.1.0": version "3.1.0" resolved "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-3.1.0.tgz#706b4524ee6dc8b103b3c995533e5ad680c02b9b" integrity sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg== From 208976022b21f5fcafbaa98cde0f648211c454e9 Mon Sep 17 00:00:00 2001 From: "roylisto.pradana" Date: Tue, 29 Jun 2021 17:52:38 +0700 Subject: [PATCH 030/204] add displayName option for Groups diagram Signed-off-by: roylisto.pradana --- .../GroupsExplorerContent/GroupsDiagram.tsx | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/plugins/explore/src/components/GroupsExplorerContent/GroupsDiagram.tsx b/plugins/explore/src/components/GroupsExplorerContent/GroupsDiagram.tsx index 53e55b96bf..27be0dae7e 100644 --- a/plugins/explore/src/components/GroupsExplorerContent/GroupsDiagram.tsx +++ b/plugins/explore/src/components/GroupsExplorerContent/GroupsDiagram.tsx @@ -96,7 +96,9 @@ function RenderNode(props: DependencyGraphTypes.RenderNodeProps) { alignmentBaseline="baseline" style={{ fontWeight: 'bold' }} > - {props.node.name} + {props.node.profile?.displayName + ? props.node.profile?.displayName + : props.node.name} @@ -107,7 +109,12 @@ function RenderNode(props: DependencyGraphTypes.RenderNodeProps) { * Dynamically generates a diagram of groups registered in the catalog. */ export function GroupsDiagram() { - const nodes = new Array<{ id: string; kind: string; name: string }>(); + const nodes = new Array<{ + id: string; + kind: string; + name: string; + profile?: any; + }>(); const edges = new Array<{ from: string; to: string; label: string }>(); const configApi = useApi(configApiRef); @@ -142,6 +149,7 @@ export function GroupsDiagram() { id: stringifyEntityRef(catalogItem), kind: catalogItem.kind, name: formatEntityRefTitle(catalogItem, { defaultKind: 'Group' }), + profile: catalogItem.spec?.profile, }); // Edge to parent From 2316beb6b3ba138fe9db9c287c7a4a5e87e67869 Mon Sep 17 00:00:00 2001 From: Philipp Hugenroth Date: Mon, 28 Jun 2021 18:15:47 +0200 Subject: [PATCH 031/204] Set height of page to 100vh - Add SidebarScroll Wrapper Signed-off-by: Philipp Hugenroth --- packages/app/src/components/Root/Root.tsx | 11 +++++++---- .../core-components/src/layout/Page/Page.tsx | 3 ++- .../src/layout/Sidebar/Items.tsx | 8 ++++++++ .../src/layout/Sidebar/index.ts | 1 + packages/core/src/layout/Page/Page.tsx | 3 ++- plugins/shortcuts/src/Shortcuts.tsx | 18 +++++++----------- 6 files changed, 27 insertions(+), 17 deletions(-) diff --git a/packages/app/src/components/Root/Root.tsx b/packages/app/src/components/Root/Root.tsx index 09ee571cf6..48141e4f53 100644 --- a/packages/app/src/components/Root/Root.tsx +++ b/packages/app/src/components/Root/Root.tsx @@ -39,6 +39,7 @@ import { SidebarItem, SidebarDivider, SidebarSpace, + SidebarScrollWrapper, } from '@backstage/core-components'; const useSidebarLogoStyles = makeStyles({ @@ -88,10 +89,12 @@ export const Root = ({ children }: PropsWithChildren<{}>) => ( {/* End global nav */} - - - - + + + + + + diff --git a/packages/core-components/src/layout/Page/Page.tsx b/packages/core-components/src/layout/Page/Page.tsx index 8acb54c268..8d1dfe2943 100644 --- a/packages/core-components/src/layout/Page/Page.tsx +++ b/packages/core-components/src/layout/Page/Page.tsx @@ -25,7 +25,8 @@ const useStyles = makeStyles(() => ({ "'pageHeader pageHeader pageHeader' 'pageSubheader pageSubheader pageSubheader' 'pageNav pageContent pageSidebar'", gridTemplateRows: 'auto auto 1fr', gridTemplateColumns: 'auto 1fr auto', - minHeight: '100vh', + height: '100vh', + overflowY: 'auto', }, })); diff --git a/packages/core-components/src/layout/Sidebar/Items.tsx b/packages/core-components/src/layout/Sidebar/Items.tsx index 9bccffc6c4..28ebab3e18 100644 --- a/packages/core-components/src/layout/Sidebar/Items.tsx +++ b/packages/core-components/src/layout/Sidebar/Items.tsx @@ -290,3 +290,11 @@ export const SidebarDivider = styled('hr')({ border: 'none', margin: '12px 0px', }); + +export const SidebarScrollWrapper = styled('div')({ + flex: '0 1 auto', + overflowY: 'scroll', + // Display at least one item in the container + // Question: Can this be a config/theme variable - if so, which? :/ + minHeight: '48px', +}); diff --git a/packages/core-components/src/layout/Sidebar/index.ts b/packages/core-components/src/layout/Sidebar/index.ts index fc0e29f9a6..58e193dbaf 100644 --- a/packages/core-components/src/layout/Sidebar/index.ts +++ b/packages/core-components/src/layout/Sidebar/index.ts @@ -23,6 +23,7 @@ export { SidebarSearchField, SidebarSpace, SidebarSpacer, + SidebarScrollWrapper, } from './Items'; export { IntroCard, SidebarIntro } from './Intro'; export { diff --git a/packages/core/src/layout/Page/Page.tsx b/packages/core/src/layout/Page/Page.tsx index 8acb54c268..8d1dfe2943 100644 --- a/packages/core/src/layout/Page/Page.tsx +++ b/packages/core/src/layout/Page/Page.tsx @@ -25,7 +25,8 @@ const useStyles = makeStyles(() => ({ "'pageHeader pageHeader pageHeader' 'pageSubheader pageSubheader pageSubheader' 'pageNav pageContent pageSidebar'", gridTemplateRows: 'auto auto 1fr', gridTemplateColumns: 'auto 1fr auto', - minHeight: '100vh', + height: '100vh', + overflowY: 'auto', }, })); diff --git a/plugins/shortcuts/src/Shortcuts.tsx b/plugins/shortcuts/src/Shortcuts.tsx index 775b0b3809..86aa9565d3 100644 --- a/plugins/shortcuts/src/Shortcuts.tsx +++ b/plugins/shortcuts/src/Shortcuts.tsx @@ -22,18 +22,14 @@ import { ShortcutItem } from './ShortcutItem'; import { AddShortcut } from './AddShortcut'; import { shortcutsApiRef } from './api'; -import { Progress, SidebarItem } from '@backstage/core-components'; +import { + Progress, + SidebarItem, + SidebarScrollWrapper, +} from '@backstage/core-components'; import { useApi } from '@backstage/core-plugin-api'; -const useStyles = makeStyles({ - root: { - flex: '1 1 auto', - overflowY: 'scroll', - }, -}); - export const Shortcuts = () => { - const classes = useStyles(); const shortcutApi = useApi(shortcutsApiRef); const shortcuts = useObservable( useMemo(() => shortcutApi.shortcut$(), [shortcutApi]), @@ -50,7 +46,7 @@ export const Shortcuts = () => { }; return ( -
+ { /> )) )} -
+ ); }; From c0bd924ebb2e22ad0ab829cfc79422f24efe1877 Mon Sep 17 00:00:00 2001 From: "roylisto.pradana" Date: Tue, 29 Jun 2021 18:35:46 +0700 Subject: [PATCH 032/204] Fix the test file Signed-off-by: roylisto.pradana --- .../components/GroupsExplorerContent/GroupsDiagram.test.tsx | 5 ++++- .../src/components/GroupsExplorerContent/GroupsDiagram.tsx | 4 +--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/plugins/explore/src/components/GroupsExplorerContent/GroupsDiagram.test.tsx b/plugins/explore/src/components/GroupsExplorerContent/GroupsDiagram.test.tsx index 5044b09f83..3b9b523b02 100644 --- a/plugins/explore/src/components/GroupsExplorerContent/GroupsDiagram.test.tsx +++ b/plugins/explore/src/components/GroupsExplorerContent/GroupsDiagram.test.tsx @@ -46,6 +46,9 @@ describe('', () => { namespace: 'my-namespace', }, spec: { + profile: { + displayName: 'Group A', + }, type: 'organization', }, }, @@ -64,6 +67,6 @@ describe('', () => { }, ); - expect(getByText('my-namespace/group-a')).toBeInTheDocument(); + expect(getByText('Group A')).toBeInTheDocument(); }); }); diff --git a/plugins/explore/src/components/GroupsExplorerContent/GroupsDiagram.tsx b/plugins/explore/src/components/GroupsExplorerContent/GroupsDiagram.tsx index 27be0dae7e..32931e8f3a 100644 --- a/plugins/explore/src/components/GroupsExplorerContent/GroupsDiagram.tsx +++ b/plugins/explore/src/components/GroupsExplorerContent/GroupsDiagram.tsx @@ -96,9 +96,7 @@ function RenderNode(props: DependencyGraphTypes.RenderNodeProps) { alignmentBaseline="baseline" style={{ fontWeight: 'bold' }} > - {props.node.profile?.displayName - ? props.node.profile?.displayName - : props.node.name} + {props.node.profile?.displayName ?? props.node.name} From e8c65b0682f47c42e77d1f580555e9d30b18cd85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?= Date: Tue, 29 Jun 2021 13:45:37 +0200 Subject: [PATCH 033/204] Clear the previously selected sign-in provider on failure MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fredrik Adelöw --- .changeset/twenty-pumpkins-work.md | 5 +++++ packages/core-components/src/layout/SignInPage/providers.tsx | 1 + 2 files changed, 6 insertions(+) create mode 100644 .changeset/twenty-pumpkins-work.md diff --git a/.changeset/twenty-pumpkins-work.md b/.changeset/twenty-pumpkins-work.md new file mode 100644 index 0000000000..b729c989e5 --- /dev/null +++ b/.changeset/twenty-pumpkins-work.md @@ -0,0 +1,5 @@ +--- +'@backstage/core-components': patch +--- + +Clear the previously selected sign-in provider on failure diff --git a/packages/core-components/src/layout/SignInPage/providers.tsx b/packages/core-components/src/layout/SignInPage/providers.tsx index 0f5d3daf2e..19915e6aa9 100644 --- a/packages/core-components/src/layout/SignInPage/providers.tsx +++ b/packages/core-components/src/layout/SignInPage/providers.tsx @@ -143,6 +143,7 @@ export const useSignInProviders = ( if (didCancel) { return; } + localStorage.removeItem(PROVIDER_STORAGE_KEY); errorApi.post(error); setLoading(false); }); From dd91185744c8b7765712b10dd812840290c577e2 Mon Sep 17 00:00:00 2001 From: "roylisto.pradana" Date: Tue, 29 Jun 2021 18:45:45 +0700 Subject: [PATCH 034/204] Add changeset Signed-off-by: roylisto.pradana --- .changeset/pretty-needles-peel.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/pretty-needles-peel.md diff --git a/.changeset/pretty-needles-peel.md b/.changeset/pretty-needles-peel.md new file mode 100644 index 0000000000..00dcc63a7d --- /dev/null +++ b/.changeset/pretty-needles-peel.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-explore': minor +--- + +Using displayName as default value when loading Groups Diagram From 8a700d14acec09db92cc6f179c127c6f11665ad2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?= Date: Tue, 29 Jun 2021 14:26:23 +0200 Subject: [PATCH 035/204] appease vale MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fredrik Adelöw --- .changeset/gold-avocados-thank.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/gold-avocados-thank.md b/.changeset/gold-avocados-thank.md index bd97499629..c7399ee016 100644 --- a/.changeset/gold-avocados-thank.md +++ b/.changeset/gold-avocados-thank.md @@ -2,4 +2,4 @@ '@backstage/backend-common': patch --- -Download archives as compressed tar files for Gitlab to fix the readtree bug in TODO Plugin. +Download archives as compressed tar files for GitLab to fix the `readTree` bug in TODO Plugin. From 64c7561dc857c93dcb57ba011b70ce15e774e261 Mon Sep 17 00:00:00 2001 From: "roylisto.pradana" Date: Tue, 29 Jun 2021 19:14:04 +0700 Subject: [PATCH 036/204] change minor to patch for changeset Signed-off-by: roylisto.pradana --- .changeset/pretty-needles-peel.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/pretty-needles-peel.md b/.changeset/pretty-needles-peel.md index 00dcc63a7d..4e77ef7cd3 100644 --- a/.changeset/pretty-needles-peel.md +++ b/.changeset/pretty-needles-peel.md @@ -1,5 +1,5 @@ --- -'@backstage/plugin-explore': minor +'@backstage/plugin-explore': patch --- Using displayName as default value when loading Groups Diagram From 99a2873c76a9311403d78ee104915affde2fe3e4 Mon Sep 17 00:00:00 2001 From: Gowind Date: Tue, 29 Jun 2021 10:58:09 +0200 Subject: [PATCH 037/204] Techdocs: Include cookies when requesting SVGs Signed-off-by: Gowind --- .changeset/bright-pans-rhyme.md | 5 +++++ plugins/techdocs/src/reader/transformers/addBaseUrl.ts | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 .changeset/bright-pans-rhyme.md diff --git a/.changeset/bright-pans-rhyme.md b/.changeset/bright-pans-rhyme.md new file mode 100644 index 0000000000..c5f72b9ac6 --- /dev/null +++ b/.changeset/bright-pans-rhyme.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-techdocs': patch +--- + +Include cookies when making fetch requests for SVG from techdocs plugin diff --git a/plugins/techdocs/src/reader/transformers/addBaseUrl.ts b/plugins/techdocs/src/reader/transformers/addBaseUrl.ts index 81021fbde8..f21cb8c47a 100644 --- a/plugins/techdocs/src/reader/transformers/addBaseUrl.ts +++ b/plugins/techdocs/src/reader/transformers/addBaseUrl.ts @@ -64,7 +64,7 @@ export const addBaseUrl = ({ const apiOrigin = await techdocsStorageApi.getApiOrigin(); if (isSvgNeedingInlining(attributeName, elemAttribute, apiOrigin)) { try { - const svg = await fetch(newValue); + const svg = await fetch(newValue, { credentials: 'include' }); const svgContent = await svg.text(); elem.setAttribute( attributeName, From 0daaffd13dd9dd0765866e74fb78cd5e36425beb Mon Sep 17 00:00:00 2001 From: James Renaud Date: Tue, 29 Jun 2021 09:25:10 -0400 Subject: [PATCH 038/204] chore: update doc with screenshots Signed-off-by: James Renaud --- plugins/pagerduty/README.md | 18 ++++++++++++++---- plugins/pagerduty/doc/pd1.png | Bin 0 -> 25299 bytes plugins/pagerduty/doc/pd2.png | Bin 0 -> 22614 bytes plugins/pagerduty/doc/pd3.png | Bin 0 -> 49915 bytes plugins/pagerduty/doc/pd4.png | Bin 0 -> 25070 bytes 5 files changed, 14 insertions(+), 4 deletions(-) create mode 100644 plugins/pagerduty/doc/pd1.png create mode 100644 plugins/pagerduty/doc/pd2.png create mode 100644 plugins/pagerduty/doc/pd3.png create mode 100644 plugins/pagerduty/doc/pd4.png diff --git a/plugins/pagerduty/README.md b/plugins/pagerduty/README.md index e1ec7f89c7..12329288b7 100644 --- a/plugins/pagerduty/README.md +++ b/plugins/pagerduty/README.md @@ -8,11 +8,21 @@ There is also an easy way to trigger an alarm directly to the person who is curr This plugin requires that entities are annotated with an [integration key](https://support.pagerduty.com/docs/services-and-integrations#add-integrations-to-an-existing-service). See more further down in this document. -This plugin provides: +## Features -- A list of incidents -- A way to trigger an alarm to the person on-call -- Information details about the person on-call +### View any open incidents + +![View Open Incidents](doc/pd1.png "PagerDuty plugin showing no incidents and the on-call rotation") + +### Email link, and view contact information for staff on call + +![On-Call Contact Information](doc/pd2.png "PagerDuty plugin showing on-call rotation contact information") + +### Trigger an incident for a service + +![Trigger an Incident](doc/pd3.png "PagerDuty plugin popup modal for creating an incident") + +![Active Incidents](doc/pd4.png "PagerDuty plugin showing an active incident") ## Setup instructions diff --git a/plugins/pagerduty/doc/pd1.png b/plugins/pagerduty/doc/pd1.png new file mode 100644 index 0000000000000000000000000000000000000000..8242792b5a2bc72ebbf241afcf56c4da9525a63c GIT binary patch literal 25299 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 literal 0 HcmV?d00001 diff --git a/plugins/pagerduty/doc/pd3.png b/plugins/pagerduty/doc/pd3.png new file mode 100644 index 0000000000000000000000000000000000000000..89d7f1820d2d8895ffa0aad48caf0af71d6ad637 GIT binary patch literal 49915 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 P&qq>JPNZ7MAn<}F#RAB}*( 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 literal 0 HcmV?d00001 From e1ec6adc3ed6f5a65eb24cd4833550e9315d7644 Mon Sep 17 00:00:00 2001 From: Philipp Hugenroth Date: Tue, 29 Jun 2021 15:25:15 +0200 Subject: [PATCH 039/204] Fix sflaky sidebar in 'peek' state Signed-off-by: Philipp Hugenroth --- packages/core-components/src/layout/Sidebar/Items.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/core-components/src/layout/Sidebar/Items.tsx b/packages/core-components/src/layout/Sidebar/Items.tsx index 28ebab3e18..dbaa50b76e 100644 --- a/packages/core-components/src/layout/Sidebar/Items.tsx +++ b/packages/core-components/src/layout/Sidebar/Items.tsx @@ -293,7 +293,7 @@ export const SidebarDivider = styled('hr')({ export const SidebarScrollWrapper = styled('div')({ flex: '0 1 auto', - overflowY: 'scroll', + overflowY: 'auto', // Display at least one item in the container // Question: Can this be a config/theme variable - if so, which? :/ minHeight: '48px', From fce011ae06371ad6b3a236b5fa616324a5f5e590 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?= Date: Tue, 29 Jun 2021 16:44:56 +0200 Subject: [PATCH 040/204] unbreak windows tests, and silence msw errors about query params MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fredrik Adelöw --- .../src/reading/BitbucketUrlReader.test.ts | 4 ++-- .../backend-common/src/reading/GithubUrlReader.test.ts | 2 +- .../backend-common/src/reading/GitlabUrlReader.test.ts | 10 +++++----- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/backend-common/src/reading/BitbucketUrlReader.test.ts b/packages/backend-common/src/reading/BitbucketUrlReader.test.ts index d8bcde2397..cc540cb83c 100644 --- a/packages/backend-common/src/reading/BitbucketUrlReader.test.ts +++ b/packages/backend-common/src/reading/BitbucketUrlReader.test.ts @@ -142,7 +142,7 @@ describe('BitbucketUrlReader', () => { ), ), rest.get( - 'https://api.bitbucket.mycompany.net/rest/api/1.0/projects/backstage/repos/mock/archive?format=tgz&prefix=mock&path=docs', + 'https://api.bitbucket.mycompany.net/rest/api/1.0/projects/backstage/repos/mock/archive', (_, res, ctx) => res( ctx.status(200), @@ -366,7 +366,7 @@ describe('BitbucketUrlReader', () => { beforeEach(() => { worker.use( rest.get( - 'https://api.bitbucket.mycompany.net/rest/api/1.0/projects/backstage/repos/mock/archive?format=tgz&prefix=mock&path=docs', + 'https://api.bitbucket.mycompany.net/rest/api/1.0/projects/backstage/repos/mock/archive', (_, res, ctx) => res( ctx.status(200), diff --git a/packages/backend-common/src/reading/GithubUrlReader.test.ts b/packages/backend-common/src/reading/GithubUrlReader.test.ts index 787ef82f60..0b3288e59c 100644 --- a/packages/backend-common/src/reading/GithubUrlReader.test.ts +++ b/packages/backend-common/src/reading/GithubUrlReader.test.ts @@ -118,7 +118,7 @@ describe('GithubUrlReader', () => { worker.use( rest.get( - 'https://ghe.github.com/api/v3/repos/backstage/mock/tree/contents/?ref=main', + 'https://ghe.github.com/api/v3/repos/backstage/mock/tree/contents/', (req, res, ctx) => { expect(req.headers.get('authorization')).toBe( mockHeaders.Authorization, diff --git a/packages/backend-common/src/reading/GitlabUrlReader.test.ts b/packages/backend-common/src/reading/GitlabUrlReader.test.ts index 5ed151c5c2..9c2e428239 100644 --- a/packages/backend-common/src/reading/GitlabUrlReader.test.ts +++ b/packages/backend-common/src/reading/GitlabUrlReader.test.ts @@ -205,7 +205,7 @@ describe('GitlabUrlReader', () => { beforeEach(() => { worker.use( rest.get( - 'https://gitlab.com/api/v4/projects/backstage%2Fmock/repository/archive?sha=main', + 'https://gitlab.com/api/v4/projects/backstage%2Fmock/repository/archive', (_, res, ctx) => res( ctx.status(200), @@ -283,7 +283,7 @@ describe('GitlabUrlReader', () => { }, ), rest.get( - 'https://gitlab.mycompany.com/api/v4/projects/backstage%2Fmock/repository/archive?sha=main', + 'https://gitlab.mycompany.com/api/v4/projects/backstage%2Fmock/repository/archive', (_, res, ctx) => res( ctx.status(200), @@ -318,7 +318,7 @@ describe('GitlabUrlReader', () => { 'https://gitlab.com/backstage/mock', ); - const dir = await response.dir({ targetDir: '/tmp' }); + const dir = await response.dir({ targetDir: tmpDir }); await expect( fs.readFile(path.join(dir, 'mkdocs.yml'), 'utf8'), @@ -375,7 +375,7 @@ describe('GitlabUrlReader', () => { 'https://gitlab.com/backstage/mock/tree/main/docs', ); - const dir = await response.dir({ targetDir: '/tmp' }); + const dir = await response.dir({ targetDir: tmpDir }); await expect( fs.readFile(path.join(dir, 'index.md'), 'utf8'), @@ -471,7 +471,7 @@ describe('GitlabUrlReader', () => { beforeEach(() => { worker.use( rest.get( - 'https://gitlab.com/api/v4/projects/backstage%2Fmock/repository/archive?sha=main', + 'https://gitlab.com/api/v4/projects/backstage%2Fmock/repository/archive', (_, res, ctx) => res( ctx.status(200), From 8ab897e0181eb4c6e9ca0c7f8624dee0cf78faf6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?= Date: Mon, 28 Jun 2021 15:54:14 +0200 Subject: [PATCH 041/204] Properly return a 404 when an unknown cluster is given MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fredrik Adelöw --- .changeset/warm-mangos-share.md | 5 +++++ plugins/kafka-backend/package.json | 1 + plugins/kafka-backend/src/service/router.test.ts | 15 ++++++++++++++- plugins/kafka-backend/src/service/router.ts | 14 ++++++++++++-- 4 files changed, 32 insertions(+), 3 deletions(-) create mode 100644 .changeset/warm-mangos-share.md diff --git a/.changeset/warm-mangos-share.md b/.changeset/warm-mangos-share.md new file mode 100644 index 0000000000..4f54b100d2 --- /dev/null +++ b/.changeset/warm-mangos-share.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-kafka-backend': patch +--- + +Properly return a 404 when an unknown cluster is given diff --git a/plugins/kafka-backend/package.json b/plugins/kafka-backend/package.json index 617dd2d3cb..d85b0974d6 100644 --- a/plugins/kafka-backend/package.json +++ b/plugins/kafka-backend/package.json @@ -34,6 +34,7 @@ "@backstage/backend-common": "^0.8.2", "@backstage/catalog-model": "^0.8.2", "@backstage/config": "^0.1.5", + "@backstage/errors": "^0.1.1", "@types/express": "^4.17.6", "express": "^4.17.1", "express-promise-router": "^4.1.0", diff --git a/plugins/kafka-backend/src/service/router.test.ts b/plugins/kafka-backend/src/service/router.test.ts index d3f19f720f..4f458fe543 100644 --- a/plugins/kafka-backend/src/service/router.test.ts +++ b/plugins/kafka-backend/src/service/router.test.ts @@ -17,7 +17,7 @@ import request from 'supertest'; import express from 'express'; import { makeRouter, ClusterApi } from './router'; -import { getVoidLogger } from '@backstage/backend-common'; +import { errorHandler, getVoidLogger } from '@backstage/backend-common'; import { KafkaApi } from './KafkaApi'; import { when } from 'jest-when'; @@ -111,6 +111,19 @@ describe('router', () => { ); }); + it('handles unknown cluster errors correctly', async () => { + const response = await request(app.use(errorHandler())).get( + '/consumers/unknown/hey/offsets', + ); + expect(response.status).toEqual(404); + expect(response.body).toMatchObject({ + error: { + message: + 'Found no configured cluster "unknown", candidates are "dev", "prod"', + }, + }); + }); + it('handles internal error correctly', async () => { prodKafkaApi.fetchGroupOffsets.mockRejectedValue(Error('oh no')); diff --git a/plugins/kafka-backend/src/service/router.ts b/plugins/kafka-backend/src/service/router.ts index 68f3924f89..6c8bce7af3 100644 --- a/plugins/kafka-backend/src/service/router.ts +++ b/plugins/kafka-backend/src/service/router.ts @@ -18,6 +18,7 @@ import express from 'express'; import Router from 'express-promise-router'; import { Logger } from 'winston'; import { Config } from '@backstage/config'; +import { NotFoundError } from '@backstage/errors'; import { KafkaApi, KafkaJsApiImpl } from './KafkaApi'; import _ from 'lodash'; import { getClusterDetails } from '../config/ClusterReader'; @@ -45,12 +46,20 @@ export const makeRouter = ( const clusterId = req.params.clusterId; const consumerId = req.params.consumerId; + const kafkaApi = kafkaApiByClusterName[clusterId]; + if (!kafkaApi) { + const candidates = Object.keys(kafkaApiByClusterName) + .map(n => `"${n}"`) + .join(', '); + throw new NotFoundError( + `Found no configured cluster "${clusterId}", candidates are ${candidates}`, + ); + } + logger.info( `Fetch consumer group ${consumerId} offsets from cluster ${clusterId}`, ); - const kafkaApi = kafkaApiByClusterName[clusterId]; - const groupOffsets = await kafkaApi.api.fetchGroupOffsets(consumerId); const groupWithTopicOffsets = await Promise.all( @@ -68,6 +77,7 @@ export const makeRouter = ( })); }), ); + res.json({ consumerId, offsets: groupWithTopicOffsets.flat() }); }); From d0a13d227e9a87677ba312f2114176fabcaab539 Mon Sep 17 00:00:00 2001 From: Johan Haals Date: Mon, 28 Jun 2021 14:02:57 +0200 Subject: [PATCH 042/204] Catalog: Disallow insertion of conflicting entityRefs Co-authored-by: Patrik Oldsberg Signed-off-by: Johan Haals --- .../database/DefaultProcessingDatabase.ts | 93 +++++++++++++------ 1 file changed, 67 insertions(+), 26 deletions(-) diff --git a/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.ts b/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.ts index c2bfb4f633..8d3873a0ad 100644 --- a/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.ts +++ b/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.ts @@ -74,8 +74,14 @@ export class DefaultProcessingDatabase implements ProcessingDatabase { location_key: locationKey, }) .where('entity_id', id) - .andWhere('location_key', locationKey) - .orWhere('location_key', ''); + .andWhere(inner => { + if (!locationKey) { + return inner.whereNull('location_key'); + } + return inner + .where('location_key', locationKey) + .orWhereNull('location_key'); + }); if (refreshResult === 0) { throw new NotFoundError(`Processing state not found for ${id}`); } @@ -319,34 +325,69 @@ export class DefaultProcessingDatabase implements ProcessingDatabase { ): Promise { const tx = txOpaque as Knex.Transaction; - const stateRows = options.entities.map( - ({ entity, locationKey }) => - ({ - entity_id: uuid(), - entity_ref: stringifyEntityRef(entity), - unprocessed_entity: JSON.stringify(entity), - errors: '', - location_key: locationKey, - next_update_at: tx.fn.now(), - last_discovery_at: tx.fn.now(), - } as Knex.DbRecord), - ); - const stateReferenceRows = stateRows.map( - stateRow => - ({ - source_entity_ref: options.entityRef, - target_entity_ref: stateRow.entity_ref, - } as Knex.DbRecord), - ); + const stateReferenceRows = new Array< + Knex.DbRecord + >(); // Upsert all of the unprocessed entities into the refresh_state table, by // their entity ref. // TODO(freben): Can this be batched somehow? - for (const row of stateRows) { - await tx('refresh_state') - .insert(row) - .onConflict('entity_ref') - .merge(['unprocessed_entity', 'last_discovery_at']); + for (const { entity, locationKey } of options.entities) { + const entityRef = stringifyEntityRef(entity); + const serializedEntity = JSON.stringify(entity); + + const refreshResult = await tx('refresh_state') + .update({ + unprocessed_entity: serializedEntity, + location_key: locationKey, + last_discovery_at: tx.fn.now(), + }) + .where('entity_ref', entityRef) + .andWhere(inner => { + if (!locationKey) { + return inner.whereNull('location_key'); + } + return inner + .where('location_key', locationKey) + .orWhereNull('location_key'); + }); + + if (refreshResult === 0) { + const result = await tx('refresh_state') + .insert({ + entity_id: uuid(), + entity_ref: entityRef, + unprocessed_entity: serializedEntity, + errors: '', + location_key: locationKey, + next_update_at: tx.fn.now(), + last_discovery_at: tx.fn.now(), + }) + .onConflict('entity_ref') + .ignore(); + + if (result.length === 0) { + // Detected conflicting entity with same entityRef but different locationKey + const [conflictingEntity] = await tx( + 'refresh_state', + ) + .where({ entity_ref: entityRef }) + .select(); + + if (conflictingEntity.location_key !== locationKey) { + this.options.logger.warn( + `Detected conflicting entityRef ${entityRef} already referenced by ${conflictingEntity.location_key} and now also ${locationKey}`, + ); + continue; + } + } + } + + // Skipped on locationKey conflict + stateReferenceRows.push({ + source_entity_ref: options.entityRef, + target_entity_ref: entityRef, + }); } // Replace all references for the originating entity before creating new ones From ba3061f53e111648662b901d951866b5677f785d Mon Sep 17 00:00:00 2001 From: Johan Haals Date: Mon, 28 Jun 2021 14:04:30 +0200 Subject: [PATCH 043/204] Fix location key migrations Co-authored-by: Patrik Oldsberg Signed-off-by: Johan Haals --- .../migrations/20210302150147_refresh_state.js | 2 -- .../20210622104022_refresh_state_location_key.js | 9 ++++++++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/plugins/catalog-backend/migrations/20210302150147_refresh_state.js b/plugins/catalog-backend/migrations/20210302150147_refresh_state.js index 2752ab0176..db66b46305 100644 --- a/plugins/catalog-backend/migrations/20210302150147_refresh_state.js +++ b/plugins/catalog-backend/migrations/20210302150147_refresh_state.js @@ -65,8 +65,6 @@ exports.up = async function up(knex) { .dateTime('last_discovery_at') // TODO: timezone or change to epoch-millis or similar .notNullable() .comment('The last timestamp of which this entity was discovered'); - // TODO: get migrations to work for this field instead. should be removed before merge. - table.text('location_key').nullable().comment('Location key'); table.unique(['entity_ref'], 'refresh_state_entity_ref_uniq'); table.index('entity_id', 'refresh_state_entity_id_idx'); table.index('entity_ref', 'refresh_state_entity_ref_idx'); diff --git a/plugins/catalog-backend/migrations/20210622104022_refresh_state_location_key.js b/plugins/catalog-backend/migrations/20210622104022_refresh_state_location_key.js index b77ff8961c..ca90bf9074 100644 --- a/plugins/catalog-backend/migrations/20210622104022_refresh_state_location_key.js +++ b/plugins/catalog-backend/migrations/20210622104022_refresh_state_location_key.js @@ -21,7 +21,13 @@ */ exports.up = async function up(knex) { await knex.schema.alterTable('refresh_state', table => { - table.text('location_key').nullable().comment('').alter(); + table + .text('location_key') + .nullable() + .comment( + 'An opaque key that uniquely identifies the location of an entity in order to support conflict resolution', + ); + // table.index(['location_key'], 'refresh_state_location_key_idx'); }); }; @@ -31,5 +37,6 @@ exports.up = async function up(knex) { exports.down = async function down(knex) { await knex.schema.alterTable('refresh_state', table => { table.dropColumn('location_key'); + // table.dropIndex([], 'refresh_state_location_key_idx'); }); }; From e4906366a3b257f6ffb686d55f0b4574c3b60765 Mon Sep 17 00:00:00 2001 From: Johan Haals Date: Mon, 28 Jun 2021 14:05:02 +0200 Subject: [PATCH 044/204] Catalog: Rename emitKey to locationkey Signed-off-by: Johan Haals --- .../catalog-backend/src/next/ConfigLocationEntityProvider.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/catalog-backend/src/next/ConfigLocationEntityProvider.ts b/plugins/catalog-backend/src/next/ConfigLocationEntityProvider.ts index 5e343b0f23..71ec84dae7 100644 --- a/plugins/catalog-backend/src/next/ConfigLocationEntityProvider.ts +++ b/plugins/catalog-backend/src/next/ConfigLocationEntityProvider.ts @@ -42,8 +42,8 @@ export class ConfigLocationEntityProvider implements EntityProvider { type, target: type === 'file' ? path.resolve(target) : target, }); - const emitKey = getEntityLocationRef(entity); - return { entity, emitKey }; + const locationKey = getEntityLocationRef(entity); + return { entity, locationKey }; }); await this.connection.applyMutation({ From 3aa0014263e03c55dbf17f3facac4b046a2d6f35 Mon Sep 17 00:00:00 2001 From: Johan Haals Date: Tue, 29 Jun 2021 09:18:20 +0200 Subject: [PATCH 045/204] Consolidate addUnprocessedEntities, compute delta using locationKey Co-authored-by: Patrik Oldsberg Signed-off-by: Johan Haals --- .../database/DefaultProcessingDatabase.ts | 122 ++++++++++-------- .../src/next/database/types.ts | 13 +- 2 files changed, 78 insertions(+), 57 deletions(-) diff --git a/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.ts b/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.ts index 8d3873a0ad..f5da7850ea 100644 --- a/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.ts +++ b/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.ts @@ -89,7 +89,7 @@ export class DefaultProcessingDatabase implements ProcessingDatabase { // Schedule all deferred entities for future processing. await this.addUnprocessedEntities(tx, { entities: deferredEntities, - entityRef: stringifyEntityRef(processedEntity), + sourceEntityRef: stringifyEntityRef(processedEntity), }); // Update fragments @@ -147,24 +147,43 @@ export class DefaultProcessingDatabase implements ProcessingDatabase { }; } + // Grab all of the existing references from the same source, and their locationKeys as well const oldRefs = await tx( 'refresh_state_references', ) .where({ source_key: options.sourceKey }) - .select('target_entity_ref') - .then(rows => rows.map(r => r.target_entity_ref)); + .leftJoin('refresh_state', { + target_entity_ref: 'entity_ref', + }) + .select(['target_entity_ref', 'location_key']); - const items = options.items.map(entity => ({ - entity, - ref: stringifyEntityRef(entity.entity), + const items = options.items.map(deferred => ({ + deferred, + ref: stringifyEntityRef(deferred.entity), })); - const oldRefsSet = new Set(oldRefs); + const oldRefsSet = new Map( + oldRefs.map(r => [r.target_entity_ref, r.location_key]), + ); const newRefsSet = new Set(items.map(item => item.ref)); - const toAdd = items.filter(item => !oldRefsSet.has(item.ref)); - const toRemove = oldRefs.filter(ref => !newRefsSet.has(ref)); - return { toAdd: toAdd.map(({ entity }) => entity), toRemove }; + const toAdd = new Array(); + const toRemove = oldRefs + .map(row => row.target_entity_ref) + .filter(ref => !newRefsSet.has(ref)); + + for (const item of items) { + if (!oldRefsSet.has(item.ref)) { + // Add any entity that does not exist in the database + toAdd.push(item.deferred); + } else if (oldRefsSet.get(item.ref) !== item.deferred.locationKey) { + // Remove and then re-add any entity that exists, but with a different location key + toRemove.push(item.ref); + toAdd.push(item.deferred); + } + } + + return { toAdd, toRemove }; } async replaceUnprocessedEntities( @@ -291,31 +310,10 @@ export class DefaultProcessingDatabase implements ProcessingDatabase { } if (toAdd.length) { - const state: Knex.DbRecord[] = toAdd.map( - ({ entity, locationKey }) => ({ - entity_id: uuid(), - entity_ref: stringifyEntityRef(entity), - unprocessed_entity: JSON.stringify(entity), - location_key: locationKey, - errors: '', - next_update_at: tx.fn.now(), - last_discovery_at: tx.fn.now(), - }), - ); - - const stateReferences: DbRefreshStateReferencesRow[] = toAdd.map( - entity => ({ - source_key: options.sourceKey, - target_entity_ref: stringifyEntityRef(entity.entity), - }), - ); - // TODO(freben): Concurrency? If we did these one by one, a .onConflict().merge would have made sense - await tx.batchInsert('refresh_state', state, BATCH_SIZE); - await tx.batchInsert( - 'refresh_state_references', - stateReferences, - BATCH_SIZE, - ); + await this.addUnprocessedEntities(tx, { + sourceKey: options.sourceKey, + entities: toAdd, + }); } } @@ -325,17 +323,17 @@ export class DefaultProcessingDatabase implements ProcessingDatabase { ): Promise { const tx = txOpaque as Knex.Transaction; - const stateReferenceRows = new Array< - Knex.DbRecord - >(); + // Keeps track of the entities that we end up inserting to update refresh_state_references afterwards + const stateReferences = new Array(); // Upsert all of the unprocessed entities into the refresh_state table, by // their entity ref. - // TODO(freben): Can this be batched somehow? for (const { entity, locationKey } of options.entities) { const entityRef = stringifyEntityRef(entity); const serializedEntity = JSON.stringify(entity); + // We optimistically try to update any existing refresh state first, as this is by far + // the most common case. const refreshResult = await tx('refresh_state') .update({ unprocessed_entity: serializedEntity, @@ -353,6 +351,7 @@ export class DefaultProcessingDatabase implements ProcessingDatabase { }); if (refreshResult === 0) { + // In the event that we can't update an existing refresh state, we first try to insert a new row const result = await tx('refresh_state') .insert({ entity_id: uuid(), @@ -366,14 +365,17 @@ export class DefaultProcessingDatabase implements ProcessingDatabase { .onConflict('entity_ref') .ignore(); + // If the row can't be inserted, we have a conflict, but it could be either + // because of a conflicting locationKey or a race with another instance, so check for that too if (result.length === 0) { - // Detected conflicting entity with same entityRef but different locationKey + // Check for conflicting entity with same entityRef but different locationKey const [conflictingEntity] = await tx( 'refresh_state', ) .where({ entity_ref: entityRef }) .select(); + // If the location key matches it means we just had a race trigger, which we can safely ignore if (conflictingEntity.location_key !== locationKey) { this.options.logger.warn( `Detected conflicting entityRef ${entityRef} already referenced by ${conflictingEntity.location_key} and now also ${locationKey}`, @@ -384,21 +386,35 @@ export class DefaultProcessingDatabase implements ProcessingDatabase { } // Skipped on locationKey conflict - stateReferenceRows.push({ - source_entity_ref: options.entityRef, - target_entity_ref: entityRef, - }); + stateReferences.push(entityRef); } - // Replace all references for the originating entity before creating new ones - await tx('refresh_state_references') - .where({ source_entity_ref: options.entityRef }) - .delete(); - await tx.batchInsert( - 'refresh_state_references', - stateReferenceRows, - BATCH_SIZE, - ); + // Replace all references for the originating entity or source and then create new ones + if ('sourceKey' in options) { + await tx('refresh_state_references') + .where({ source_key: options.sourceKey }) + .delete(); + await tx.batchInsert( + 'refresh_state_references', + stateReferences.map(entityRef => ({ + source_key: options.sourceKey, + target_entity_ref: entityRef, + })), + BATCH_SIZE, + ); + } else { + await tx('refresh_state_references') + .where({ source_entity_ref: options.sourceEntityRef }) + .delete(); + await tx.batchInsert( + 'refresh_state_references', + stateReferences.map(entityRef => ({ + source_entity_ref: options.sourceEntityRef, + target_entity_ref: entityRef, + })), + BATCH_SIZE, + ); + } } async getProcessableEntities( diff --git a/plugins/catalog-backend/src/next/database/types.ts b/plugins/catalog-backend/src/next/database/types.ts index cd5d2a362d..132b462751 100644 --- a/plugins/catalog-backend/src/next/database/types.ts +++ b/plugins/catalog-backend/src/next/database/types.ts @@ -19,10 +19,15 @@ import { JsonObject } from '@backstage/config'; import { Transaction } from '../../database/types'; import { DeferredEntity } from '../processing/types'; -export type AddUnprocessedEntitiesOptions = { - entityRef: string; - entities: DeferredEntity[]; -}; +export type AddUnprocessedEntitiesOptions = + | { + sourceEntityRef: string; + entities: DeferredEntity[]; + } + | { + sourceKey: string; + entities: DeferredEntity[]; + }; export type AddUnprocessedEntitiesResult = {}; From 03f1076fa60023df08950ecc7dba70342062d3cf Mon Sep 17 00:00:00 2001 From: Johan Haals Date: Tue, 29 Jun 2021 11:30:36 +0200 Subject: [PATCH 046/204] Remove addUnprocessedEntities from public interface This is only used internally. Co-authored-by: Patrik Oldsberg Signed-off-by: Johan Haals --- plugins/catalog-backend/src/next/database/types.ts | 5 ----- 1 file changed, 5 deletions(-) diff --git a/plugins/catalog-backend/src/next/database/types.ts b/plugins/catalog-backend/src/next/database/types.ts index 132b462751..78199900e4 100644 --- a/plugins/catalog-backend/src/next/database/types.ts +++ b/plugins/catalog-backend/src/next/database/types.ts @@ -78,11 +78,6 @@ export type ReplaceUnprocessedEntitiesOptions = export interface ProcessingDatabase { transaction(fn: (tx: Transaction) => Promise): Promise; - addUnprocessedEntities( - tx: Transaction, - options: AddUnprocessedEntitiesOptions, - ): Promise; - replaceUnprocessedEntities( txOpaque: Transaction, options: ReplaceUnprocessedEntitiesOptions, From 72849d64954c109ca00cd13a0bfdd89832eaf764 Mon Sep 17 00:00:00 2001 From: Johan Haals Date: Tue, 29 Jun 2021 11:31:59 +0200 Subject: [PATCH 047/204] Add locationKey tests Signed-off-by: Johan Haals --- .../DefaultProcessingDatabase.test.ts | 215 +++++++++++++++--- 1 file changed, 185 insertions(+), 30 deletions(-) diff --git a/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.test.ts b/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.test.ts index a0db3b293f..db9f209c22 100644 --- a/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.test.ts +++ b/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.test.ts @@ -57,6 +57,105 @@ describe('Default Processing Database', () => { await db('refresh_state').insert(ref); }; + describe('addUprocessedEntities', () => { + function mockEntity(name: string, type: string): Entity { + return { + apiVersion: '1', + kind: 'Component', + metadata: { + name, + }, + spec: { + type, + }, + }; + } + + it.each(databases.eachSupportedId())( + 'updates refresh state with varying location keys, %p', + async databaseId => { + const { db } = await createDatabase(databaseId); + await db.transaction(async tx => { + const knexTx = tx as Knex.Transaction; + + const steps = [ + { + locationKey: undefined, + expectedLocationKey: null, + type: 'a', + expectedType: 'a', + }, + { + locationKey: undefined, + expectedLocationKey: null, + type: 'b', + expectedType: 'b', + }, + { + locationKey: 'x', + expectedLocationKey: 'x', + type: 'c', + expectedType: 'c', + }, + { + locationKey: 'y', + expectedLocationKey: 'x', + type: 'd', + expectedType: 'c', + }, + { + locationKey: undefined, + expectedLocationKey: 'x', + type: 'e', + expectedType: 'c', + }, + { + locationKey: 'x', + expectedLocationKey: 'x', + type: 'f', + expectedType: 'f', + }, + ]; + for (const step of steps) { + await db.addUnprocessedEntities(tx, { + sourceKey: 'testing', + entities: [ + { + entity: mockEntity('1', step.type), + locationKey: step.locationKey, + }, + ], + }); + + const entities = await knexTx( + 'refresh_state', + ).select(); + expect(entities).toEqual([ + expect.objectContaining({ + entity_ref: 'component:default/1', + location_key: step.expectedLocationKey, + }), + ]); + const entity = JSON.parse(entities[0].unprocessed_entity) as Entity; + expect(entity.spec?.type).toEqual(step.expectedType); + + await expect( + knexTx( + 'refresh_state_references', + ).select(), + ).resolves.toEqual([ + expect.objectContaining({ + source_key: 'testing', + target_entity_ref: 'component:default/1', + }), + ]); + } + }); + }, + 60_000, + ); + }); + describe('updateProcessedEntity', () => { let id: string; let processedEntity: Entity; @@ -77,7 +176,7 @@ describe('Default Processing Database', () => { }); it.each(databases.eachSupportedId())( - 'fails when there is no processing state for the entity, %p', + 'fails when an entity is processed with a different locationKey, %p', async databaseId => { const { db } = await createDatabase(databaseId); await db.transaction(async tx => { @@ -95,6 +194,45 @@ describe('Default Processing Database', () => { 60_000, ); + it.each(databases.eachSupportedId())( + 'fails when the locationKey is different, %p', + async databaseId => { + const options = { + id, + processedEntity, + state: new Map(), + relations: [], + deferredEntities: [], + locationKey: 'key', + errors: "['something broke']", + }; + const { knex, db } = await createDatabase(databaseId); + await insertRefreshStateRow(knex, { + entity_id: id, + entity_ref: 'location:default/fakelocation', + unprocessed_entity: '{}', + processed_entity: '{}', + location_key: 'key', + errors: '[]', + next_update_at: '2021-04-01 13:37:00', + last_discovery_at: '2021-04-01 13:37:00', + }); + await db.transaction(tx => db.updateProcessedEntity(tx, options)); + + const entities = await knex( + 'refresh_state', + ).select(); + expect(entities.length).toBe(1); + + await db.transaction(tx => + expect( + db.updateProcessedEntity(tx, { ...options, locationKey: 'fail' }), + ).rejects.toThrow(`Processing state not found for ${id}`), + ); + }, + 60_000, + ); + it.each(databases.eachSupportedId())( 'updates the refresh state entry with the cache, processed entity and errors, %p', async databaseId => { @@ -119,6 +257,7 @@ describe('Default Processing Database', () => { state, relations: [], deferredEntities: [], + locationKey: 'key', errors: "['something broke']", }), ); @@ -132,6 +271,7 @@ describe('Default Processing Database', () => { ); expect(entities[0].cache).toEqual(JSON.stringify(state)); expect(entities[0].errors).toEqual("['something broke']"); + expect(entities[0].location_key).toEqual('key'); }, 60_000, ); @@ -206,11 +346,14 @@ describe('Default Processing Database', () => { const deferredEntities = [ { - apiVersion: '1', - kind: 'Location', - metadata: { - name: 'next', + entity: { + apiVersion: '1', + kind: 'Location', + metadata: { + name: 'next', + }, }, + locationKey: 'mock', }, ]; @@ -227,7 +370,7 @@ describe('Default Processing Database', () => { const refreshStateEntries = await knex( 'refresh_state', ) - .where({ entity_ref: stringifyEntityRef(deferredEntities[0]) }) + .where({ entity_ref: stringifyEntityRef(deferredEntities[0].entity) }) .select(); expect(refreshStateEntries).toHaveLength(1); @@ -297,12 +440,15 @@ describe('Default Processing Database', () => { sourceKey: 'config', items: [ { - apiVersion: '1.0.0', - metadata: { - name: 'new-root', - }, - kind: 'Location', - } as Entity, + entity: { + apiVersion: '1.0.0', + metadata: { + name: 'new-root', + }, + kind: 'Location', + } as Entity, + locationKey: 'file:/tmp/foobar', + }, ], }), ); @@ -411,12 +557,15 @@ describe('Default Processing Database', () => { sourceKey: 'config', items: [ { - apiVersion: '1.0.0', - metadata: { - name: 'new-root', - }, - kind: 'Location', - } as Entity, + entity: { + apiVersion: '1.0.0', + metadata: { + name: 'new-root', + }, + kind: 'Location', + } as Entity, + locationKey: 'file:/tmp/foobar', + }, ], }); }); @@ -510,12 +659,15 @@ describe('Default Processing Database', () => { removed: [], added: [ { - apiVersion: '1.0.0', - metadata: { - name: 'new-root', - }, - kind: 'Location', - } as Entity, + entity: { + apiVersion: '1.0.0', + metadata: { + name: 'new-root', + }, + kind: 'Location', + } as Entity, + locationKey: 'file:/tmp/foobar', + }, ], }); }); @@ -614,12 +766,15 @@ describe('Default Processing Database', () => { added: [], removed: [ { - apiVersion: '1.0.0', - metadata: { - name: 'new-root', - }, - kind: 'Location', - } as Entity, + entity: { + apiVersion: '1.0.0', + metadata: { + name: 'new-root', + }, + kind: 'Location', + } as Entity, + locationKey: 'file:/tmp/foobar', + }, ], }); }); From 057e78ebb1c212c238f71b1e03054bf3b8add795 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Tue, 29 Jun 2021 14:07:19 +0200 Subject: [PATCH 048/204] catalog-backend: more tests for DB + fix ref handling during conflicts Co-authored-by: blam Co-authored-by: Johan Haals Signed-off-by: Patrik Oldsberg --- .../DefaultProcessingDatabase.test.ts | 99 ++++++++++++++++++- .../database/DefaultProcessingDatabase.ts | 25 ++--- 2 files changed, 107 insertions(+), 17 deletions(-) diff --git a/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.test.ts b/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.test.ts index db9f209c22..9a9c09daaf 100644 --- a/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.test.ts +++ b/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.test.ts @@ -19,6 +19,7 @@ import { TestDatabaseId, TestDatabases } from '@backstage/backend-test-utils'; import { Entity, stringifyEntityRef } from '@backstage/catalog-model'; import { JsonObject } from '@backstage/config'; import { Knex } from 'knex'; +import { Logger } from 'winston'; import * as uuid from 'uuid'; import { DatabaseManager } from './DatabaseManager'; import { DefaultProcessingDatabase } from './DefaultProcessingDatabase'; @@ -29,12 +30,15 @@ import { } from './tables'; describe('Default Processing Database', () => { - const logger = getVoidLogger(); + const defaultLogger = getVoidLogger(); const databases = TestDatabases.create({ ids: ['POSTGRES_13', 'POSTGRES_9', 'SQLITE_3'], }); - async function createDatabase(databaseId: TestDatabaseId) { + async function createDatabase( + databaseId: TestDatabaseId, + logger: Logger = defaultLogger, + ) { const knex = await databases.init(databaseId); await DatabaseManager.createDatabase(knex); return { @@ -74,7 +78,11 @@ describe('Default Processing Database', () => { it.each(databases.eachSupportedId())( 'updates refresh state with varying location keys, %p', async databaseId => { - const { db } = await createDatabase(databaseId); + const mockWarn = jest.fn(); + const { db } = await createDatabase(databaseId, ({ + debug: jest.fn(), + warn: mockWarn, + } as unknown) as Logger); await db.transaction(async tx => { const knexTx = tx as Knex.Transaction; @@ -102,12 +110,14 @@ describe('Default Processing Database', () => { expectedLocationKey: 'x', type: 'd', expectedType: 'c', + expectConflict: true, }, { locationKey: undefined, expectedLocationKey: 'x', type: 'e', expectedType: 'c', + expectConflict: true, }, { locationKey: 'x', @@ -117,6 +127,8 @@ describe('Default Processing Database', () => { }, ]; for (const step of steps) { + mockWarn.mockClear(); + await db.addUnprocessedEntities(tx, { sourceKey: 'testing', entities: [ @@ -127,6 +139,16 @@ describe('Default Processing Database', () => { ], }); + if (step.expectConflict) { + // eslint-disable-next-line jest/no-conditional-expect + expect(mockWarn).toHaveBeenCalledWith( + expect.stringMatching(/^Detected conflicting entityRef/), + ); + } else { + // eslint-disable-next-line jest/no-conditional-expect + expect(mockWarn).not.toHaveBeenCalled(); + } + const entities = await knexTx( 'refresh_state', ).select(); @@ -447,7 +469,7 @@ describe('Default Processing Database', () => { }, kind: 'Location', } as Entity, - locationKey: 'file:/tmp/foobar', + locationKey: 'file:///tmp/foobar', }, ], }), @@ -666,7 +688,7 @@ describe('Default Processing Database', () => { }, kind: 'Location', } as Entity, - locationKey: 'file:/tmp/foobar', + locationKey: 'file:///tmp/foobar', }, ], }); @@ -803,6 +825,73 @@ describe('Default Processing Database', () => { }, 60_000, ); + + it.each(databases.eachSupportedId())( + 'should update the location key during full replace, %p', + async databaseId => { + const { knex, db } = await createDatabase(databaseId); + await createLocations(knex, ['location:default/removed']); + await insertRefreshStateRow(knex, { + entity_id: uuid.v4(), + entity_ref: 'location:default/replaced', + unprocessed_entity: '{}', + processed_entity: '{}', + errors: '[]', + next_update_at: '2021-04-01 13:37:00', + last_discovery_at: '2021-04-01 13:37:00', + location_key: 'file:///tmp/old', + }); + + await insertRefRow(knex, { + source_key: 'lols', + target_entity_ref: 'location:default/removed', + }); + await insertRefRow(knex, { + source_key: 'lols', + target_entity_ref: 'location:default/replaced', + }); + + await db.transaction(async tx => { + await db.replaceUnprocessedEntities(tx, { + type: 'full', + sourceKey: 'lols', + items: [ + { + entity: { + apiVersion: '1.0.0', + metadata: { + name: 'replaced', + }, + kind: 'Location', + } as Entity, + locationKey: 'file:///tmp/foobar', + }, + ], + }); + }); + + const currentRefreshState = await knex( + 'refresh_state', + ).select(); + expect(currentRefreshState).toEqual([ + expect.objectContaining({ + entity_ref: 'location:default/replaced', + location_key: 'file:///tmp/foobar', + }), + ]); + + const currentRefRowState = await knex( + 'refresh_state_references', + ).select(); + expect(currentRefRowState).toEqual([ + expect.objectContaining({ + source_key: 'lols', + target_entity_ref: 'location:default/replaced', + }), + ]); + }, + 60_000, + ); }); describe('getProcessableEntities', () => { diff --git a/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.ts b/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.ts index f5da7850ea..67b83bdb34 100644 --- a/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.ts +++ b/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.ts @@ -325,6 +325,7 @@ export class DefaultProcessingDatabase implements ProcessingDatabase { // Keeps track of the entities that we end up inserting to update refresh_state_references afterwards const stateReferences = new Array(); + const conflictingStateReferences = new Array(); // Upsert all of the unprocessed entities into the refresh_state table, by // their entity ref. @@ -352,8 +353,8 @@ export class DefaultProcessingDatabase implements ProcessingDatabase { if (refreshResult === 0) { // In the event that we can't update an existing refresh state, we first try to insert a new row - const result = await tx('refresh_state') - .insert({ + try { + await tx('refresh_state').insert({ entity_id: uuid(), entity_ref: entityRef, unprocessed_entity: serializedEntity, @@ -361,14 +362,11 @@ export class DefaultProcessingDatabase implements ProcessingDatabase { location_key: locationKey, next_update_at: tx.fn.now(), last_discovery_at: tx.fn.now(), - }) - .onConflict('entity_ref') - .ignore(); - - // If the row can't be inserted, we have a conflict, but it could be either - // because of a conflicting locationKey or a race with another instance, so check for that too - if (result.length === 0) { - // Check for conflicting entity with same entityRef but different locationKey + }); + } catch (error) { + // If the row can't be inserted, we have a conflict, but it could be either + // because of a conflicting locationKey or a race with another instance, so check + // whether the conflicting entity has the same entityRef but a different locationKey const [conflictingEntity] = await tx( 'refresh_state', ) @@ -380,6 +378,7 @@ export class DefaultProcessingDatabase implements ProcessingDatabase { this.options.logger.warn( `Detected conflicting entityRef ${entityRef} already referenced by ${conflictingEntity.location_key} and now also ${locationKey}`, ); + conflictingStateReferences.push(entityRef); continue; } } @@ -392,7 +391,8 @@ export class DefaultProcessingDatabase implements ProcessingDatabase { // Replace all references for the originating entity or source and then create new ones if ('sourceKey' in options) { await tx('refresh_state_references') - .where({ source_key: options.sourceKey }) + .whereNotIn('target_entity_ref', conflictingStateReferences) + .andWhere({ source_key: options.sourceKey }) .delete(); await tx.batchInsert( 'refresh_state_references', @@ -404,7 +404,8 @@ export class DefaultProcessingDatabase implements ProcessingDatabase { ); } else { await tx('refresh_state_references') - .where({ source_entity_ref: options.sourceEntityRef }) + .whereNotIn('target_entity_ref', conflictingStateReferences) + .andWhere({ source_entity_ref: options.sourceEntityRef }) .delete(); await tx.batchInsert( 'refresh_state_references', From 698e823bbe171ac68b9b27c2d79ea9a03ee49d16 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Tue, 29 Jun 2021 16:58:09 +0200 Subject: [PATCH 049/204] catalog-backend: fix unprocessed entity conflict handling when using postgres Co-authored-by: blam Co-authored-by: Johan Haals Signed-off-by: Patrik Oldsberg --- .../database/DefaultProcessingDatabase.ts | 23 ++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.ts b/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.ts index 67b83bdb34..d18f194a57 100644 --- a/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.ts +++ b/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.ts @@ -354,7 +354,7 @@ export class DefaultProcessingDatabase implements ProcessingDatabase { if (refreshResult === 0) { // In the event that we can't update an existing refresh state, we first try to insert a new row try { - await tx('refresh_state').insert({ + let query = tx('refresh_state').insert({ entity_id: uuid(), entity_ref: entityRef, unprocessed_entity: serializedEntity, @@ -363,7 +363,28 @@ export class DefaultProcessingDatabase implements ProcessingDatabase { next_update_at: tx.fn.now(), last_discovery_at: tx.fn.now(), }); + + // TODO(Rugvip): only tested towards Postgres and SQLite + // We have to do this because the only way to detect if there was a conflict with + // SQLite is to catch the error, while Postgres needs to ignore the conflict to not + // break the ongoing transaction. + if (tx.client.config.client !== 'sqlite3') { + query = query.onConflict('entity_ref').ignore(); + } + + const result = await query; + if (result.rowCount === 0) { + throw new ConflictError( + 'Insert failed due to conflicting entity_ref', + ); + } } catch (error) { + if ( + !error.message.contains('UNIQUE constraint failed') && + error.name !== 'ConflictError' + ) { + throw error; + } // If the row can't be inserted, we have a conflict, but it could be either // because of a conflicting locationKey or a race with another instance, so check // whether the conflicting entity has the same entityRef but a different locationKey From a446bffdb2636e3ac56da33d7392b674b1e13c2f Mon Sep 17 00:00:00 2001 From: Philipp Hugenroth Date: Tue, 29 Jun 2021 17:10:53 +0200 Subject: [PATCH 050/204] Add changeset Signed-off-by: Philipp Hugenroth --- .changeset/beige-ladybugs-sip.md | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 .changeset/beige-ladybugs-sip.md diff --git a/.changeset/beige-ladybugs-sip.md b/.changeset/beige-ladybugs-sip.md new file mode 100644 index 0000000000..8587d3bb92 --- /dev/null +++ b/.changeset/beige-ladybugs-sip.md @@ -0,0 +1,7 @@ +--- +'example-app': patch +'@backstage/core': patch +'@backstage/core-components': patch +--- + +Improve UX of the Sidebar by adding SidebarScrollWrapper component allowing the user to scroll through Plugins & Shortcuts on smaller screens. Prevent the Sidebar from opening on click on small devices From 9c0f0dd3277ee0139ea6cb72c1949f3fe12ead8b Mon Sep 17 00:00:00 2001 From: Philipp Hugenroth Date: Tue, 29 Jun 2021 17:37:29 +0200 Subject: [PATCH 051/204] Remove unused import Signed-off-by: Philipp Hugenroth --- plugins/shortcuts/src/Shortcuts.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/plugins/shortcuts/src/Shortcuts.tsx b/plugins/shortcuts/src/Shortcuts.tsx index 86aa9565d3..69ab6a48ac 100644 --- a/plugins/shortcuts/src/Shortcuts.tsx +++ b/plugins/shortcuts/src/Shortcuts.tsx @@ -16,7 +16,6 @@ import React, { useMemo } from 'react'; import { useObservable } from 'react-use'; -import { makeStyles } from '@material-ui/core'; import PlayListAddIcon from '@material-ui/icons/PlaylistAdd'; import { ShortcutItem } from './ShortcutItem'; import { AddShortcut } from './AddShortcut'; From b74666f46c5db08942f07ce3fb3c6f13999bd703 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Tue, 29 Jun 2021 17:46:39 +0200 Subject: [PATCH 052/204] catalog-backend: couple of cleanups and fixes Signed-off-by: Patrik Oldsberg --- .../20210622104022_refresh_state_location_key.js | 2 -- .../src/next/DefaultLocationService.test.ts | 11 +++++++---- .../src/next/DefaultLocationService.ts | 1 - 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/plugins/catalog-backend/migrations/20210622104022_refresh_state_location_key.js b/plugins/catalog-backend/migrations/20210622104022_refresh_state_location_key.js index ca90bf9074..37ab5e12cb 100644 --- a/plugins/catalog-backend/migrations/20210622104022_refresh_state_location_key.js +++ b/plugins/catalog-backend/migrations/20210622104022_refresh_state_location_key.js @@ -27,7 +27,6 @@ exports.up = async function up(knex) { .comment( 'An opaque key that uniquely identifies the location of an entity in order to support conflict resolution', ); - // table.index(['location_key'], 'refresh_state_location_key_idx'); }); }; @@ -37,6 +36,5 @@ exports.up = async function up(knex) { exports.down = async function down(knex) { await knex.schema.alterTable('refresh_state', table => { table.dropColumn('location_key'); - // table.dropIndex([], 'refresh_state_location_key_idx'); }); }; diff --git a/plugins/catalog-backend/src/next/DefaultLocationService.test.ts b/plugins/catalog-backend/src/next/DefaultLocationService.test.ts index ae2c4e9a20..f965ec3077 100644 --- a/plugins/catalog-backend/src/next/DefaultLocationService.test.ts +++ b/plugins/catalog-backend/src/next/DefaultLocationService.test.ts @@ -48,11 +48,14 @@ describe('DefaultLocationServiceTest', () => { }, deferredEntities: [ { - apiVersion: 'backstage.io/v1alpha1', - kind: 'Component', - metadata: { - name: 'bar', + entity: { + apiVersion: 'backstage.io/v1alpha1', + kind: 'Component', + metadata: { + name: 'bar', + }, }, + locationKey: 'file:///tmp/mock.yaml', }, ], relations: [], diff --git a/plugins/catalog-backend/src/next/DefaultLocationService.ts b/plugins/catalog-backend/src/next/DefaultLocationService.ts index 70679a3bd6..2820ba14b1 100644 --- a/plugins/catalog-backend/src/next/DefaultLocationService.ts +++ b/plugins/catalog-backend/src/next/DefaultLocationService.ts @@ -92,7 +92,6 @@ export class DefaultLocationService implements LocationService { }); if (processed.ok) { - // todo unprocessedEntities.push(...processed.deferredEntities); entities.push(processed.completedEntity); } else { From 45af985df09a2972449f5014351cb8fb57bc7b9d Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Tue, 29 Jun 2021 20:24:58 +0200 Subject: [PATCH 053/204] changesets: add changeset for the location key changes Signed-off-by: Patrik Oldsberg --- .changeset/rude-windows-live.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 .changeset/rude-windows-live.md diff --git a/.changeset/rude-windows-live.md b/.changeset/rude-windows-live.md new file mode 100644 index 0000000000..b8f0e0e158 --- /dev/null +++ b/.changeset/rude-windows-live.md @@ -0,0 +1,17 @@ +--- +'@backstage/plugin-catalog-backend': minor +--- + +Handle entity name conflicts in a deterministic way and avoid crashes due to naming conflicts at startup. + +This is a breaking change for the database and entity provider interfaces of the new catalog. The interfaces with breaking changes are `EntityProvider` and `ProcessingDatabase`, and while it's unlikely that these interfaces have much usage yet, a migration guide is provided below. + +The breaking change to the `EntityProvider` interface lies within the items passed in the `EntityProviderMutation` type. Rather than passing along entities directly, they are now wrapped up in a `DeferredEntity` type, which is a tuple of an `entity` and a `locationKey`. The `entity` houses the entity as it was passed on before, while the `locationKey` is a new concept that is used for conflict resolution within the catalog. + +The `locationKey` is an opaque string that should be unique for each location that an entity could be located at, and undefined if the entity does not have a fixed location. In practice it should be set to the serialized location reference if the entity is stored in Git, for example `https://github.com/backstage/backstage/blob/master/catalog-info.yaml`. A conflict between two entity definitions happen when they have the same entity reference, i.e. kind, namespace, and name. In the event of a conflict the location key will be used according to the following rules to resolve the conflict: + +- If the entity is already present in the database but does not have a location key set, the new entity wins and will override the existing one. +- If the entity is already present in the database the new entity will only win if the location keys of the existing and new entity are the same. +- If the entity is not already present, insert the entity into the database along with the provided location key. + +The breaking change to the `ProcessingDatabase` is similar to the one for the entity provider, as it reflects the switch from `Entity` to `DeferredEntity` in the `ReplaceUnprocessedEntitiesOptions`. In addition, the `addUnprocessedEntities` method has been removed from the `ProcessingDatabase` interface, and the `RefreshStateItem` and `UpdateProcessedEntityOptions` types have received a new optional `locationKey` property. From 9eecbf40412656eb239e4d5732dff9d19edbd5ff Mon Sep 17 00:00:00 2001 From: Phil Kuang Date: Tue, 29 Jun 2021 16:54:53 -0400 Subject: [PATCH 054/204] chore(adopters): add FactSet Signed-off-by: Phil Kuang --- ADOPTERS.md | 1 + 1 file changed, 1 insertion(+) diff --git a/ADOPTERS.md b/ADOPTERS.md index 70a6cbc3f4..461b32853c 100644 --- a/ADOPTERS.md +++ b/ADOPTERS.md @@ -34,3 +34,4 @@ | [FundApps](https://www.fundapps.co/) | [Elliot Greenwood](https://github.com/egnwd) | Developer Portal - A place for us to keep track of our projects and documentation for all services and processes | | [DAZN](https://dazn.com/) | [Lou Bichard](https://twitter.com/loujaybee), [Marco Crivellaro](https://github.com/crivetechie), [Alex Hollerith](mailto:alex.hollerith@dazn.com) | Ingesting all of DAZN's repos for the catalog, migrating our internal platform apps (pull request boards, release information, inner source marketplace etc) to Backstage plugins (where applicable). | | [HelloFresh](https://www.hellofresh.de/) | [@iammuho](https://github.com/iammuho), [@ElenaForester](https://github.com/ElenaForester), [@diegomarangoni](https://github.com/diegomarangoni) | Our developer portal at HelloFresh - Spread across an organisation of 500+ engineers globally. | +| [FactSet](https://www.factset.com/) | [@kuangp](https://github.com/kuangp) | Developer portal to provide discoverability to all internal components, APIs, documentation, and scaffold templates with integrations to our internal infrastructure tools. | From c991df871f8b24544f82a58160746f90a4f6ce04 Mon Sep 17 00:00:00 2001 From: "roylisto.pradana" Date: Wed, 30 Jun 2021 10:27:16 +0700 Subject: [PATCH 055/204] use GroupEntity as casting to catalogItem Signed-off-by: roylisto.pradana --- .../components/GroupsExplorerContent/GroupsDiagram.tsx | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/plugins/explore/src/components/GroupsExplorerContent/GroupsDiagram.tsx b/plugins/explore/src/components/GroupsExplorerContent/GroupsDiagram.tsx index 32931e8f3a..28de4e4661 100644 --- a/plugins/explore/src/components/GroupsExplorerContent/GroupsDiagram.tsx +++ b/plugins/explore/src/components/GroupsExplorerContent/GroupsDiagram.tsx @@ -18,6 +18,7 @@ import { RELATION_CHILD_OF, stringifyEntityRef, parseEntityRef, + GroupEntity, } from '@backstage/catalog-model'; import { catalogApiRef, @@ -96,7 +97,7 @@ function RenderNode(props: DependencyGraphTypes.RenderNodeProps) { alignmentBaseline="baseline" style={{ fontWeight: 'bold' }} > - {props.node.profile?.displayName ?? props.node.name} + {props.node.name} @@ -146,8 +147,9 @@ export function GroupsDiagram() { nodes.push({ id: stringifyEntityRef(catalogItem), kind: catalogItem.kind, - name: formatEntityRefTitle(catalogItem, { defaultKind: 'Group' }), - profile: catalogItem.spec?.profile, + name: + (catalogItem as GroupEntity).spec?.profile?.displayName || + formatEntityRefTitle(catalogItem, { defaultKind: 'Group' }), }); // Edge to parent From fb26a1946bfe526012534ca58d13e6629728c652 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 30 Jun 2021 04:12:50 +0000 Subject: [PATCH 056/204] chore(deps): bump json5 from 2.1.3 to 2.2.0 Bumps [json5](https://github.com/json5/json5) from 2.1.3 to 2.2.0. - [Release notes](https://github.com/json5/json5/releases) - [Changelog](https://github.com/json5/json5/blob/master/CHANGELOG.md) - [Commits](https://github.com/json5/json5/compare/v2.1.3...v2.2.0) --- updated-dependencies: - dependency-name: json5 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 6ff8fa8115..8c663ab35c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -16925,9 +16925,9 @@ json5@^1.0.1: minimist "^1.2.0" json5@^2.1.1, json5@^2.1.2, json5@^2.1.3: - version "2.1.3" - resolved "https://registry.npmjs.org/json5/-/json5-2.1.3.tgz#c9b0f7fa9233bfe5807fe66fcf3a5617ed597d43" - integrity sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA== + version "2.2.0" + resolved "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz#2dfefe720c6ba525d9ebd909950f0515316c89a3" + integrity sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA== dependencies: minimist "^1.2.5" From 8939f9ee17261f65aa4bb8a878bf7c07c076fff2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 30 Jun 2021 04:20:38 +0000 Subject: [PATCH 057/204] chore(deps): bump ts-node from 9.1.1 to 10.0.0 Bumps [ts-node](https://github.com/TypeStrong/ts-node) from 9.1.1 to 10.0.0. - [Release notes](https://github.com/TypeStrong/ts-node/releases) - [Commits](https://github.com/TypeStrong/ts-node/compare/v9.1.1...v10.0.0) --- updated-dependencies: - dependency-name: ts-node dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- packages/cli/package.json | 2 +- packages/codemods/package.json | 2 +- packages/create-app/package.json | 2 +- packages/docgen/package.json | 2 +- packages/e2e-test/package.json | 2 +- plugins/catalog-graphql/package.json | 2 +- yarn.lock | 36 ++++++++++++++++++++++++++++ 7 files changed, 42 insertions(+), 6 deletions(-) diff --git a/packages/cli/package.json b/packages/cli/package.json index 73277036c3..9f3fb09ed0 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -146,7 +146,7 @@ "del": "^6.0.0", "mock-fs": "^4.13.0", "nodemon": "^2.0.2", - "ts-node": "^9.1.1" + "ts-node": "^10.0.0" }, "files": [ "asset-types", diff --git a/packages/codemods/package.json b/packages/codemods/package.json index d9ea7fb1b7..d4b0c18e6c 100644 --- a/packages/codemods/package.json +++ b/packages/codemods/package.json @@ -43,7 +43,7 @@ "@types/jscodeshift": "^0.11.0", "@types/node": "^14.14.32", "commander": "^6.1.0", - "ts-node": "^9.1.1" + "ts-node": "^10.0.0" }, "nodemonConfig": { "watch": "./src", diff --git a/packages/create-app/package.json b/packages/create-app/package.json index d21563dad5..968d927d3d 100644 --- a/packages/create-app/package.json +++ b/packages/create-app/package.json @@ -41,7 +41,7 @@ "@types/inquirer": "^7.3.1", "@types/react-dev-utils": "^9.0.4", "@types/recursive-readdir": "^2.2.0", - "ts-node": "^9.1.1" + "ts-node": "^10.0.0" }, "peerDependencies": { "@backstage/backend-common": "*", diff --git a/packages/docgen/package.json b/packages/docgen/package.json index a7d7615e19..6ee4419349 100644 --- a/packages/docgen/package.json +++ b/packages/docgen/package.json @@ -30,7 +30,7 @@ "commander": "^6.1.0", "fs-extra": "^9.0.0", "github-slugger": "^1.3.0", - "ts-node": "^9.1.1", + "ts-node": "^10.0.0", "typescript": "^4.0.3" }, "devDependencies": { diff --git a/packages/e2e-test/package.json b/packages/e2e-test/package.json index 77a3e3960a..304da9816b 100644 --- a/packages/e2e-test/package.json +++ b/packages/e2e-test/package.json @@ -34,7 +34,7 @@ "handlebars": "^4.7.3", "pgtools": "^0.3.0", "tree-kill": "^1.2.2", - "ts-node": "^9.1.1", + "ts-node": "^10.0.0", "zombie": "^6.1.4" }, "nodemonConfig": { diff --git a/plugins/catalog-graphql/package.json b/plugins/catalog-graphql/package.json index 4e30d2d218..d14ae5df42 100644 --- a/plugins/catalog-graphql/package.json +++ b/plugins/catalog-graphql/package.json @@ -52,7 +52,7 @@ "eslint-plugin-graphql": "^4.0.0", "msw": "^0.29.0", "supertest": "^6.1.3", - "ts-node": "^9.1.1" + "ts-node": "^10.0.0" }, "files": [ "dist" diff --git a/yarn.lock b/yarn.lock index 6ff8fa8115..2d416033b9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5436,6 +5436,26 @@ resolved "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz#ccb91445360179a04e7fe6aff78c00ffc1eeaf82" integrity sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw== +"@tsconfig/node10@^1.0.7": + version "1.0.8" + resolved "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.8.tgz#c1e4e80d6f964fbecb3359c43bd48b40f7cadad9" + integrity sha512-6XFfSQmMgq0CFLY1MslA/CPUfhIL919M1rMsa5lP2P097N2Wd1sSX0tx1u4olM16fLNhtHZpRhedZJphNJqmZg== + +"@tsconfig/node12@^1.0.7": + version "1.0.9" + resolved "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.9.tgz#62c1f6dee2ebd9aead80dc3afa56810e58e1a04c" + integrity sha512-/yBMcem+fbvhSREH+s14YJi18sp7J9jpuhYByADT2rypfajMZZN4WQ6zBGgBKp53NKmqI36wFYDb3yaMPurITw== + +"@tsconfig/node14@^1.0.0": + version "1.0.1" + resolved "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.1.tgz#95f2d167ffb9b8d2068b0b235302fafd4df711f2" + integrity sha512-509r2+yARFfHHE7T6Puu2jjkoycftovhXRqW328PDXTVGKihlb1P8Z9mMZH04ebyajfRY7dedfGynlrFHJUQCg== + +"@tsconfig/node16@^1.0.1": + version "1.0.1" + resolved "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.1.tgz#a6ca6a9a0ff366af433f42f5f0e124794ff6b8f1" + integrity sha512-FTgBI767POY/lKNDNbIzgAX6miIDBs6NTCbdlDb8TrWovHsSvaVIZDlTqym29C6UqhzwcJx4CYr+AlrMywA0cA== + "@types/accepts@*", "@types/accepts@^1.3.5": version "1.3.5" resolved "https://registry.npmjs.org/@types/accepts/-/accepts-1.3.5.tgz#c34bec115cfc746e04fe5a059df4ce7e7b391575" @@ -25519,6 +25539,22 @@ ts-log@^2.2.3: resolved "https://registry.npmjs.org/ts-log/-/ts-log-2.2.3.tgz#4da5640fe25a9fb52642cd32391c886721318efb" integrity sha512-XvB+OdKSJ708Dmf9ore4Uf/q62AYDTzFcAdxc8KNML1mmAWywRFVt/dn1KYJH8Agt5UJNujfM3znU5PxgAzA2w== +ts-node@^10.0.0: + version "10.0.0" + resolved "https://registry.npmjs.org/ts-node/-/ts-node-10.0.0.tgz#05f10b9a716b0b624129ad44f0ea05dac84ba3be" + integrity sha512-ROWeOIUvfFbPZkoDis0L/55Fk+6gFQNZwwKPLinacRl6tsxstTF1DbAcLKkovwnpKMVvOMHP1TIbnwXwtLg1gg== + dependencies: + "@tsconfig/node10" "^1.0.7" + "@tsconfig/node12" "^1.0.7" + "@tsconfig/node14" "^1.0.0" + "@tsconfig/node16" "^1.0.1" + arg "^4.1.0" + create-require "^1.1.0" + diff "^4.0.1" + make-error "^1.1.1" + source-map-support "^0.5.17" + yn "3.1.1" + ts-node@^9, ts-node@^9.1.1: version "9.1.1" resolved "https://registry.npmjs.org/ts-node/-/ts-node-9.1.1.tgz#51a9a450a3e959401bda5f004a72d54b936d376d" From c7cf94a239d8dbc1411af58072ae60862bdd7de7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 30 Jun 2021 04:24:43 +0000 Subject: [PATCH 058/204] chore(deps): bump ora from 5.4.0 to 5.4.1 Bumps [ora](https://github.com/sindresorhus/ora) from 5.4.0 to 5.4.1. - [Release notes](https://github.com/sindresorhus/ora/releases) - [Commits](https://github.com/sindresorhus/ora/compare/v5.4.0...v5.4.1) --- updated-dependencies: - dependency-name: ora dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 6ff8fa8115..9543a4ccd2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -19802,9 +19802,9 @@ optionator@^0.9.1: word-wrap "^1.2.3" ora@^5.3.0: - version "5.4.0" - resolved "https://registry.npmjs.org/ora/-/ora-5.4.0.tgz#42eda4855835b9cd14d33864c97a3c95a3f56bf4" - integrity sha512-1StwyXQGoU6gdjYkyVcqOLnVlbKj+6yPNNOxJVgpt9t4eksKjiriiHuxktLYkgllwk+D6MbC4ihH84L1udRXPg== + version "5.4.1" + resolved "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz#1b2678426af4ac4a509008e5e4ac9e9959db9e18" + integrity sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ== dependencies: bl "^4.1.0" chalk "^4.1.0" From a94587cad4d0f9d342a4b3601220dcacf4b7c13e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 30 Jun 2021 04:09:55 +0000 Subject: [PATCH 059/204] chore(deps): bump use-immer from 0.5.1 to 0.6.0 Bumps [use-immer](https://github.com/mweststrate/use-immer) from 0.5.1 to 0.6.0. - [Release notes](https://github.com/mweststrate/use-immer/releases) - [Changelog](https://github.com/immerjs/use-immer/blob/master/CHANGELOG.md) - [Commits](https://github.com/mweststrate/use-immer/compare/v0.5.1...v0.6.0) --- updated-dependencies: - dependency-name: use-immer dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .changeset/tasty-timers-grin.md | 5 +++++ plugins/scaffolder/package.json | 2 +- yarn.lock | 8 ++++---- 3 files changed, 10 insertions(+), 5 deletions(-) create mode 100644 .changeset/tasty-timers-grin.md diff --git a/.changeset/tasty-timers-grin.md b/.changeset/tasty-timers-grin.md new file mode 100644 index 0000000000..b2195d691d --- /dev/null +++ b/.changeset/tasty-timers-grin.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder': patch +--- + +Update dependencies diff --git a/plugins/scaffolder/package.json b/plugins/scaffolder/package.json index 6e2827cbe5..c14466359d 100644 --- a/plugins/scaffolder/package.json +++ b/plugins/scaffolder/package.json @@ -58,7 +58,7 @@ "react-router": "6.0.0-beta.0", "react-router-dom": "6.0.0-beta.0", "react-use": "^17.2.4", - "use-immer": "^0.5.1", + "use-immer": "^0.6.0", "zen-observable": "^0.8.15" }, "devDependencies": { diff --git a/yarn.lock b/yarn.lock index 6ff8fa8115..e74d310918 100644 --- a/yarn.lock +++ b/yarn.lock @@ -26125,10 +26125,10 @@ use-composed-ref@^1.0.0: dependencies: ts-essentials "^2.0.3" -use-immer@^0.5.1: - version "0.5.1" - resolved "https://registry.npmjs.org/use-immer/-/use-immer-0.5.1.tgz#3862ebbb194ebfe66b8eb221082c2fb2585f8fe1" - integrity sha512-Orb7PokM+jiLQfA1oJ3B3P7Guq0c2IxUHHmBpLeEMnJiz4ZOMlj9mkqq6D7iXJsnurRX0EOB134annf3RjEWHw== +use-immer@^0.6.0: + version "0.6.0" + resolved "https://registry.npmjs.org/use-immer/-/use-immer-0.6.0.tgz#ca6aa5ade93018e2c65cf128d19ada54fc23f70d" + integrity sha512-dFGRfvWCqPDTOt/S431ETYTg6+uxbpb7A1pptufwXVzGJY3RlXr38+3wyLNpc6SbbmAKjWl6+EP6uW74fkEsXQ== use-isomorphic-layout-effect@^1.0.0: version "1.0.0" From 3fb229ec6339572ea0f11a529142224b445ceb7e Mon Sep 17 00:00:00 2001 From: "roylisto.pradana" Date: Wed, 30 Jun 2021 15:25:16 +0700 Subject: [PATCH 060/204] Remove profile var Signed-off-by: roylisto.pradana --- .../src/components/GroupsExplorerContent/GroupsDiagram.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/plugins/explore/src/components/GroupsExplorerContent/GroupsDiagram.tsx b/plugins/explore/src/components/GroupsExplorerContent/GroupsDiagram.tsx index 28de4e4661..ce09f0d268 100644 --- a/plugins/explore/src/components/GroupsExplorerContent/GroupsDiagram.tsx +++ b/plugins/explore/src/components/GroupsExplorerContent/GroupsDiagram.tsx @@ -112,7 +112,6 @@ export function GroupsDiagram() { id: string; kind: string; name: string; - profile?: any; }>(); const edges = new Array<{ from: string; to: string; label: string }>(); From 27e90f969d990013f0615ac90113aea35b8060d3 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Wed, 30 Jun 2021 10:53:01 +0200 Subject: [PATCH 061/204] catalob-backend: more test fixes Signed-off-by: Patrik Oldsberg --- .../next/ConfigLocationEntityProvider.test.ts | 38 +++++++++++------- .../src/next/DefaultLocationStore.test.ts | 40 +++++++++++-------- .../database/DefaultProcessingDatabase.ts | 2 +- 3 files changed, 48 insertions(+), 32 deletions(-) diff --git a/plugins/catalog-backend/src/next/ConfigLocationEntityProvider.test.ts b/plugins/catalog-backend/src/next/ConfigLocationEntityProvider.test.ts index 37d549c7f2..7592182bad 100644 --- a/plugins/catalog-backend/src/next/ConfigLocationEntityProvider.test.ts +++ b/plugins/catalog-backend/src/next/ConfigLocationEntityProvider.test.ts @@ -41,26 +41,34 @@ describe('ConfigLocationEntityProvider', () => { expect(mockConnection.applyMutation).toHaveBeenCalledWith({ type: 'full', entities: expect.arrayContaining([ - expect.objectContaining({ - spec: { - target: path.join( - resolvePackagePath('@backstage/plugin-catalog-backend'), - './lols.yaml', - ), - type: 'file', - }, - }), + { + entity: expect.objectContaining({ + spec: { + target: path.join( + resolvePackagePath('@backstage/plugin-catalog-backend'), + './lols.yaml', + ), + type: 'file', + }, + }), + locationKey: expect.stringMatching( + /plugins\/catalog-backend\/lols\.yaml$/, + ), + }, ]), }); expect(mockConnection.applyMutation).toHaveBeenCalledWith({ type: 'full', entities: expect.arrayContaining([ - expect.objectContaining({ - spec: { - target: 'https://github.com/backstage/backstage', - type: 'url', - }, - }), + { + entity: expect.objectContaining({ + spec: { + target: 'https://github.com/backstage/backstage', + type: 'url', + }, + }), + locationKey: 'url:https://github.com/backstage/backstage', + }, ]), }); }); diff --git a/plugins/catalog-backend/src/next/DefaultLocationStore.test.ts b/plugins/catalog-backend/src/next/DefaultLocationStore.test.ts index 762a585754..82b08f2e70 100644 --- a/plugins/catalog-backend/src/next/DefaultLocationStore.test.ts +++ b/plugins/catalog-backend/src/next/DefaultLocationStore.test.ts @@ -113,13 +113,17 @@ describe('DefaultLocationStore', () => { type: 'delta', removed: [], added: expect.arrayContaining([ - expect.objectContaining({ - spec: { - target: - 'https://github.com/backstage/demo/blob/master/catalog-info.yml', - type: 'url', - }, - }), + { + entity: expect.objectContaining({ + spec: { + target: + 'https://github.com/backstage/demo/blob/master/catalog-info.yml', + type: 'url', + }, + }), + locationKey: + 'url:https://github.com/backstage/demo/blob/master/catalog-info.yml', + }, ]), }); }, @@ -156,15 +160,19 @@ describe('DefaultLocationStore', () => { expect(connection.applyMutation).toHaveBeenCalledWith({ type: 'delta', added: [], - removed: expect.arrayContaining([ - expect.objectContaining({ - spec: { - target: - 'https://github.com/backstage/demo/blob/master/catalog-info.yml', - type: 'url', - }, - }), - ]), + removed: [ + { + entity: expect.objectContaining({ + spec: { + target: + 'https://github.com/backstage/demo/blob/master/catalog-info.yml', + type: 'url', + }, + }), + locationKey: + 'url:https://github.com/backstage/demo/blob/master/catalog-info.yml', + }, + ], }); }, 60_000, diff --git a/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.ts b/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.ts index d18f194a57..53025682ac 100644 --- a/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.ts +++ b/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.ts @@ -380,7 +380,7 @@ export class DefaultProcessingDatabase implements ProcessingDatabase { } } catch (error) { if ( - !error.message.contains('UNIQUE constraint failed') && + !error.message.includes('UNIQUE constraint failed') && error.name !== 'ConflictError' ) { throw error; From c2db794f5a0105ac6e9fc30b2802d33fda9d6feb Mon Sep 17 00:00:00 2001 From: shoukoo Date: Wed, 30 Jun 2021 19:38:58 +1000 Subject: [PATCH 062/204] feat: add default branch prop for publish:github Signed-off-by: shoukoo --- .changeset/violet-maps-smell.md | 6 ++ packages/backend-common/api-report.md | 3 +- packages/backend-common/src/scm/git.test.ts | 4 +- packages/backend-common/src/scm/git.ts | 9 ++- .../actions/builtin/publish/github.test.ts | 60 +++++++++++++++++++ .../actions/builtin/publish/github.ts | 11 +++- .../src/scaffolder/stages/publish/helpers.ts | 7 ++- 7 files changed, 95 insertions(+), 5 deletions(-) create mode 100644 .changeset/violet-maps-smell.md diff --git a/.changeset/violet-maps-smell.md b/.changeset/violet-maps-smell.md new file mode 100644 index 0000000000..fdb4c6b46d --- /dev/null +++ b/.changeset/violet-maps-smell.md @@ -0,0 +1,6 @@ +--- +'@backstage/backend-common': patch +'@backstage/plugin-scaffolder-backend': patch +--- + +add defaultBranch property for publish GitHub action diff --git a/packages/backend-common/api-report.md b/packages/backend-common/api-report.md index fcddb8dda5..7534f8826f 100644 --- a/packages/backend-common/api-report.md +++ b/packages/backend-common/api-report.md @@ -183,8 +183,9 @@ export class Git { logger?: Logger | undefined; }) => Git; // (undocumented) - init({ dir }: { + init({ dir, defaultBranch, }: { dir: string; + defaultBranch?: string; }): Promise; // (undocumented) merge({ dir, theirs, ours, author, committer, }: { diff --git a/packages/backend-common/src/scm/git.test.ts b/packages/backend-common/src/scm/git.test.ts index af9dfeef1b..0b70edc45d 100644 --- a/packages/backend-common/src/scm/git.test.ts +++ b/packages/backend-common/src/scm/git.test.ts @@ -201,14 +201,16 @@ describe('Git', () => { describe('init', () => { it('should call isomorphic-git with the correct arguments', async () => { const dir = '/some/mock/dir'; + const defaultBranch = 'master'; const git = Git.fromAuth({}); - await git.init({ dir }); + await git.init({ dir, defaultBranch }); expect(isomorphic.init).toHaveBeenCalledWith({ fs, dir, + defaultBranch, }); }); }); diff --git a/packages/backend-common/src/scm/git.ts b/packages/backend-common/src/scm/git.ts index 3afa551d5f..e786c279a1 100644 --- a/packages/backend-common/src/scm/git.ts +++ b/packages/backend-common/src/scm/git.ts @@ -150,12 +150,19 @@ export class Git { }); } - async init({ dir }: { dir: string }): Promise { + async init({ + dir, + defaultBranch = 'master', + }: { + dir: string; + defaultBranch?: string; + }): Promise { this.config.logger?.info(`Init git repository {dir=${dir}}`); return git.init({ fs, dir, + defaultBranch, }); } diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/github.test.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/github.test.ts index 716fa704e9..910fa27b46 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/github.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/github.test.ts @@ -175,6 +175,36 @@ describe('publish:github', () => { expect(initRepoAndPush).toHaveBeenCalledWith({ dir: mockContext.workspacePath, remoteUrl: 'https://github.com/clone/url.git', + defaultBranch: 'master', + auth: { username: 'x-access-token', password: 'tokenlols' }, + logger: mockContext.logger, + }); + }); + + it('should call initRepoAndPush with the correct defaultBranch main', async () => { + mockGithubClient.users.getByUsername.mockResolvedValue({ + data: { type: 'User' }, + }); + + mockGithubClient.repos.createForAuthenticatedUser.mockResolvedValue({ + data: { + clone_url: 'https://github.com/clone/url.git', + html_url: 'https://github.com/html/url', + }, + }); + + await action.handler({ + ...mockContext, + input: { + ...mockContext.input, + defaultBranch: 'main', + }, + }); + + expect(initRepoAndPush).toHaveBeenCalledWith({ + dir: mockContext.workspacePath, + remoteUrl: 'https://github.com/clone/url.git', + defaultBranch: 'main', auth: { username: 'x-access-token', password: 'tokenlols' }, logger: mockContext.logger, }); @@ -430,4 +460,34 @@ describe('publish:github', () => { 'https://github.com/html/url/blob/master', ); }); + + it('should use main as default branch', async () => { + mockGithubClient.users.getByUsername.mockResolvedValue({ + data: { type: 'User' }, + }); + + mockGithubClient.repos.createForAuthenticatedUser.mockResolvedValue({ + data: { + clone_url: 'https://github.com/clone/url.git', + html_url: 'https://github.com/html/url', + }, + }); + + await action.handler({ + ...mockContext, + input: { + ...mockContext.input, + defaultBranch: 'main', + }, + }); + + expect(mockContext.output).toHaveBeenCalledWith( + 'remoteUrl', + 'https://github.com/clone/url.git', + ); + expect(mockContext.output).toHaveBeenCalledWith( + 'repoContentsUrl', + 'https://github.com/html/url/blob/main', + ); + }); }); diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/github.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/github.ts index 48d59024eb..856197a808 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/github.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/github.ts @@ -45,6 +45,7 @@ export function createPublishGithubAction(options: { repoUrl: string; description?: string; access?: string; + defaultBranch?: string; sourcePath?: string; repoVisibility: 'private' | 'internal' | 'public'; collaborators: Collaborator[]; @@ -77,6 +78,11 @@ export function createPublishGithubAction(options: { type: 'string', enum: ['private', 'public', 'internal'], }, + defaultBranch: { + title: 'Default Branch', + type: 'string', + description: `Sets the default branch on the repository. The default value is 'master'`, + }, sourcePath: { title: 'Path within the workspace that will be used as the repository root. If omitted, the entire workspace will be published as the repository.', @@ -131,6 +137,7 @@ export function createPublishGithubAction(options: { description, access, repoVisibility = 'private', + defaultBranch = 'master', collaborators, topics, } = ctx.input; @@ -239,11 +246,12 @@ export function createPublishGithubAction(options: { } const remoteUrl = newRepo.clone_url; - const repoContentsUrl = `${newRepo.html_url}/blob/master`; + const repoContentsUrl = `${newRepo.html_url}/blob/${defaultBranch}`; await initRepoAndPush({ dir: getRepoSourceDirectory(ctx.workspacePath, ctx.input.sourcePath), remoteUrl, + defaultBranch, auth: { username: 'x-access-token', password: token, @@ -257,6 +265,7 @@ export function createPublishGithubAction(options: { client, repoName: newRepo.name, logger: ctx.logger, + defaultBranch, }); } catch (e) { throw new Error( diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/publish/helpers.ts b/plugins/scaffolder-backend/src/scaffolder/stages/publish/helpers.ts index 6eebb4692a..dff0feb5f2 100644 --- a/plugins/scaffolder-backend/src/scaffolder/stages/publish/helpers.ts +++ b/plugins/scaffolder-backend/src/scaffolder/stages/publish/helpers.ts @@ -24,11 +24,13 @@ export async function initRepoAndPush({ remoteUrl, auth, logger, + defaultBranch = 'master', }: { dir: string; remoteUrl: string; auth: { username: string; password: string }; logger: Logger; + defaultBranch?: string; }): Promise { const git = Git.fromAuth({ username: auth.username, @@ -38,6 +40,7 @@ export async function initRepoAndPush({ await git.init({ dir, + defaultBranch, }); const paths = await globby(['./**', './**/.*', '!.git'], { @@ -74,6 +77,7 @@ type BranchProtectionOptions = { owner: string; repoName: string; logger: Logger; + defaultBranch?: string; }; export const enableBranchProtectionOnDefaultRepoBranch = async ({ @@ -81,6 +85,7 @@ export const enableBranchProtectionOnDefaultRepoBranch = async ({ client, owner, logger, + defaultBranch = 'master', }: BranchProtectionOptions): Promise => { const tryOnce = async () => { try { @@ -97,7 +102,7 @@ export const enableBranchProtectionOnDefaultRepoBranch = async ({ }, owner, repo: repoName, - branch: 'master', + branch: defaultBranch, required_status_checks: { strict: true, contexts: [] }, restrictions: null, enforce_admins: true, From 65faa89574a46f3eb2ad277bf251ba6ee0ee2e4d Mon Sep 17 00:00:00 2001 From: irma12 Date: Wed, 30 Jun 2021 10:04:50 +0200 Subject: [PATCH 063/204] Update plugin versions Signed-off-by: irma12 --- .changeset/two-badgers-sit.md | 5 + packages/app/package.json | 8 +- yarn.lock | 222 +++++++++++++--------------------- 3 files changed, 94 insertions(+), 141 deletions(-) create mode 100644 .changeset/two-badgers-sit.md diff --git a/.changeset/two-badgers-sit.md b/.changeset/two-badgers-sit.md new file mode 100644 index 0000000000..a23ced389b --- /dev/null +++ b/.changeset/two-badgers-sit.md @@ -0,0 +1,5 @@ +--- +'example-app': patch +--- + +Bump roadie plugins versions diff --git a/packages/app/package.json b/packages/app/package.json index d239615b64..448dbb4e9a 100644 --- a/packages/app/package.json +++ b/packages/app/package.json @@ -43,10 +43,10 @@ "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", "@octokit/rest": "^18.5.3", - "@roadiehq/backstage-plugin-buildkite": "^1.0.3", - "@roadiehq/backstage-plugin-github-insights": "^1.1.11", - "@roadiehq/backstage-plugin-github-pull-requests": "^1.0.5", - "@roadiehq/backstage-plugin-travis-ci": "^1.0.0", + "@roadiehq/backstage-plugin-buildkite": "^1.0.4", + "@roadiehq/backstage-plugin-github-insights": "^1.1.15", + "@roadiehq/backstage-plugin-github-pull-requests": "^1.0.8", + "@roadiehq/backstage-plugin-travis-ci": "^1.0.4", "history": "^5.0.0", "prop-types": "^15.7.2", "react": "^16.12.0", diff --git a/yarn.lock b/yarn.lock index c2367f2aea..fdc4576492 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1360,32 +1360,6 @@ "@babel/helper-validator-identifier" "^7.14.0" to-fast-properties "^2.0.0" -"@backstage/catalog-model@^0.7.4": - version "0.8.4" - dependencies: - "@backstage/config" "^0.1.5" - "@backstage/errors" "^0.1.1" - "@types/json-schema" "^7.0.5" - "@types/yup" "^0.29.8" - ajv "^7.0.3" - json-schema "^0.3.0" - lodash "^4.17.15" - uuid "^8.0.0" - yup "^0.29.3" - -"@backstage/catalog-model@^0.7.9": - version "0.8.4" - dependencies: - "@backstage/config" "^0.1.5" - "@backstage/errors" "^0.1.1" - "@types/json-schema" "^7.0.5" - "@types/yup" "^0.29.8" - ajv "^7.0.3" - json-schema "^0.3.0" - lodash "^4.17.15" - uuid "^8.0.0" - yup "^0.29.3" - "@backstage/core-api@^0.2.23": version "0.2.23" resolved "https://registry.npmjs.org/@backstage/core-api/-/core-api-0.2.23.tgz#c0ec13407ff7c78d376eb18e9d8e1490d54d995b" @@ -1404,7 +1378,7 @@ react-use "^17.2.4" zen-observable "^0.8.15" -"@backstage/core@*", "@backstage/core@^0.7.11", "@backstage/core@^0.7.3", "@backstage/core@^0.7.9": +"@backstage/core@*": version "0.7.14" resolved "https://registry.npmjs.org/@backstage/core/-/core-0.7.14.tgz#863844fe40bb6a29bcc2d297e42055633b0e886f" integrity sha512-W7EMspBXrp1GPALK6+qdJjsvkqcaYGFyoh8/bRAXABIkJpGQGiy4xUZUKDoMhd+OdVHv/mzyyv3fH2yc32J07w== @@ -1450,48 +1424,6 @@ remark-gfm "^1.0.0" zen-observable "^0.8.15" -"@backstage/plugin-catalog-react@^0.1.4": - version "0.1.6" - resolved "https://registry.npmjs.org/@backstage/plugin-catalog-react/-/plugin-catalog-react-0.1.6.tgz#1d72756cce22b880987c30ac27e23af8efa22843" - integrity sha512-/60GIrcFfyAiKn3bylXegwtHf1NQxQa4PcXD7nSIB5ISCuot2mkI32LMjciEvNHR7efGA5Yv6yWelFSFdvbcKQ== - dependencies: - "@backstage/catalog-client" "^0.3.11" - "@backstage/catalog-model" "^0.7.9" - "@backstage/core" "^0.7.9" - "@material-ui/core" "^4.11.0" - "@types/react" "^16.9" - lodash "^4.17.15" - react "^16.13.1" - react-router "6.0.0-beta.0" - react-router-dom "6.0.0-beta.0" - react-use "^17.2.4" - -"@backstage/plugin-catalog@^0.5.1": - version "0.6.4" - dependencies: - "@backstage/catalog-client" "^0.3.14" - "@backstage/catalog-model" "^0.8.4" - "@backstage/core-components" "^0.1.3" - "@backstage/core-plugin-api" "^0.1.3" - "@backstage/errors" "^0.1.1" - "@backstage/integration" "^0.5.6" - "@backstage/integration-react" "^0.1.4" - "@backstage/plugin-catalog-react" "^0.2.4" - "@backstage/theme" "^0.2.8" - "@material-ui/core" "^4.11.0" - "@material-ui/icons" "^4.9.1" - "@material-ui/lab" "4.0.0-alpha.45" - "@types/react" "^16.9" - classnames "^2.2.6" - git-url-parse "^11.4.4" - lodash "^4.17.21" - react "^16.13.1" - react-dom "^16.13.1" - react-helmet "6.1.0" - react-router "6.0.0-beta.0" - react-router-dom "6.0.0-beta.0" - react-use "^17.2.4" - "@bcoe/v8-coverage@^0.2.3": version "0.2.3" resolved "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" @@ -3491,7 +3423,7 @@ resolved "https://registry.npmjs.org/@material-icons/font/-/font-1.0.3.tgz#f722e5a69a03f20ef47d015cb69420bebeeaabe5" integrity sha512-aIRd0Z9b/HJ/O24KOaP7dNsXypMnXhpWrpLVYvQB/JesVqXYSbioYND200sR+C14a0LSCp+qWnWCnSXmN1hWGw== -"@material-ui/core@^4.11.0", "@material-ui/core@^4.9.1": +"@material-ui/core@^4.11.0": version "4.11.3" resolved "https://registry.npmjs.org/@material-ui/core/-/core-4.11.3.tgz#f22e41775b0bd075e36a7a093d43951bf7f63850" integrity sha512-Adt40rGW6Uds+cAyk3pVgcErpzU/qxc7KBR94jFHBYretU4AtWZltYcNsbeMn9tXL86jjVL1kuGcIHsgLgFGRw== @@ -3509,7 +3441,25 @@ react-is "^16.8.0 || ^17.0.0" react-transition-group "^4.4.0" -"@material-ui/icons@^4.9.1": +"@material-ui/core@^4.11.3": + version "4.11.4" + resolved "https://registry.npmjs.org/@material-ui/core/-/core-4.11.4.tgz#4fb9fe5dec5dcf780b687e3a40cff78b2b9640a4" + integrity sha512-oqb+lJ2Dl9HXI9orc6/aN8ZIAMkeThufA5iZELf2LQeBn2NtjVilF5D2w7e9RpntAzDb4jK5DsVhkfOvFY/8fg== + dependencies: + "@babel/runtime" "^7.4.4" + "@material-ui/styles" "^4.11.4" + "@material-ui/system" "^4.11.3" + "@material-ui/types" "5.1.0" + "@material-ui/utils" "^4.11.2" + "@types/react-transition-group" "^4.2.0" + clsx "^1.0.4" + hoist-non-react-statics "^3.3.2" + popper.js "1.16.1-lts" + prop-types "^15.7.2" + react-is "^16.8.0 || ^17.0.0" + react-transition-group "^4.4.0" + +"@material-ui/icons@^4.11.2", "@material-ui/icons@^4.9.1": version "4.11.2" resolved "https://registry.npmjs.org/@material-ui/icons/-/icons-4.11.2.tgz#b3a7353266519cd743b6461ae9fdfcb1b25eb4c5" integrity sha512-fQNsKX2TxBmqIGJCSi3tGTO/gZ+eJgWmMJkgDiOfyNaunNaxcklJQFaFogYcFl0qFuaEz1qaXYXboa/bUXVSOQ== @@ -3527,6 +3477,17 @@ prop-types "^15.7.2" react-is "^16.8.0" +"@material-ui/lab@4.0.0-alpha.57": + version "4.0.0-alpha.57" + resolved "https://registry.npmjs.org/@material-ui/lab/-/lab-4.0.0-alpha.57.tgz#e8961bcf6449e8a8dabe84f2700daacfcafbf83a" + integrity sha512-qo/IuIQOmEKtzmRD2E4Aa6DB4A87kmY6h0uYhjUmrrgmEAgbbw9etXpWPVXuRK6AGIQCjFzV6WO2i21m1R4FCw== + dependencies: + "@babel/runtime" "^7.4.4" + "@material-ui/utils" "^4.11.2" + clsx "^1.0.4" + prop-types "^15.7.2" + react-is "^16.8.0 || ^17.0.0" + "@material-ui/pickers@^3.2.2": version "3.2.10" resolved "https://registry.npmjs.org/@material-ui/pickers/-/pickers-3.2.10.tgz#19df024895876eb0ec7cd239bbaea595f703f0ae" @@ -3551,7 +3512,7 @@ react-transition-group "^4.0.0" rifm "^0.7.0" -"@material-ui/styles@^4.10.0", "@material-ui/styles@^4.11.0", "@material-ui/styles@^4.11.3", "@material-ui/styles@^4.9.6": +"@material-ui/styles@^4.10.0", "@material-ui/styles@^4.11.0", "@material-ui/styles@^4.11.3", "@material-ui/styles@^4.11.4", "@material-ui/styles@^4.9.6": version "4.11.4" resolved "https://registry.npmjs.org/@material-ui/styles/-/styles-4.11.4.tgz#eb9dfccfcc2d208243d986457dff025497afa00d" integrity sha512-KNTIZcnj/zprG5LW0Sao7zw+yG3O35pviHzejMdcSGCdWbiO8qzRgOYL8JAxAsWBKOKYwVZxXtHWaB5T2Kvxew== @@ -4131,18 +4092,20 @@ resolved "https://registry.npmjs.org/@rjsf/material-ui/-/material-ui-3.0.0.tgz#69ece2cb549f0e860b5f89898db90edcc95b15ba" integrity sha512-T2B8QnrDQphbFNxDz7baAa0zTd5TXJmO9soHBPTKKdniRbMEOQ19AJBbZkA3ED2XZa/xrUY/6XjERQLpNACddw== -"@roadiehq/backstage-plugin-buildkite@^1.0.3": - version "1.0.3" - resolved "https://registry.npmjs.org/@roadiehq/backstage-plugin-buildkite/-/backstage-plugin-buildkite-1.0.3.tgz#d865da83380e1cdcec5825f856597446f5652f53" - integrity sha512-HMDworpWRgwhmQETAe2DUX3cxddP+N1q8bTWxAQwOHO6mecF08uvZDGA1VdWabXSPpJwFUiZEi9OLlNYkl32GA== +"@roadiehq/backstage-plugin-buildkite@^1.0.4": + version "1.0.4" + resolved "https://registry.npmjs.org/@roadiehq/backstage-plugin-buildkite/-/backstage-plugin-buildkite-1.0.4.tgz#8bd89d235c12b0093dd8c35d5397d8332bb62df0" + integrity sha512-SkPJzkLhVo1vMM76EShJRRQegXFKkY1bf1TMVIqR2Cm3E9QXHyN099+dSimFW8f5uyNioEHuRkSh7Iwm7AZekA== dependencies: - "@backstage/catalog-model" "^0.8.0" - "@backstage/core" "^0.7.11" - "@backstage/plugin-catalog-react" "^0.2.0" - "@backstage/theme" "^0.2.7" - "@material-ui/core" "^4.11.0" - "@material-ui/icons" "^4.9.1" - "@material-ui/lab" "4.0.0-alpha.45" + "@backstage/catalog-model" "^0.8.4" + "@backstage/core-app-api" "^0.1.3" + "@backstage/core-components" "^0.1.3" + "@backstage/core-plugin-api" "^0.1.3" + "@backstage/plugin-catalog-react" "^0.2.4" + "@backstage/theme" "^0.2.6" + "@material-ui/core" "^4.11.3" + "@material-ui/icons" "^4.11.2" + "@material-ui/lab" "4.0.0-alpha.57" history "^5.0.0" moment "^2.29.1" react "^16.13.1" @@ -4152,13 +4115,15 @@ react-router-dom "6.0.0-beta.0" react-use "^17.2.4" -"@roadiehq/backstage-plugin-github-insights@^1.1.11": - version "1.1.11" - resolved "https://registry.npmjs.org/@roadiehq/backstage-plugin-github-insights/-/backstage-plugin-github-insights-1.1.11.tgz#6f716a0864b7e3a7255d7ec97c92a68a99874025" - integrity sha512-fDW92aCGXJtZ36TLgEkHiLCZgNKh5lqRFSmStd+58o4QRMiJp852Tcbi2ySrtf03SnGKn7rvD2CqThx/VcwPwg== +"@roadiehq/backstage-plugin-github-insights@^1.1.15": + version "1.1.15" + resolved "https://registry.npmjs.org/@roadiehq/backstage-plugin-github-insights/-/backstage-plugin-github-insights-1.1.15.tgz#ef033f85c54f5203a2bc161290f46e861dc6feca" + integrity sha512-UH8lvDZd1OVP6fX+mF0eTrxqo/QmGWiCWvxumxkyU61sF3XkXzEqhQDKlWWEtpGLPa++yf98p00wfSeXRfjRWA== dependencies: - "@backstage/catalog-model" "^0.8.0" - "@backstage/core" "^0.7.11" + "@backstage/catalog-model" "^0.8.4" + "@backstage/core-app-api" "^0.1.3" + "@backstage/core-components" "^0.1.3" + "@backstage/core-plugin-api" "^0.1.3" "@backstage/plugin-catalog-react" "^0.2.0" "@backstage/theme" "^0.2.7" "@date-io/core" "2.10.7" @@ -4168,18 +4133,20 @@ "@octokit/rest" "^18.5.3" "@octokit/types" "^6.14.2" history "^5.0.0" - react "^16.13.1" - react-dom "^16.13.1" + react "^16.12.0" + react-dom "^16.12.0" react-router "^6.0.0-beta.0" react-use "^17.2.4" -"@roadiehq/backstage-plugin-github-pull-requests@^1.0.5": - version "1.0.5" - resolved "https://registry.npmjs.org/@roadiehq/backstage-plugin-github-pull-requests/-/backstage-plugin-github-pull-requests-1.0.5.tgz#7b71823b1c39dbcb89276a5725815c15a0e27943" - integrity sha512-be+buEb4tkMfVB1qFn3OwFc4pq9/Nu+5C5LsdEwhRnJHN7eLcOBMnhH5l0zAYkHErpF3zbI3xngbap+TATbm0Q== +"@roadiehq/backstage-plugin-github-pull-requests@^1.0.8": + version "1.0.8" + resolved "https://registry.npmjs.org/@roadiehq/backstage-plugin-github-pull-requests/-/backstage-plugin-github-pull-requests-1.0.8.tgz#7d6202ec60808156058bd2d335f7df332934ae56" + integrity sha512-g1CudaKX1NYW0wfbtjcZxFWmDMfw1IvpJD4ymmwZmsogBOHFknlowVmwwSL4W4LwK6IPypIZkOe95Vd2PrjO+Q== dependencies: - "@backstage/catalog-model" "^0.8.0" - "@backstage/core" "^0.7.11" + "@backstage/catalog-model" "^0.8.4" + "@backstage/core-app-api" "^0.1.3" + "@backstage/core-components" "^0.1.3" + "@backstage/core-plugin-api" "^0.1.3" "@backstage/plugin-catalog-react" "^0.2.0" "@material-ui/core" "^4.11.0" "@material-ui/icons" "^4.9.1" @@ -4189,25 +4156,26 @@ history "^5.0.0" moment "^2.27.0" node-fetch "^2.6.1" - react "^16.13.1" - react-dom "^16.13.1" + react "^16.12.0" + react-dom "^16.12.0" react-router "6.0.0-beta.0" react-use "^17.2.4" -"@roadiehq/backstage-plugin-travis-ci@^1.0.0": - version "1.0.0" - resolved "https://registry.npmjs.org/@roadiehq/backstage-plugin-travis-ci/-/backstage-plugin-travis-ci-1.0.0.tgz#5aa29f4ba2086b6341a903a22c843d898808f503" - integrity sha512-JjMDwbou1iY0sSoit8ttpzXEP6lhmLmxf/Pj6Am/1rcia5KLdeMUqpilkzQ33LeHiMXXxu95gp4r6aJ5vC9wGg== +"@roadiehq/backstage-plugin-travis-ci@^1.0.4": + version "1.0.4" + resolved "https://registry.npmjs.org/@roadiehq/backstage-plugin-travis-ci/-/backstage-plugin-travis-ci-1.0.4.tgz#224d17749b6bb33fbc5bf50489d7e7a87b06aa3a" + integrity sha512-rSMB+ZuI9xXIwgqJv7NW/wt3ulZa9rSLsCzkMO30/6/TMbenmsIyfmIP9XI32D9mPew4dVX9spi6KsgEo41WHw== dependencies: - "@backstage/catalog-model" "^0.7.4" - "@backstage/core" "^0.7.3" - "@backstage/plugin-catalog" "^0.5.1" - "@backstage/plugin-catalog-react" "^0.1.4" - "@backstage/theme" "^0.2.5" - "@material-ui/core" "^4.9.1" - "@material-ui/icons" "^4.9.1" - "@material-ui/lab" "4.0.0-alpha.45" - cross-fetch "^3.0.6" + "@backstage/catalog-model" "^0.8.4" + "@backstage/core-app-api" "^0.1.3" + "@backstage/core-components" "^0.1.3" + "@backstage/core-plugin-api" "^0.1.3" + "@backstage/plugin-catalog-react" "^0.2.4" + "@backstage/theme" "^0.2.6" + "@material-ui/core" "^4.11.3" + "@material-ui/icons" "^4.11.2" + "@material-ui/lab" "4.0.0-alpha.57" + cross-fetch "^3.1.3" date-fns "^2.18.0" history "^5.0.0" moment "^2.29.1" @@ -4215,7 +4183,7 @@ react-dom "^16.13.1" react-router "6.0.0-beta.0" react-router-dom "6.0.0-beta.0" - react-use "^15.3.3" + react-use "^17.2.4" "@rollup/plugin-commonjs@^17.1.0": version "17.1.0" @@ -5987,7 +5955,7 @@ dependencies: "@types/sizzle" "*" -"@types/js-cookie@2.2.6", "@types/js-cookie@^2.2.6": +"@types/js-cookie@^2.2.6": version "2.2.6" resolved "https://registry.npmjs.org/@types/js-cookie/-/js-cookie-2.2.6.tgz#f1a1cb35aff47bc5cfb05cb0c441ca91e914c26f" integrity sha512-+oY0FDTO2GYKEV0YPvSshGq9t7YozVkgvXLty7zogQNuCxBhT9/3INX9Q7H1aRZ4SUDRXAKlJuA4EA5nTt7SNw== @@ -7109,7 +7077,7 @@ dependencies: tslib "^1.9.3" -"@xobotyi/scrollbar-width@1.9.5", "@xobotyi/scrollbar-width@^1.9.5": +"@xobotyi/scrollbar-width@^1.9.5": version "1.9.5" resolved "https://registry.npmjs.org/@xobotyi/scrollbar-width/-/scrollbar-width-1.9.5.tgz#80224a6919272f405b87913ca13b92929bdf3c4d" integrity sha512-N8tkAACJx2ww8vFMneJmaAgmjAG1tnVBZJRLRcx061tmsLRZHSEZSLuGWnwPtunsSLvSqXQ2wfp7Mgqg1I+2dQ== @@ -10394,7 +10362,7 @@ cross-fetch@3.0.6: dependencies: node-fetch "2.6.1" -cross-fetch@3.1.4, cross-fetch@^3.0.4, cross-fetch@^3.0.6: +cross-fetch@3.1.4, cross-fetch@^3.0.4, cross-fetch@^3.0.6, cross-fetch@^3.1.3: version "3.1.4" resolved "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.4.tgz#9723f3a3a247bf8b89039f3a380a9244e8fa2f39" integrity sha512-1eAtFWdIubi6T4XPy6ei9iUFoKpUkIF971QLN8lIvvvwueI65+Nw5haMNKUwfJxabqlIIDODJKGrQ66gxC0PbQ== @@ -18976,7 +18944,7 @@ nan@2.14.1, nan@^2.12.1, nan@^2.14.0: resolved "https://registry.npmjs.org/nan/-/nan-2.14.1.tgz#d7be34dfa3105b91494c3147089315eff8874b01" integrity sha512-isWHgVjnFjh2x2yuJ/tj3JbwoHu3UC2dX5G/88Cm24yB6YopVgxvBObDY7n5xW6ExmFhJpSEQqFPvq9zaXc8Jw== -nano-css@^5.1.0, nano-css@^5.2.1, nano-css@^5.3.1: +nano-css@^5.1.0, nano-css@^5.3.1: version "5.3.1" resolved "https://registry.npmjs.org/nano-css/-/nano-css-5.3.1.tgz#b709383e07ad3be61f64edffacb9d98250b87a1f" integrity sha512-ENPIyNzANQRyYVvb62ajDd7PAyIgS2LIUnT9ewih4yrXSZX4hKoUwssy8WjUH++kEOA5wUTMgNnV7ko5n34kUA== @@ -22281,26 +22249,6 @@ react-use@^12.2.0: ts-easing "^0.2.0" tslib "^1.10.0" -react-use@^15.3.3: - version "15.3.8" - resolved "https://registry.npmjs.org/react-use/-/react-use-15.3.8.tgz#ca839ac7fb3d696e5ccbeabbc8dadc2698969d30" - integrity sha512-GeGcrmGuUvZrY5wER3Lnph9DSYhZt5nEjped4eKDq8BRGr2CnLf9bDQWG9RFc7oCPphnscUUdOovzq0E5F2c6Q== - dependencies: - "@types/js-cookie" "2.2.6" - "@xobotyi/scrollbar-width" "1.9.5" - copy-to-clipboard "^3.2.0" - fast-deep-equal "^3.1.3" - fast-shallow-equal "^1.0.0" - js-cookie "^2.2.1" - nano-css "^5.2.1" - react-universal-interface "^0.6.2" - resize-observer-polyfill "^1.5.1" - screenfull "^5.0.0" - set-harmonic-interval "^1.0.1" - throttle-debounce "^2.1.0" - ts-easing "^0.2.0" - tslib "^2.0.0" - react-use@^17.2.4: version "17.2.4" resolved "https://registry.npmjs.org/react-use/-/react-use-17.2.4.tgz#1f89be3db0a8237c79253db0a15e12bbe3cfeff1" From 13bf0f38671e403e8e78bfa7cb542b725fadf683 Mon Sep 17 00:00:00 2001 From: Hammar Johan Date: Wed, 30 Jun 2021 11:56:39 +0200 Subject: [PATCH 064/204] Remove autofocus for the description field Signed-off-by: Hammar Johan --- .../sample-templates/docs-template/template.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/plugins/scaffolder-backend/sample-templates/docs-template/template.yaml b/plugins/scaffolder-backend/sample-templates/docs-template/template.yaml index 7b3d58d0b3..1e81242e7a 100644 --- a/plugins/scaffolder-backend/sample-templates/docs-template/template.yaml +++ b/plugins/scaffolder-backend/sample-templates/docs-template/template.yaml @@ -29,7 +29,6 @@ spec: title: Description type: string description: A description for the component - ui:autofocus: true ui:options: rows: 5 owner: From 831626ff3f0dbda3a8e0f48b61839d894186e5d5 Mon Sep 17 00:00:00 2001 From: Irma12 Date: Wed, 30 Jun 2021 13:41:31 +0200 Subject: [PATCH 065/204] Delete two-badgers-sit.md Signed-off-by: irma12 --- .changeset/two-badgers-sit.md | 5 ----- 1 file changed, 5 deletions(-) delete mode 100644 .changeset/two-badgers-sit.md diff --git a/.changeset/two-badgers-sit.md b/.changeset/two-badgers-sit.md deleted file mode 100644 index a23ced389b..0000000000 --- a/.changeset/two-badgers-sit.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'example-app': patch ---- - -Bump roadie plugins versions From 35a3e4e4cf30266a2c4ccfa08da7fd141ef3d80c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?= Date: Wed, 30 Jun 2021 14:37:43 +0200 Subject: [PATCH 066/204] Fix repetitive error reporting in EntityTypePicker MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fredrik Adelöw --- .changeset/giant-meals-smile.md | 5 +++++ .../EntityTypePicker/EntityTypePicker.tsx | 17 ++++++++++------- 2 files changed, 15 insertions(+), 7 deletions(-) create mode 100644 .changeset/giant-meals-smile.md diff --git a/.changeset/giant-meals-smile.md b/.changeset/giant-meals-smile.md new file mode 100644 index 0000000000..188bb77351 --- /dev/null +++ b/.changeset/giant-meals-smile.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-react': patch +--- + +Fix repetitive error reporting in EntityTypePicker diff --git a/plugins/catalog-react/src/components/EntityTypePicker/EntityTypePicker.tsx b/plugins/catalog-react/src/components/EntityTypePicker/EntityTypePicker.tsx index 52b8ec8ff1..7b7845b8bc 100644 --- a/plugins/catalog-react/src/components/EntityTypePicker/EntityTypePicker.tsx +++ b/plugins/catalog-react/src/components/EntityTypePicker/EntityTypePicker.tsx @@ -14,7 +14,7 @@ * limitations under the License. */ -import React from 'react'; +import React, { useEffect } from 'react'; import { capitalize } from 'lodash'; import { Box } from '@material-ui/core'; import { useEntityTypeFilter } from '../../hooks/useEntityTypeFilter'; @@ -26,13 +26,16 @@ export const EntityTypePicker = () => { const alertApi = useApi(alertApiRef); const { error, types, selectedType, setType } = useEntityTypeFilter(); - if (!types) return null; + useEffect(() => { + if (error) { + alertApi.post({ + message: `Failed to load entity types`, + severity: 'error', + }); + } + }, [error, alertApi]); - if (error) { - alertApi.post({ - message: `Failed to load entity types`, - severity: 'error', - }); + if (!types || error) { return null; } From 3cf22d0a92542dfa81526cdb0482d271201cb359 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Wed, 30 Jun 2021 14:29:31 +0200 Subject: [PATCH 067/204] catalog-backend: review fixes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Johan Haals Co-authored-by: Fredrik Adelöw Signed-off-by: Patrik Oldsberg --- .../next/database/DefaultProcessingDatabase.test.ts | 8 ++++++-- .../src/next/database/DefaultProcessingDatabase.ts | 13 +++++++++---- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.test.ts b/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.test.ts index 9a9c09daaf..e449e5580c 100644 --- a/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.test.ts +++ b/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.test.ts @@ -210,7 +210,9 @@ describe('Default Processing Database', () => { relations: [], deferredEntities: [], }), - ).rejects.toThrow(`Processing state not found for ${id}`); + ).rejects.toThrow( + `Conflicting write of processing result for ${id} with location key 'undefined'`, + ); }); }, 60_000, @@ -249,7 +251,9 @@ describe('Default Processing Database', () => { await db.transaction(tx => expect( db.updateProcessedEntity(tx, { ...options, locationKey: 'fail' }), - ).rejects.toThrow(`Processing state not found for ${id}`), + ).rejects.toThrow( + `Conflicting write of processing result for ${id} with location key 'fail'`, + ), ); }, 60_000, diff --git a/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.ts b/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.ts index 53025682ac..1f1ea4bf84 100644 --- a/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.ts +++ b/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.ts @@ -16,7 +16,7 @@ import { Entity, stringifyEntityRef } from '@backstage/catalog-model'; import { JsonObject } from '@backstage/config'; -import { ConflictError, NotFoundError } from '@backstage/errors'; +import { ConflictError } from '@backstage/errors'; import { Knex } from 'knex'; import lodash from 'lodash'; import { v4 as uuid } from 'uuid'; @@ -83,7 +83,9 @@ export class DefaultProcessingDatabase implements ProcessingDatabase { .orWhereNull('location_key'); }); if (refreshResult === 0) { - throw new NotFoundError(`Processing state not found for ${id}`); + throw new ConflictError( + `Conflicting write of processing result for ${id} with location key '${locationKey}'`, + ); } // Schedule all deferred entities for future processing. @@ -372,7 +374,7 @@ export class DefaultProcessingDatabase implements ProcessingDatabase { query = query.onConflict('entity_ref').ignore(); } - const result = await query; + const result: { /* postgres */ rowCount?: number } = await query; if (result.rowCount === 0) { throw new ConflictError( 'Insert failed due to conflicting entity_ref', @@ -395,7 +397,10 @@ export class DefaultProcessingDatabase implements ProcessingDatabase { .select(); // If the location key matches it means we just had a race trigger, which we can safely ignore - if (conflictingEntity.location_key !== locationKey) { + if ( + !conflictingEntity || + conflictingEntity.location_key !== locationKey + ) { this.options.logger.warn( `Detected conflicting entityRef ${entityRef} already referenced by ${conflictingEntity.location_key} and now also ${locationKey}`, ); From e15c4156a9262649d8b210ec3cf5cf0daed3b89c Mon Sep 17 00:00:00 2001 From: James Renaud Date: Wed, 30 Jun 2021 10:08:07 -0400 Subject: [PATCH 068/204] fix: remove image tooltips Signed-off-by: James Renaud --- plugins/pagerduty/README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/plugins/pagerduty/README.md b/plugins/pagerduty/README.md index 12329288b7..bdafeb984a 100644 --- a/plugins/pagerduty/README.md +++ b/plugins/pagerduty/README.md @@ -12,17 +12,17 @@ This plugin requires that entities are annotated with an [integration key](https ### View any open incidents -![View Open Incidents](doc/pd1.png "PagerDuty plugin showing no incidents and the on-call rotation") +![PagerDuty plugin showing no incidents and the on-call rotation](doc/pd1.png) ### Email link, and view contact information for staff on call -![On-Call Contact Information](doc/pd2.png "PagerDuty plugin showing on-call rotation contact information") +![PagerDuty plugin showing on-call rotation contact information](doc/pd2.png) ### Trigger an incident for a service -![Trigger an Incident](doc/pd3.png "PagerDuty plugin popup modal for creating an incident") +![PagerDuty plugin popup modal for creating an incident](doc/pd3.png) -![Active Incidents](doc/pd4.png "PagerDuty plugin showing an active incident") +![PagerDuty plugin showing an active incident](doc/pd4.png) ## Setup instructions From d1e9b0e139c973774b06960c971a7cc1d8b83369 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Wed, 30 Jun 2021 16:43:44 +0200 Subject: [PATCH 069/204] catalog-backend: fix test on windows Co-authored-by: Johan Haals Signed-off-by: Patrik Oldsberg --- .../src/next/ConfigLocationEntityProvider.test.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/plugins/catalog-backend/src/next/ConfigLocationEntityProvider.test.ts b/plugins/catalog-backend/src/next/ConfigLocationEntityProvider.test.ts index 7592182bad..d177b1aa32 100644 --- a/plugins/catalog-backend/src/next/ConfigLocationEntityProvider.test.ts +++ b/plugins/catalog-backend/src/next/ConfigLocationEntityProvider.test.ts @@ -51,9 +51,7 @@ describe('ConfigLocationEntityProvider', () => { type: 'file', }, }), - locationKey: expect.stringMatching( - /plugins\/catalog-backend\/lols\.yaml$/, - ), + locationKey: expect.stringMatching(/lols\.yaml$/), }, ]), }); From 6b96dd2e5c64f67adad5e5df5ba2ab7fcc82dd93 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Wed, 30 Jun 2021 16:52:37 +0200 Subject: [PATCH 070/204] backend-common: add new optional readUrl method to UrlReader Co-authored-by: Johan Haals Signed-off-by: Patrik Oldsberg --- packages/backend-common/src/reading/types.ts | 56 ++++++++++++++++++-- 1 file changed, 52 insertions(+), 4 deletions(-) diff --git a/packages/backend-common/src/reading/types.ts b/packages/backend-common/src/reading/types.ts index f7fad4dd7a..dd230a754d 100644 --- a/packages/backend-common/src/reading/types.ts +++ b/packages/backend-common/src/reading/types.ts @@ -23,7 +23,17 @@ import { Config } from '@backstage/config'; */ export type UrlReader = { read(url: string): Promise; + + /** + * A replacement for the read method that supports options and complex responses. + * + * Use this whenever it is available, as the read method will be deprecated and + * eventually removed in the future. + */ + readUrl?(url: string, options?: ReadUrlOptions): Promise; + readTree(url: string, options?: ReadTreeOptions): Promise; + search(url: string, options?: SearchOptions): Promise; }; @@ -42,6 +52,40 @@ export type ReaderFactory = (options: { treeResponseFactory: ReadTreeResponseFactory; }) => UrlReaderPredicateTuple[]; +/** + * An options object for readUrl operations. + */ +export type ReadUrlOptions = { + /** + * An etag can be provided to check whether readUrl's response has changed from a previous execution. + * + * In the readUrl() response, an etag is returned along with the data. The etag is a unique identifer + * of the data, usually the commit SHA or etag from the target. + * + * When an etag is given in ReadUrlOptions, readUrl will first compare the etag against the etag + * on the target branch. If they match, readUrl will throw a NotModifiedError indicating that the readUrl + * response will not differ from the previous response which included this particular etag. If they + * do not match, readUrl will return the rest of ReadUrlResponse along with a new etag. + */ + etag?: string; +}; + +/** + * A response object for readUrl operations. + */ +export type ReadUrlResponse = { + /** + * Returns the data that was read from the remote URL. + */ + buffer(): Promise; + + /** + * Etag returned by content provider. + * Can be used to compare and cache responses when doing subsequent calls. + */ + etag?: string; +}; + /** * An options object for readTree operations. */ @@ -66,14 +110,17 @@ export type ReadTreeOptions = { * In the readTree() response, an etag is returned along with the tree blob. The etag is a unique identifer * of the tree blob, usually the commit SHA or etag from the target. * - * When a etag is given in ReadTreeOptions, readTree will first compare the etag against the etag + * When an etag is given in ReadTreeOptions, readTree will first compare the etag against the etag * on the target branch. If they match, readTree will throw a NotModifiedError indicating that the readTree - * response will not differ from the previous response which included this particular etag. If they mismatch, - * readTree will return the rest of ReadTreeResponse along with a new etag. + * response will not differ from the previous response which included this particular etag. If they + * do not match, readTree will return the rest of ReadTreeResponse along with a new etag. */ etag?: string; }; +/** + * A response object for readTree operations. + */ export type ReadTreeResponse = { /** * files() returns an array of all the files inside the tree and corresponding functions to read their content. @@ -87,7 +134,8 @@ export type ReadTreeResponse = { dir(options?: ReadTreeResponseDirOptions): Promise; /** - * A unique identifer of the tree blob, usually the commit SHA or etag from the target. + * Etag returned by content provider. + * Can be used to compare and cache responses when doing subsequent calls. */ etag: string; }; From 7b1dd36f7809fe4bba11c29379a23d929f966494 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Wed, 30 Jun 2021 16:55:54 +0200 Subject: [PATCH 071/204] backend-common: implement readUrl in UrlReaderPredicateMux, and have it fall back to read Co-authored-by: Johan Haals Signed-off-by: Patrik Oldsberg --- .../src/reading/UrlReaderPredicateMux.ts | 25 ++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/packages/backend-common/src/reading/UrlReaderPredicateMux.ts b/packages/backend-common/src/reading/UrlReaderPredicateMux.ts index c9afecf907..cf3e4d62f5 100644 --- a/packages/backend-common/src/reading/UrlReaderPredicateMux.ts +++ b/packages/backend-common/src/reading/UrlReaderPredicateMux.ts @@ -18,6 +18,8 @@ import { NotAllowedError } from '@backstage/errors'; import { ReadTreeOptions, ReadTreeResponse, + ReadUrlOptions, + ReadUrlResponse, SearchOptions, SearchResponse, UrlReader, @@ -35,7 +37,7 @@ export class UrlReaderPredicateMux implements UrlReader { this.readers.push(tuple); } - read(url: string): Promise { + async read(url: string): Promise { const parsed = new URL(url); for (const { predicate, reader } of this.readers) { @@ -47,6 +49,27 @@ export class UrlReaderPredicateMux implements UrlReader { throw new NotAllowedError(`Reading from '${url}' is not allowed`); } + async readUrl( + url: string, + options?: ReadUrlOptions, + ): Promise { + const parsed = new URL(url); + + for (const { predicate, reader } of this.readers) { + if (predicate(parsed)) { + if (reader.readUrl) { + return reader.readUrl(url, options); + } + const buffer = await reader.read(url); + return { + buffer: async () => buffer, + }; + } + } + + throw new NotAllowedError(`Reading from '${url}' is not allowed`); + } + async readTree( url: string, options?: ReadTreeOptions, From 80177048d213441936640f30ac3080f4af1742b6 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Wed, 30 Jun 2021 17:08:32 +0200 Subject: [PATCH 072/204] backstage-common: implement readUrl for GitHub UrlReader Co-authored-by: Johan Haals Signed-off-by: Patrik Oldsberg --- .../src/reading/GithubUrlReader.ts | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/packages/backend-common/src/reading/GithubUrlReader.ts b/packages/backend-common/src/reading/GithubUrlReader.ts index 70bc9601df..7d12634365 100644 --- a/packages/backend-common/src/reading/GithubUrlReader.ts +++ b/packages/backend-common/src/reading/GithubUrlReader.ts @@ -35,6 +35,8 @@ import { SearchResponse, SearchResponseFile, UrlReader, + ReadUrlOptions, + ReadUrlResponse, } from './types'; export type GhRepoResponse = RestEndpointMethodTypes['repos']['get']['response']['data']; @@ -77,6 +79,14 @@ export class GithubUrlReader implements UrlReader { } async read(url: string): Promise { + const response = await this.readUrl(url); + return response.buffer(); + } + + async readUrl( + url: string, + options?: ReadUrlOptions, + ): Promise { const ghUrl = getGitHubFileFetchUrl(url, this.integration.config); const { headers } = await this.deps.credentialsProvider.getCredentials({ url, @@ -86,6 +96,7 @@ export class GithubUrlReader implements UrlReader { response = await fetch(ghUrl.toString(), { headers: { ...headers, + ...(options?.etag && { 'If-None-Match': options.etag }), Accept: 'application/vnd.github.v3.raw', }, }); @@ -93,8 +104,12 @@ export class GithubUrlReader implements UrlReader { throw new Error(`Unable to read ${url}, ${e}`); } + if (response.status === 304) { + throw new NotModifiedError(); + } + if (response.ok) { - return Buffer.from(await response.text()); + return { buffer: async () => Buffer.from(await response.text()) }; } const message = `${url} could not be read as ${ghUrl}, ${response.status} ${response.statusText}`; From bbdeb50ba7671a0f2bd93d5800fc36760cfaea9d Mon Sep 17 00:00:00 2001 From: Deepak Bhardwaj Date: Wed, 30 Jun 2021 21:53:09 +0530 Subject: [PATCH 073/204] Replaced material button to core-components Signed-off-by: Deepak Bhardwaj --- packages/core-components/src/components/Link/Link.tsx | 10 +++++++++- plugins/explore/src/components/ToolCard/ToolCard.tsx | 7 +++---- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/packages/core-components/src/components/Link/Link.tsx b/packages/core-components/src/components/Link/Link.tsx index dd169390a5..89f5a69245 100644 --- a/packages/core-components/src/components/Link/Link.tsx +++ b/packages/core-components/src/components/Link/Link.tsx @@ -29,6 +29,7 @@ export const isExternalUri = (uri: string) => /^([a-z+.-]+):/.test(uri); export type LinkProps = MaterialLinkProps & RouterLinkProps & { component?: ElementType; + externalLinkTarget?: undefined | '_blank'; }; /** @@ -39,7 +40,14 @@ export const Link = React.forwardRef((props, ref) => { const to = String(props.to); return isExternalUri(to) ? ( // External links - + ) : ( // Interact with React Router for internal links diff --git a/plugins/explore/src/components/ToolCard/ToolCard.tsx b/plugins/explore/src/components/ToolCard/ToolCard.tsx index 00c9851865..584d0a54a6 100644 --- a/plugins/explore/src/components/ToolCard/ToolCard.tsx +++ b/plugins/explore/src/components/ToolCard/ToolCard.tsx @@ -18,7 +18,6 @@ import { ExploreTool } from '@backstage/plugin-explore-react'; import { BackstageTheme } from '@backstage/theme'; import { Box, - Button, Card, CardActions, CardContent, @@ -27,6 +26,7 @@ import { makeStyles, Typography, } from '@material-ui/core'; +import { Button } from '@backstage/core-components'; import classNames from 'classnames'; import React from 'react'; @@ -63,7 +63,6 @@ export const ToolCard = ({ card, objectFit }: Props) => { const classes = useStyles(); const { title, description, url, image, lifecycle, tags } = card; - const isExternalUrl = url.startsWith('https://') || url.startsWith('http://'); return ( @@ -99,9 +98,9 @@ export const ToolCard = ({ card, objectFit }: Props) => { From 65915a85db51cac8f799293ca673b2a4951c85a2 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Thu, 1 Jul 2021 15:41:56 +0200 Subject: [PATCH 095/204] changesets: update readUrl changeset with migration instructions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Fredrik Adelöw Co-authored-by: Johan Haals Signed-off-by: Patrik Oldsberg --- .changeset/honest-cars-glow.md | 51 ++++++++++++++++++++++++++++++++-- 1 file changed, 48 insertions(+), 3 deletions(-) diff --git a/.changeset/honest-cars-glow.md b/.changeset/honest-cars-glow.md index f6efd55d3c..3fdc6e335a 100644 --- a/.changeset/honest-cars-glow.md +++ b/.changeset/honest-cars-glow.md @@ -2,8 +2,53 @@ '@backstage/backend-common': patch --- -Adds `readUrl` method to the `UrlReader` interface that allows for complex response objects. This new method is currently optional to implement which allows for a soft migration to `readUrl` instead of `read` in the future. +Added a `readUrl` method to the `UrlReader` interface that allows for complex response objects and is intended to replace the `read` method. This new method is currently optional to implement which allows for a soft migration to `readUrl` instead of `read` in the future. -The main use case for `readUrl` returning an object instead of solely a read buffer is to allow for additional metadata such as etag which will is a requirement for cacheable processing. +The main use case for `readUrl` returning an object instead of solely a read buffer is to allow for additional metadata such as ETag, which is a requirement for more efficient catalog processing. -Implements `readUrl` in `GithubUrlReader`. +The `GithubUrlReader` and `GitlabUrlReader` readers fully implement `readUrl`. The other existing readers implement the new method but do not propagate or return ETags. + +While the `readUrl` method is not yet required, it will be in the future, and we already log deprecation warnings when custom `UrlReader` implementations that do not implement `readUrl` are used. We therefore recommend that any existing custom implementations are migrated to implement `readUrl`. + +The old `read` and the new `readUrl` methods can easily be implemented using one another, but we recommend moving the chunk of the implementation to the new `readUrl` method as `read` is being removed, for example this: + +```ts +class CustomUrlReader implements UrlReader { + read(url: string): Promise { + const res = await fetch(url); + + if (!res.ok) { + // error handling ... + } + + return Buffer.from(await res.text()); + } +} +``` + +Can be migrated to something like this: + +```ts +class CustomUrlReader implements UrlReader { + read(url: string): Promise { + const res = await this.readUrl(url); + return res.buffer(); + } + + async readUrl( + url: string, + _options?: ReadUrlOptions, + ): Promise { + const res = await fetch(url); + + if (!res.ok) { + // error handling ... + } + + const buffer = Buffer.from(await res.text()); + return { buffer: async () => buffer }; + } +} +``` + +While there is no usage of the ETag capability yet in the main Backstage packages, you can already add it to your custom implementations. To do so, refer to the documentation of the `readUrl` method and surrounding types, and the existing implementation in `packages/backend-common/src/reading/GithubUrlReader.ts`. From 9bb672c06a7af41d976b76f7d34581c6abb9ca88 Mon Sep 17 00:00:00 2001 From: Deepak Bhardwaj Date: Thu, 1 Jul 2021 19:39:37 +0530 Subject: [PATCH 096/204] Open http external links in new window by default Signed-off-by: Deepak Bhardwaj --- packages/core-components/src/components/Link/Link.tsx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/core-components/src/components/Link/Link.tsx b/packages/core-components/src/components/Link/Link.tsx index 67a5a4994b..7853c4f52f 100644 --- a/packages/core-components/src/components/Link/Link.tsx +++ b/packages/core-components/src/components/Link/Link.tsx @@ -37,12 +37,14 @@ export type LinkProps = MaterialLinkProps & */ export const Link = React.forwardRef((props, ref) => { const to = String(props.to); - return isExternalUri(to) ? ( + const external = isExternalUri(to); + const newWindow = external && !!/^https?:/.exec(to); + return external ? ( // External links ) : ( From 6494c09b0914255179fcf2872cf9ba11d0bb3558 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?= Date: Thu, 1 Jul 2021 16:56:37 +0200 Subject: [PATCH 097/204] manually patch snapshot MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fredrik Adelöw --- plugins/git-release-manager/src/features/Features.test.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/git-release-manager/src/features/Features.test.tsx b/plugins/git-release-manager/src/features/Features.test.tsx index ac3004f690..b5404a21d9 100644 --- a/plugins/git-release-manager/src/features/Features.test.tsx +++ b/plugins/git-release-manager/src/features/Features.test.tsx @@ -69,6 +69,7 @@ describe('Features', () => { From b691a938e470b41d89c5c804fa4e08addc691707 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mathias=20A=CC=8Ahsberg?= Date: Thu, 1 Jul 2021 14:48:27 +0000 Subject: [PATCH 098/204] Fix downloads for repositories located at bitbucket.org MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Mathias Åhsberg --- .changeset/serious-falcons-greet.md | 5 +++++ .../backend-common/src/reading/BitbucketUrlReader.test.ts | 8 ++++---- packages/integration/src/bitbucket/core.test.ts | 2 +- packages/integration/src/bitbucket/core.ts | 2 +- 4 files changed, 11 insertions(+), 6 deletions(-) create mode 100644 .changeset/serious-falcons-greet.md diff --git a/.changeset/serious-falcons-greet.md b/.changeset/serious-falcons-greet.md new file mode 100644 index 0000000000..f793ed26d4 --- /dev/null +++ b/.changeset/serious-falcons-greet.md @@ -0,0 +1,5 @@ +--- +'@backstage/integration': patch +--- + +Fix downloads from repositories located at bitbucket.org diff --git a/packages/backend-common/src/reading/BitbucketUrlReader.test.ts b/packages/backend-common/src/reading/BitbucketUrlReader.test.ts index cc540cb83c..4d8d865084 100644 --- a/packages/backend-common/src/reading/BitbucketUrlReader.test.ts +++ b/packages/backend-common/src/reading/BitbucketUrlReader.test.ts @@ -119,14 +119,14 @@ describe('BitbucketUrlReader', () => { ), ), rest.get( - 'https://bitbucket.org/backstage/mock/get/master.tgz', + 'https://bitbucket.org/backstage/mock/get/master.tar.gz', (_, res, ctx) => res( ctx.status(200), ctx.set('Content-Type', 'application/zip'), ctx.set( 'content-disposition', - 'attachment; filename=backstage-mock-12ab34cd56ef.tgz', + 'attachment; filename=backstage-mock-12ab34cd56ef.tar.gz', ), ctx.body(repoBuffer), ), @@ -304,14 +304,14 @@ describe('BitbucketUrlReader', () => { ), ), rest.get( - 'https://bitbucket.org/backstage/mock/get/master.tgz', + 'https://bitbucket.org/backstage/mock/get/master.tar.gz', (_, res, ctx) => res( ctx.status(200), ctx.set('Content-Type', 'application/zip'), ctx.set( 'content-disposition', - 'attachment; filename=backstage-mock-12ab34cd56ef.tgz', + 'attachment; filename=backstage-mock-12ab34cd56ef.tar.gz', ), ctx.body(repoBuffer), ), diff --git a/packages/integration/src/bitbucket/core.test.ts b/packages/integration/src/bitbucket/core.test.ts index 62f81179ee..0de1d5aaab 100644 --- a/packages/integration/src/bitbucket/core.test.ts +++ b/packages/integration/src/bitbucket/core.test.ts @@ -192,7 +192,7 @@ describe('bitbucket core', () => { config, ); expect(result).toEqual( - 'https://bitbucket.org/backstage/mock/get/master.tgz', + 'https://bitbucket.org/backstage/mock/get/master.tar.gz', ); }); }); diff --git a/packages/integration/src/bitbucket/core.ts b/packages/integration/src/bitbucket/core.ts index 0a1b247f10..f8f8f56fa8 100644 --- a/packages/integration/src/bitbucket/core.ts +++ b/packages/integration/src/bitbucket/core.ts @@ -98,7 +98,7 @@ export async function getBitbucketDownloadUrl( // /docs/index.md will download the docs folder and everything below it const path = filepath ? `&path=${encodeURIComponent(filepath)}` : ''; const archiveUrl = isHosted - ? `${protocol}://${resource}/${project}/${repoName}/get/${branch}.tgz` + ? `${protocol}://${resource}/${project}/${repoName}/get/${branch}.tar.gz` : `${config.apiBaseUrl}/projects/${project}/repos/${repoName}/archive?format=tgz&at=${branch}&prefix=${project}-${repoName}${path}`; return archiveUrl; From f66a53d06f0725e07bd2f47850cfa80f6343a377 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Thu, 1 Jul 2021 18:17:18 +0200 Subject: [PATCH 099/204] backend-common: add readUrl to API report Signed-off-by: Patrik Oldsberg --- packages/backend-common/api-report.md | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/packages/backend-common/api-report.md b/packages/backend-common/api-report.md index 6b9e7bbbe0..3d17f959fd 100644 --- a/packages/backend-common/api-report.md +++ b/packages/backend-common/api-report.md @@ -42,6 +42,8 @@ export class AzureUrlReader implements UrlReader { // (undocumented) readTree(url: string, options?: ReadTreeOptions): Promise; // (undocumented) + readUrl(url: string, _options?: ReadUrlOptions): Promise; + // (undocumented) search(url: string, options?: SearchOptions): Promise; // (undocumented) toString(): string; @@ -59,6 +61,8 @@ export class BitbucketUrlReader implements UrlReader { // (undocumented) readTree(url: string, options?: ReadTreeOptions): Promise; // (undocumented) + readUrl(url: string, _options?: ReadUrlOptions): Promise; + // (undocumented) search(url: string, options?: SearchOptions): Promise; // (undocumented) toString(): string; @@ -231,6 +235,8 @@ export class GithubUrlReader implements UrlReader { // (undocumented) readTree(url: string, options?: ReadTreeOptions): Promise; // (undocumented) + readUrl(url: string, options?: ReadUrlOptions): Promise; + // (undocumented) search(url: string, options?: SearchOptions): Promise; // (undocumented) toString(): string; @@ -248,6 +254,8 @@ export class GitlabUrlReader implements UrlReader { // (undocumented) readTree(url: string, options?: ReadTreeOptions): Promise; // (undocumented) + readUrl(url: string, options?: ReadUrlOptions): Promise; + // (undocumented) search(url: string, options?: SearchOptions): Promise; // (undocumented) toString(): string; @@ -277,7 +285,7 @@ export type PluginEndpointDiscovery = { getExternalBaseUrl(pluginId: string): Promise; }; -// @public (undocumented) +// @public export type ReadTreeResponse = { files(): Promise; archive(): Promise; @@ -366,6 +374,7 @@ export interface StatusCheckHandlerOptions { // @public export type UrlReader = { read(url: string): Promise; + readUrl?(url: string, options?: ReadUrlOptions): Promise; readTree(url: string, options?: ReadTreeOptions): Promise; search(url: string, options?: SearchOptions): Promise; }; From ac663f51609fad5c461bd7b8699ad6b232ebac0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?= Date: Thu, 1 Jul 2021 23:42:58 +0200 Subject: [PATCH 100/204] Update packages/core-components/src/components/ResponseErrorPanel/ResponseErrorPanel.tsx MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fredrik Adelöw Co-authored-by: Tim --- .../src/components/ResponseErrorPanel/ResponseErrorPanel.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/core-components/src/components/ResponseErrorPanel/ResponseErrorPanel.tsx b/packages/core-components/src/components/ResponseErrorPanel/ResponseErrorPanel.tsx index 5a19d32eef..ccfb706bf9 100644 --- a/packages/core-components/src/components/ResponseErrorPanel/ResponseErrorPanel.tsx +++ b/packages/core-components/src/components/ResponseErrorPanel/ResponseErrorPanel.tsx @@ -76,7 +76,7 @@ export const ResponseErrorPanel = ({ From b7cd1f31516662f28ae7f642985d8a0ebff4085a Mon Sep 17 00:00:00 2001 From: "roylisto.pradana" Date: Wed, 30 Jun 2021 13:55:53 +0700 Subject: [PATCH 101/204] Add edit button to Group Profile card Signed-off-by: roylisto.pradana --- .../src/layout/InfoCard/InfoCard.tsx | 4 +++- .../Cards/Group/GroupProfile/GroupProfileCard.tsx | 14 ++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/packages/core-components/src/layout/InfoCard/InfoCard.tsx b/packages/core-components/src/layout/InfoCard/InfoCard.tsx index 763038388b..cc15bbd9f4 100644 --- a/packages/core-components/src/layout/InfoCard/InfoCard.tsx +++ b/packages/core-components/src/layout/InfoCard/InfoCard.tsx @@ -37,7 +37,6 @@ const useStyles = makeStyles(theme => ({ }, }, header: { - display: 'inline-block', padding: theme.spacing(2, 2, 2, 2.5), }, headerTitle: { @@ -121,6 +120,7 @@ type Props = { children?: ReactNode; headerStyle?: object; headerProps?: CardHeaderProps; + action?: ReactNode; actionsClassName?: string; actions?: ReactNode; cardClassName?: string; @@ -141,6 +141,7 @@ export const InfoCard = ({ children, headerStyle, headerProps, + action, actionsClassName, actions, cardClassName, @@ -190,6 +191,7 @@ export const InfoCard = ({ }} title={title} subheader={subheader} + action={action} style={{ ...headerStyle }} titleTypographyProps={titleTypographyProps} {...headerProps} diff --git a/plugins/org/src/components/Cards/Group/GroupProfile/GroupProfileCard.tsx b/plugins/org/src/components/Cards/Group/GroupProfile/GroupProfileCard.tsx index 853dbc53e8..a96c53da6e 100644 --- a/plugins/org/src/components/Cards/Group/GroupProfile/GroupProfileCard.tsx +++ b/plugins/org/src/components/Cards/Group/GroupProfile/GroupProfileCard.tsx @@ -33,10 +33,12 @@ import { ListItemIcon, ListItemText, Tooltip, + IconButton, } from '@material-ui/core'; import AccountTreeIcon from '@material-ui/icons/AccountTree'; import EmailIcon from '@material-ui/icons/Email'; import GroupIcon from '@material-ui/icons/Group'; +import EditIcon from '@material-ui/icons/Edit'; import Alert from '@material-ui/lab/Alert'; import React from 'react'; import { Avatar, InfoCard, InfoCardVariants } from '@backstage/core-components'; @@ -80,6 +82,18 @@ export const GroupProfileCard = ({ title={} subheader={description} variant={variant} + action={ + { + // window.open(entityMetadataEditUrl ?? '#', '_blank'); + }} + > + + + } > From 5a80de8ff602b185575bdcbcb9daa891aaeb659d Mon Sep 17 00:00:00 2001 From: "roylisto.pradana" Date: Wed, 30 Jun 2021 14:14:48 +0700 Subject: [PATCH 102/204] get metadata edit url Signed-off-by: roylisto.pradana --- .../Cards/Group/GroupProfile/GroupProfileCard.tsx | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/plugins/org/src/components/Cards/Group/GroupProfile/GroupProfileCard.tsx b/plugins/org/src/components/Cards/Group/GroupProfile/GroupProfileCard.tsx index a96c53da6e..8d44e9157a 100644 --- a/plugins/org/src/components/Cards/Group/GroupProfile/GroupProfileCard.tsx +++ b/plugins/org/src/components/Cards/Group/GroupProfile/GroupProfileCard.tsx @@ -23,6 +23,7 @@ import { EntityRefLinks, getEntityRelations, useEntity, + getEntityMetadataEditUrl, } from '@backstage/plugin-catalog-react'; import { Box, @@ -74,6 +75,8 @@ export const GroupProfileCard = ({ kind: 'group', }); + const entityMetadataEditUrl = getEntityMetadataEditUrl(group); + const displayName = profile?.displayName ?? name; const emailHref = profile?.email ? `mailto:${profile.email}` : undefined; @@ -85,10 +88,10 @@ export const GroupProfileCard = ({ action={ { - // window.open(entityMetadataEditUrl ?? '#', '_blank'); + window.open(entityMetadataEditUrl ?? '#', '_blank'); }} > From 34352a79c4f2c397e7d21f2aab916ae99da698c9 Mon Sep 17 00:00:00 2001 From: "roylisto.pradana" Date: Wed, 30 Jun 2021 14:33:00 +0700 Subject: [PATCH 103/204] add changeset Signed-off-by: roylisto.pradana --- .changeset/six-birds-approve.md | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 .changeset/six-birds-approve.md diff --git a/.changeset/six-birds-approve.md b/.changeset/six-birds-approve.md new file mode 100644 index 0000000000..ce666dd09c --- /dev/null +++ b/.changeset/six-birds-approve.md @@ -0,0 +1,6 @@ +--- +'@backstage/core-components': patch +'@backstage/plugin-org': patch +--- + +Add edit button to Group Profile Card From f0863735d90c35805cbc9129a7dd11679290ceda Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Fri, 2 Jul 2021 11:43:44 +0200 Subject: [PATCH 104/204] Update README.md Signed-off-by: Patrik Oldsberg --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index f8b54ad200..895106c967 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,8 @@ # [Backstage](https://backstage.io) +_During the month of July the majority of the maintainers will be on summer vacation 🏖️ Development will continue as usual, but expect a slower pace for discussions and PR reviews. Why not take this opportunity to [build a plugin](https://backstage.io/docs/plugins/)?_ + [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) [![CNCF Status](https://img.shields.io/badge/cncf%20status-sandbox-blue.svg)](https://www.cncf.io/projects) [![Main CI Build](https://github.com/backstage/backstage/workflows/Main%20Master%20Build/badge.svg)](https://github.com/backstage/backstage/actions?query=workflow%3A%22Main+Master+Build%22) From 67adbd46bc0dcc6ffd6d27dc76de0719caf45768 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Fri, 2 Jul 2021 11:55:57 +0200 Subject: [PATCH 105/204] Update packages/backend-common/src/reading/types.ts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Patrik Oldsberg Co-authored-by: Fredrik Adelöw --- packages/backend-common/src/reading/types.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/backend-common/src/reading/types.ts b/packages/backend-common/src/reading/types.ts index dd230a754d..ecaa582612 100644 --- a/packages/backend-common/src/reading/types.ts +++ b/packages/backend-common/src/reading/types.ts @@ -63,7 +63,7 @@ export type ReadUrlOptions = { * of the data, usually the commit SHA or etag from the target. * * When an etag is given in ReadUrlOptions, readUrl will first compare the etag against the etag - * on the target branch. If they match, readUrl will throw a NotModifiedError indicating that the readUrl + * on the target. If they match, readUrl will throw a NotModifiedError indicating that the readUrl * response will not differ from the previous response which included this particular etag. If they * do not match, readUrl will return the rest of ReadUrlResponse along with a new etag. */ From f96de94864412a17132bae73f3d4764d4932f4a3 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Fri, 2 Jul 2021 12:53:45 +0200 Subject: [PATCH 106/204] microsite: add display of no search results Signed-off-by: Patrik Oldsberg --- microsite/static/css/custom.css | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/microsite/static/css/custom.css b/microsite/static/css/custom.css index 6404b25251..33d9a43556 100644 --- a/microsite/static/css/custom.css +++ b/microsite/static/css/custom.css @@ -137,6 +137,15 @@ td { color: $navigatorItemTextColor; } +/* search */ +[aria-expanded="true"] ~ .aa-without-1 { + display: block !important; +} + +[aria-expanded="true"] ~ .aa-without-1 .aa-dataset-1:after { + content: "No results" +} + /* header */ .fixedHeaderContainer { position: fixed; From e5d765f41969198c50fcda804afdccc1937de9e4 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Fri, 2 Jul 2021 13:07:58 +0200 Subject: [PATCH 107/204] microsite: fix search box breakage and avoid unecessary wrapping Signed-off-by: Patrik Oldsberg --- microsite/static/css/custom.css | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/microsite/static/css/custom.css b/microsite/static/css/custom.css index 33d9a43556..ddc1239efa 100644 --- a/microsite/static/css/custom.css +++ b/microsite/static/css/custom.css @@ -146,6 +146,11 @@ td { content: "No results" } +.navSearchWrapper { + /* Prevents the search box from detaching from its icon when pushed down */ + justify-content: flex-start; +} + /* header */ .fixedHeaderContainer { position: fixed; @@ -155,6 +160,12 @@ td { box-shadow: 3px 3px 8px rgba(38, 38, 38, 0.25); color: #fff; } + +.wrapper.headerWrapper { + /* Keep the header stretched across the screen on the mid breakpoint, since we need a bit more space */ + max-width: 1400px; +} + @media only screen and (min-width: 1024px) { .fixedHeaderContainer { height: 66px; From 228e294d5bd7b74d5687102327e5fbcfde528cda Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Fri, 2 Jul 2021 13:19:59 +0200 Subject: [PATCH 108/204] prettier Signed-off-by: Patrik Oldsberg --- microsite/static/css/custom.css | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/microsite/static/css/custom.css b/microsite/static/css/custom.css index ddc1239efa..2c8b46ff00 100644 --- a/microsite/static/css/custom.css +++ b/microsite/static/css/custom.css @@ -138,12 +138,12 @@ td { } /* search */ -[aria-expanded="true"] ~ .aa-without-1 { +[aria-expanded='true'] ~ .aa-without-1 { display: block !important; } -[aria-expanded="true"] ~ .aa-without-1 .aa-dataset-1:after { - content: "No results" +[aria-expanded='true'] ~ .aa-without-1 .aa-dataset-1:after { + content: 'No results'; } .navSearchWrapper { From e4244f94ba973e0f72143b93c8a0e36835991a9d Mon Sep 17 00:00:00 2001 From: Philipp Hugenroth Date: Fri, 2 Jul 2021 14:46:19 +0200 Subject: [PATCH 109/204] Apply sidebar changes to create-app Signed-off-by: Philipp Hugenroth --- .changeset/shy-garlics-tap.md | 5 +++++ .../default-app/packages/app/src/components/Root/Root.tsx | 5 ++++- 2 files changed, 9 insertions(+), 1 deletion(-) create mode 100644 .changeset/shy-garlics-tap.md diff --git a/.changeset/shy-garlics-tap.md b/.changeset/shy-garlics-tap.md new file mode 100644 index 0000000000..7be84ddbb1 --- /dev/null +++ b/.changeset/shy-garlics-tap.md @@ -0,0 +1,5 @@ +--- +'@backstage/create-app': patch +--- + +Use SidebarScrollWrapper to imporve responiveness of the current sidebar. Change: Wrap a section of SidebarItems with this component to enable scroll for smaller screens. It can also be used in sidebar plugins (see Shortcuts plugin for an example). diff --git a/packages/create-app/templates/default-app/packages/app/src/components/Root/Root.tsx b/packages/create-app/templates/default-app/packages/app/src/components/Root/Root.tsx index 5e5a71a635..d8665a2f9b 100644 --- a/packages/create-app/templates/default-app/packages/app/src/components/Root/Root.tsx +++ b/packages/create-app/templates/default-app/packages/app/src/components/Root/Root.tsx @@ -34,6 +34,7 @@ import { SidebarItem, SidebarDivider, SidebarSpace, + SidebarScrollWrapper, } from '@backstage/core-components'; const useSidebarLogoStyles = makeStyles({ @@ -82,7 +83,9 @@ export const Root = ({ children }: PropsWithChildren<{}>) => ( {/* End global nav */} - + + + From 86aa88803313305e8a39d6968218689d5b90e2ad Mon Sep 17 00:00:00 2001 From: Philipp Hugenroth Date: Fri, 2 Jul 2021 14:54:20 +0200 Subject: [PATCH 110/204] Fix changeset language issues Signed-off-by: Philipp Hugenroth --- .changeset/shy-garlics-tap.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/shy-garlics-tap.md b/.changeset/shy-garlics-tap.md index 7be84ddbb1..58c660e864 100644 --- a/.changeset/shy-garlics-tap.md +++ b/.changeset/shy-garlics-tap.md @@ -2,4 +2,4 @@ '@backstage/create-app': patch --- -Use SidebarScrollWrapper to imporve responiveness of the current sidebar. Change: Wrap a section of SidebarItems with this component to enable scroll for smaller screens. It can also be used in sidebar plugins (see Shortcuts plugin for an example). +Use SidebarScrollWrapper to improve responsiveness of the current sidebar. Change: Wrap a section of SidebarItems with this component to enable scroll for smaller screens. It can also be used in sidebar plugins (see shortcuts plugin for an example). From eada77623e9c780a6bcdb4432dbce74df2033c0a Mon Sep 17 00:00:00 2001 From: ImgBotApp Date: Fri, 2 Jul 2021 13:01:11 +0000 Subject: [PATCH 111/204] [ImgBot] Optimize images *Total -- 922.39kb -> 715.96kb (22.38%) /microsite/blog/assets/21-06-24/backstage-search-platform.png -- 270.48kb -> 131.16kb (51.51%) /microsite/blog/assets/21-06-24/search-results.png -- 115.74kb -> 87.29kb (24.58%) /microsite/blog/assets/21-06-24/jobs-to-be-done.png -- 536.17kb -> 497.52kb (7.21%) Signed-off-by: ImgBotApp --- .../21-06-24/backstage-search-platform.png | Bin 276972 -> 134304 bytes .../blog/assets/21-06-24/jobs-to-be-done.png | Bin 549039 -> 509458 bytes .../blog/assets/21-06-24/search-results.png | Bin 118514 -> 89385 bytes 3 files changed, 0 insertions(+), 0 deletions(-) diff --git a/microsite/blog/assets/21-06-24/backstage-search-platform.png b/microsite/blog/assets/21-06-24/backstage-search-platform.png index bb7e828ea9b1b39715bcc276d83bfd3191b1318b..b83b3aa0f4069331db5dd30ae510d563a0facf7b 100644 GIT binary patch literal 134304 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

  • vMEoKO#ZBU)O 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 QpCAW#y85}Sb4q9e0574WHvj+t literal 276972 zcmeFacUV(*`#(;{Q`^T@+ghaxLIo8C0jr>8rd5Wbh-_uWDvIn11W3rRwJlYI6cwo; zL_t7C5(NT=kyx#QAVh=^S&7OB5FwBdLI_EI?{}1r&m)vSe*b;tx_X5slylB~?(rJ; zp{MunbNuMPtNyE@q4Ck~U3P978oE0)G(Nfb{(In^i+-|v@bbZTyADQcXslQV|9NY- z+uAYk=3CKjjyp6c&DulYU)~M+#`zl!jhn>9GvEG4<6VpIciVmA5&zbUo;}M?eXa5C z?;n|#K3eRwxzs`Q?3VHOMU7{Z@T=>_S0bXD-va;jJYUvb452jQoq2u&d~|5smL<03 zpgx-a$4)ZC=l=nXO+P-G|9nn22#%@6kZ2Wo%x-@G`)V`c8qs&Bt}lJmux-xnWGwKzkZ-6N%Xf%)Y+Ki8qm$jlk^do1FMF5-Z-( zmkHCzCOKuSVMzQ?nfPnkXF;{GS8DH zr?a}EdDih?NyS4Qul=pFZ{B*C0#|(J`MUl6Jq-3pGWGY%(Ib|+E!^Pc3>Ef%ZhIR^Y_5eUyO{TTDOYF?8K_wrf73CTb*J&wo7kUx7+ zMi=TL=3S{pJh@4FvVm&-Od8~LvE!Dtmh|n+mgSqS>@|I~oX}VP%ezsFt5UCa zg+%YGw}&FWJGp7(iLdh3cJCamtw|R@|LF4%0?jV%XYSF*D zvn9WMBzWCtzS|s$+?o}NQ8Ckw`T4ESjhVmgp7*!VuKYUh=NcM@ZR<3i+|Gy{{Y9tR zT$^mV?HapW^62~HjR^@kL@MtW+f`K=^ZtsW!UY}T@D4eB>xd`Y70VBMN0#x!U$~oLP+d^wf0n{8#enzg&sN zl^yoKOSt;z;7F+dya8%bzMd`B}^9Nj#kU4_+KJMqC^gxlp&QU)vTF3LrI=y!Hs%Gvevo#e?%*9Bd~J0OdW%k#dsbCTTq z`M9kP*?(~zKk56VmJS2=d9&te-GWX(^uVjr_iQZ|H4cj9OLM?wcSWG7Rkt9-YZfSEu>ZsoO0^PYMI>gPGLqs8qz_iEj-<9d+7{_mxGjmSc!V`og1bxI%$sa+D{2#J3@j1e0gr_?47~pIjPlf=Jc$=1xcW}vMYGD06y<0m z;S63ON7#w^$YJS!<~u?=Vh#fUD|F6hXE>Xra#OoX9m`)sIyg+#&WUk} zRtwuU;5CQ+^R3$=S>Jh=oP`Y7uRl7@wEo-}g}N4!ft%ihk;c2k;3=1ju7Ycv?r^Ma z2~S+=AeAD2S>d~_z^7FDV(2(1Rm;f}$QTS(Z{Dj6b^q5WT;HRy|38_ll3ElBO?AaP z|80)A8>8{6Z(^p4PY+Vu4RS#q?4wzTNrnr3u?~j&t(8 z!4@zK017C~SRcttO34!J3H^P>&tm%cV93N!{qYG7NSdbbYIoxf%;4AM{k1kNGjv@f zGxg87zvi2hon8y-us^*1_y=K4G@s5^cXT;Oge2okcjN1(+w7#$EMkOJ`IrSletkPA z;C-(-_@8fm9lmkiVfG3Nc|FR%e|TaL%yxIdq=))m)HO@;B!e==qLv}*`kaIWP#3tV zZ;IA|IOH<{aTqKX%wA4>ZK^?Oe*+ zdRD5B&v^1{$TwgdaspibWx!ssTo4vH`Urrkaz(?_I|7(~_nW1T296HPRQ|RmydJ{G zJzWXw)g9aTIMZybGnD_ypO^NUZ@iETsk^Zy|3HhYta!Rv+AE!B%0b_mcy{~VaodOy z@Aq<@$zAT|G~}vZE~<{Mx3saHKiSy}f)g_zI$Oor5qnmp08Hd&o}48lLZE_Y05s8( z$+Y;ShXbw`v>Fd*$Db2(RJW$+4W`HDg+Vt;7Zm4880T5=>e&i1XRxpS_+gpNDu67M zA$pj=_zhK^d>a*k$*}&sHaf>(-VSF}ypU;g;D^6q*}rbCQ6y-f7=FAQB2bfUBk&_QRCYr~ykJIkoV{o^+_P!>6{(8%6 z--0sf9f+milmb}2aMj=Nl#>V2b}30R;Q$!bMK5r&fDXUEX_ZWY@a|64OqaE65 z^y>P2N�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
  • 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

    v`&uof3A#PxwPIXG|%6=?c~o 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

    c*puZ)fr>D2RCDEdcjJ&M7e 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 `T2 zx&TjHKkVq91WdO;-3k7RpvVd}IBSyq|y} zt36<9{GM%R*=>j0Fu`zh3J|fJ!Wv&Y&Ra;&o z2~A95bPh%V?>#U;;a!Jt6tq@|KJzdhHQpt;`&44q0$9$*;8p2QEXVh49R(YGC*?CD zll0)bmAh06pnduk)Ez2hFW4j_AHlqrb!iG+&5JN0WyU`k&DbWF3zk6Zc{q*0t*+8z zzoZ6dWl9WVAPip4SHku68?tiP5_p1kFy$COB__NkuFsO?kS45gE#%?&;PDyG(gv1z zE;9*;TqXRwe8LGC*I*ft7(^mKt)741?E3m3!KKJ`nenwo7c#R&n_FRcfkRns=7^>;V&$HcF5Tty=EdQ4N@Nm*pL2@8cLivS z*nRPPe;^s(mV-BR)6?`l>4irP_C0cdp_STPk#rRfbwJZC*_fc{qP!#%*65`X|BDV$ zyx?vRktC3)=t15e`WB;)l5q=y4bapA#U@^ud6c?9E}}$uLn`*g=@OH!?UNPlvI+3S zJExVT56*l7sP=_S*x*+eor)Xo7_`&?PtfH`x%k!lF-5>oh1BMJq93|MVN)B zj40r@+>#^Hl9^yI-VJGMR|O|!6a0(htkt5OE@Qy4O7c_PkoS$bQuS#Y1fGjabmsdw zwi}Sa1!yd!8s#Wuz%_y~oW$p0N5pN6z8gjPLkMb`W(74a#D~qIxM0Y6Xv6^(G(w8d z#C&gIy_HU(UkZ8yXN}>tAepJiodZRoed0M4e$v*4`xp!wJXE?C4d41OnF* z4x(neQ|&PG;I)6J<;K>_`HYe{nIC?|vG0W{c ~g7Zg^%3+TXtiIl`?IHY)0j5Hz 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

    mFA)%+>9X{J5$BY7;!Z0L+5^=0bLJOu3;8Hf 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%0AseTS+kPLKvUk@?wg_5UYdgKW=%l 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ᾧl`bdpE~V}J|xb3NZzCG z#s235$X6?JbgMl2%lTemtS1z{em z>IWp1C$4jo-AvLZ8%PMo@U)+`dp`&sxAUqml66uv?Px01+ z<*FU7oM6XuzOJIVvkCLEaZFpL*0h7lB9{KUACMb2j{u2@;_ zgt7JTfqKx&ks)DnNC6%iCh}UZ%J%rzcj53sZ_U1I!MvoNjM@cN)R58q>FI3Th;(<0 zm%*)i*NzdEy6_#;YE$wHOwj_&38eS@bdx1v6i2z&=~-`F8in7F5Z902)EWfgbU^Qc z0pvXnnMVR`cz+Y+-9-crk|FRHs%kn84YAYDgwGH+T}tvp+A_ppv-?%;YkVLhi0>LFzI`m3IRB{H{q?wrtg(!N z#Dq9?pf-CdR})tP*J$O)06ZJz4rTX{8b1)fJj4Nt1SIj8jb#dtRH7u+g1r169gE3u zyWCGFeaD;@#ajVeMS(gr1ry4$5o%$?84#KDvT5zg3?2dt;(oC>}2;*2Ey(CmU`DjN3 zpShXp2ji1`F7nC$azR3` zu2Jc{ysJVxidXtN4D-AS_c9thl5#nnMtMGNv8K0DBiFL(c;I3^6Ru3@ZAX~Kzu4bm z2c>bBI_(Sco~JU29kLZcp5xFDchH6ggL7ZvIyL6-1zP8sY%=S#FC-U|vMOB-w2pY% zwuEBJ*mX`2Yvt22x(X%E)c7Td<~BhqW$hv=Q?|@Fl}vYXR%oF=;H`W zp6QfwcvZUIIXLx1Jt>!0rWQ3TW8i>LF);GE&qM^0;fVk}Z3Vatpaczk@IU^(%X;9q#eCT+dq3-uI!QI*sHK-nvps^<6uZ3fvorz6Z!heqwHF%%?PL zQzGuL>P74bq*RbAWfpL5AWD$v@BnCGF2qxHwZqTvI3Td(BX&*#p$*n@QpCQKYTi67_vB1-K*11mVVWQ|&{b zHioefYC*nkM>*QHj0)N}aQOYrR*1n6jV)Vl_W=G`J^g>z1D8~8bK%<(Z;#f#$RWS~ zKff^*+Clth17eLmgX_FJ1XNz2w+H9#R${<%ZLbEoy&=w1(uEJPrdRU)-LM@I*qmcwVD-2L*e z`i=-{{hOV|?RL4B#UgDRp3Yhz8Ricr`gG4uOzKx+P^tZ2)=v@syzlUe3MDX35KwH% zrn4%CYFAtemq+}f(R^(T%0R{i;oIq)q$GTmDg5g&AtE>Y%Q!eP=J~@darZC({*YFf z08sy}3H(}2HqsCLga_}D8It(gL~CG90n4^3w#N_>UW;%w+%=*F5ZE-_=tFc zPoV&Lt^A;uR62_I6j4?UikB=+WMT#3)_&>#^6e<$wQp>hA|BrXNSe|b{O!scR1+WV zr`xrNhyj|oM1SPl(cvd7T!*cAjbWnEe0cfa;avVVFG+;~plAoH_;B?tU)WdWCj$k* z#$J)Xg{x8ZPd_!nko=t)6oAXO`0(YuCv8Nl_WMSl>mh=H2%Z<#G34?EzP)oNp2f6Z zw!X3W;@Nz&^T5h5a`_Fj@S1hzk(C-x!-FGtCfWr4a)>I3q{3ybBK|trzXUMzXTm|v zSM?w>7QDTb|HDJakiu!(L-VYuXsif_KNzC zdkQc8saZ2_@xDD2aSqPn!4JJ~%>fYIq_k-&Py6kiz`uM=Oe6^CLYmRw-@E{&3G;s? z{IlEM-ah@qj+t7b%Y{=$R@^ea(EB=ZeLfM2Gx`V`g(E=!iI&t^V!;cf{%=svq}B#; zV@E$B7^%G$jl_k8q2RTjNQZD8e2QznIioE>n-qTkAOV6CVQJgg=7=5HbA_1c5+qHB zk8x2VGajw(QFz&4Yu%mIeWuM$-m|k6^E6(~$6;PduNyT)0f^6qr*oGI=Vq|x1j$C5sAw+kQj3N4 z#=a|7Af{l?I1z3S+Ut>#N`Fl(z>6JX+kmjidqBpE<8M(JXNkYW7%moi5H3QbgBP2; z#O3fxB5eV!oQUqUuY@dQrb;X_mw?lTggHLH)6>*$QAC43>K%}n-)sIJ2CJPWqLK8+ z8pQJ+D3oZBgmqR@Sn$HHsJN!%QlsEmx6W(lX0E70ZDq^Vx}k3E??1CgB;prIBRA%d zenhSjW>FXq&LV=MaC<>ULNId7aly8q$c*GqIN>D-JoQqzRo{nFj8Q^gP$3$Dr4f)EY28tVLT34iozz7!Ebxe!=;@kft$+17_N^@|RN)L9GpgbH)%;4Fd`AAllV3Cc}`6K(?!x=!Q?j#z>Iu+6{H~ z-M!+D4oOgyT8Ijpp}_c<Wk zI6YGjRbVGWIPZ!?g{{DXw=5Z6~CTmjSD&Ug+4SWT$gn!9gI z<#_X-E)i94mg%R(Y-thqKvh!#zHhoa_`Y+j#KnK+n|(d?=GQo4wn}iRa(WjrO@X>O zy6GO+tBXh-bk)oyxT~1X;bEk7?|Ag#Z=uS2enzOWCn6FSGk-!w!FV`~g1cRNO$g%{ zs9}tcD)knJ$MH)s1qE~7S|wAKM*`SXp2>dh__(^M(b%`2ToMPOtEmz57})r)+NKju z`#EM4aq0vK976L!MpKbeBb>D%^z7tvPNr3A{9>eg$Oa)PA{CCjihEf|T%cH`m1&9m z(NV4b&*Kh{5KCyA16T-UuS5o}+)4t6{NyQRAA;P~e0K_}!Pze0HYh(H377}eD3n=VUNh4(6a?k- zX!YON$((Fd=@}|%z%U4BVIRvOJwN-Zc`xSZ%~?^l|H-c~n#d@5sb!?Y9Jcv>X$VvJ z4I%b@t3d4cE%NsViKCmyar=2vPCbaT7FvdVnVCp7!G4~27QRdoAp}{NlsPbqXlriC zF&BzvnbQ4L?uK22>0z5Rf()kTeF&9{b>D|rUrQ{n6=W=%>FJKSginj2j%@1Y+^AX= zJHv>WeQ=b3X%#$b^}Hpp5Q^babpOwT!~S^6PVMmRqmms% zLAz5vQC#aaUNI;yLH62qWZ&>Ane?$)C7Vu5$tvR97?cl8$k58T50s@#q~;zu6?=2X zZQL}sd8DO^m{#jKshmKh*>F3_*DPugw7FwmY7 z_OUw2t6Fs}lr>@U#wVr=805EdO{@5Z{Hs;;PQ zc^oi`28RH-L<}p;Z#lhq8BROCODt;TK17lIxpVsWZz;+!VyDx~oRVIJfVw~%moi!U ze&{q+Xd{q~@n>Q30m0er>r!#7)WaZ$DO^q@z+5H=;C~qBSDa`E1;f+!s;EEL%o02N zJEBWaNBG=!R%Ko^=71#C-V`9=7@_qO$e&6&B8c?lWZ6~Q5)&VsKXE2D?B5wUG-!Su zegl1&iARi<0YxF!xk3+Lhcf|_MBYBd<6k@)x#D&L_Vd#7M<|jw_9t3*W}d!62hxd# zQ^FZm2mD39XtZea*7arAlJXJjNu+j7Rb#Xg+3vI*3lY3oidd&phQl&c9HH+(EdR0h zB!2!f?h(74h?zh`6uMDh!{3_WNhCda&RuhOH|{yhqGAcN^D*HVgDxDOr|6eEG>=H9 znYHZL5Ms^Fn@z<&S((sf>NQ^pRd6&Dk4%Fs$apOZgLxSQx$F2laDM;1`{#nd#gPt& z^>h}@uZPh?D65;+KQKx9h8}Y1rdOP8QIz>E3iqYzLZ&Ss?skm`uYn zFrN|lZh?K+0;HYoxdIt2*oqx}tE0t7XnG71lGkVQ&t^6EHz8_7h`TSl4w@Iy^1eRVXR zc`^Gr1fPElw@9pYQu1gofzSfY&#_J0ViJ7xsa2P)luk3BK!2$rh@=VY&(o%Yli2EN zC)Gc7RU^G>>eM`BIUZzk)c{E8=dza(&VVpkbELx|`>uMOVu|AvSB*Kfkfk{LugtiQ zj{KPT3uy5I7`xd^6SKC61+hFc^dK`NkJdX;GKIVU9IirK(0;o86ccl`KzC!r1_vT; zGgaxf zur;R=pAr7>wZg~LSULylh}|ai5Wu#=&|u8{diI*^HaPgB&|wxnJrTw3ytf%Q!6~{z zun51U(84ApFQ1|0_Y5OM5rAWhG1IeiBk=pcNN7xk2Dklp^=x^{)M=ZgrsoLZYt_(U zAR5)Uv*OWc9>8c6uQr05o&5SusDa%R)fK(&y@w&fQEOgE&{U9o+bg|92eer_=iFCI zm5|H^_V^9+6rc5)c?uOibVAX}nLLk^^A{y;j7QDOAtF)qqxA|T9m;7(pdoZ@Q;z#ujG%R8gw#qqQKWnrzIVb@V9l;lW?B!4Q#>=gBWKZd!1_N-4dDe=J`M*#kJv z5KGOJCQ1oXrm38hv|S1-R^na7i(e%AFIcg%?M6>pQZ2>zHY-;`yIcD8S63n*`E zuz=8!5vAy=Vsb%P*hG4e*d-lACFUJX<=W2bV!Y}_+bJM1TLaj9APXR$w4tbhWClqm zP}ro>*U>;LhSEkR)6$_bJ2~q=$BX}d9mV*}sjULYEO*tyU~7XHP5(JL?~f=D@$-KN zTfXisrY8Bk1CIO8$IRj>@!O^UqMrzzGJO0=jPv~m{g?Cb{)p|#u=4w*`+kr9 zeS!|k<=>Hd;zux^{{`Xlz8JkPMsMi9_f_|O)txr&H5vUHetX{;ApvLV&zrerQ-Ar5 zA0>W%Uv>W}4*UOGQ!f=#RZ z+Cd0prvBXgPL2L;{fDowih;Y+it(vC(@-avW!`D-7e%j+Yes~xo@>XL+p6BD0A6)!>+zlq=&1sQ+-Ru4S z9;bbYIh3_}7pMJn+S=f;!m6#)ZXsoV>UF1m4Jw7`-ux|TF1QZEXVb}^hK^Ubo?906Wo2L@6vbpHAEa|89i;J0^w?Ek!v_5Pzw zd;e7am;2`Z0(-x}{-=fc{Q`Txz}_#gcWYwa@0Is^<^5iHzgOPhSN;#UQNAz6?~C#O zg~d4Y5{ui{H~AU|+6t5?#e3-o)8=LR{jK%T2krkJg1JXb2*95&FO$1M+A!I8KPDTW zj-GyT!)pWx|Ifbxdaf;}-ZHrm`1!PR=UIU(&&vKV``@BTo$X=dsCAzG1nrI&d`=gQ z#7>u#9Sb$s{2Pw-2#}P{ze9Rn|FfTpTi?7rYlHu%z3U8XDqGi?<55RZafWeFQNap| z1t}sm%t1wk5gZXzN>CA`DEpl}$9`Do$p`l~?sl^p*u$H%C}vkxIv|1<*zp4o{j^`a9XW5+A31+`#Ca8Vb9OTUF~I?d znDZUiYRz-ct8`*8t;*QB{RVa^20vRH%^Wmu1k$mXbmm>mqm%nZ%eL}%z5{;F_E^c? zC*|xx&RrPbOcwzD*jB=u_gxMAN%!s}=;kJ;1?QzE-8~)yehE^ZCzMu3V@c*! zQHchb1>As$QQPA*(!p#tkETU)_w12z3wO-B4RQqe@bq7ZOCZPQKj?DrqJj^D?_MjB z005uW`GFTP;4_##VmwcVPpK_M5(9kd6~G=oHvfGclJnpO-<9Ga^4(HAB)-!RLE^hl z@u2t~D0oPG4-`Bk{{MlZe!XbqVS3L_C1l9C4~6%4A_-7!X=PLvwT{@ZKkxEX$>&hH z#Z67j9`Y`!W5hsVgCFV9rnD!&Z8$@ms-shE(pM~QU!jF&@sAsFq!?{%k9`6?IJ#<^ z<7er`ZKalQ{)>zITH9UH@ko&EaW*L!HxOTyd$F%sNO*{McD|8}ADV(6CDmKoxZ7&m z=rKtd<7p#(`FVsA4L)xP9npH2;Sl z5w%r3%r3eTX+Rs;(xG}t*%oeXv7q%YvHHags-t=o9hQ1#l5+AuXyW3r7ee{eLtHTG zyrVOLqQ^?b7AQJiY|>lYTIw2Aiy3%e z1ns}+zu zh2VL&ync*pK-XD{&CsT@XhK)23K8F6oB3%e?=<%vEbiyaK@9b`0_AIN)$L4xWEHDb zQh3=i8>lsdy`Xtim{8(AzZtrl$majhJoEiN`I2o;y{&+{bfcx;sAmLLA&c5E1=^=a z&AwOC6D1SMU=7GSP}W~`mlus7)TUM@GK7V#MY5&MAlr7fqQmPH*1rpsbI5R9(^EyV zXx6avfSK@A28F)hjrvHG3$-B_XsgY%9BMvrpcw+b7c3{|(efJJRTL%?-Bzykq=?-$ivD%`{S$dpjv8qU1e3LUN_ORC>??Nl)Ffz*ZvDwyIg3BhdqZ zIJ4eSFk}evT2l>R2jp#pzZnLS!C>oE_e$3VRVXu4b-n~ zkJw#*gAN+D22(UT4%S%07s0>qeuHI()AUHVjQa`TyaE&CO$Ex9;CU#UmufhWfM&O)nP_tRP)KPtn6OGl_uNSE1oeq)~fS z91f{6I)9z~4M?w$7BYBl;`*CrY4B9gg)gZSC`4wDnXUfH*CxgR^f)p4qu&uan;bhl$?^d()^qJ8L{PZ`d6pR1w87`C@Y?sVEd}r>MSI}mrOJ|BwBXC5lee3H3(;j?- zquViRVPJ5atF;D22cP(o_4Ss`hY$@oN_|A3KmIvIy8u5}DHo|u6J&fC2Qa}@dvy;L z{f{CIabx${$d&{*z=M1ALpW7JJuLfO6!)63o}0D)}xtu4d_BR%^Ytw0F1O6w1ga&`7_ zd=HyW7TrXWIw~iAq4hDLsj;;egi)8`{#g1lK0_#>hB#AQC`^gUHaD81cEOi1Bao2! zI%q8DQ2x=yVW4J?OzJfM4i@7}zBud)TDS!rN=ntuqi5?|kSMxczld)Js|6k2Q+q!S zR24J=9X6E_fE#IGw@5*8C;;rm&XdWj-_x~oQi$Xc;~+t5I76m(CslvB4jaw_Em2<8 zfC;|+J4JC!Lwap&2lr7)s0$j!-^!X2F2AfM642!DJ7ls1w1ru4G>Pd<S49kn0QZ@&yD!rn$6s|(6Go4hx|1IpJ1TMWN{fSYc>t!KZFD#IQ%(}~(W;Hs7H-a4dtq0WY zO}3f)mMxy40z8n7cch1UsY)NXfkz`Zh380FL#AH9RMGza&JqEEj=_y(gvn`&V7@c# z%$$o~Jbgt?*#_RCIXA9=q00rF?;CEAfg~@KLj@t%(r&(6H)8`N$2mH)1Npr&0NkBC zKekTO$8!#?4({Jr?KRwdEK*e@I6|F~_P` z_(Bz$halR8UHZ=X0oI8UHWwP12iQ3*P($${+JUBi7SZ?RpL#3{hejP1@U{G07I8=q zb^r`^foIBtygAdN{f(TJU?oYYXX8CbE7rk6F|Hv(6>7h@ zm=u^R=+?VgQeaGqK07a$m|3k5L~d+tO1??~i+>o`lc-Nt=+McEjL(UZoTR2Q^^!1A z12P1hLUa@nLzomPV5PFY7JM>NrwQ0zn6A{M8+?L83uf1CBr{9hzVCm^+9D4NQaLcS z@HepfV4Q`O*4l#35XbRi-{E1PG|q+IuRan9C!9i4G(Ofi_f>ojQ!vQ+a~!NJ!=v!# z)-G*O6vBWDDD$TG3Yur0^M@KB4!~BF%1D3_0vD5co>4m6pC(h)mX>5C!M+(DLP#D{ z%dO8?zt{?DI}q{3ep46rZd6T9wBjT{+|20oo7>xAKl=+^%I$d3ZcE7O>s$g>>A=bi zVWx(vq6O^wuTg>esI#NloRtTFXLP1&$e4b@A&;-aO4K!XXDJ>|9V;~gOKzYs#ma6~ zRQ@G+0`LS4p2oEXx$UfLweRS5#vO7&>=K(dYX%j~;0_B)&d{RDO{A>u84<1xh%DEc zlHh}UCfWyAM z=+u`9KB>N3&e^lo~==b*4PU6Nh!E%1Mf0v?RWenH*1^peREWD8K?z;S z@|+>(<#CgHCUN#ESesm3Om&RRO++RsAJ*)2;N46js8B%RiZe_es(G>%*1LjpKLaD$ zX*fN8rQ#2rqm(7~<;QHC%&m*Vu5U7T3JZ&A4%@Z=S*YZde!VT-Kl=XFx%$LUd0s9j z$^`br-`VlQHs|+CiX9#hr;jS7@auW=NV zgcK;WYes~ckov4*7)V|(U3S30z+s|I@E%kojqXLzQ41&y?AzXIAYf0~(i4(!KVz7* zG1_$-EDfO$mF9!>-i{o$WocP2Q2AC{Np)&QX`ltHa_A#eWvzJA{@gevHdS+~EtU~+ zoaVlIN&AOqkW_0+kU6NHGekj;l(B0i5+rMz-zm+*x_frQGJQc!h7+M#Jd1m!U>bx= zm2LsTd3^JMU8N!f6$qCS-wcQ&oY>V+mSHq7FnnXu2ezDV8qXoT5*ixi z-cllCLE}WL*GaN%r*=JrVM-Q5^cK@xJ@sI-gzbtAJ$7#CUv;~~o9Yr^CH9ITN|Y!9 zy@}2^i3&+U*Pccj1sPRYK3D}R5i_J7_xN_gz1^>-J{U-(GO}r4VB^o6N3R8gSFZZI}m}%N+bxyIW2&oltnc%(HvzLnBi1^^-M-XF&j=$(lfQM!9x zh%A7I^YH-c{ie4}x6y`tM#>u+?tm_?vHd4M44H0==j#%PaA>c)(a?-@-dPdg&gVC% z7|@0WyRu*-=Q$!;C*NnfI3zRL{|q>d|IN0$ce)|Ix)`=Xz%IlJCg`Pr=hVAIE&BRtCHY-g1DLl-k+5JlG zn{|Lgn+GhFs+a*MUpPW$7E?jHNUx1{wT~G-*4JMK(ny2cSz*B&yS}byhhRN!j_4fF z@X)8*`FH0GV!J38rp-ft{r;&Ray7MC)YW8zPsZ7%PYqtc34RW-$&#_CLWbx#nK#KiwNQ>R>m-3rsA+!rz2^N@n1n5+29of4#Nq!jk>c0Q^; zK#U+}r0gbzf10)PS`f)yof&C|{{{B59yB2s7knugo2^M(n*CcWBURoiDYH#;=NUfH z6HrLYWfi2`N1JIN(*j5{u=+SfdzqiKdtrc;6T=|21vQ+@=ku>Omd^wtg5~Ekjo{i!;9g+xi27X<>~|m2$R@bFAZy&vWU#C{j4? znCJj3*D=&fUj+OmuDCIG-qa<2bs&t@U}Inp+E9V`>96|IfsCZSQ_bOW0I!IWn_nM$ ztHi=^1&krqFiCm-M|>;A-6@eMu&GBMf9=v!_jB?P{Zi2|zxUqAfoYb*hnT|CEPaAf zjYA?1P70~_5MJy}?x?(3l3V;Q4O*^z9a)w9=pWpn6@};)ZS0%LB(n$%{vgxRE`93x z!(+S<$CJr)H|n66{KzHMjL)Z8)9G}jjkynfp4;-8&A*$mof3qJ0eXvN z(gvO{@dPR)qIxQ?VoCjx8~;K~{%R0z{K8~iR5{ka7!DL(WRwbGg6_uzA4jao?iTJo zawz{o^<;fdbnzCLJ(wyqMLDb=7QyPY{d|~Hdf7Ey$J?7;fGtbCj4G^k`Szn?RU1i= zF+tYJ{{wI8K5(3U2S#-5dxUNH;-=2J>QvYJ*wcA%AAksrQV!1MWIbl8Ql9(ueglx*2fxdY| zhP@J4c>r$D#j01Z?4#R|;Y%#HGljgdPl_ejYAL6AB`eQZdsiW}Nv(@r-Ua?rZS`g# z#Tr{xl{%{+-U5u*T%d@DiC2P5o4hg3EkjHm08eCe9$~j@!2VbG9x<$#uW}Z1RPD3_ zRf04d8&{CDl@F4G2yX(`xhXB5VKN5_HSxcl>c)viGWsgF^K}?QJA45h-l!`7q*_L1 zkHtq9h}OUy{xuu{aKjsl8$p(I&?5-PyncqAf01uw3v}e0Zb?%iq{g+XWyIaq!zB7~ zm|EvfBGfW{pesGae9-}j;;=nE`~vW-=TM;ZdST9st!lfD?|LX-=?Io2!m4H1EZU^b zNT?$Z>iPH4R78~Iyq!X&R-c?fRbm2Aw4He3J)`jg9zO)hDPBGOrPj}4QwC~DTYlU$ zS6{tNu*tGBRD|X@z8ukDFE%ZO`nP&yE6Z>*@F&-OZlEMP6YI}6%_I^M3hl>T?Bi~* z>$N*xt=!y0yniT!Ffrkx#W#yQI*TAk%i^Rw-SG>u9zg`lsw=U)qMRq%aRa3F^W5s2 zr67siW9$BOxQxu0EvT)2(6@rWixqoWd^1%^H1gfQCeE@pp>MPl%kYW?#aNTi#piYnOc~+{`U@L!n^09^@*dWjwJoZ Hso7XNU)lU9PQpydueEB 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

    >O(zNuOb}aavrJ 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�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Νx2w5MM;uH0Hj&T^e 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%0D;)hN*h{u0|q=3cza5#E9?;);c`DqP^%yoP? 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

    >Wf0UB9`c_K{)fk+p*is9|F?tmtG^X8BR?OF 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 NZpllfOZ@Td{{WyMQ~>}0 diff --git a/microsite/blog/assets/21-06-24/search-results.png b/microsite/blog/assets/21-06-24/search-results.png index 041f86488c7bad05d0e5d583b0ac12078c702666..5524d89d7e2626ef82dc045f75a546db28d34c83 100644 GIT binary patch literal 89385 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 ar(59venG2%^y=nkXQXec_f+TNpZ@{qBZa;I literal 118514 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℞2`F<4`4sS*En>3 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

    CX>MP6kEh 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 E4^54V>Hq)$ From 4d2528ad4aced5c8163880ce7aa94e3e89d96238 Mon Sep 17 00:00:00 2001 From: Himanshu Mishra Date: Thu, 1 Jul 2021 22:07:15 +0200 Subject: [PATCH 112/204] docs: Document URL Reader Concept Interface Using inside a plugin Writing a new one Signed-off-by: Himanshu Mishra --- docs/integrations/url-reader.md | 219 ++++++++++++++++++++++++++++++++ microsite/sidebars.json | 3 +- mkdocs.yml | 1 + 3 files changed, 222 insertions(+), 1 deletion(-) create mode 100644 docs/integrations/url-reader.md diff --git a/docs/integrations/url-reader.md b/docs/integrations/url-reader.md new file mode 100644 index 0000000000..e9d6caf17c --- /dev/null +++ b/docs/integrations/url-reader.md @@ -0,0 +1,219 @@ +--- +id: url-reader +title: URL Reader +sidebar_label: URL Reader +# prettier-ignore +description: URL Reader is a backend core API responsible for reading files from external locations. +--- + +## Concept + +Some of the core plugins of Backstage have to read files from an external +location. [Software Catalog](../features/software-catalog/index.md) has to read +the [`catalog-info.yaml`](../features/software-catalog/descriptor-format.md) +entity descriptor files to register and track an entity. +[Software Templates](../features/software-templates/index.md) have to download +the template skeleton files before creating a new component. +[TechDocs](../features/techdocs/README.md) has to download the markdown source +files before generating a documentation site. + +Since, the requirement for reading files is so essential for Backstage plugins, +the +[`@backstage/backend-common`](https://github.com/backstage/backstage/tree/master/packages/backend-common) +package provides a dedicated API for reading from such URL based remote +locations like GitHub, GitLab, Bitbucket, Google Cloud Storage, etc. This is +commonly referred to as "URL Reader". It takes care of making authenticated +requests to the remote host so that private files can be read securely. If users +have [GitHub App based authentication](../plugins/github-apps.md) set up, URL +Reader even refreshes the token, to avoid reaching the GitHub API rate limit. + +As a result, plugin authors do not have to worry about any of these problems +when trying to read files. + +## Interface + +When the Backstage backend starts, a new instance of URL Reader is created. You +can see this in the index file of your Backstage backend +i.e.`packages/backend/src/index.ts`. +[Example](https://github.com/backstage/backstage/blob/ebbe91dbe79038a61d35cf6ed2d96e0e0d5a15f3/packages/backend/src/index.ts#L57) + +```ts +// File: packages/backend/src/index.ts + +import { URLReaders } from '@backstage/backend-common'; + +function makeCreateEnv(config: Config) { + // .... + const reader = UrlReaders.default({ logger, config }); + // +} +``` + +This instance contains all +[the default URL Reader providers](https://github.com/backstage/backstage/blob/master/packages/backend-common/src/reading/UrlReaders.ts) +in the backend-common package including GitHub, Gitlab, Bitbucket, Azure, Google +GCS. As the need arises, more URL Readers are being written to support different +providers. + +The generic interface of a URL Reader instance looks like this. + +```ts +export type UrlReader = { + /* Used to read a single file and return its content. */ + read(url: string): Promise; + /* Used to read a file tree and download as a directory. */ + readTree(url: string, options?: ReadTreeOptions): Promise; + /* Used to search a file in a tree. */ + search(url: string, options?: SearchOptions): Promise; +}; +``` + +## Using inside a plugin + +The `reader` instance is available in the backend plugin environment and passed +on to all the backend plugins. You can see an +[example](https://github.com/backstage/backstage/blob/b0be185369ebaad22255b7cdf18535d1d4ffd0e7/packages/backend/src/plugins/techdocs.ts#L31). +When any of the methods on this instance is called with a URL, URL Reader +extracts the host for that URL (e.g. `github.com`, `ghe.mycompany.com`, etc.). +Using the +[`@backstage/integration`](https://github.com/backstage/backstage/tree/master/packages/integration) +package, it looks inside the +[`integrations:`](https://github.com/backstage/backstage/blob/d5c83bb889b8142e343ebc4e4c0b90a02d1c1a3d/app-config.yaml#L134-L158) +config of the `app-config.yaml` to find out how to work with the host based on +the configs provided like authentication token, API base URL, etc. + +Make sure your plugin-specific backend file at +`packages/backend/src/plugins/.ts` is forwarding the `reader` instance +passed on as the `PluginEnvironment` to the actual plugin's `createRouter` +function. See how this is done in +[Catalog](https://github.com/backstage/backstage/blob/d5c83bb889b8142e343ebc4e4c0b90a02d1c1a3d/packages/backend/src/plugins/catalog.ts#L25-L27) +and +[TechDocs](https://github.com/backstage/backstage/blob/d5c83bb889b8142e343ebc4e4c0b90a02d1c1a3d/packages/backend/src/plugins/techdocs.ts#L31-L36) +backend plugins. + +Once the reader instance is available inside the plugin, one of its methods can +directly be used with a URL. Some example usages - + +- [`read`](https://github.com/backstage/backstage/blob/d5c83bb889b8142e343ebc4e4c0b90a02d1c1a3d/plugins/catalog-backend/src/ingestion/processors/codeowners/read.ts#L24-L33) - + Catalog using the `read` method to read the CODEOWNERS file in a repository. +- [`readTree`](https://github.com/backstage/backstage/blob/d5c83bb889b8142e343ebc4e4c0b90a02d1c1a3d/packages/techdocs-common/src/helpers.ts#L198-L220) - + TechDocs using the `readTree` method to download markdown files in order to + generate the documentation site. +- [`readTree`](https://github.com/backstage/backstage/blob/d5c83bb889b8142e343ebc4e4c0b90a02d1c1a3d/packages/techdocs-common/src/stages/prepare/url.ts#L33-L54) - + TechDocs using `NotModifiedError` to maintain cache and speed up and limit the + number of requests. +- [`search`](https://github.com/backstage/backstage/blob/d5c83bb889b8142e343ebc4e4c0b90a02d1c1a3d/plugins/catalog-backend/src/ingestion/processors/UrlReaderProcessor.ts#L88-L108) - + Catalog using the `search` method to find files for a location URL containing + a glob pattern. + +## Writing a new URL Reader + +If the available URL Readers are not sufficient for your use case and you want +to add a new URL Reader for any other provider, you are most welcome to +contribute one! + +Feel free to use the +[GitHub URL Reader](https://github.com/backstage/backstage/blob/d5c83bb889b8142e343ebc4e4c0b90a02d1c1a3d/packages/backend-common/src/reading/GithubUrlReader.ts) +as a source of inspiration. + +### Add an integration + +The provider for your new URL Reader can also be called an "integration" in +Backstage. The `integrations:` section of your Backstage `app-config.yaml` +config file is supposed to be the place where a Backstage integrator defines the +host URL for the integration, authentication details and other integration +related configurations. + +The `@backstage/integration` package is where most of the integration specific +code lives, so that it is shareable across Backstage. Functions like "read the +integrations config and process it", "construct headers for authenticated +requests to the host" or "convert a plain file URL into its API URL for +downloading the file" would live in this package. + +### Create the URL Reader + +Create a new class which implements the +[`UrlReader` type](https://github.com/backstage/backstage/blob/d5c83bb889b8142e343ebc4e4c0b90a02d1c1a3d/packages/backend-common/src/reading/types.ts#L21-L28) +inside `@backstage/backend-common`. Create and export a static `factory` method +which reads the integration config and returns a map of host URLs the new reader +should be used for. See the +[GitHub URL Reader](https://github.com/backstage/backstage/blob/d5c83bb889b8142e343ebc4e4c0b90a02d1c1a3d/packages/backend-common/src/reading/GithubUrlReader.ts#L50-L63) +for example. + +### Implement the methods + +We want to make sure all URL Readers behave in the same way. Hence if possible, +all the methods of the `UrlReader` interface should be implemented. However it +is okay to start by implementing just one of them and create issues for the +remaining. + +#### read + +`read` method expects a user-friendly URL, something which can be copied from +the browser naturally when a person is browsing the provider in their browser. + +- ✅ Valid URL : + `https://github.com/backstage/backstage/blob/master/ADOPTERS.md` +- ❌ Not a valid URL : + `https://raw.githubusercontent.com/backstage/backstage/master/ADOPTERS.md` +- ❌ Not a valid URL : `https://github.com/backstage/backstage/ADOPTERS.md` + +Upon receiving the URL, `read` converts the user-friendly URL into an API URL +which can be used to request the provider's API. + +`read` then makes an authenticated request to the provider API and returns the +file's content. + +#### readTree + +`readTree` method also expects user-friendly URLs similar to `read` but the URL +should point to a tree (could be the root of a repository or even a +sub-directory). + +- ✅ Valid URL : `https://github.com/backstage/backstage` +- ✅ Valid URL : `https://github.com/backstage/backstage/blob/master` +- ✅ Valid URL : `https://github.com/backstage/backstage/blob/master/docs` + +Using the provider's API documentation, find out an API endpoint which can be +used to download either a zip or a tarball. You can download the entire tree +(e.g. a repository) and filter out in case the user is expecting only a +sub-tree. But some APIs are smart enough to accept a path and return only a +sub-tree in the downloaded archive. + +#### search + +`search` method expects a glob pattern of a URL and returns a list of files +matching the query. + +- ✅ Valid URL : + `https://github.com/backstage/backstage/blob/master/**/catalog-info.yaml` +- ✅ Valid URL : `https://github.com/backstage/backstage/blob/master/**/*.md` +- ✅ Valid URL : + `https://github.com/backstage/backstage/blob/master/*/package.json` +- ✅ Valid URL : `https://github.com/backstage/backstage/blob/master/READM` + +The core logic of `readTree` can be used here to extract all the files inside +the tree and return the files matching the pattern in the `url`. + +### Caching + +All of the methods above support an ETag based caching (except `read` which is +work in progress!). If the method is called without an `etag`, the response +contains an ETag of the resource (should ideally forward the ETag returned by +the provider). If the method is called with an `etag`, it first compares the +ETag and returns a `NotModifiedError` in case the resource has not been +modified. This approach is very similar to the actual +[ETag](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/ETag) and +[If-None-Match](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/If-None-Match) +HTTP headers. + +### Debugging + +When debugging one of the URL Readers, you can straightforward use the +[`reader` instance created](https://github.com/backstage/backstage/blob/ebbe91dbe79038a61d35cf6ed2d96e0e0d5a15f3/packages/backend/src/index.ts#L57) +when the backend starts and call one of the methods with your debugging URL. +This will be run every time you restart the backend. Note that after any change +in the URL Reader code, you need to kill the backend and restart, since the +`reader` instance is memoized and does not update on hot module reloading. Also, +there are a lot of unit tests written for the URL Readers, which you can make +use of. diff --git a/microsite/sidebars.json b/microsite/sidebars.json index 0231d8f692..5530fc6f61 100644 --- a/microsite/sidebars.json +++ b/microsite/sidebars.json @@ -149,7 +149,8 @@ "type": "subcategory", "label": "LDAP", "ids": ["integrations/ldap/org"] - } + }, + "integrations/url-reader" ], "Plugins": [ "plugins/index", diff --git a/mkdocs.yml b/mkdocs.yml index c3d77e179f..47b7084146 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -98,6 +98,7 @@ nav: - Locations: 'integrations/google-cloud-storage/locations.md' - LDAP: - Org Data: 'integrations/ldap/org.md' + - URL Reader: 'integrations/url-reader.md' - Plugins: - Intro to plugins: 'plugins/index.md' - Existing plugins: 'plugins/existing-plugins.md' From 31621bee6943d38daad97112781d81933a0ccf83 Mon Sep 17 00:00:00 2001 From: Himanshu Mishra Date: Thu, 1 Jul 2021 22:07:43 +0200 Subject: [PATCH 113/204] backend-common: Update doc strings of URL Reader interface methods Signed-off-by: Himanshu Mishra --- packages/backend-common/src/reading/types.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/backend-common/src/reading/types.ts b/packages/backend-common/src/reading/types.ts index ecaa582612..8efc833ead 100644 --- a/packages/backend-common/src/reading/types.ts +++ b/packages/backend-common/src/reading/types.ts @@ -22,6 +22,7 @@ import { Config } from '@backstage/config'; * A generic interface for fetching plain data from URLs. */ export type UrlReader = { + /* Used to read a single file and return its content. */ read(url: string): Promise; /** @@ -32,8 +33,9 @@ export type UrlReader = { */ readUrl?(url: string, options?: ReadUrlOptions): Promise; + /* Used to read a file tree and download as a directory. */ readTree(url: string, options?: ReadTreeOptions): Promise; - + /* Used to search a file in a tree using a glob pattern. */ search(url: string, options?: SearchOptions): Promise; }; From ce338869136eb554c2560edba9fd584d21c17bcb Mon Sep 17 00:00:00 2001 From: Himanshu Mishra Date: Thu, 1 Jul 2021 22:12:45 +0200 Subject: [PATCH 114/204] docs: fix vale spelling errors Signed-off-by: Himanshu Mishra --- .github/styles/vocab.txt | 1 + docs/integrations/url-reader.md | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/styles/vocab.txt b/.github/styles/vocab.txt index 846e050c49..736b654486 100644 --- a/.github/styles/vocab.txt +++ b/.github/styles/vocab.txt @@ -137,6 +137,7 @@ maintainership makefile md memcache +memoized microservice microservices microsite diff --git a/docs/integrations/url-reader.md b/docs/integrations/url-reader.md index e9d6caf17c..23500a3dcb 100644 --- a/docs/integrations/url-reader.md +++ b/docs/integrations/url-reader.md @@ -51,7 +51,7 @@ function makeCreateEnv(config: Config) { This instance contains all [the default URL Reader providers](https://github.com/backstage/backstage/blob/master/packages/backend-common/src/reading/UrlReaders.ts) -in the backend-common package including GitHub, Gitlab, Bitbucket, Azure, Google +in the backend-common package including GitHub, GitLab, Bitbucket, Azure, Google GCS. As the need arises, more URL Readers are being written to support different providers. From 7edef795a391e546e6ad2ccfb0ce5c18321c65cc Mon Sep 17 00:00:00 2001 From: Himanshu Mishra Date: Fri, 2 Jul 2021 16:00:56 +0200 Subject: [PATCH 115/204] docs: Add a note about readUrl with read Signed-off-by: Himanshu Mishra --- docs/integrations/url-reader.md | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/docs/integrations/url-reader.md b/docs/integrations/url-reader.md index 23500a3dcb..83f6a743d9 100644 --- a/docs/integrations/url-reader.md +++ b/docs/integrations/url-reader.md @@ -149,6 +149,8 @@ remaining. #### read +NOTE: Use `readUrl` instead of `read`. + `read` method expects a user-friendly URL, something which can be copied from the browser naturally when a person is browsing the provider in their browser. @@ -164,6 +166,13 @@ which can be used to request the provider's API. `read` then makes an authenticated request to the provider API and returns the file's content. +#### readUrl + +`readUrl` is a new interface that allows complex response objects and is +intended to replace the `read` method. This new method is currently optional to +implement which allows for a soft migration to `readUrl` instead of `read` in +the future. + #### readTree `readTree` method also expects user-friendly URLs similar to `read` but the URL @@ -197,12 +206,11 @@ the tree and return the files matching the pattern in the `url`. ### Caching -All of the methods above support an ETag based caching (except `read` which is -work in progress!). If the method is called without an `etag`, the response -contains an ETag of the resource (should ideally forward the ETag returned by -the provider). If the method is called with an `etag`, it first compares the -ETag and returns a `NotModifiedError` in case the resource has not been -modified. This approach is very similar to the actual +All of the methods above support an ETag based caching. If the method is called +without an `etag`, the response contains an ETag of the resource (should ideally +forward the ETag returned by the provider). If the method is called with an +`etag`, it first compares the ETag and returns a `NotModifiedError` in case the +resource has not been modified. This approach is very similar to the actual [ETag](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/ETag) and [If-None-Match](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/If-None-Match) HTTP headers. From 43a4ef6442ee2eb8d05de5b2e88a78e0c862079c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?= Date: Fri, 2 Jul 2021 16:18:42 +0200 Subject: [PATCH 116/204] More helpful error message when trying to import by folder from non-github MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fredrik Adelöw --- .changeset/angry-hounds-bow.md | 5 ++ .changeset/eighty-deers-jam.md | 5 ++ .github/styles/vocab.txt | 1 + packages/integration/src/helpers.ts | 8 ++- .../src/api/CatalogImportClient.test.ts | 68 ++++++++----------- .../src/api/CatalogImportClient.ts | 6 ++ 6 files changed, 52 insertions(+), 41 deletions(-) create mode 100644 .changeset/angry-hounds-bow.md create mode 100644 .changeset/eighty-deers-jam.md diff --git a/.changeset/angry-hounds-bow.md b/.changeset/angry-hounds-bow.md new file mode 100644 index 0000000000..4bbfffd4f1 --- /dev/null +++ b/.changeset/angry-hounds-bow.md @@ -0,0 +1,5 @@ +--- +'@backstage/integration': patch +--- + +Do not throw in `ScmIntegration` `byUrl` for invalid URLs diff --git a/.changeset/eighty-deers-jam.md b/.changeset/eighty-deers-jam.md new file mode 100644 index 0000000000..df8b84aff1 --- /dev/null +++ b/.changeset/eighty-deers-jam.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-import': patch +--- + +More helpful error message when trying to import by folder from non-github diff --git a/.github/styles/vocab.txt b/.github/styles/vocab.txt index 846e050c49..80488056d8 100644 --- a/.github/styles/vocab.txt +++ b/.github/styles/vocab.txt @@ -281,6 +281,7 @@ unregistration untracked upvote url +URLs utils validator validators diff --git a/packages/integration/src/helpers.ts b/packages/integration/src/helpers.ts index 20c282c5a3..b1e74035f1 100644 --- a/packages/integration/src/helpers.ts +++ b/packages/integration/src/helpers.ts @@ -44,8 +44,12 @@ export function basicIntegrations( return integrations; }, byUrl(url: string | URL): T | undefined { - const parsed = typeof url === 'string' ? new URL(url) : url; - return integrations.find(i => getHost(i) === parsed.hostname); + try { + const parsed = typeof url === 'string' ? new URL(url) : url; + return integrations.find(i => getHost(i) === parsed.hostname); + } catch { + return undefined; + } }, byHost(host: string): T | undefined { return integrations.find(i => getHost(i) === host); diff --git a/plugins/catalog-import/src/api/CatalogImportClient.test.ts b/plugins/catalog-import/src/api/CatalogImportClient.test.ts index 8ab8f75db1..e2c3f2dc47 100644 --- a/plugins/catalog-import/src/api/CatalogImportClient.test.ts +++ b/plugins/catalog-import/src/api/CatalogImportClient.test.ts @@ -46,29 +46,19 @@ jest.doMock('@octokit/rest', () => { return { Octokit }; }); -// Mock the value to control which integrations are activated -jest.mock('./GitHub', () => ({ - getGithubIntegrationConfig: jest.fn(), -})); - -import { - GitHubIntegrationConfig, - ScmIntegrations, -} from '@backstage/integration'; +import { ScmIntegrations } from '@backstage/integration'; import { catalogApiRef } from '@backstage/plugin-catalog-react'; import { msw } from '@backstage/test-utils'; import { Octokit } from '@octokit/rest'; import { rest } from 'msw'; import { setupServer } from 'msw/node'; import { CatalogImportClient } from './CatalogImportClient'; -import { getGithubIntegrationConfig } from './GitHub'; import { ConfigReader, UrlPatternDiscovery } from '@backstage/core-app-api'; import { OAuthApi } from '@backstage/core-plugin-api'; -const server = setupServer(); - describe('CatalogImportClient', () => { + const server = setupServer(); msw.setupDefaultHandlers(server); const mockBaseUrl = 'http://backstage:9191/api/catalog'; @@ -92,7 +82,19 @@ describe('CatalogImportClient', () => { }, }; - const scmIntegrationsApi = ScmIntegrations.fromConfig(new ConfigReader({})); + const scmIntegrationsApi = ScmIntegrations.fromConfig( + new ConfigReader({ + integrations: { + github: [{ host: 'example.com' }], + gitlab: [ + { + host: 'registered-but-not-github.com', + apiBaseUrl: 'https://registered-but-not-github.com', + }, + ], + }, + }), + ); const catalogApi: jest.Mocked = { getEntities: jest.fn(), @@ -106,7 +108,6 @@ describe('CatalogImportClient', () => { }; let catalogImportClient: CatalogImportClient; - let getGithubIntegrationConfigFn: jest.Mock; beforeEach(() => { catalogImportClient = new CatalogImportClient({ @@ -116,9 +117,6 @@ describe('CatalogImportClient', () => { identityApi, catalogApi, }); - - getGithubIntegrationConfigFn = getGithubIntegrationConfig as jest.Mock; - getGithubIntegrationConfigFn.mockReset(); }); describe('analyzeUrl', () => { @@ -169,10 +167,22 @@ describe('CatalogImportClient', () => { }); }); - it('should ignore missing github integration', async () => { + it('should reject for integrations that are not github ones', async () => { await expect( catalogImportClient.analyzeUrl( - 'https://github.com/backstage/backstage', + 'https://registered-but-not-github.com/backstage/backstage', + ), + ).rejects.toThrow( + new Error( + 'The registered-but-not-github.com integration only supports full URLs to catalog-info.yaml files. Did you try to pass in the URL of a directory instead?', + ), + ); + }); + + it('should reject when unable to match with any integration', async () => { + await expect( + catalogImportClient.analyzeUrl( + 'https://not-registered-as-integration.com/foo/bar', ), ).rejects.toThrow( new Error( @@ -182,12 +192,6 @@ describe('CatalogImportClient', () => { }); it('should find locations from github', async () => { - getGithubIntegrationConfigFn.mockReturnValue({ - repo: 'backstage', - owner: 'backstage', - githubIntegrationConfig: {} as GitHubIntegrationConfig, - }); - ((new Octokit().search.code as any) as jest.Mock).mockResolvedValueOnce({ data: { total_count: 2, @@ -244,12 +248,6 @@ describe('CatalogImportClient', () => { }); it('should find repository from github', async () => { - getGithubIntegrationConfigFn.mockReturnValue({ - repo: 'backstage', - owner: 'backstage', - githubIntegrationConfig: {} as GitHubIntegrationConfig, - }); - ((new Octokit().search.code as any) as jest.Mock).mockResolvedValueOnce({ data: { total_count: 0, items: [] }, }); @@ -300,14 +298,6 @@ describe('CatalogImportClient', () => { describe('submitPullRequest', () => { it('should create GitHub pull request', async () => { - getGithubIntegrationConfigFn.mockReturnValue({ - repo: 'backstage', - owner: 'backstage', - githubIntegrationConfig: { - host: 'github.com', - } as GitHubIntegrationConfig, - }); - await expect( catalogImportClient.submitPullRequest({ repositoryUrl: 'https://github.com/backstage/backstage', diff --git a/plugins/catalog-import/src/api/CatalogImportClient.ts b/plugins/catalog-import/src/api/CatalogImportClient.ts index f53570617e..aa29c95247 100644 --- a/plugins/catalog-import/src/api/CatalogImportClient.ts +++ b/plugins/catalog-import/src/api/CatalogImportClient.ts @@ -77,6 +77,12 @@ export class CatalogImportClient implements CatalogImportApi { const ghConfig = getGithubIntegrationConfig(this.scmIntegrationsApi, url); if (!ghConfig) { + const other = this.scmIntegrationsApi.byUrl(url); + if (other) { + throw new Error( + `The ${other.title} integration only supports full URLs to catalog-info.yaml files. Did you try to pass in the URL of a directory instead?`, + ); + } throw new Error( 'This URL was not recognized as a valid GitHub URL because there was no configured integration that matched the given host name. You could try to paste the full URL to a catalog-info.yaml file instead.', ); From 3e0e21a5d5c2664b93aace3147e5dbf240eb0886 Mon Sep 17 00:00:00 2001 From: Christopher Diaz Date: Fri, 2 Jul 2021 13:44:21 -0400 Subject: [PATCH 117/204] add adopter Signed-off-by: Christopher Diaz --- ADOPTERS.md | 1 + 1 file changed, 1 insertion(+) diff --git a/ADOPTERS.md b/ADOPTERS.md index 83fbc79eca..1dcd4a774f 100644 --- a/ADOPTERS.md +++ b/ADOPTERS.md @@ -36,3 +36,4 @@ | [HelloFresh](https://www.hellofresh.de/) | [@iammuho](https://github.com/iammuho), [@ElenaForester](https://github.com/ElenaForester), [@diegomarangoni](https://github.com/diegomarangoni) | Our developer portal at HelloFresh - Spread across an organisation of 500+ engineers globally. | | [FactSet](https://www.factset.com/) | [@kuangp](https://github.com/kuangp) | Developer portal to provide discoverability to all internal components, APIs, documentation, and scaffold templates with integrations to our internal infrastructure tools. | | [Workrise](https://www.workrise.com/) | [Michael Rode](https://github.com/michaelrode) | Developer portal, main gateway to our infrastructure, documentation and internal tooling. | +| [RedVentures](https://www.redventures.com/) | [Chris Diaz](https://github.com/codingdiaz) | Developer portal that brings everything an engineer needs to provide value into a single pane of glass. | From 253136fba7739a94d3c476102f5e736f4cd1874f Mon Sep 17 00:00:00 2001 From: Eugene Sh Date: Fri, 2 Jul 2021 22:17:32 +0300 Subject: [PATCH 118/204] Make branch protection attempt less restrictive In case if something wrong happens along the way when trying to apply protection of a newly created branch - log error, instead of throwing an it, making scaffolder exit with non-zero exit code. This one addresses the issue #6330 Signed-off-by: Eugene S --- .changeset/wet-queens-deny.md | 5 +++++ .../src/scaffolder/actions/builtin/publish/github.ts | 4 ++-- 2 files changed, 7 insertions(+), 2 deletions(-) create mode 100644 .changeset/wet-queens-deny.md diff --git a/.changeset/wet-queens-deny.md b/.changeset/wet-queens-deny.md new file mode 100644 index 0000000000..1e446c619c --- /dev/null +++ b/.changeset/wet-queens-deny.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder-backend': patch +--- + +removing mandatory of protection for the default branch, that could be handled by the GitHub automation in async manner, thus throwing floating errors diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/github.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/github.ts index 856197a808..7dd790cb62 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/github.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/github.ts @@ -268,8 +268,8 @@ export function createPublishGithubAction(options: { defaultBranch, }); } catch (e) { - throw new Error( - `Failed to add branch protection to '${newRepo.name}', ${e}`, + ctx.logger.warn( + `Skipping: default branch protection on '${newRepo.name}', ${e.message}`, ); } From b124633526b1a2daf079604876c607a4ff9fc326 Mon Sep 17 00:00:00 2001 From: Crevil Date: Sat, 3 Jul 2021 12:04:36 +0200 Subject: [PATCH 119/204] Document techdocs svg_object limitation Currently it is not possible to use the PlantUML format 'svg_object' as this makes it possible for bad actors to inject malicious content into documentation. This change documents this limitation under the troubleshooting section of the techdocs feature. Signed-off-by: Crevil --- docs/features/techdocs/troubleshooting.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/docs/features/techdocs/troubleshooting.md b/docs/features/techdocs/troubleshooting.md index e6efefc578..d8b413be5c 100644 --- a/docs/features/techdocs/troubleshooting.md +++ b/docs/features/techdocs/troubleshooting.md @@ -55,3 +55,20 @@ INFO - Start watching changes [I 210115 19:00:45 handlers:64] Start detecting changes INFO - Start detecting changes ``` + +## PlantUML with `svg_object` doesn't render + +The [plantuml-markdown](https://pypi.org/project/plantuml-markdown/) MkDocs +plugin available in +[`mkdocs-techdocs-core`](https://github.com/backstage/mkdocs-techdocs-core) +supports different formats for rendering diagrams. TechDocs does however not +support all of them. + +The `svg_object` format renders a diagram as an HTML `` tag but this is +not allowed as it enables bad actors to inject malicious content into +documentation pages. See +[CVE-2021-32661](https://github.com/advisories/GHSA-gg96-f8wr-p89f) for more +details. + +Instead use `svg_inline` which renders as an `` tag and provides the same +benefits as `svg_object`. From 76fc5e29c9677383958d73ca10c2ae26c853ecd5 Mon Sep 17 00:00:00 2001 From: shoukoo Date: Sun, 4 Jul 2021 08:36:16 +1000 Subject: [PATCH 120/204] feat:add default branch prop for publish:gitlab action Signed-off-by: shoukoo --- .../publish/{gitab.test.ts => gitlab.test.ts} | 24 +++++++++++++++++++ .../actions/builtin/publish/gitlab.ts | 13 +++++++++- 2 files changed, 36 insertions(+), 1 deletion(-) rename plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/{gitab.test.ts => gitlab.test.ts} (88%) diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitab.test.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.test.ts similarity index 88% rename from plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitab.test.ts rename to plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.test.ts index 79de6fd669..67064efde7 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitab.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.test.ts @@ -139,6 +139,30 @@ describe('publish:gitlab', () => { expect(initRepoAndPush).toHaveBeenCalledWith({ dir: mockContext.workspacePath, + defaultBranch: 'master', + remoteUrl: 'http://mockurl.git', + auth: { username: 'oauth2', password: 'tokenlols' }, + logger: mockContext.logger, + }); + }); + + it('should call initRepoAndPush with the correct default branch', async () => { + mockGitlabClient.Namespaces.show.mockResolvedValue({ id: 1234 }); + mockGitlabClient.Projects.create.mockResolvedValue({ + http_url_to_repo: 'http://mockurl.git', + }); + + await action.handler({ + ...mockContext, + input: { + ...mockContext.input, + defaultBranch: 'main', + }, + }); + + expect(initRepoAndPush).toHaveBeenCalledWith({ + dir: mockContext.workspacePath, + defaultBranch: 'main', remoteUrl: 'http://mockurl.git', auth: { username: 'oauth2', password: 'tokenlols' }, logger: mockContext.logger, diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.ts index 3f24b98e6c..57c7fdf752 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.ts @@ -28,6 +28,7 @@ export function createPublishGitlabAction(options: { return createTemplateAction<{ repoUrl: string; + defaultBranch?: string; repoVisibility: 'private' | 'internal' | 'public'; sourcePath?: string; }>({ @@ -48,6 +49,11 @@ export function createPublishGitlabAction(options: { type: 'string', enum: ['private', 'public', 'internal'], }, + defaultBranch: { + title: 'Default Branch', + type: 'string', + description: `Sets the default branch on the repository. The default value is 'master'`, + }, sourcePath: { title: 'Path within the workspace that will be used as the repository root. If omitted, the entire workspace will be published as the repository.', @@ -70,7 +76,11 @@ export function createPublishGitlabAction(options: { }, }, async handler(ctx) { - const { repoUrl, repoVisibility = 'private' } = ctx.input; + const { + repoUrl, + repoVisibility = 'private', + defaultBranch = 'master', + } = ctx.input; const { owner, repo, host } = parseRepoUrl(repoUrl); @@ -114,6 +124,7 @@ export function createPublishGitlabAction(options: { await initRepoAndPush({ dir: getRepoSourceDirectory(ctx.workspacePath, ctx.input.sourcePath), remoteUrl: http_url_to_repo as string, + defaultBranch, auth: { username: 'oauth2', password: integrationConfig.config.token, From 330f2ac32ded4b124afea3b7c0b56688b1f2a1b1 Mon Sep 17 00:00:00 2001 From: shoukoo Date: Sun, 4 Jul 2021 08:52:48 +1000 Subject: [PATCH 121/204] feat:add default branch prop for publish:bitbucket action Signed-off-by: shoukoo --- .../actions/builtin/publish/bitbucket.test.ts | 43 +++++++++++++++++++ .../actions/builtin/publish/bitbucket.ts | 8 ++++ 2 files changed, 51 insertions(+) diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/bitbucket.test.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/bitbucket.test.ts index 00ada3a4bc..16b84737a7 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/bitbucket.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/bitbucket.test.ts @@ -286,6 +286,49 @@ describe('publish:bitbucket', () => { expect(initRepoAndPush).toHaveBeenCalledWith({ dir: mockContext.workspacePath, remoteUrl: 'https://bitbucket.org/owner/cloneurl', + defaultBranch: 'master', + auth: { username: 'x-token-auth', password: 'tokenlols' }, + logger: mockContext.logger, + }); + }); + + it('should call initAndPush with the correct default branch', async () => { + server.use( + rest.post( + 'https://api.bitbucket.org/2.0/repositories/owner/repo', + (_, res, ctx) => + res( + ctx.status(200), + ctx.set('Content-Type', 'application/json'), + ctx.json({ + links: { + html: { + href: 'https://bitbucket.org/owner/repo', + }, + clone: [ + { + name: 'https', + href: 'https://bitbucket.org/owner/cloneurl', + }, + ], + }, + }), + ), + ), + ); + + await action.handler({ + ...mockContext, + input: { + ...mockContext.input, + defaultBranch: 'main', + }, + }); + + expect(initRepoAndPush).toHaveBeenCalledWith({ + dir: mockContext.workspacePath, + remoteUrl: 'https://bitbucket.org/owner/cloneurl', + defaultBranch: 'main', auth: { username: 'x-token-auth', password: 'tokenlols' }, logger: mockContext.logger, }); diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/bitbucket.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/bitbucket.ts index ce937108c4..295f4d1574 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/bitbucket.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/bitbucket.ts @@ -190,6 +190,7 @@ export function createPublishBitbucketAction(options: { return createTemplateAction<{ repoUrl: string; description: string; + defaultBranch?: string; repoVisibility: 'private' | 'public'; sourcePath?: string; enableLFS: boolean; @@ -215,6 +216,11 @@ export function createPublishBitbucketAction(options: { type: 'string', enum: ['private', 'public'], }, + defaultBranch: { + title: 'Default Branch', + type: 'string', + description: `Sets the default branch on the repository. The default value is 'master'`, + }, sourcePath: { title: 'Path within the workspace that will be used as the repository root. If omitted, the entire workspace will be published as the repository.', @@ -245,6 +251,7 @@ export function createPublishBitbucketAction(options: { const { repoUrl, description, + defaultBranch = 'master', repoVisibility = 'private', enableLFS = false, } = ctx.input; @@ -288,6 +295,7 @@ export function createPublishBitbucketAction(options: { ? integrationConfig.config.appPassword : integrationConfig.config.token ?? '', }, + defaultBranch, logger: ctx.logger, }); From 73195b6e65a84e2b0e29fa460f28338dda84a98d Mon Sep 17 00:00:00 2001 From: shoukoo Date: Sun, 4 Jul 2021 08:59:14 +1000 Subject: [PATCH 122/204] feat:add default branch prop for publish:azure action Signed-off-by: shoukoo --- .../actions/builtin/publish/azure.test.ts | 23 +++++++++++++++++++ .../actions/builtin/publish/azure.ts | 13 ++++++++--- 2 files changed, 33 insertions(+), 3 deletions(-) diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/azure.test.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/azure.test.ts index 2f468cda25..d3cb4ccafc 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/azure.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/azure.test.ts @@ -162,6 +162,29 @@ describe('publish:azure', () => { expect(initRepoAndPush).toHaveBeenCalledWith({ dir: mockContext.workspacePath, remoteUrl: 'https://dev.azure.com/organization/project/_git/repo', + defaultBranch: 'master', + auth: { username: 'notempty', password: 'tokenlols' }, + logger: mockContext.logger, + }); + }); + + it('should call initRepoAndPush with the correct default branch', async () => { + mockGitClient.createRepository.mockImplementation(() => ({ + remoteUrl: 'https://dev.azure.com/organization/project/_git/repo', + })); + + await action.handler({ + ...mockContext, + input: { + ...mockContext.input, + defaultBranch: 'main', + }, + }); + + expect(initRepoAndPush).toHaveBeenCalledWith({ + dir: mockContext.workspacePath, + remoteUrl: 'https://dev.azure.com/organization/project/_git/repo', + defaultBranch: 'master', auth: { username: 'notempty', password: 'tokenlols' }, logger: mockContext.logger, }); diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/azure.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/azure.ts index 21b2537614..eb1b0522c6 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/azure.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/azure.ts @@ -30,6 +30,7 @@ export function createPublishAzureAction(options: { return createTemplateAction<{ repoUrl: string; description?: string; + defaultBranch?: string; sourcePath?: string; }>({ id: 'publish:azure', @@ -48,6 +49,11 @@ export function createPublishAzureAction(options: { title: 'Repository Description', type: 'string', }, + defaultBranch: { + title: 'Default Branch', + type: 'string', + description: `Sets the default branch on the repository. The default value is 'master'`, + }, sourcePath: { title: 'Path within the workspace that will be used as the repository root. If omitted, the entire workspace will be published as the repository.', @@ -70,9 +76,9 @@ export function createPublishAzureAction(options: { }, }, async handler(ctx) { - const { owner, repo, host, organization } = parseRepoUrl( - ctx.input.repoUrl, - ); + const { repoUrl, defaultBranch = 'master' } = ctx.input; + + const { owner, repo, host, organization } = parseRepoUrl(repoUrl); if (!organization) { throw new InputError( @@ -120,6 +126,7 @@ export function createPublishAzureAction(options: { await initRepoAndPush({ dir: getRepoSourceDirectory(ctx.workspacePath, ctx.input.sourcePath), remoteUrl, + defaultBranch, auth: { username: 'notempty', password: integrationConfig.config.token, From dad4817939094eaf64c2a24ba7be2ce8399c0ebd Mon Sep 17 00:00:00 2001 From: shoukoo Date: Sun, 4 Jul 2021 09:01:44 +1000 Subject: [PATCH 123/204] Add new changeset Signed-off-by: shoukoo --- .changeset/brown-olives-hang.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/brown-olives-hang.md diff --git a/.changeset/brown-olives-hang.md b/.changeset/brown-olives-hang.md new file mode 100644 index 0000000000..64ce4e25d5 --- /dev/null +++ b/.changeset/brown-olives-hang.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder-backend': patch +--- + +add default branch property for publish GitLab, Bitbucket and Azure actions From 2ac448e380f6e389e3684664bdf16185acdfff42 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 5 Jul 2021 04:20:00 +0000 Subject: [PATCH 124/204] chore(deps): bump @types/yup from 0.29.11 to 0.29.12 Bumps [@types/yup](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/yup) from 0.29.11 to 0.29.12. - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases) - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/yup) --- updated-dependencies: - dependency-name: "@types/yup" dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index b04756527c..d73d3fe955 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6866,9 +6866,9 @@ integrity sha512-/emrKCfQMQmFCqRqqBJ0JueHBT06jBRM3e8OgnvDUcvuExONujIk2hFA5dNsN9Nt41ljGVDdChvCydATZ+KOZw== "@types/yup@^0.29.8": - version "0.29.11" - resolved "https://registry.npmjs.org/@types/yup/-/yup-0.29.11.tgz#d654a112973f5e004bf8438122bd7e56a8e5cd7e" - integrity sha512-9cwk3c87qQKZrT251EDoibiYRILjCmxBvvcb4meofCmx1vdnNcR9gyildy5vOHASpOKMsn42CugxUvcwK5eu1g== + version "0.29.12" + resolved "https://registry.npmjs.org/@types/yup/-/yup-0.29.12.tgz#59c9577bea11d2b3d78717ea7591caacad6dfa1b" + integrity sha512-fA7bXyBzWEAgOwX2SD/5/iaZY/4In0EvJEzFmBWzaGNF4vxr8d5iOFUMFBpL4cMEmlSx2wW9ginJNnoZjE/vOg== "@types/zen-observable@^0.8.0", "@types/zen-observable@^0.8.2": version "0.8.2" From 28f557a7dd4c5a97a6b8bc4e95187bda3bb89f52 Mon Sep 17 00:00:00 2001 From: Brett Wright Date: Mon, 5 Jul 2021 10:07:05 +0200 Subject: [PATCH 125/204] add harbor plugin Signed-off-by: Brett Wright --- microsite/data/plugins/harbor.yaml | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 microsite/data/plugins/harbor.yaml diff --git a/microsite/data/plugins/harbor.yaml b/microsite/data/plugins/harbor.yaml new file mode 100644 index 0000000000..a851f99545 --- /dev/null +++ b/microsite/data/plugins/harbor.yaml @@ -0,0 +1,13 @@ +--- +title: Harbor +author: BESTSELLER +authorUrl: bestsellerit.com +category: Discovery +description: This plugin will show you information about docker images within harbor. +documentation: https://github.com/BESTSELLER/backstage-plugin-harbor/blob/master/README.md +iconUrl: https://bestsellerit.com/img/terraform-harbor/goharbor.jpeg +npmPackageName: '@bestsellerit/backstage-plugin-harbor' +tags: + - goharbor + - harbor + - docker From 9813f6c2c72a7c61ec9173385ae2f0137ee61f6e Mon Sep 17 00:00:00 2001 From: Himanshu Mishra Date: Mon, 5 Jul 2021 10:21:31 +0200 Subject: [PATCH 126/204] document how to add a new url reader (oss vs private) and update section title Signed-off-by: Himanshu Mishra --- docs/integrations/url-reader.md | 34 +++++++++++++++++++++++++++------ 1 file changed, 28 insertions(+), 6 deletions(-) diff --git a/docs/integrations/url-reader.md b/docs/integrations/url-reader.md index 83f6a743d9..c37549cf8b 100644 --- a/docs/integrations/url-reader.md +++ b/docs/integrations/url-reader.md @@ -68,7 +68,7 @@ export type UrlReader = { }; ``` -## Using inside a plugin +## Using a URL Reader inside a plugin The `reader` instance is available in the backend plugin environment and passed on to all the backend plugins. You can see an @@ -116,7 +116,7 @@ Feel free to use the [GitHub URL Reader](https://github.com/backstage/backstage/blob/d5c83bb889b8142e343ebc4e4c0b90a02d1c1a3d/packages/backend-common/src/reading/GithubUrlReader.ts) as a source of inspiration. -### Add an integration +### 1. Add an integration The provider for your new URL Reader can also be called an "integration" in Backstage. The `integrations:` section of your Backstage `app-config.yaml` @@ -130,7 +130,7 @@ integrations config and process it", "construct headers for authenticated requests to the host" or "convert a plain file URL into its API URL for downloading the file" would live in this package. -### Create the URL Reader +### 2. Create the URL Reader Create a new class which implements the [`UrlReader` type](https://github.com/backstage/backstage/blob/d5c83bb889b8142e343ebc4e4c0b90a02d1c1a3d/packages/backend-common/src/reading/types.ts#L21-L28) @@ -140,7 +140,7 @@ should be used for. See the [GitHub URL Reader](https://github.com/backstage/backstage/blob/d5c83bb889b8142e343ebc4e4c0b90a02d1c1a3d/packages/backend-common/src/reading/GithubUrlReader.ts#L50-L63) for example. -### Implement the methods +### 3. Implement the methods We want to make sure all URL Readers behave in the same way. Hence if possible, all the methods of the `UrlReader` interface should be implemented. However it @@ -204,7 +204,29 @@ matching the query. The core logic of `readTree` can be used here to extract all the files inside the tree and return the files matching the pattern in the `url`. -### Caching +### 4. Add to available URL Readers + +There are two ways to make your new URL Reader available for use. + +You can choose to make it open source, by updating the +[`default` factory](https://github.com/backstage/backstage/blob/d5c83bb889b8142e343ebc4e4c0b90a02d1c1a3d/packages/backend-common/src/reading/UrlReaders.ts#L62-L81) +method of URL Readers. + +But for something internal which you don't want to make open source, you can +update your `packages/backend/src/index.ts` file and update how the `reader` +instance is created. + +```ts +// File: packages/backend/src/index.ts +const reader = UrlReaders.default({ + logger: root, + config, + // This is where your internal URL Readers would go. + factories: [myCustomReader.factory], +}); +``` + +### 5. Caching All of the methods above support an ETag based caching. If the method is called without an `etag`, the response contains an ETag of the resource (should ideally @@ -215,7 +237,7 @@ resource has not been modified. This approach is very similar to the actual [If-None-Match](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/If-None-Match) HTTP headers. -### Debugging +### 6. Debugging When debugging one of the URL Readers, you can straightforward use the [`reader` instance created](https://github.com/backstage/backstage/blob/ebbe91dbe79038a61d35cf6ed2d96e0e0d5a15f3/packages/backend/src/index.ts#L57) From d1bd7bb825423304a1108eebf7291a81af5dd965 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?= Date: Mon, 5 Jul 2021 10:23:39 +0200 Subject: [PATCH 127/204] Update README MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fredrik Adelöw --- .changeset/breezy-kings-applaud.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/breezy-kings-applaud.md diff --git a/.changeset/breezy-kings-applaud.md b/.changeset/breezy-kings-applaud.md new file mode 100644 index 0000000000..867d135739 --- /dev/null +++ b/.changeset/breezy-kings-applaud.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-pagerduty': patch +--- + +Update README From 918e2be318282d21fb8bea5bb9ed476e6ce0fa28 Mon Sep 17 00:00:00 2001 From: Himanshu Mishra Date: Mon, 5 Jul 2021 10:42:56 +0200 Subject: [PATCH 128/204] docs: Add an example code block for debugging new url reader Signed-off-by: Himanshu Mishra --- docs/integrations/url-reader.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/docs/integrations/url-reader.md b/docs/integrations/url-reader.md index c37549cf8b..a2108d5c71 100644 --- a/docs/integrations/url-reader.md +++ b/docs/integrations/url-reader.md @@ -242,6 +242,23 @@ HTTP headers. When debugging one of the URL Readers, you can straightforward use the [`reader` instance created](https://github.com/backstage/backstage/blob/ebbe91dbe79038a61d35cf6ed2d96e0e0d5a15f3/packages/backend/src/index.ts#L57) when the backend starts and call one of the methods with your debugging URL. + +```ts +// File: packages/backend/src/index.ts + +async function main() { + // ... + const createEnv = makeCreateEnv(config); + + const testReader = createEnv('test-url-reader').reader; + const response = await testReader.readUrl( + 'https://github.com/backstage/backstage/blob/master/catalog-info.yaml', + ); + console.log((await response.buffer()).toString()); + // ... +} +``` + This will be run every time you restart the backend. Note that after any change in the URL Reader code, you need to kill the backend and restart, since the `reader` instance is memoized and does not update on hot module reloading. Also, From a6b4aebbd214a0409ae78f7fd9ff230f8a765bc0 Mon Sep 17 00:00:00 2001 From: roylisto Date: Mon, 5 Jul 2021 16:20:45 +0700 Subject: [PATCH 129/204] Use Link from @backstage/core-components Signed-off-by: roylisto --- .../Group/GroupProfile/GroupProfileCard.tsx | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/plugins/org/src/components/Cards/Group/GroupProfile/GroupProfileCard.tsx b/plugins/org/src/components/Cards/Group/GroupProfile/GroupProfileCard.tsx index 8d44e9157a..637a7279f6 100644 --- a/plugins/org/src/components/Cards/Group/GroupProfile/GroupProfileCard.tsx +++ b/plugins/org/src/components/Cards/Group/GroupProfile/GroupProfileCard.tsx @@ -28,7 +28,6 @@ import { import { Box, Grid, - Link, List, ListItem, ListItemIcon, @@ -42,7 +41,12 @@ import GroupIcon from '@material-ui/icons/Group'; import EditIcon from '@material-ui/icons/Edit'; import Alert from '@material-ui/lab/Alert'; import React from 'react'; -import { Avatar, InfoCard, InfoCardVariants } from '@backstage/core-components'; +import { + Avatar, + InfoCard, + InfoCardVariants, + Link, +} from '@backstage/core-components'; const CardTitle = ({ title }: { title: string }) => ( @@ -75,10 +79,10 @@ export const GroupProfileCard = ({ kind: 'group', }); - const entityMetadataEditUrl = getEntityMetadataEditUrl(group); + const entityMetadataEditUrl = getEntityMetadataEditUrl(group) ?? '#'; const displayName = profile?.displayName ?? name; - const emailHref = profile?.email ? `mailto:${profile.email}` : undefined; + const emailHref = profile?.email ? `mailto:${profile.email}` : '#'; return ( { - window.open(entityMetadataEditUrl ?? '#', '_blank'); - }} + component={Link} + target="_blank" + to={entityMetadataEditUrl} > @@ -112,7 +116,7 @@ export const GroupProfileCard = ({ - {profile.email} + {profile.email} )} From 62c2f10f7d3e4e54fc2007052a782ca087bf6a72 Mon Sep 17 00:00:00 2001 From: Andrea Falzetti Date: Fri, 2 Jul 2021 17:16:39 +0100 Subject: [PATCH 130/204] feat(scaffolder): add fs:delete custom step Signed-off-by: Andrea Falzetti --- .changeset/eight-pots-remember.md | 5 + .../actions/builtin/createBuiltinActions.ts | 6 + .../actions/builtin/filesystem/delete.test.ts | 120 ++++++++++ .../actions/builtin/filesystem/delete.ts | 58 +++++ .../actions/builtin/filesystem/index.ts | 18 ++ .../actions/builtin/filesystem/rename.test.ts | 206 ++++++++++++++++++ .../actions/builtin/filesystem/rename.ts | 93 ++++++++ .../src/scaffolder/actions/builtin/index.ts | 1 + 8 files changed, 507 insertions(+) create mode 100644 .changeset/eight-pots-remember.md create mode 100644 plugins/scaffolder-backend/src/scaffolder/actions/builtin/filesystem/delete.test.ts create mode 100644 plugins/scaffolder-backend/src/scaffolder/actions/builtin/filesystem/delete.ts create mode 100644 plugins/scaffolder-backend/src/scaffolder/actions/builtin/filesystem/index.ts create mode 100644 plugins/scaffolder-backend/src/scaffolder/actions/builtin/filesystem/rename.test.ts create mode 100644 plugins/scaffolder-backend/src/scaffolder/actions/builtin/filesystem/rename.ts diff --git a/.changeset/eight-pots-remember.md b/.changeset/eight-pots-remember.md new file mode 100644 index 0000000000..34c6d018b5 --- /dev/null +++ b/.changeset/eight-pots-remember.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder-backend': patch +--- + +Added filesystem remove/rename built-in actions diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/createBuiltinActions.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/createBuiltinActions.ts index 598d36938e..46b8db72b4 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/createBuiltinActions.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/createBuiltinActions.ts @@ -24,6 +24,10 @@ import { } from './catalog'; import { createDebugLogAction } from './debug'; import { createFetchCookiecutterAction, createFetchPlainAction } from './fetch'; +import { + createFilesystemDeleteAction, + createFilesystemRenameAction, +} from './filesystem'; import { createPublishAzureAction, createPublishBitbucketAction, @@ -68,5 +72,7 @@ export const createBuiltinActions = (options: { createDebugLogAction(), createCatalogRegisterAction({ catalogClient, integrations }), createCatalogWriteAction(), + createFilesystemDeleteAction(), + createFilesystemRenameAction(), ]; }; diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/filesystem/delete.test.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/filesystem/delete.test.ts new file mode 100644 index 0000000000..f8fc1f1dc5 --- /dev/null +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/filesystem/delete.test.ts @@ -0,0 +1,120 @@ +/* + * Copyright 2021 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import * as os from 'os'; +import mockFs from 'mock-fs'; +import { resolve as resolvePath } from 'path'; +import { createFilesystemDeleteAction } from './delete'; +import { getVoidLogger } from '@backstage/backend-common'; +import { PassThrough } from 'stream'; +import fs from 'fs-extra'; + +const root = os.platform() === 'win32' ? 'C:\\rootDir' : '/rootDir'; +const workspacePath = resolvePath(root, 'my-workspace'); + +describe('fs:delete', () => { + const action = createFilesystemDeleteAction(); + + const mockContext = { + input: { + files: ['unit-test-a.js', 'unit-test-b.js'], + }, + workspacePath, + logger: getVoidLogger(), + logStream: new PassThrough(), + output: jest.fn(), + createTemporaryDirectory: jest.fn(), + }; + + beforeEach(() => { + jest.restoreAllMocks(); + + mockFs({ + [workspacePath]: { + 'unit-test-a.js': 'hello', + 'unit-test-b.js': 'world', + }, + }); + }); + + afterEach(() => { + mockFs.restore(); + }); + + it('should throw an error when files is not an array', async () => { + await expect( + action.handler({ + ...mockContext, + input: { files: undefined }, + }), + ).rejects.toThrow(/files must be an Array/); + + await expect( + action.handler({ + ...mockContext, + input: { files: {} }, + }), + ).rejects.toThrow(/files must be an Array/); + + await expect( + action.handler({ + ...mockContext, + input: { files: '' }, + }), + ).rejects.toThrow(/files must be an Array/); + + await expect( + action.handler({ + ...mockContext, + input: { files: null }, + }), + ).rejects.toThrow(/files must be an Array/); + }); + + it('should throw when file name is not relative to the workspace', async () => { + await expect( + action.handler({ + ...mockContext, + input: { files: ['/foo/../../../index.js'] }, + }), + ).rejects.toThrow(/Relative path is not allowed to refer to a directory outside its parent/); + + await expect( + action.handler({ + ...mockContext, + input: { files: ['../../../index.js'] }, + }), + ).rejects.toThrow(/Relative path is not allowed to refer to a directory outside its parent/); + }); + + it('should call fs.rm with the correct values', async () => { + const files = ['unit-test-a.js', 'unit-test-b.js']; + + files.forEach(file => { + const filePath = resolvePath(workspacePath, file); + const fileExists = fs.existsSync(filePath); + expect(fileExists).toBe(true); + }); + + await action.handler(mockContext); + + files.forEach(file => { + const filePath = resolvePath(workspacePath, file); + const fileExists = fs.existsSync(filePath); + expect(fileExists).toBe(false); + }); + }); +}); diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/filesystem/delete.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/filesystem/delete.ts new file mode 100644 index 0000000000..ec8d60f955 --- /dev/null +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/filesystem/delete.ts @@ -0,0 +1,58 @@ +/* + * Copyright 2021 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { createTemplateAction } from '../../createTemplateAction'; +import { InputError } from '@backstage/errors'; +import { resolveSafeChildPath } from '@backstage/backend-common'; +import fs from 'fs-extra'; + +export const createFilesystemDeleteAction = () => { + return createTemplateAction<{ files: string[] }>({ + id: 'fs:delete', + schema: { + input: { + required: ['files'], + type: 'object', + properties: { + files: { + title: 'Files', + description: 'A list of files or directories that will be deleted', + type: 'array', + items: { + type: 'string', + }, + }, + }, + }, + }, + async handler(ctx) { + if (!Array.isArray(ctx.input?.files)) { + throw new InputError('files must be an Array'); + } + + for (const file of ctx.input.files) { + const filepath = resolveSafeChildPath(ctx.workspacePath, file); + + try { + await fs.remove(filepath); + ctx.logger.info(`File ${filepath} deleted successfully`); + } catch (err) { + ctx.logger.error(`Failed to delete file ${filepath}:`, err); + throw err; + } + } + }, + }); +}; diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/filesystem/index.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/filesystem/index.ts new file mode 100644 index 0000000000..84e477b16b --- /dev/null +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/filesystem/index.ts @@ -0,0 +1,18 @@ +/* + * Copyright 2021 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export { createFilesystemDeleteAction } from './delete'; +export { createFilesystemRenameAction } from './rename'; diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/filesystem/rename.test.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/filesystem/rename.test.ts new file mode 100644 index 0000000000..58bb558ff5 --- /dev/null +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/filesystem/rename.test.ts @@ -0,0 +1,206 @@ +/* + * Copyright 2021 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import * as os from 'os'; +import mockFs from 'mock-fs'; +import { resolve as resolvePath } from 'path'; +import { createFilesystemRenameAction } from './rename'; +import { getVoidLogger } from '@backstage/backend-common'; +import { PassThrough } from 'stream'; +import fs from 'fs-extra'; + +const root = os.platform() === 'win32' ? 'C:\\rootDir' : '/rootDir'; +const workspacePath = resolvePath(root, 'my-workspace'); + +describe('fs:rename', () => { + const action = createFilesystemRenameAction(); + + const mockInputFiles = [ + { + from: 'unit-test-a.js', + to: 'new-a.js', + }, + { + from: 'unit-test-b.js', + to: 'new-b.js', + }, + ]; + const mockContext = { + input: { + files: mockInputFiles, + }, + workspacePath, + logger: getVoidLogger(), + logStream: new PassThrough(), + output: jest.fn(), + createTemporaryDirectory: jest.fn(), + }; + + beforeEach(() => { + jest.restoreAllMocks(); + + mockFs({ + [workspacePath]: { + 'unit-test-a.js': 'hello', + 'unit-test-b.js': 'world', + 'unit-test-c.js': 'i will be overwritten :-(', + }, + }); + }); + + afterEach(() => { + mockFs.restore(); + }); + + it('should throw an error when files is not an array', async () => { + await expect( + action.handler({ + ...mockContext, + input: { files: undefined }, + }), + ).rejects.toThrow(/files must be an Array/); + + await expect( + action.handler({ + ...mockContext, + input: { files: {} }, + }), + ).rejects.toThrow(/files must be an Array/); + + await expect( + action.handler({ + ...mockContext, + input: { files: '' }, + }), + ).rejects.toThrow(/files must be an Array/); + + await expect( + action.handler({ + ...mockContext, + input: { files: null }, + }), + ).rejects.toThrow(/files must be an Array/); + }); + + it('should throw an error when files have missing from/to', async () => { + await expect( + action.handler({ + ...mockContext, + input: { files: ['old.md'] }, + }), + ).rejects.toThrow(/each file must have a from and to property/); + + await expect( + action.handler({ + ...mockContext, + input: { files: [{ from: 'old.md' }] }, + }), + ).rejects.toThrow(/each file must have a from and to property/); + + await expect( + action.handler({ + ...mockContext, + input: { files: [{ to: 'new.md' }] }, + }), + ).rejects.toThrow(/each file must have a from and to property/); + }); + + it('should throw when file name is not relative to the workspace', async () => { + await expect( + action.handler({ + ...mockContext, + input: { files: [{ from: 'index.js', to: '/core/../../../index.js' }] }, + }), + ).rejects.toThrow(/Relative path is not allowed to refer to a directory outside its parent/); + + await expect( + action.handler({ + ...mockContext, + input: { files: [{ from: '/core/../../../index.js', to: 'index.js' }] }, + }), + ).rejects.toThrow(/Relative path is not allowed to refer to a directory outside its parent/); + }); + + it('should throw is trying to override by mistake', async () => { + const destFile = 'unit-test-c.js'; + const filePath = resolvePath(workspacePath, destFile); + const beforeContent = fs.readFileSync(filePath, 'utf-8'); + + await expect( + action.handler({ + ...mockContext, + input: { + files: [ + { + from: 'unit-test-a.js', + to: 'unit-test-c.js', + }, + ], + }, + }), + ).rejects.toThrow(/dest already exists/); + + const afterContent = fs.readFileSync(filePath, 'utf-8'); + + expect(beforeContent).toEqual(afterContent); + }); + + it('should call fs.move with the correct values', async () => { + mockInputFiles.forEach(file => { + const filePath = resolvePath(workspacePath, file.from); + const fileExists = fs.existsSync(filePath); + expect(fileExists).toBe(true); + }); + + await action.handler(mockContext); + + mockInputFiles.forEach(file => { + const filePath = resolvePath(workspacePath, file.from); + const fileExists = fs.existsSync(filePath); + expect(fileExists).toBe(false); + }); + }); + + it('should override when requested', async () => { + const sourceFile = 'unit-test-a.js'; + const destFile = 'unit-test-c.js'; + const sourceFilePath = resolvePath(workspacePath, sourceFile); + const destFilePath = resolvePath(workspacePath, destFile); + + const sourceBeforeContent = fs.readFileSync(sourceFilePath, 'utf-8'); + const destBeforeContent = fs.readFileSync(destFilePath, 'utf-8'); + + expect(sourceBeforeContent).not.toEqual(destBeforeContent); + + + await action.handler({ + ...mockContext, + input: { + files: [ + { + from: sourceFile, + to: destFile, + overwrite: true, + }, + ], + }, + }); + + const destAfterContent = fs.readFileSync(destFilePath, 'utf-8'); + + expect(sourceBeforeContent).toEqual(destAfterContent); + }); +}); diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/filesystem/rename.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/filesystem/rename.ts new file mode 100644 index 0000000000..bcfb35025c --- /dev/null +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/filesystem/rename.ts @@ -0,0 +1,93 @@ +/* + * Copyright 2021 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { createTemplateAction } from '../../createTemplateAction'; +import { resolveSafeChildPath } from '@backstage/backend-common'; + +import { InputError } from '@backstage/errors'; +import { JsonObject } from '@backstage/config'; +import fs from 'fs-extra'; + +interface FilesToRename extends JsonObject { + from: string; + to: string; +} + +export const createFilesystemRenameAction = () => { + return createTemplateAction<{ files: FilesToRename }>({ + id: 'fs:rename', + schema: { + input: { + required: ['files'], + type: 'object', + properties: { + files: { + title: 'Files', + description: 'A list of file names that will be renamed', + type: 'array', + items: { + type: 'object', + required: ['from', 'to'], + properties: { + from: { + type: 'string', + title: 'The source location of the file to be renamed', + }, + to: { + type: 'string', + title: 'The destination of the new file', + }, + overwrite: { + type: 'boolean', + title: + 'Overwrite existing file or directory, default is false', + }, + }, + }, + }, + }, + }, + }, + async handler(ctx) { + if (!Array.isArray(ctx.input?.files)) { + throw new InputError('files must be an Array'); + } + + for (const file of ctx.input.files) { + if (!file.from || !file.to) { + throw new InputError('each file must have a from and to property'); + } + + const sourceFilepath = resolveSafeChildPath(ctx.workspacePath, file.from); + const destFilepath = resolveSafeChildPath(ctx.workspacePath, file.to); + + try { + await fs.move(sourceFilepath, destFilepath, { + overwrite: file.overwrite || false, + }); + ctx.logger.info( + `File ${sourceFilepath} renamed to ${destFilepath} successfully`, + ); + } catch (err) { + ctx.logger.error( + `Failed to rename file ${sourceFilepath} to ${destFilepath}:`, + err, + ); + throw err; + } + } + }, + }); +}; diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/index.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/index.ts index 047bcb421d..a5d5092327 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/index.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/index.ts @@ -18,4 +18,5 @@ export * from './catalog'; export { createBuiltinActions } from './createBuiltinActions'; export * from './debug'; export * from './fetch'; +export * from './filesystem'; export * from './publish'; From 19b459d2ba2b7499cd597f9e51cbc75d43ab325c Mon Sep 17 00:00:00 2001 From: Himanshu Mishra Date: Mon, 5 Jul 2021 14:46:04 +0200 Subject: [PATCH 131/204] move url reader docs to plugins -> backend apis Signed-off-by: Himanshu Mishra --- docs/{integrations => plugins}/url-reader.md | 12 ++++++++++-- microsite/sidebars.json | 6 +++--- mkdocs.yml | 2 +- 3 files changed, 14 insertions(+), 6 deletions(-) rename docs/{integrations => plugins}/url-reader.md (96%) diff --git a/docs/integrations/url-reader.md b/docs/plugins/url-reader.md similarity index 96% rename from docs/integrations/url-reader.md rename to docs/plugins/url-reader.md index a2108d5c71..41aba98a66 100644 --- a/docs/integrations/url-reader.md +++ b/docs/plugins/url-reader.md @@ -24,8 +24,8 @@ package provides a dedicated API for reading from such URL based remote locations like GitHub, GitLab, Bitbucket, Google Cloud Storage, etc. This is commonly referred to as "URL Reader". It takes care of making authenticated requests to the remote host so that private files can be read securely. If users -have [GitHub App based authentication](../plugins/github-apps.md) set up, URL -Reader even refreshes the token, to avoid reaching the GitHub API rate limit. +have [GitHub App based authentication](github-apps.md) set up, URL Reader even +refreshes the token, to avoid reaching the GitHub API rate limit. As a result, plugin authors do not have to worry about any of these problems when trying to read files. @@ -61,6 +61,14 @@ The generic interface of a URL Reader instance looks like this. export type UrlReader = { /* Used to read a single file and return its content. */ read(url: string): Promise; + /** + * A replacement for the read method that supports options and complex responses. + * + * Use this whenever it is available, as the read method will be deprecated and + * eventually removed in the future. + */ + readUrl?(url: string, options?: ReadUrlOptions): Promise; + /* Used to read a file tree and download as a directory. */ readTree(url: string, options?: ReadTreeOptions): Promise; /* Used to search a file in a tree. */ diff --git a/microsite/sidebars.json b/microsite/sidebars.json index 5530fc6f61..5999524073 100644 --- a/microsite/sidebars.json +++ b/microsite/sidebars.json @@ -149,8 +149,7 @@ "type": "subcategory", "label": "LDAP", "ids": ["integrations/ldap/org"] - }, - "integrations/url-reader" + } ], "Plugins": [ "plugins/index", @@ -167,7 +166,8 @@ "plugins/proxying", "plugins/backend-plugin", "plugins/call-existing-api", - "plugins/github-apps" + "plugins/github-apps", + "plugins/url-reader" ] }, { diff --git a/mkdocs.yml b/mkdocs.yml index 47b7084146..4d984e63e3 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -98,7 +98,6 @@ nav: - Locations: 'integrations/google-cloud-storage/locations.md' - LDAP: - Org Data: 'integrations/ldap/org.md' - - URL Reader: 'integrations/url-reader.md' - Plugins: - Intro to plugins: 'plugins/index.md' - Existing plugins: 'plugins/existing-plugins.md' @@ -113,6 +112,7 @@ nav: - Backend plugin: 'plugins/backend-plugin.md' - Call existing API: 'plugins/call-existing-api.md' - GitHub Apps for Backend Authentication: 'plugins/github-apps.md' + - URL Reader: 'plugins/url-reader.md' - Testing: - Testing with Jest: 'plugins/testing.md' - Publishing: From 00f590ad5341672b1fa18c64680fab1d5262d24b Mon Sep 17 00:00:00 2001 From: Andrea Falzetti Date: Mon, 5 Jul 2021 13:37:03 +0100 Subject: [PATCH 132/204] feat(scaffolder): add description and tests for directories Signed-off-by: Andrea Falzetti --- .../actions/builtin/filesystem/delete.test.ts | 11 +++++++++-- .../actions/builtin/filesystem/delete.ts | 3 ++- .../actions/builtin/filesystem/rename.test.ts | 16 +++++++++++++--- .../actions/builtin/filesystem/rename.ts | 11 ++++++++--- 4 files changed, 32 insertions(+), 9 deletions(-) diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/filesystem/delete.test.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/filesystem/delete.test.ts index f8fc1f1dc5..ba8a145721 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/filesystem/delete.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/filesystem/delete.test.ts @@ -46,6 +46,9 @@ describe('fs:delete', () => { [workspacePath]: { 'unit-test-a.js': 'hello', 'unit-test-b.js': 'world', + 'a-folder': { + 'unit-test-in-a-folder.js2': 'content', + }, }, }); }); @@ -90,14 +93,18 @@ describe('fs:delete', () => { ...mockContext, input: { files: ['/foo/../../../index.js'] }, }), - ).rejects.toThrow(/Relative path is not allowed to refer to a directory outside its parent/); + ).rejects.toThrow( + /Relative path is not allowed to refer to a directory outside its parent/, + ); await expect( action.handler({ ...mockContext, input: { files: ['../../../index.js'] }, }), - ).rejects.toThrow(/Relative path is not allowed to refer to a directory outside its parent/); + ).rejects.toThrow( + /Relative path is not allowed to refer to a directory outside its parent/, + ); }); it('should call fs.rm with the correct values', async () => { diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/filesystem/delete.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/filesystem/delete.ts index ec8d60f955..068f777ec5 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/filesystem/delete.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/filesystem/delete.ts @@ -21,6 +21,7 @@ import fs from 'fs-extra'; export const createFilesystemDeleteAction = () => { return createTemplateAction<{ files: string[] }>({ id: 'fs:delete', + description: 'Deletes files and directories from the workspace', schema: { input: { required: ['files'], @@ -28,7 +29,7 @@ export const createFilesystemDeleteAction = () => { properties: { files: { title: 'Files', - description: 'A list of files or directories that will be deleted', + description: 'A list of files and directories that will be deleted', type: 'array', items: { type: 'string', diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/filesystem/rename.test.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/filesystem/rename.test.ts index 58bb558ff5..8452735083 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/filesystem/rename.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/filesystem/rename.test.ts @@ -37,6 +37,10 @@ describe('fs:rename', () => { from: 'unit-test-b.js', to: 'new-b.js', }, + { + from: 'a-folder', + to: 'brand-new-folder', + }, ]; const mockContext = { input: { @@ -57,6 +61,9 @@ describe('fs:rename', () => { 'unit-test-a.js': 'hello', 'unit-test-b.js': 'world', 'unit-test-c.js': 'i will be overwritten :-(', + 'a-folder': { + 'file.md': 'content', + }, }, }); }); @@ -124,14 +131,18 @@ describe('fs:rename', () => { ...mockContext, input: { files: [{ from: 'index.js', to: '/core/../../../index.js' }] }, }), - ).rejects.toThrow(/Relative path is not allowed to refer to a directory outside its parent/); + ).rejects.toThrow( + /Relative path is not allowed to refer to a directory outside its parent/, + ); await expect( action.handler({ ...mockContext, input: { files: [{ from: '/core/../../../index.js', to: 'index.js' }] }, }), - ).rejects.toThrow(/Relative path is not allowed to refer to a directory outside its parent/); + ).rejects.toThrow( + /Relative path is not allowed to refer to a directory outside its parent/, + ); }); it('should throw is trying to override by mistake', async () => { @@ -184,7 +195,6 @@ describe('fs:rename', () => { const destBeforeContent = fs.readFileSync(destFilePath, 'utf-8'); expect(sourceBeforeContent).not.toEqual(destBeforeContent); - await action.handler({ ...mockContext, diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/filesystem/rename.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/filesystem/rename.ts index bcfb35025c..aaadd5df57 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/filesystem/rename.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/filesystem/rename.ts @@ -28,6 +28,7 @@ interface FilesToRename extends JsonObject { export const createFilesystemRenameAction = () => { return createTemplateAction<{ files: FilesToRename }>({ id: 'fs:rename', + description: 'Renames files and directories within the workspace', schema: { input: { required: ['files'], @@ -35,7 +36,8 @@ export const createFilesystemRenameAction = () => { properties: { files: { title: 'Files', - description: 'A list of file names that will be renamed', + description: + 'A list of file and directory names that will be renamed', type: 'array', items: { type: 'object', @@ -70,12 +72,15 @@ export const createFilesystemRenameAction = () => { throw new InputError('each file must have a from and to property'); } - const sourceFilepath = resolveSafeChildPath(ctx.workspacePath, file.from); + const sourceFilepath = resolveSafeChildPath( + ctx.workspacePath, + file.from, + ); const destFilepath = resolveSafeChildPath(ctx.workspacePath, file.to); try { await fs.move(sourceFilepath, destFilepath, { - overwrite: file.overwrite || false, + overwrite: file.overwrite ?? false, }); ctx.logger.info( `File ${sourceFilepath} renamed to ${destFilepath} successfully`, From 4f9192223f5353734ef4d0ff940d5422f333525c Mon Sep 17 00:00:00 2001 From: Philipp Hugenroth Date: Mon, 5 Jul 2021 15:37:36 +0200 Subject: [PATCH 133/204] Use Grid components for catalog layout Signed-off-by: Philipp Hugenroth --- .../components/CatalogPage/CatalogPage.tsx | 58 ++++++++----------- 1 file changed, 25 insertions(+), 33 deletions(-) diff --git a/plugins/catalog/src/components/CatalogPage/CatalogPage.tsx b/plugins/catalog/src/components/CatalogPage/CatalogPage.tsx index ba19d6036c..85855237fb 100644 --- a/plugins/catalog/src/components/CatalogPage/CatalogPage.tsx +++ b/plugins/catalog/src/components/CatalogPage/CatalogPage.tsx @@ -15,7 +15,7 @@ */ import React from 'react'; -import { makeStyles } from '@material-ui/core'; +import { Grid } from '@material-ui/core'; import { EntityKindPicker, EntityLifecyclePicker, @@ -39,18 +39,6 @@ import { TableProps, } from '@backstage/core-components'; -const useStyles = makeStyles(theme => ({ - contentWrapper: { - display: 'grid', - gridTemplateAreas: "'filters' 'table'", - gridTemplateColumns: '250px 1fr', - gridColumnGap: theme.spacing(2), - }, - buttonSpacing: { - marginLeft: theme.spacing(2), - }, -})); - export type CatalogPageProps = { initiallySelectedFilter?: UserListFilterKind; columns?: TableColumn[]; @@ -61,30 +49,34 @@ export const CatalogPage = ({ initiallySelectedFilter = 'owned', columns, actions, -}: CatalogPageProps) => { - const styles = useStyles(); - - return ( - - - - - All your software catalog entities - -
    - -
    +}: CatalogPageProps) => ( + + + + + All your software catalog entities + + + + + + + + -
    + + + -
    -
    - - - ); -}; + + + + + +); From c93fb2c93d67c23a13d85c75c4a3ed296503a4d6 Mon Sep 17 00:00:00 2001 From: Andrea Falzetti Date: Mon, 5 Jul 2021 16:03:45 +0100 Subject: [PATCH 134/204] docs(scaffolder): update docs Signed-off-by: Andrea Falzetti --- plugins/scaffolder-backend/api-report.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/plugins/scaffolder-backend/api-report.md b/plugins/scaffolder-backend/api-report.md index 792913749b..7528388a47 100644 --- a/plugins/scaffolder-backend/api-report.md +++ b/plugins/scaffolder-backend/api-report.md @@ -143,6 +143,12 @@ export function createFetchPlainAction(options: { integrations: ScmIntegrations; }): TemplateAction; +// @public (undocumented) +export const createFilesystemDeleteAction: () => TemplateAction; + +// @public (undocumented) +export const createFilesystemRenameAction: () => TemplateAction; + // @public (undocumented) export function createLegacyActions(options: Options): TemplateAction[]; From 24b4b01cd73a1f5338074dba76c242193974ebf5 Mon Sep 17 00:00:00 2001 From: Philipp Hugenroth Date: Mon, 5 Jul 2021 17:31:03 +0200 Subject: [PATCH 135/204] ACustomize scrollbar for sidebar items wrapper Signed-off-by: Philipp Hugenroth --- .../src/layout/Sidebar/Items.tsx | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/packages/core-components/src/layout/Sidebar/Items.tsx b/packages/core-components/src/layout/Sidebar/Items.tsx index dbaa50b76e..e53cdfaa57 100644 --- a/packages/core-components/src/layout/Sidebar/Items.tsx +++ b/packages/core-components/src/layout/Sidebar/Items.tsx @@ -291,10 +291,21 @@ export const SidebarDivider = styled('hr')({ margin: '12px 0px', }); -export const SidebarScrollWrapper = styled('div')({ +export const SidebarScrollWrapper = styled('div')(({ theme }) => ({ flex: '0 1 auto', - overflowY: 'auto', + overflowX: 'hidden', + // 5px space to the right of the scrollbar + width: 'calc(100% - 5px)', // Display at least one item in the container // Question: Can this be a config/theme variable - if so, which? :/ minHeight: '48px', -}); + '&::-webkit-scrollbar': { + backgroundColor: theme.palette.background.default, + width: '5px', + borderRadius: '5px', + }, + '&::-webkit-scrollbar-thumb': { + backgroundColor: theme.palette.text.hint, + borderRadius: '5px', + }, +})); From 612e25fd7c5be2366c94f3e518837d6a571f85b3 Mon Sep 17 00:00:00 2001 From: Philipp Hugenroth Date: Mon, 5 Jul 2021 17:34:29 +0200 Subject: [PATCH 136/204] Add changeset Signed-off-by: Philipp Hugenroth --- .changeset/young-pigs-beg.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/young-pigs-beg.md diff --git a/.changeset/young-pigs-beg.md b/.changeset/young-pigs-beg.md new file mode 100644 index 0000000000..bbbc7b0f74 --- /dev/null +++ b/.changeset/young-pigs-beg.md @@ -0,0 +1,5 @@ +--- +'@backstage/core-components': patch +--- + +Add custom styles for scrollbar of sidebar items wrapper to fix flaky behavior From c97e06e1c15c9ea42b76224a250714bd6afdd1ef Mon Sep 17 00:00:00 2001 From: Philipp Hugenroth Date: Mon, 5 Jul 2021 18:01:09 +0200 Subject: [PATCH 137/204] Fix changeset spelling Signed-off-by: Philipp Hugenroth --- .changeset/young-pigs-beg.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/young-pigs-beg.md b/.changeset/young-pigs-beg.md index bbbc7b0f74..f40c02b872 100644 --- a/.changeset/young-pigs-beg.md +++ b/.changeset/young-pigs-beg.md @@ -2,4 +2,4 @@ '@backstage/core-components': patch --- -Add custom styles for scrollbar of sidebar items wrapper to fix flaky behavior +Add custom styles to Scrollbar of the Sidebar Wrapper to fix flaky behaviour From 4ca8e569a5154207bd4adfe6187caf9145062434 Mon Sep 17 00:00:00 2001 From: Ben Lambert Date: Mon, 5 Jul 2021 18:06:12 +0200 Subject: [PATCH 138/204] Add changeset Signed-off-by: Ben Lambert --- .changeset/rotten-cooks-try.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/rotten-cooks-try.md diff --git a/.changeset/rotten-cooks-try.md b/.changeset/rotten-cooks-try.md new file mode 100644 index 0000000000..b5a09f399f --- /dev/null +++ b/.changeset/rotten-cooks-try.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-ilert': patch +--- + +chore: bump @date-io/luxon from 1.3.13 to 2.10.11 From 0b684849f37df9880621fd82e790f6acf29934c6 Mon Sep 17 00:00:00 2001 From: Philipp Hugenroth Date: Mon, 5 Jul 2021 18:06:57 +0200 Subject: [PATCH 139/204] Please - don't embarrass me - I'm not a native speaker, bot... Signed-off-by: Philipp Hugenroth --- .changeset/young-pigs-beg.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/young-pigs-beg.md b/.changeset/young-pigs-beg.md index f40c02b872..bfdf726911 100644 --- a/.changeset/young-pigs-beg.md +++ b/.changeset/young-pigs-beg.md @@ -2,4 +2,4 @@ '@backstage/core-components': patch --- -Add custom styles to Scrollbar of the Sidebar Wrapper to fix flaky behaviour +Add custom styles to scroll bar of the sidebar wrapper to fix flaky behaviour From 6cbeafcbb98a75551ab8f07f297fd91da9c23a4a Mon Sep 17 00:00:00 2001 From: Ben Lambert Date: Mon, 5 Jul 2021 18:14:25 +0200 Subject: [PATCH 140/204] Update spelling Signed-off-by: Ben Lambert --- .changeset/rotten-cooks-try.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/rotten-cooks-try.md b/.changeset/rotten-cooks-try.md index b5a09f399f..ccbd315ebe 100644 --- a/.changeset/rotten-cooks-try.md +++ b/.changeset/rotten-cooks-try.md @@ -2,4 +2,4 @@ '@backstage/plugin-ilert': patch --- -chore: bump @date-io/luxon from 1.3.13 to 2.10.11 +chore: bump `@date-io/luxon` from 1.3.13 to 2.10.11 From 3a55daf7b6ec515e29984cad376edea1ff17ccfd Mon Sep 17 00:00:00 2001 From: Erik Larsson Date: Mon, 5 Jul 2021 23:03:36 +0200 Subject: [PATCH 141/204] Authorize scaffolder list actions request Signed-off-by: Erik Larsson --- plugins/scaffolder/src/api.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/plugins/scaffolder/src/api.ts b/plugins/scaffolder/src/api.ts index 85df77f2f5..37d78d0fda 100644 --- a/plugins/scaffolder/src/api.ts +++ b/plugins/scaffolder/src/api.ts @@ -245,7 +245,10 @@ export class ScaffolderClient implements ScaffolderApi { */ async listActions(): Promise { const baseUrl = await this.discoveryApi.getBaseUrl('scaffolder'); - const response = await fetch(`${baseUrl}/v2/actions`); + const token = await this.identityApi.getIdToken(); + const response = await fetch(`${baseUrl}/v2/actions`, { + headers: token ? { Authorization: `Bearer ${token}` } : {}, + }); if (!response.ok) { throw ResponseError.fromResponse(response); From bd764f78accb90d76cd5c192bad496bb1ced9023 Mon Sep 17 00:00:00 2001 From: Erik Larsson Date: Mon, 5 Jul 2021 23:04:33 +0200 Subject: [PATCH 142/204] changeset Signed-off-by: Erik Larsson --- .changeset/tasty-chairs-flash.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/tasty-chairs-flash.md diff --git a/.changeset/tasty-chairs-flash.md b/.changeset/tasty-chairs-flash.md new file mode 100644 index 0000000000..186c10e98f --- /dev/null +++ b/.changeset/tasty-chairs-flash.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder': patch +--- + +Authorize scaffolder list actions request From 3e3227afc06aabb3c35e8f6cf4567edc59d287bc Mon Sep 17 00:00:00 2001 From: roylisto Date: Tue, 6 Jul 2021 10:27:56 +0700 Subject: [PATCH 143/204] Add infoCardAction Signed-off-by: roylisto --- .../Group/GroupProfile/GroupProfileCard.tsx | 29 ++++++++++--------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/plugins/org/src/components/Cards/Group/GroupProfile/GroupProfileCard.tsx b/plugins/org/src/components/Cards/Group/GroupProfile/GroupProfileCard.tsx index 637a7279f6..b44fbe6c5c 100644 --- a/plugins/org/src/components/Cards/Group/GroupProfile/GroupProfileCard.tsx +++ b/plugins/org/src/components/Cards/Group/GroupProfile/GroupProfileCard.tsx @@ -79,28 +79,31 @@ export const GroupProfileCard = ({ kind: 'group', }); - const entityMetadataEditUrl = getEntityMetadataEditUrl(group) ?? '#'; + const entityMetadataEditUrl = getEntityMetadataEditUrl(group); const displayName = profile?.displayName ?? name; const emailHref = profile?.email ? `mailto:${profile.email}` : '#'; + const infoCardAction = entityMetadataEditUrl ? ( + + + + ) : ( + + + + ); return ( } subheader={description} variant={variant} - action={ - - - - } + action={infoCardAction} > From 30f28ef11ce18d94e2c846fbe5ce24e72e9cc83b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 6 Jul 2021 04:10:52 +0000 Subject: [PATCH 144/204] chore(deps-dev): bump @types/aws4 from 1.5.1 to 1.5.2 Bumps [@types/aws4](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/aws4) from 1.5.1 to 1.5.2. - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases) - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/aws4) --- updated-dependencies: - dependency-name: "@types/aws4" dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 272e7e229f..6cf36a7dfa 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5459,9 +5459,9 @@ integrity sha512-iIgQNzCm0v7QMhhe4Jjn9uRh+I6GoPmt03CbEtwx3ao8/EfoQcmgtqH4vQ5Db/lxiIGaWDv6nwvunuh0RyX0+A== "@types/aws4@^1.5.1": - version "1.5.1" - resolved "https://registry.npmjs.org/@types/aws4/-/aws4-1.5.1.tgz#361fadab198a030ab398269183ae3fa86e958ed9" - integrity sha1-Nh+tqxmKAwqzmCaRg64/qG6Vjtk= + version "1.5.2" + resolved "https://registry.npmjs.org/@types/aws4/-/aws4-1.5.2.tgz#34e35b4405a619b9205be3e7678963bc7c8a47db" + integrity sha512-r8+XOv0BKw3Br0oU6w9cfu21PaQq/5ZeXvMOivNQYJLc9WcPCpEFDaQu72QNEQjYv5Otu48VhjjnbtwrSmk/rg== "@types/babel__core@^7.0.0", "@types/babel__core@^7.1.7": version "7.1.9" From c669940656302de5384fd6c6e1beb0a369b55b87 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 6 Jul 2021 04:14:07 +0000 Subject: [PATCH 145/204] chore(deps-dev): bump @types/archiver from 5.1.0 to 5.3.0 Bumps [@types/archiver](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/archiver) from 5.1.0 to 5.3.0. - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases) - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/archiver) --- updated-dependencies: - dependency-name: "@types/archiver" dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 272e7e229f..7e5e209489 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5442,9 +5442,9 @@ integrity sha512-/+CRPXpBDpo2RK9C68N3b2cOvO0Cf5B9aPijHsoDQTHivnGSObdOF2BRQOYjojWTDy6nQvMjmqRXIxH55VjxxA== "@types/archiver@^5.1.0": - version "5.1.0" - resolved "https://registry.npmjs.org/@types/archiver/-/archiver-5.1.0.tgz#869f4ce4028e49cf9a0243cf914415f4cc3d1f3d" - integrity sha512-baFOhanb/hxmcOd1Uey2TfFg43kTSmM6py1Eo7Rjbv/ivcl7PXLhY0QgXGf50Hx/eskGCFqPfhs/7IZLb15C5g== + version "5.3.0" + resolved "https://registry.npmjs.org/@types/archiver/-/archiver-5.3.0.tgz#2b34ba56d4d7102d256b922c7e91e09eab79db6f" + integrity sha512-qJ79qsmq7O/k9FYwsF6O1xVA1PeLV+9Bh3TYkVCu3VzMR6vN9JQkgEOh/rrQ0R+F4Ta+R3thHGewxQtFglwVfg== dependencies: "@types/glob" "*" From 34143f5c9ab5897e59141b78d8bc80d72fb67214 Mon Sep 17 00:00:00 2001 From: Ben Lambert Date: Tue, 6 Jul 2021 11:15:21 +0200 Subject: [PATCH 146/204] Update tasty-chairs-flash.md Signed-off-by: Ben Lambert --- .changeset/tasty-chairs-flash.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/tasty-chairs-flash.md b/.changeset/tasty-chairs-flash.md index 186c10e98f..8be48d92b3 100644 --- a/.changeset/tasty-chairs-flash.md +++ b/.changeset/tasty-chairs-flash.md @@ -2,4 +2,4 @@ '@backstage/plugin-scaffolder': patch --- -Authorize scaffolder list actions request +Pass through the `idToken` in `Authorization` Header for `listActions` request From ad5d05b6903dd4213777d4ef06eb04b4d1e29c81 Mon Sep 17 00:00:00 2001 From: Philipp Hugenroth Date: Tue, 6 Jul 2021 11:23:59 +0200 Subject: [PATCH 147/204] Add changeset Signed-off-by: Philipp Hugenroth --- .changeset/happy-pugs-notice.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/happy-pugs-notice.md diff --git a/.changeset/happy-pugs-notice.md b/.changeset/happy-pugs-notice.md new file mode 100644 index 0000000000..4120018da9 --- /dev/null +++ b/.changeset/happy-pugs-notice.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog': patch +--- + +Change catalog page layout to use Grid components to improve responsiveness From a632f1afd8d20f729b8c0149062eecc241e61f6a Mon Sep 17 00:00:00 2001 From: blam Date: Tue, 6 Jul 2021 11:42:28 +0200 Subject: [PATCH 148/204] chore: fixing hopefully fixing the cypress tugboat tests Signed-off-by: blam --- cypress/src/integration/catalog.ts | 2 +- cypress/src/integration/integrations.ts | 12 +++++++++--- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/cypress/src/integration/catalog.ts b/cypress/src/integration/catalog.ts index 1db2eb8a13..20dcdd9b8a 100644 --- a/cypress/src/integration/catalog.ts +++ b/cypress/src/integration/catalog.ts @@ -23,7 +23,7 @@ describe('Catalog', () => { cy.visit('/catalog'); - cy.contains('Owned (8)').should('be.visible'); + cy.contains('Owned (10)').should('be.visible'); }); }); }); diff --git a/cypress/src/integration/integrations.ts b/cypress/src/integration/integrations.ts index 3e3a10aca2..d732e25edf 100644 --- a/cypress/src/integration/integrations.ts +++ b/cypress/src/integration/integrations.ts @@ -27,8 +27,10 @@ describe('Integrations', () => { type: 'url', }); + cy.wait(1000); + cy.visit('/catalog'); - cy.contains('All').click(); + cy.get('[data-testid="user-picker-all"]').click(); cy.get('table').should('contain', 'github-repo'); cy.get('table').should('contain', 'github-repo-nested'); }); @@ -52,8 +54,10 @@ describe('Integrations', () => { type: 'url', }); + cy.wait(1000); + cy.visit('/catalog'); - cy.contains('All').click(); + cy.get('[data-testid="user-picker-all"]').click(); cy.get('table').should('contain', 'gitlab-repo'); cy.get('table').should('contain', 'gitlab-repo-nested'); }); @@ -67,8 +71,10 @@ describe('Integrations', () => { type: 'url', }); + cy.wait(1000); + cy.visit('/catalog'); - cy.contains('All').click(); + cy.get('[data-testid="user-picker-all"]').click(); cy.get('table').should('contain', 'bitbucket-repo'); cy.get('table').should('contain', 'bitbucket-repo-nested'); }); From b055ef88aafc2ecb33d0baa694fe2ea615ecf2ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mathias=20A=CC=8Ahsberg?= Date: Mon, 5 Jul 2021 15:09:31 +0000 Subject: [PATCH 149/204] Add extension points for the LDAP processor for modifying group and user entities MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Mathias Åhsberg --- .changeset/large-mice-sin.md | 6 + docs/integrations/ldap/org.md | 44 ++- .../catalog-backend-module-ldap/api-report.md | 27 +- .../src/ldap/index.ts | 8 +- .../src/ldap/read.ts | 269 ++++++++++-------- .../src/ldap/types.ts | 47 +++ .../src/ldap/util.ts | 25 +- .../src/processors/LdapOrgReaderProcessor.ts | 27 +- 8 files changed, 325 insertions(+), 128 deletions(-) create mode 100644 .changeset/large-mice-sin.md create mode 100644 plugins/catalog-backend-module-ldap/src/ldap/types.ts diff --git a/.changeset/large-mice-sin.md b/.changeset/large-mice-sin.md new file mode 100644 index 0000000000..77aba8d3c5 --- /dev/null +++ b/.changeset/large-mice-sin.md @@ -0,0 +1,6 @@ +--- +'@backstage/plugin-catalog-backend-module-ldap': minor +--- + +Add extension points to the `LdapOrgReaderProcessor` to make it possible to do more advanced modifications +of the ingested users and groups. diff --git a/docs/integrations/ldap/org.md b/docs/integrations/ldap/org.md index 836601971c..d1438aba8b 100644 --- a/docs/integrations/ldap/org.md +++ b/docs/integrations/ldap/org.md @@ -122,8 +122,8 @@ The DN under which users are stored, e.g. #### users.options The search options to use when sending the query to the server, when reading all -users. All of the options are shown below, with their default values, but they -are all optional. +users. All the options are shown below, with their default values, but they are +all optional. ```yaml options: @@ -158,8 +158,8 @@ set: Mappings from well known entity fields, to LDAP attribute names. This is where you are able to define how to interpret the attributes of each LDAP result item, -and to move them into the corresponding entity fields. All of the options are -shown below, with their default values, but they are all optional. +and to move them into the corresponding entity fields. All the options are shown +below, with their default values, but they are all optional. If you leave out an optional mapping, it will still be copied using that default value. For example, even if you do not put in the field `displayName` in your @@ -204,8 +204,8 @@ The DN under which groups are stored, e.g. #### groups.options The search options to use when sending the query to the server, when reading all -groups. All of the options are shown below, with their default values, but they -are all optional. +groups. All the options are shown below, with their default values, but they are +all optional. ```yaml options: @@ -282,3 +282,35 @@ map: # the spec.children field of the entity. members: member ``` + +## Customize the Processor + +In case you want to customize the ingested entities, the +`LdapOrgReaderProcessor` allows to pass transformers for users and groups. + +1. Create a transformer: + +```ts +export async function myGroupTransformer( + vendor: LdapVendor, + config: GroupConfig, + group: SearchEntry, +): Promise { + // Transformations may change namespace, change entity naming pattern, fill + // profile with more or other details... + + // Create the group entity on your own, or wrap the default transformer + return await defaultGroupTransformer(vendor, config, group); +} +``` + +2. Configure the processor with the transformer: + +```ts +builder.addProcessor( + LdapOrgReaderProcessor.fromConfig(config, { + logger, + groupTransformer: myGroupTransformer, + }), +); +``` diff --git a/plugins/catalog-backend-module-ldap/api-report.md b/plugins/catalog-backend-module-ldap/api-report.md index d5e9d731ea..55405cab41 100644 --- a/plugins/catalog-backend-module-ldap/api-report.md +++ b/plugins/catalog-backend-module-ldap/api-report.md @@ -16,6 +16,15 @@ import { SearchEntry } from 'ldapjs'; import { SearchOptions } from 'ldapjs'; import { UserEntity } from '@backstage/catalog-model'; +// @public (undocumented) +export function defaultGroupTransformer(vendor: LdapVendor, config: GroupConfig, entry: SearchEntry): Promise; + +// @public (undocumented) +export function defaultUserTransformer(vendor: LdapVendor, config: UserConfig, entry: SearchEntry): Promise; + +// @public +export type GroupTransformer = (vendor: LdapVendor, config: GroupConfig, group: SearchEntry) => Promise; + // @public export const LDAP_DN_ANNOTATION = "backstage.io/ldap-dn"; @@ -40,14 +49,18 @@ export class LdapOrgReaderProcessor implements CatalogProcessor { constructor(options: { providers: LdapProviderConfig[]; logger: Logger; + groupTransformer?: GroupTransformer; + userTransformer?: UserTransformer; }); // (undocumented) static fromConfig(config: Config, options: { logger: Logger; + groupTransformer?: GroupTransformer; + userTransformer?: UserTransformer; }): LdapOrgReaderProcessor; // (undocumented) readLocation(location: LocationSpec, _optional: boolean, emit: CatalogProcessorEmit): Promise; -} + } // @public export type LdapProviderConfig = { @@ -57,15 +70,25 @@ export type LdapProviderConfig = { groups: GroupConfig; }; +// @public +export function mapStringAttr(entry: SearchEntry, vendor: LdapVendor, attributeName: string | undefined, setter: (value: string) => void): void; + // @public export function readLdapConfig(config: Config): LdapProviderConfig[]; // @public -export function readLdapOrg(client: LdapClient, userConfig: UserConfig, groupConfig: GroupConfig): Promise<{ +export function readLdapOrg(client: LdapClient, userConfig: UserConfig, groupConfig: GroupConfig, options: { + groupTransformer?: GroupTransformer; + userTransformer?: UserTransformer; + logger: Logger; +}): Promise<{ users: UserEntity[]; groups: GroupEntity[]; }>; +// @public +export type UserTransformer = (vendor: LdapVendor, config: UserConfig, user: SearchEntry) => Promise; + // (No @packageDocumentation comment for this package) diff --git a/plugins/catalog-backend-module-ldap/src/ldap/index.ts b/plugins/catalog-backend-module-ldap/src/ldap/index.ts index 194a75ac60..a9f127a3a7 100644 --- a/plugins/catalog-backend-module-ldap/src/ldap/index.ts +++ b/plugins/catalog-backend-module-ldap/src/ldap/index.ts @@ -15,6 +15,7 @@ */ export { LdapClient } from './client'; +export { mapStringAttr } from './util'; export { readLdapConfig } from './config'; export type { LdapProviderConfig } from './config'; export { @@ -22,4 +23,9 @@ export { LDAP_RDN_ANNOTATION, LDAP_UUID_ANNOTATION, } from './constants'; -export { readLdapOrg } from './read'; +export { + defaultGroupTransformer, + defaultUserTransformer, + readLdapOrg, +} from './read'; +export type { GroupTransformer, UserTransformer } from './types'; diff --git a/plugins/catalog-backend-module-ldap/src/ldap/read.ts b/plugins/catalog-backend-module-ldap/src/ldap/read.ts index a662b36d87..f3ee09d32d 100644 --- a/plugins/catalog-backend-module-ldap/src/ldap/read.ts +++ b/plugins/catalog-backend-module-ldap/src/ldap/read.ts @@ -26,74 +26,97 @@ import { LDAP_UUID_ANNOTATION, } from './constants'; import { LdapVendor } from './vendors'; +import { Logger } from 'winston'; +import { GroupTransformer, UserTransformer } from './types'; +import { mapStringAttr } from './util'; + +export async function defaultUserTransformer( + vendor: LdapVendor, + config: UserConfig, + entry: SearchEntry, +): Promise { + const { set, map } = config; + + const entity: UserEntity = { + apiVersion: 'backstage.io/v1alpha1', + kind: 'User', + metadata: { + name: '', + annotations: {}, + }, + spec: { + profile: {}, + memberOf: [], + }, + }; + + if (set) { + for (const [path, value] of Object.entries(set)) { + lodashSet(entity, path, value); + } + } + + mapStringAttr(entry, vendor, map.name, v => { + entity.metadata.name = v; + }); + mapStringAttr(entry, vendor, map.description, v => { + entity.metadata.description = v; + }); + mapStringAttr(entry, vendor, map.rdn, v => { + entity.metadata.annotations![LDAP_RDN_ANNOTATION] = v; + }); + mapStringAttr(entry, vendor, vendor.uuidAttributeName, v => { + entity.metadata.annotations![LDAP_UUID_ANNOTATION] = v; + }); + mapStringAttr(entry, vendor, vendor.dnAttributeName, v => { + entity.metadata.annotations![LDAP_DN_ANNOTATION] = v; + }); + mapStringAttr(entry, vendor, map.displayName, v => { + entity.spec.profile!.displayName = v; + }); + mapStringAttr(entry, vendor, map.email, v => { + entity.spec.profile!.email = v; + }); + mapStringAttr(entry, vendor, map.picture, v => { + entity.spec.profile!.picture = v; + }); + + return entity; +} /** * Reads users out of an LDAP provider. * * @param client The LDAP client * @param config The user data configuration + * @param opts */ export async function readLdapUsers( client: LdapClient, config: UserConfig, + opts?: { transformer?: UserTransformer }, ): Promise<{ users: UserEntity[]; // With all relations empty userMemberOf: Map>; // DN -> DN or UUID of groups }> { - const { dn, options, set, map } = config; + const { dn, options, map } = config; const vendor = await client.getVendor(); - const entries = await client.search(dn, options); - const entities: UserEntity[] = []; const userMemberOf: Map> = new Map(); - for (const entry of entries) { - const entity: UserEntity = { - apiVersion: 'backstage.io/v1alpha1', - kind: 'User', - metadata: { - name: '', - annotations: {}, - }, - spec: { - profile: {}, - memberOf: [], - }, - }; + const transformer = opts?.transformer ?? defaultUserTransformer; - if (set) { - for (const [path, value] of Object.entries(set)) { - lodashSet(entity, path, value); - } + const entries = await client.search(dn, options); + + for (const user of entries) { + const entity = await transformer(vendor, config, user); + + if (!entity) { + continue; } - mapStringAttr(entry, vendor, map.name, v => { - entity.metadata.name = v; - }); - mapStringAttr(entry, vendor, map.description, v => { - entity.metadata.description = v; - }); - mapStringAttr(entry, vendor, map.rdn, v => { - entity.metadata.annotations![LDAP_RDN_ANNOTATION] = v; - }); - mapStringAttr(entry, vendor, vendor.uuidAttributeName, v => { - entity.metadata.annotations![LDAP_UUID_ANNOTATION] = v; - }); - mapStringAttr(entry, vendor, vendor.dnAttributeName, v => { - entity.metadata.annotations![LDAP_DN_ANNOTATION] = v; - }); - mapStringAttr(entry, vendor, map.displayName, v => { - entity.spec.profile!.displayName = v; - }); - mapStringAttr(entry, vendor, map.email, v => { - entity.spec.profile!.email = v; - }); - mapStringAttr(entry, vendor, map.picture, v => { - entity.spec.profile!.picture = v; - }); - - mapReferencesAttr(entry, vendor, map.memberOf, (myDn, vs) => { + mapReferencesAttr(user, vendor, map.memberOf, (myDn, vs) => { ensureItems(userMemberOf, myDn, vs); }); @@ -103,82 +126,103 @@ export async function readLdapUsers( return { users: entities, userMemberOf }; } +export async function defaultGroupTransformer( + vendor: LdapVendor, + config: GroupConfig, + entry: SearchEntry, +): Promise { + const { set, map } = config; + const entity: GroupEntity = { + apiVersion: 'backstage.io/v1alpha1', + kind: 'Group', + metadata: { + name: '', + annotations: {}, + }, + spec: { + type: 'unknown', + profile: {}, + children: [], + }, + }; + + if (set) { + for (const [path, value] of Object.entries(set)) { + lodashSet(entity, path, value); + } + } + + mapStringAttr(entry, vendor, map.name, v => { + entity.metadata.name = v; + }); + mapStringAttr(entry, vendor, map.description, v => { + entity.metadata.description = v; + }); + mapStringAttr(entry, vendor, map.rdn, v => { + entity.metadata.annotations![LDAP_RDN_ANNOTATION] = v; + }); + mapStringAttr(entry, vendor, vendor.uuidAttributeName, v => { + entity.metadata.annotations![LDAP_UUID_ANNOTATION] = v; + }); + mapStringAttr(entry, vendor, vendor.dnAttributeName, v => { + entity.metadata.annotations![LDAP_DN_ANNOTATION] = v; + }); + mapStringAttr(entry, vendor, map.type, v => { + entity.spec.type = v; + }); + mapStringAttr(entry, vendor, map.displayName, v => { + entity.spec.profile!.displayName = v; + }); + mapStringAttr(entry, vendor, map.email, v => { + entity.spec.profile!.email = v; + }); + mapStringAttr(entry, vendor, map.picture, v => { + entity.spec.profile!.picture = v; + }); + + return entity; +} + /** * Reads groups out of an LDAP provider. * * @param client The LDAP client * @param config The group data configuration + * @param opts */ export async function readLdapGroups( client: LdapClient, config: GroupConfig, + opts?: { + transformer?: GroupTransformer; + }, ): Promise<{ groups: GroupEntity[]; // With all relations empty groupMemberOf: Map>; // DN -> DN or UUID of groups groupMember: Map>; // DN -> DN or UUID of groups & users }> { - const { dn, options, set, map } = config; - const vendor = await client.getVendor(); - - const entries = await client.search(dn, options); - const groups: GroupEntity[] = []; const groupMemberOf: Map> = new Map(); const groupMember: Map> = new Map(); - for (const entry of entries) { - const entity: GroupEntity = { - apiVersion: 'backstage.io/v1alpha1', - kind: 'Group', - metadata: { - name: '', - annotations: {}, - }, - spec: { - type: 'unknown', - profile: {}, - children: [], - }, - }; + const { dn, map, options } = config; + const vendor = await client.getVendor(); - if (set) { - for (const [path, value] of Object.entries(set)) { - lodashSet(entity, path, value); - } + const transformer = opts?.transformer ?? defaultGroupTransformer; + + const entries = await client.search(dn, options); + + for (const group of entries) { + const entity = await transformer(vendor, config, group); + + if (!entity) { + continue; } - mapStringAttr(entry, vendor, map.name, v => { - entity.metadata.name = v; - }); - mapStringAttr(entry, vendor, map.description, v => { - entity.metadata.description = v; - }); - mapStringAttr(entry, vendor, map.rdn, v => { - entity.metadata.annotations![LDAP_RDN_ANNOTATION] = v; - }); - mapStringAttr(entry, vendor, vendor.uuidAttributeName, v => { - entity.metadata.annotations![LDAP_UUID_ANNOTATION] = v; - }); - mapStringAttr(entry, vendor, vendor.dnAttributeName, v => { - entity.metadata.annotations![LDAP_DN_ANNOTATION] = v; - }); - mapStringAttr(entry, vendor, map.type, v => { - entity.spec.type = v; - }); - mapStringAttr(entry, vendor, map.displayName, v => { - entity.spec.profile!.displayName = v; - }); - mapStringAttr(entry, vendor, map.email, v => { - entity.spec.profile!.email = v; - }); - mapStringAttr(entry, vendor, map.picture, v => { - entity.spec.profile!.picture = v; - }); - - mapReferencesAttr(entry, vendor, map.memberOf, (myDn, vs) => { + mapReferencesAttr(group, vendor, map.memberOf, (myDn, vs) => { ensureItems(groupMemberOf, myDn, vs); }); - mapReferencesAttr(entry, vendor, map.members, (myDn, vs) => { + mapReferencesAttr(group, vendor, map.members, (myDn, vs) => { ensureItems(groupMember, myDn, vs); }); @@ -199,22 +243,30 @@ export async function readLdapGroups( * with all relations etc filled in. * * @param client The LDAP client - * @param logger A logger instance * @param userConfig The user data configuration * @param groupConfig The group data configuration + * @param options */ export async function readLdapOrg( client: LdapClient, userConfig: UserConfig, groupConfig: GroupConfig, + options: { + groupTransformer?: GroupTransformer; + userTransformer?: UserTransformer; + logger: Logger; + }, ): Promise<{ users: UserEntity[]; groups: GroupEntity[]; }> { - const { users, userMemberOf } = await readLdapUsers(client, userConfig); + const { users, userMemberOf } = await readLdapUsers(client, userConfig, { + transformer: options?.userTransformer, + }); const { groups, groupMemberOf, groupMember } = await readLdapGroups( client, groupConfig, + { transformer: options?.groupTransformer }, ); resolveRelations(groups, users, userMemberOf, groupMemberOf, groupMember); @@ -228,21 +280,6 @@ export async function readLdapOrg( // Helpers // -// Maps a single-valued attribute to a consumer -function mapStringAttr( - entry: SearchEntry, - vendor: LdapVendor, - attributeName: string | undefined, - setter: (value: string) => void, -) { - if (attributeName) { - const values = vendor.decodeStringAttribute(entry, attributeName); - if (values && values.length === 1) { - setter(values[0]); - } - } -} - // Maps a multi-valued attribute of references to other objects, to a consumer function mapReferencesAttr( entry: SearchEntry, diff --git a/plugins/catalog-backend-module-ldap/src/ldap/types.ts b/plugins/catalog-backend-module-ldap/src/ldap/types.ts new file mode 100644 index 0000000000..e32e4c5b42 --- /dev/null +++ b/plugins/catalog-backend-module-ldap/src/ldap/types.ts @@ -0,0 +1,47 @@ +/* + * Copyright 2021 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { GroupEntity, UserEntity } from '@backstage/catalog-model'; +import { SearchEntry } from 'ldapjs'; +import { LdapVendor } from './vendors'; +import { GroupConfig, UserConfig } from './config'; + +/** + * Customize the ingested User entity + * + * @param vendor The LDAP vendor that can be used to find and decode vendor specific attributes + * @param config The User specific config used by the default transformer. + * @param user The found LDAP entry in its source format. This is the entry that you want to transform + * @return A `UserEntity` or `undefined` if you want to ignore the found user for being ingested by the catalog + */ +export type UserTransformer = ( + vendor: LdapVendor, + config: UserConfig, + user: SearchEntry, +) => Promise; + +/** + * Customize the ingested Group entity + * + * @param vendor The LDAP vendor that can be used to find and decode vendor specific attributes + * @param config The Group specific config used by the default transformer. + * @param group The found LDAP entry in its source format. This is the entry that you want to transform + * @return A `GroupEntity` or `undefined` if you want to ignore the found group for being ingested by the catalog + */ +export type GroupTransformer = ( + vendor: LdapVendor, + config: GroupConfig, + group: SearchEntry, +) => Promise; diff --git a/plugins/catalog-backend-module-ldap/src/ldap/util.ts b/plugins/catalog-backend-module-ldap/src/ldap/util.ts index 74dd84cdc9..21ee40f52c 100644 --- a/plugins/catalog-backend-module-ldap/src/ldap/util.ts +++ b/plugins/catalog-backend-module-ldap/src/ldap/util.ts @@ -14,7 +14,8 @@ * limitations under the License. */ -import { Error as LDAPError } from 'ldapjs'; +import { Error as LDAPError, SearchEntry } from 'ldapjs'; +import { LdapVendor } from './vendors'; /** * Builds a string form of an LDAP Error structure. @@ -24,3 +25,25 @@ import { Error as LDAPError } from 'ldapjs'; export function errorString(error: LDAPError) { return `${error.code} ${error.name}: ${error.message}`; } + +/** + * Maps a single-valued attribute to a consumer + * + * @param entry The LDAP source entry + * @param vendor The LDAP vendor + * @param attributeName The source attribute to map. If the attribute is undefined the mapping will be silently ignored. + * @param setter The function to be called with the decoded attribute from the source entry + */ +export function mapStringAttr( + entry: SearchEntry, + vendor: LdapVendor, + attributeName: string | undefined, + setter: (value: string) => void, +) { + if (attributeName) { + const values = vendor.decodeStringAttribute(entry, attributeName); + if (values && values.length === 1) { + setter(values[0]); + } + } +} diff --git a/plugins/catalog-backend-module-ldap/src/processors/LdapOrgReaderProcessor.ts b/plugins/catalog-backend-module-ldap/src/processors/LdapOrgReaderProcessor.ts index 79c0ed6964..f87afc38b9 100644 --- a/plugins/catalog-backend-module-ldap/src/processors/LdapOrgReaderProcessor.ts +++ b/plugins/catalog-backend-module-ldap/src/processors/LdapOrgReaderProcessor.ts @@ -18,10 +18,12 @@ import { LocationSpec } from '@backstage/catalog-model'; import { Config } from '@backstage/config'; import { Logger } from 'winston'; import { + GroupTransformer, LdapClient, LdapProviderConfig, readLdapConfig, readLdapOrg, + UserTransformer, } from '../ldap'; import { CatalogProcessor, @@ -35,8 +37,17 @@ import { export class LdapOrgReaderProcessor implements CatalogProcessor { private readonly providers: LdapProviderConfig[]; private readonly logger: Logger; + private readonly groupTransformer?: GroupTransformer; + private readonly userTransformer?: UserTransformer; - static fromConfig(config: Config, options: { logger: Logger }) { + static fromConfig( + config: Config, + options: { + logger: Logger; + groupTransformer?: GroupTransformer; + userTransformer?: UserTransformer; + }, + ) { const c = config.getOptionalConfig('catalog.processors.ldapOrg'); return new LdapOrgReaderProcessor({ ...options, @@ -44,9 +55,16 @@ export class LdapOrgReaderProcessor implements CatalogProcessor { }); } - constructor(options: { providers: LdapProviderConfig[]; logger: Logger }) { + constructor(options: { + providers: LdapProviderConfig[]; + logger: Logger; + groupTransformer?: GroupTransformer; + userTransformer?: UserTransformer; + }) { this.providers = options.providers; this.logger = options.logger; + this.groupTransformer = options.groupTransformer; + this.userTransformer = options.userTransformer; } async readLocation( @@ -81,6 +99,11 @@ export class LdapOrgReaderProcessor implements CatalogProcessor { client, provider.users, provider.groups, + { + groupTransformer: this.groupTransformer, + userTransformer: this.userTransformer, + logger: this.logger, + }, ); const duration = ((Date.now() - startTimestamp) / 1000).toFixed(1); From 98e5a4919379f9547bf508fae9c0c5ea0b08a2eb Mon Sep 17 00:00:00 2001 From: Ben Lambert Date: Tue, 6 Jul 2021 12:24:28 +0200 Subject: [PATCH 150/204] chore: change timeout Signed-off-by: Ben Lambert --- cypress/src/integration/integrations.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cypress/src/integration/integrations.ts b/cypress/src/integration/integrations.ts index d732e25edf..4703c18881 100644 --- a/cypress/src/integration/integrations.ts +++ b/cypress/src/integration/integrations.ts @@ -27,7 +27,7 @@ describe('Integrations', () => { type: 'url', }); - cy.wait(1000); + cy.wait(5000); cy.visit('/catalog'); cy.get('[data-testid="user-picker-all"]').click(); @@ -54,7 +54,7 @@ describe('Integrations', () => { type: 'url', }); - cy.wait(1000); + cy.wait(5000); cy.visit('/catalog'); cy.get('[data-testid="user-picker-all"]').click(); @@ -71,7 +71,7 @@ describe('Integrations', () => { type: 'url', }); - cy.wait(1000); + cy.wait(5000); cy.visit('/catalog'); cy.get('[data-testid="user-picker-all"]').click(); From 3beeff1c820273f1ae001238bc9b12fbfc1d1407 Mon Sep 17 00:00:00 2001 From: David Tuite Date: Tue, 6 Jul 2021 12:13:53 +0100 Subject: [PATCH 151/204] Use target=_blank on MissingAnnotation Read More link I would like Backstage to stay open so I can continue to work with it while I read the docs. Signed-off-by: David Tuite --- .../src/components/EmptyState/MissingAnnotationEmptyState.tsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/core-components/src/components/EmptyState/MissingAnnotationEmptyState.tsx b/packages/core-components/src/components/EmptyState/MissingAnnotationEmptyState.tsx index 39cce709c0..2b2f2b7738 100644 --- a/packages/core-components/src/components/EmptyState/MissingAnnotationEmptyState.tsx +++ b/packages/core-components/src/components/EmptyState/MissingAnnotationEmptyState.tsx @@ -76,6 +76,8 @@ export const MissingAnnotationEmptyState = ({ annotation }: Props) => { variant="contained" color="primary" href="https://backstage.io/docs/features/software-catalog/well-known-annotations" + target="_blank" + rel="noopener noreferrer" > Read more From 76bb7aeda08ad5f9cda1f6d787bb31bc662b01fb Mon Sep 17 00:00:00 2001 From: Philipp Hugenroth Date: Tue, 6 Jul 2021 14:01:23 +0200 Subject: [PATCH 152/204] Show scroll bar on hover only Signed-off-by: Philipp Hugenroth --- .changeset/late-pants-itch.md | 5 +++++ packages/core-components/src/layout/Sidebar/Items.tsx | 9 +++++++-- 2 files changed, 12 insertions(+), 2 deletions(-) create mode 100644 .changeset/late-pants-itch.md diff --git a/.changeset/late-pants-itch.md b/.changeset/late-pants-itch.md new file mode 100644 index 0000000000..7bd3087316 --- /dev/null +++ b/.changeset/late-pants-itch.md @@ -0,0 +1,5 @@ +--- +'@backstage/core-components': patch +--- + +Show scroll bar of the sidebar wrapper only on hover diff --git a/packages/core-components/src/layout/Sidebar/Items.tsx b/packages/core-components/src/layout/Sidebar/Items.tsx index e53cdfaa57..90dae01cd4 100644 --- a/packages/core-components/src/layout/Sidebar/Items.tsx +++ b/packages/core-components/src/layout/Sidebar/Items.tsx @@ -299,12 +299,17 @@ export const SidebarScrollWrapper = styled('div')(({ theme }) => ({ // Display at least one item in the container // Question: Can this be a config/theme variable - if so, which? :/ minHeight: '48px', - '&::-webkit-scrollbar': { + overflowY: 'hidden', + + '&:hover': { + overflowY: 'auto', + }, + '&:hover::-webkit-scrollbar': { backgroundColor: theme.palette.background.default, width: '5px', borderRadius: '5px', }, - '&::-webkit-scrollbar-thumb': { + '&:hover::-webkit-scrollbar-thumb': { backgroundColor: theme.palette.text.hint, borderRadius: '5px', }, From f1cffe88075c04357712066ef408a3e869bbbb5f Mon Sep 17 00:00:00 2001 From: Philipp Hugenroth Date: Tue, 6 Jul 2021 14:41:08 +0200 Subject: [PATCH 153/204] Don't hide scrollbar on touch devices Signed-off-by: Philipp Hugenroth --- .../src/layout/Sidebar/Items.tsx | 39 +++++++++++-------- 1 file changed, 23 insertions(+), 16 deletions(-) diff --git a/packages/core-components/src/layout/Sidebar/Items.tsx b/packages/core-components/src/layout/Sidebar/Items.tsx index 90dae01cd4..28abbce53c 100644 --- a/packages/core-components/src/layout/Sidebar/Items.tsx +++ b/packages/core-components/src/layout/Sidebar/Items.tsx @@ -21,8 +21,10 @@ import { makeStyles, styled, TextField, + Theme, Typography, } from '@material-ui/core'; +import { CreateCSSProperties } from '@material-ui/core/styles/withStyles'; import SearchIcon from '@material-ui/icons/Search'; import clsx from 'clsx'; import React, { @@ -291,26 +293,31 @@ export const SidebarDivider = styled('hr')({ margin: '12px 0px', }); -export const SidebarScrollWrapper = styled('div')(({ theme }) => ({ - flex: '0 1 auto', - overflowX: 'hidden', - // 5px space to the right of the scrollbar - width: 'calc(100% - 5px)', - // Display at least one item in the container - // Question: Can this be a config/theme variable - if so, which? :/ - minHeight: '48px', - overflowY: 'hidden', - - '&:hover': { - overflowY: 'auto', - }, - '&:hover::-webkit-scrollbar': { +const styledScrollbar = (theme: Theme): CreateCSSProperties => ({ + overflowY: 'auto', + '&::-webkit-scrollbar': { backgroundColor: theme.palette.background.default, width: '5px', borderRadius: '5px', }, - '&:hover::-webkit-scrollbar-thumb': { + '&::-webkit-scrollbar-thumb': { backgroundColor: theme.palette.text.hint, borderRadius: '5px', }, -})); +}); + +export const SidebarScrollWrapper = styled('div')(({ theme }) => { + const scrollbarStyles = styledScrollbar(theme); + return { + flex: '0 1 auto', + overflowX: 'hidden', + // 5px space to the right of the scrollbar + width: 'calc(100% - 5px)', + // Display at least one item in the container + // Question: Can this be a config/theme variable - if so, which? :/ + minHeight: '48px', + overflowY: 'hidden', + '@media (hover: none)': scrollbarStyles, + '&:hover': scrollbarStyles, + }; +}); From 10113f47b221ff44c36364700effb60fddecd5bc Mon Sep 17 00:00:00 2001 From: David Tuite Date: Tue, 6 Jul 2021 14:05:49 +0100 Subject: [PATCH 154/204] Use Link from core-components Signed-off-by: David Tuite --- .../components/EmptyState/MissingAnnotationEmptyState.tsx | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/packages/core-components/src/components/EmptyState/MissingAnnotationEmptyState.tsx b/packages/core-components/src/components/EmptyState/MissingAnnotationEmptyState.tsx index 2b2f2b7738..d477494964 100644 --- a/packages/core-components/src/components/EmptyState/MissingAnnotationEmptyState.tsx +++ b/packages/core-components/src/components/EmptyState/MissingAnnotationEmptyState.tsx @@ -17,6 +17,7 @@ import React from 'react'; import { Button, makeStyles, Typography } from '@material-ui/core'; import { BackstageTheme } from '@backstage/theme'; +import { Link } from '../Link'; import { EmptyState } from './EmptyState'; import { CodeSnippet } from '../CodeSnippet'; @@ -73,11 +74,9 @@ export const MissingAnnotationEmptyState = ({ annotation }: Props) => { /> From 2a13aa1b753f39d62954a7bed9f1d855cf39771c Mon Sep 17 00:00:00 2001 From: irma12 Date: Tue, 6 Jul 2021 15:06:43 +0200 Subject: [PATCH 155/204] Handle empty strings in code blocks Signed-off-by: irma12 --- .changeset/shaggy-ties-carry.md | 5 +++++ .../src/components/MarkdownContent/MarkdownContent.tsx | 4 ++-- 2 files changed, 7 insertions(+), 2 deletions(-) create mode 100644 .changeset/shaggy-ties-carry.md diff --git a/.changeset/shaggy-ties-carry.md b/.changeset/shaggy-ties-carry.md new file mode 100644 index 0000000000..83b7782cd0 --- /dev/null +++ b/.changeset/shaggy-ties-carry.md @@ -0,0 +1,5 @@ +--- +'@backstage/core-components': patch +--- + +Handle empty code blocks in markdown files so they don't fail rendering diff --git a/packages/core-components/src/components/MarkdownContent/MarkdownContent.tsx b/packages/core-components/src/components/MarkdownContent/MarkdownContent.tsx index 2167da6fd2..296df22ecd 100644 --- a/packages/core-components/src/components/MarkdownContent/MarkdownContent.tsx +++ b/packages/core-components/src/components/MarkdownContent/MarkdownContent.tsx @@ -65,8 +65,8 @@ type Props = { }; const renderers = { - code: ({ language, value }: { language: string; value: string }) => { - return ; + code: ({ language, value }: { language: string; value?: string }) => { + return ; }, }; From 4176a60e50ac172874ccc3fdd931447d0ffba13e Mon Sep 17 00:00:00 2001 From: Oliver Sand Date: Tue, 6 Jul 2021 14:58:37 +0200 Subject: [PATCH 156/204] Make sure that the search scheduler doesn't run to many tasks in parallel Signed-off-by: Oliver Sand --- .changeset/tasty-ghosts-raise.md | 8 +++ plugins/search-backend-node/src/Scheduler.ts | 17 +++--- .../src/runPeriodically.ts | 54 +++++++++++++++++++ 3 files changed, 69 insertions(+), 10 deletions(-) create mode 100644 .changeset/tasty-ghosts-raise.md create mode 100644 plugins/search-backend-node/src/runPeriodically.ts diff --git a/.changeset/tasty-ghosts-raise.md b/.changeset/tasty-ghosts-raise.md new file mode 100644 index 0000000000..4e9de7043a --- /dev/null +++ b/.changeset/tasty-ghosts-raise.md @@ -0,0 +1,8 @@ +--- +'@backstage/plugin-search-backend-node': patch +--- + +Change search scheduler from starting indexing in a fixed interval (for example +every 60 seconds), to wait a fixed time between index runs. +This makes sure that no second index process for the same document type is +started when the previous one is still running. diff --git a/plugins/search-backend-node/src/Scheduler.ts b/plugins/search-backend-node/src/Scheduler.ts index 6c0b748b03..56cefc52df 100644 --- a/plugins/search-backend-node/src/Scheduler.ts +++ b/plugins/search-backend-node/src/Scheduler.ts @@ -15,6 +15,7 @@ */ import { Logger } from 'winston'; +import { runPeriodically } from './runPeriodically'; type TaskEnvelope = { task: Function; @@ -28,7 +29,7 @@ type TaskEnvelope = { export class Scheduler { private logger: Logger; private schedule: TaskEnvelope[]; - private intervalTimeouts: NodeJS.Timeout[] = []; + private runningTasks: Function[] = []; constructor({ logger }: { logger: Logger }) { this.logger = logger; @@ -40,7 +41,7 @@ export class Scheduler { * */ addToSchedule(task: Function, interval: number) { - if (this.intervalTimeouts.length) { + if (this.runningTasks.length) { throw new Error( 'Cannot add task to schedule that has already been started.', ); @@ -56,11 +57,7 @@ export class Scheduler { this.schedule.forEach(({ task, interval }) => { // Fire the task immediately, then schedule it. task(); - this.intervalTimeouts.push( - setInterval(() => { - task(); - }, interval), - ); + this.runningTasks.push(runPeriodically(() => task(), interval)); }); } @@ -69,9 +66,9 @@ export class Scheduler { */ stop() { this.logger.info('Stopping all scheduled search tasks.'); - this.intervalTimeouts.forEach(timeout => { - clearInterval(timeout); + this.runningTasks.forEach(cancel => { + cancel(); }); - this.intervalTimeouts = []; + this.runningTasks = []; } } diff --git a/plugins/search-backend-node/src/runPeriodically.ts b/plugins/search-backend-node/src/runPeriodically.ts new file mode 100644 index 0000000000..d5f5f87d7f --- /dev/null +++ b/plugins/search-backend-node/src/runPeriodically.ts @@ -0,0 +1,54 @@ +/* + * Copyright 2020 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Runs a function repeatedly, with a fixed wait between invocations. + * + * Supports async functions, and silently ignores exceptions and rejections. + * + * @param fn The function to run. May return a Promise. + * @param delayMs The delay between a completed function invocation and the + * next. + * @returns A function that, when called, stops the invocation loop. + */ +export function runPeriodically(fn: () => any, delayMs: number): () => void { + let cancel: () => void; + let cancelled = false; + const cancellationPromise = new Promise(resolve => { + cancel = () => { + resolve(); + cancelled = true; + }; + }); + + const startRefresh = async () => { + while (!cancelled) { + try { + await fn(); + } catch { + // ignore intentionally + } + + await Promise.race([ + new Promise(resolve => setTimeout(resolve, delayMs)), + cancellationPromise, + ]); + } + }; + startRefresh(); + + return cancel!; +} From 03715ceaa4c92d51561196f5352fcf146e05b31d Mon Sep 17 00:00:00 2001 From: Oliver Sand Date: Tue, 6 Jul 2021 16:37:01 +0200 Subject: [PATCH 157/204] Add comment and remove initial run Signed-off-by: Oliver Sand --- plugins/search-backend-node/src/Scheduler.ts | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/plugins/search-backend-node/src/Scheduler.ts b/plugins/search-backend-node/src/Scheduler.ts index 56cefc52df..3e356aa6aa 100644 --- a/plugins/search-backend-node/src/Scheduler.ts +++ b/plugins/search-backend-node/src/Scheduler.ts @@ -37,8 +37,9 @@ export class Scheduler { } /** - * Adds each task and interval to the schedule - * + * Adds each task and interval to the schedule. + * When running the tasks, the scheduler waits at least for the time specified + * in the interval once the task was completed, before running it again. */ addToSchedule(task: Function, interval: number) { if (this.runningTasks.length) { @@ -55,8 +56,6 @@ export class Scheduler { start() { this.logger.info('Starting all scheduled search tasks.'); this.schedule.forEach(({ task, interval }) => { - // Fire the task immediately, then schedule it. - task(); this.runningTasks.push(runPeriodically(() => task(), interval)); }); } From b578be10f89470e8e19baceb268524034154f0fe Mon Sep 17 00:00:00 2001 From: Philipp Hugenroth Date: Tue, 6 Jul 2021 17:16:52 +0200 Subject: [PATCH 158/204] Seperate Grid container & item in wrapped components to avoid wrong spacing Signed-off-by: Philipp Hugenroth --- .../components/CatalogPage/CatalogPage.tsx | 26 ++++++++++--------- 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/plugins/catalog/src/components/CatalogPage/CatalogPage.tsx b/plugins/catalog/src/components/CatalogPage/CatalogPage.tsx index 85855237fb..089e61f0fb 100644 --- a/plugins/catalog/src/components/CatalogPage/CatalogPage.tsx +++ b/plugins/catalog/src/components/CatalogPage/CatalogPage.tsx @@ -58,18 +58,20 @@ export const CatalogPage = ({ - - - - - - - - - - + + + + + + + + + + + + From 0466606d845511f14c5b236431a7481dee621367 Mon Sep 17 00:00:00 2001 From: Oliver Sand Date: Tue, 6 Jul 2021 18:57:32 +0200 Subject: [PATCH 159/204] Add test for runPeriodically Signed-off-by: Oliver Sand --- .../src/runPeriodically.test.ts | 80 +++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 plugins/search-backend-node/src/runPeriodically.test.ts diff --git a/plugins/search-backend-node/src/runPeriodically.test.ts b/plugins/search-backend-node/src/runPeriodically.test.ts new file mode 100644 index 0000000000..4d8e991b9e --- /dev/null +++ b/plugins/search-backend-node/src/runPeriodically.test.ts @@ -0,0 +1,80 @@ +/* + * Copyright 2020 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { runPeriodically } from './runPeriodically'; + +jest.useFakeTimers(); + +describe('runPeriodically', () => { + const flushPromises = () => new Promise(setImmediate); + const advanceTimersByTime = async (time: number) => { + jest.advanceTimersByTime(time); + // Advancing the time with jest doesn't run all promises, but only sync code + await flushPromises(); + }; + + it('runs task initially', async () => { + const task = jest.fn(async () => {}); + const cancel = runPeriodically(task, 1000); + expect(task).toHaveBeenCalledTimes(1); + cancel(); + }); + + it('runs at requested interval', async () => { + const task = jest.fn(async () => {}); + const cancel = runPeriodically(task, 1000); + await flushPromises(); + await advanceTimersByTime(1000); + await advanceTimersByTime(1000); + expect(task).toHaveBeenCalledTimes(3); + cancel(); + }); + + it('stops after being canceled', async () => { + const task = jest.fn(async () => {}); + const cancel = runPeriodically(task, 1000); + await flushPromises(); + cancel(); + await advanceTimersByTime(1000); + await advanceTimersByTime(1000); + expect(task).toHaveBeenCalledTimes(1); + }); + + it('continues running after failures', async () => { + const task = jest.fn(async () => { + throw new Error(); + }); + const cancel = runPeriodically(task, 1000); + await flushPromises(); + await advanceTimersByTime(1000); + await advanceTimersByTime(1000); + expect(task).toHaveBeenCalledTimes(3); + cancel(); + }); + + it('waits till a long running task is completed', async () => { + const task = jest.fn( + () => new Promise(resolve => setTimeout(resolve, 10000)), + ); + const cancel = runPeriodically(task, 1000); + await flushPromises(); + await advanceTimersByTime(1000); + expect(task).toHaveBeenCalledTimes(1); + await advanceTimersByTime(9000); + await advanceTimersByTime(1000); + expect(task).toHaveBeenCalledTimes(2); + cancel(); + }); +}); From 11e66e8040004a4c79004a36854b025744b52e28 Mon Sep 17 00:00:00 2001 From: Alex Landovskis Date: Tue, 6 Jul 2021 19:55:57 -0400 Subject: [PATCH 160/204] build: bump azure-devops-node-api to 10.2.2 Signed-off-by: Alex Landovskis --- .changeset/sweet-terms-approve.md | 6 +++++ packages/backend/package.json | 2 +- plugins/scaffolder-backend/package.json | 2 +- yarn.lock | 29 ++++++++++++------------- 4 files changed, 22 insertions(+), 17 deletions(-) create mode 100644 .changeset/sweet-terms-approve.md diff --git a/.changeset/sweet-terms-approve.md b/.changeset/sweet-terms-approve.md new file mode 100644 index 0000000000..56297f694d --- /dev/null +++ b/.changeset/sweet-terms-approve.md @@ -0,0 +1,6 @@ +--- +'example-backend': patch +'@backstage/plugin-scaffolder-backend': patch +--- + +bump azure-devops-node to 10.2.2 diff --git a/packages/backend/package.json b/packages/backend/package.json index a2c5906696..9a019c6cfe 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -48,7 +48,7 @@ "@backstage/plugin-todo-backend": "^0.1.6", "@gitbeaker/node": "^30.2.0", "@octokit/rest": "^18.5.3", - "azure-devops-node-api": "^10.1.1", + "azure-devops-node-api": "^10.2.2", "dockerode": "^3.2.1", "example-app": "^0.2.32", "express": "^4.17.1", diff --git a/plugins/scaffolder-backend/package.json b/plugins/scaffolder-backend/package.json index ab7ab1f552..0a0ccd36b1 100644 --- a/plugins/scaffolder-backend/package.json +++ b/plugins/scaffolder-backend/package.json @@ -40,7 +40,7 @@ "@octokit/rest": "^18.5.3", "@types/express": "^4.17.6", "@types/git-url-parse": "^9.0.0", - "azure-devops-node-api": "^10.1.1", + "azure-devops-node-api": "^10.2.2", "command-exists": "^1.2.9", "compression": "^1.7.4", "cors": "^2.8.5", diff --git a/yarn.lock b/yarn.lock index 27a6fcc250..ae7fa6c4f0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8036,14 +8036,13 @@ axobject-query@^2.2.0: resolved "https://registry.npmjs.org/axobject-query/-/axobject-query-2.2.0.tgz#943d47e10c0b704aa42275e20edf3722648989be" integrity sha512-Td525n+iPOOyUQIeBfcASuG6uJsDOITl7Mds5gFyerkWiX7qhUTdYUBlSgNMyVqtSJqwpt1kXGLdUt6SykLMRA== -azure-devops-node-api@^10.1.1: - version "10.2.1" - resolved "https://registry.npmjs.org/azure-devops-node-api/-/azure-devops-node-api-10.2.1.tgz#835080164f8c30cec6506c47198b044c053f1f36" - integrity sha512-XuSiUaYpk0tQpd9fD8qfRa5y1IdavupKNVmwxy0w/RhmxG2Wl8uAYnNJchUoWd3Rn9On0mYTCCZSn+UlYdYFSg== +azure-devops-node-api@^10.2.2: + version "10.2.2" + resolved "https://registry.npmjs.org/azure-devops-node-api/-/azure-devops-node-api-10.2.2.tgz#9f557e622dd07bbaa9bd5e7e84e17c761e2151b2" + integrity sha512-4TVv2X7oNStT0vLaEfExmy3J4/CzfuXolEcQl/BRUmvGySqKStTG2O55/hUQ0kM7UJlZBLgniM0SBq4d/WkKow== dependencies: tunnel "0.0.6" - typed-rest-client "^1.8.0" - underscore "1.8.3" + typed-rest-client "^1.8.4" babel-code-frame@^6.22.0: version "6.26.0" @@ -25697,14 +25696,14 @@ type@^2.0.0: resolved "https://registry.npmjs.org/type/-/type-2.0.0.tgz#5f16ff6ef2eb44f260494dae271033b29c09a9c3" integrity sha512-KBt58xCHry4Cejnc2ISQAF7QY+ORngsWfxezO68+12hKV6lQY8P/psIkcbjeHWn7MqcgciWJyCCevFMJdIXpow== -typed-rest-client@^1.8.0: - version "1.8.0" - resolved "https://registry.npmjs.org/typed-rest-client/-/typed-rest-client-1.8.0.tgz#3b6c22a7cc31b665ec1e4bedb3482ebe12e2fbe6" - integrity sha512-Nu1MrdH6ECrRW5gHoRAdubgCs4oH6q5/J76jsEC8bVDfvVoVPkigukPalhMHPwb7ZvpsZqPptd5zpt/QdtrdBw== +typed-rest-client@^1.8.4: + version "1.8.4" + resolved "https://registry.npmjs.org/typed-rest-client/-/typed-rest-client-1.8.4.tgz#ba3fb788e5b9322547406392533f12d660a5ced6" + integrity sha512-MyfKKYzk3I6/QQp6e1T50py4qg+c+9BzOEl2rBmQIpStwNUoqQ73An+Tkfy9YuV7O+o2mpVVJpe+fH//POZkbg== dependencies: qs "^6.9.1" tunnel "0.0.6" - underscore "1.8.3" + underscore "^1.12.1" typedarray-to-buffer@^3.1.5: version "3.1.5" @@ -25803,10 +25802,10 @@ undefsafe@^2.0.3: dependencies: debug "^2.2.0" -underscore@1.8.3: - version "1.8.3" - resolved "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz#4f3fb53b106e6097fcf9cb4109f2a5e9bdfa5022" - integrity sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI= +underscore@^1.12.1: + version "1.13.1" + resolved "https://registry.npmjs.org/underscore/-/underscore-1.13.1.tgz#0c1c6bd2df54b6b69f2314066d65b6cde6fcf9d1" + integrity sha512-hzSoAVtJF+3ZtiFX0VgfFPHEDRm7Y/QPjGyNo4TVdnDTdft3tr8hEkD25a1jC+TjTuE7tkHGKkhwCgs9dgBB2g== underscore@^1.9.1: version "1.11.0" From f7134c368419d1b43733f6aa0c4854d2fceef62f Mon Sep 17 00:00:00 2001 From: Alex Landovskis Date: Tue, 6 Jul 2021 19:48:03 -0400 Subject: [PATCH 161/204] chore: bump sqlite3 to 5.0.1 Signed-off-by: Alex Landovskis --- .changeset/healthy-colts-watch.md | 8 ++++++++ packages/backend-test-utils/package.json | 2 +- packages/backend/package.json | 2 +- .../packages/backend/package.json.hbs | 2 +- plugins/catalog-backend/package.json | 2 +- yarn.lock | 18 +++++++++--------- 6 files changed, 21 insertions(+), 13 deletions(-) create mode 100644 .changeset/healthy-colts-watch.md diff --git a/.changeset/healthy-colts-watch.md b/.changeset/healthy-colts-watch.md new file mode 100644 index 0000000000..763f2a9828 --- /dev/null +++ b/.changeset/healthy-colts-watch.md @@ -0,0 +1,8 @@ +--- +'example-backend': patch +'@backstage/backend-test-utils': patch +'@backstage/create-app': patch +'@backstage/plugin-catalog-backend': patch +--- + +bump sqlite3 to 5.0.1 diff --git a/packages/backend-test-utils/package.json b/packages/backend-test-utils/package.json index 3079041c7f..65852c3a4f 100644 --- a/packages/backend-test-utils/package.json +++ b/packages/backend-test-utils/package.json @@ -36,7 +36,7 @@ "knex": "^0.95.1", "mysql2": "^2.2.5", "pg": "^8.3.0", - "sqlite3": "^5.0.0", + "sqlite3": "^5.0.1", "testcontainers": "^7.10.0", "uuid": "^8.0.0" }, diff --git a/packages/backend/package.json b/packages/backend/package.json index a2c5906696..f524636db1 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -56,7 +56,7 @@ "knex": "^0.95.1", "pg": "^8.3.0", "pg-connection-string": "^2.3.0", - "sqlite3": "^5.0.0", + "sqlite3": "^5.0.1", "winston": "^3.2.1" }, "devDependencies": { diff --git a/packages/create-app/templates/default-app/packages/backend/package.json.hbs b/packages/create-app/templates/default-app/packages/backend/package.json.hbs index 8f5a116de4..44af516099 100644 --- a/packages/create-app/templates/default-app/packages/backend/package.json.hbs +++ b/packages/create-app/templates/default-app/packages/backend/package.json.hbs @@ -40,7 +40,7 @@ "pg": "^8.3.0", {{/if}} {{#if dbTypeSqlite}} - "sqlite3": "^5.0.0", + "sqlite3": "^5.0.1", {{/if}} "winston": "^3.2.1" }, diff --git a/plugins/catalog-backend/package.json b/plugins/catalog-backend/package.json index 2a8588c964..13cd430d01 100644 --- a/plugins/catalog-backend/package.json +++ b/plugins/catalog-backend/package.json @@ -71,7 +71,7 @@ "@types/uuid": "^8.0.0", "@types/yup": "^0.29.8", "msw": "^0.29.0", - "sqlite3": "^5.0.0", + "sqlite3": "^5.0.1", "supertest": "^6.1.3", "wait-for-expect": "^3.0.2" }, diff --git a/yarn.lock b/yarn.lock index 27a6fcc250..1789c11047 100644 --- a/yarn.lock +++ b/yarn.lock @@ -19107,10 +19107,10 @@ node-abi@^2.7.0: dependencies: semver "^5.4.1" -node-addon-api@2.0.0: - version "2.0.0" - resolved "https://registry.npmjs.org/node-addon-api/-/node-addon-api-2.0.0.tgz#f9afb8d777a91525244b01775ea0ddbe1125483b" - integrity sha512-ASCL5U13as7HhOExbT6OlWJJUV/lLzL2voOSP1UVehpRD8FbSrSDjfScK/KwAvVTI5AS6r4VwbOMlIqtvRidnA== +node-addon-api@^3.0.0: + version "3.2.1" + resolved "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.2.1.tgz#81325e0a2117789c0128dab65e7e38f07ceba161" + integrity sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A== node-cache@^5.1.2: version "5.1.2" @@ -24066,12 +24066,12 @@ sprintf-js@~1.0.2: resolved "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= -sqlite3@^5.0.0: - version "5.0.0" - resolved "https://registry.npmjs.org/sqlite3/-/sqlite3-5.0.0.tgz#1bfef2151c6bc48a3ab1a6c126088bb8dd233566" - integrity sha512-rjvqHFUaSGnzxDy2AHCwhHy6Zp6MNJzCPGYju4kD8yi6bze4d1/zMTg6C7JI49b7/EM7jKMTvyfN/4ylBKdwfw== +sqlite3@^5.0.1: + version "5.0.2" + resolved "https://registry.npmjs.org/sqlite3/-/sqlite3-5.0.2.tgz#00924adcc001c17686e0a6643b6cbbc2d3965083" + integrity sha512-1SdTNo+BVU211Xj1csWa8lV6KM0CtucDwRyA0VHl91wEH1Mgh7RxUpI4rVvG7OhHrzCSGaVyW5g8vKvlrk9DJA== dependencies: - node-addon-api "2.0.0" + node-addon-api "^3.0.0" node-pre-gyp "^0.11.0" optionalDependencies: node-gyp "3.x" From 921e3ca569c7a81a20ab2b5e9c271ef822a1efae Mon Sep 17 00:00:00 2001 From: Chase Rutherford-Jenkins Date: Tue, 29 Jun 2021 22:10:56 -0700 Subject: [PATCH 162/204] use configured git author in scaffolder actions Co-authored-by: Himanshu Mishra Signed-off-by: Chase Rutherford-Jenkins --- app-config.yaml | 5 +++ plugins/scaffolder-backend/api-report.md | 5 +++ plugins/scaffolder-backend/config.d.ts | 9 ++++ .../actions/builtin/createBuiltinActions.ts | 8 +++- .../actions/builtin/publish/azure.test.ts | 23 +++++----- .../actions/builtin/publish/azure.ts | 10 ++++- .../actions/builtin/publish/bitbucket.test.ts | 43 ++++++++++--------- .../actions/builtin/publish/bitbucket.ts | 10 ++++- .../actions/builtin/publish/github.test.ts | 24 ++++++----- .../actions/builtin/publish/github.ts | 10 ++++- .../actions/builtin/publish/gitlab.test.ts | 37 ++++++++-------- .../actions/builtin/publish/gitlab.ts | 10 ++++- .../src/scaffolder/stages/publish/helpers.ts | 12 +++++- .../scaffolder-backend/src/service/router.ts | 1 + 14 files changed, 139 insertions(+), 68 deletions(-) diff --git a/app-config.yaml b/app-config.yaml index e3ab12587e..c0bea41b34 100644 --- a/app-config.yaml +++ b/app-config.yaml @@ -250,6 +250,11 @@ catalog: target: ../catalog-model/examples/acme-corp.yaml scaffolder: + # Use to customize commit author info used when new components are created + # git: + # author: + # name: Scaffolder + # email: scaffolder@backstage.io github: token: ${GITHUB_TOKEN} visibility: public # or 'internal' or 'private' diff --git a/plugins/scaffolder-backend/api-report.md b/plugins/scaffolder-backend/api-report.md index 7528388a47..21c6e03b0f 100644 --- a/plugins/scaffolder-backend/api-report.md +++ b/plugins/scaffolder-backend/api-report.md @@ -116,6 +116,7 @@ export const createBuiltinActions: (options: { integrations: ScmIntegrations; catalogClient: CatalogApi; templaters: TemplaterBuilder; + config: Config; }) => TemplateAction[]; // @public (undocumented) @@ -155,11 +156,13 @@ export function createLegacyActions(options: Options): TemplateAction[]; // @public (undocumented) export function createPublishAzureAction(options: { integrations: ScmIntegrationRegistry; + config: Config; }): TemplateAction; // @public (undocumented) export function createPublishBitbucketAction(options: { integrations: ScmIntegrationRegistry; + config: Config; }): TemplateAction; // @public @@ -168,6 +171,7 @@ export function createPublishFileAction(): TemplateAction; // @public (undocumented) export function createPublishGithubAction(options: { integrations: ScmIntegrationRegistry; + config: Config; }): TemplateAction; // @public (undocumented) @@ -176,6 +180,7 @@ export const createPublishGithubPullRequestAction: ({ integrations, clientFactor // @public (undocumented) export function createPublishGitlabAction(options: { integrations: ScmIntegrationRegistry; + config: Config; }): TemplateAction; // @public (undocumented) diff --git a/plugins/scaffolder-backend/config.d.ts b/plugins/scaffolder-backend/config.d.ts index 971c3036d6..07602b649a 100644 --- a/plugins/scaffolder-backend/config.d.ts +++ b/plugins/scaffolder-backend/config.d.ts @@ -17,6 +17,15 @@ export interface Config { /** Configuration options for the scaffolder plugin */ scaffolder?: { + git?: { + /** + * The commit author info used when new components are created. + */ + author?: { + name?: string; + email?: string; + }; + }; github?: { [key: string]: string; /** diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/createBuiltinActions.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/createBuiltinActions.ts index 46b8db72b4..b3757571ff 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/createBuiltinActions.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/createBuiltinActions.ts @@ -17,6 +17,7 @@ import { UrlReader } from '@backstage/backend-common'; import { CatalogApi } from '@backstage/catalog-client'; import { ScmIntegrations } from '@backstage/integration'; +import { Config } from '@backstage/config'; import { TemplaterBuilder } from '../../stages'; import { createCatalogRegisterAction, @@ -41,8 +42,9 @@ export const createBuiltinActions = (options: { integrations: ScmIntegrations; catalogClient: CatalogApi; templaters: TemplaterBuilder; + config: Config; }) => { - const { reader, integrations, templaters, catalogClient } = options; + const { reader, integrations, templaters, catalogClient, config } = options; return [ createFetchPlainAction({ @@ -56,18 +58,22 @@ export const createBuiltinActions = (options: { }), createPublishGithubAction({ integrations, + config, }), createPublishGithubPullRequestAction({ integrations, }), createPublishGitlabAction({ integrations, + config, }), createPublishBitbucketAction({ integrations, + config, }), createPublishAzureAction({ integrations, + config, }), createDebugLogAction(), createCatalogRegisterAction({ catalogClient, integrations }), diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/azure.test.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/azure.test.ts index d3cb4ccafc..6a1c8fdc55 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/azure.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/azure.test.ts @@ -28,17 +28,17 @@ import { PassThrough } from 'stream'; import { initRepoAndPush } from '../../../stages/publish/helpers'; describe('publish:azure', () => { - const integrations = ScmIntegrations.fromConfig( - new ConfigReader({ - integrations: { - azure: [ - { host: 'dev.azure.com', token: 'tokenlols' }, - { host: 'myazurehostnotoken.com' }, - ], - }, - }), - ); - const action = createPublishAzureAction({ integrations }); + const config = new ConfigReader({ + integrations: { + azure: [ + { host: 'dev.azure.com', token: 'tokenlols' }, + { host: 'myazurehostnotoken.com' }, + ], + }, + }); + + const integrations = ScmIntegrations.fromConfig(config); + const action = createPublishAzureAction({ integrations, config }); const mockContext = { input: { repoUrl: 'dev.azure.com?repo=repo&owner=owner&organization=org', @@ -187,6 +187,7 @@ describe('publish:azure', () => { defaultBranch: 'master', auth: { username: 'notempty', password: 'tokenlols' }, logger: mockContext.logger, + gitAuthorInfo: {}, }); }); diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/azure.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/azure.ts index eb1b0522c6..677abc3a08 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/azure.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/azure.ts @@ -21,11 +21,13 @@ import { GitRepositoryCreateOptions } from 'azure-devops-node-api/interfaces/Git import { getPersonalAccessTokenHandler, WebApi } from 'azure-devops-node-api'; import { getRepoSourceDirectory, parseRepoUrl } from './util'; import { createTemplateAction } from '../../createTemplateAction'; +import { Config } from '@backstage/config'; export function createPublishAzureAction(options: { integrations: ScmIntegrationRegistry; + config: Config; }) { - const { integrations } = options; + const { integrations, config } = options; return createTemplateAction<{ repoUrl: string; @@ -123,6 +125,11 @@ export function createPublishAzureAction(options: { // so it's just the base path I think const repoContentsUrl = remoteUrl; + const gitAuthorInfo = { + name: config.getOptionalString('scaffolder.git.author.name'), + email: config.getOptionalString('scaffolder.git.author.email'), + }; + await initRepoAndPush({ dir: getRepoSourceDirectory(ctx.workspacePath, ctx.input.sourcePath), remoteUrl, @@ -132,6 +139,7 @@ export function createPublishAzureAction(options: { password: integrationConfig.config.token, }, logger: ctx.logger, + gitAuthorInfo, }); ctx.output('remoteUrl', remoteUrl); diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/bitbucket.test.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/bitbucket.test.ts index 16b84737a7..f173959aa0 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/bitbucket.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/bitbucket.test.ts @@ -26,27 +26,27 @@ import { PassThrough } from 'stream'; import { initRepoAndPush } from '../../../stages/publish/helpers'; describe('publish:bitbucket', () => { - const integrations = ScmIntegrations.fromConfig( - new ConfigReader({ - integrations: { - bitbucket: [ - { - host: 'bitbucket.org', - token: 'tokenlols', - }, - { - host: 'hosted.bitbucket.com', - token: 'thing', - apiBaseUrl: 'https://hosted.bitbucket.com/rest/api/1.0', - }, - { - host: 'notoken.bitbucket.com', - }, - ], - }, - }), - ); - const action = createPublishBitbucketAction({ integrations }); + const config = new ConfigReader({ + integrations: { + bitbucket: [ + { + host: 'bitbucket.org', + token: 'tokenlols', + }, + { + host: 'hosted.bitbucket.com', + token: 'thing', + apiBaseUrl: 'https://hosted.bitbucket.com/rest/api/1.0', + }, + { + host: 'notoken.bitbucket.com', + }, + ], + }, + }); + + const integrations = ScmIntegrations.fromConfig(config); + const action = createPublishBitbucketAction({ integrations, config }); const mockContext = { input: { repoUrl: 'bitbucket.org?repo=repo&owner=owner', @@ -331,6 +331,7 @@ describe('publish:bitbucket', () => { defaultBranch: 'main', auth: { username: 'x-token-auth', password: 'tokenlols' }, logger: mockContext.logger, + gitAuthorInfo: {}, }); }); diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/bitbucket.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/bitbucket.ts index 295f4d1574..b05b51a7eb 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/bitbucket.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/bitbucket.ts @@ -23,6 +23,7 @@ import fetch from 'cross-fetch'; import { initRepoAndPush } from '../../../stages/publish/helpers'; import { createTemplateAction } from '../../createTemplateAction'; import { getRepoSourceDirectory, parseRepoUrl } from './util'; +import { Config } from '@backstage/config'; const createBitbucketCloudRepository = async (opts: { owner: string; @@ -184,8 +185,9 @@ const performEnableLFS = async (opts: { export function createPublishBitbucketAction(options: { integrations: ScmIntegrationRegistry; + config: Config; }) { - const { integrations } = options; + const { integrations, config } = options; return createTemplateAction<{ repoUrl: string; @@ -284,6 +286,11 @@ export function createPublishBitbucketAction(options: { apiBaseUrl, }); + const gitAuthorInfo = { + name: config.getOptionalString('scaffolder.git.author.name'), + email: config.getOptionalString('scaffolder.git.author.email'), + }; + await initRepoAndPush({ dir: getRepoSourceDirectory(ctx.workspacePath, ctx.input.sourcePath), remoteUrl, @@ -297,6 +304,7 @@ export function createPublishBitbucketAction(options: { }, defaultBranch, logger: ctx.logger, + gitAuthorInfo, }); if (enableLFS && host !== 'bitbucket.org') { diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/github.test.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/github.test.ts index 910fa27b46..058168d666 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/github.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/github.test.ts @@ -25,17 +25,17 @@ import { initRepoAndPush } from '../../../stages/publish/helpers'; import { when } from 'jest-when'; describe('publish:github', () => { - const integrations = ScmIntegrations.fromConfig( - new ConfigReader({ - integrations: { - github: [ - { host: 'github.com', token: 'tokenlols' }, - { host: 'ghe.github.com' }, - ], - }, - }), - ); - const action = createPublishGithubAction({ integrations }); + const config = new ConfigReader({ + integrations: { + github: [ + { host: 'github.com', token: 'tokenlols' }, + { host: 'ghe.github.com' }, + ], + }, + }); + + const integrations = ScmIntegrations.fromConfig(config); + const action = createPublishGithubAction({ integrations, config }); const mockContext = { input: { repoUrl: 'github.com?repo=repo&owner=owner', @@ -178,6 +178,7 @@ describe('publish:github', () => { defaultBranch: 'master', auth: { username: 'x-access-token', password: 'tokenlols' }, logger: mockContext.logger, + gitAuthorInfo: {}, }); }); @@ -207,6 +208,7 @@ describe('publish:github', () => { defaultBranch: 'main', auth: { username: 'x-access-token', password: 'tokenlols' }, logger: mockContext.logger, + gitAuthorInfo: {}, }); }); diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/github.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/github.ts index 7dd790cb62..f14dd817b0 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/github.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/github.ts @@ -25,14 +25,16 @@ import { } from '../../../stages/publish/helpers'; import { getRepoSourceDirectory, parseRepoUrl } from './util'; import { createTemplateAction } from '../../createTemplateAction'; +import { Config } from '@backstage/config'; type Permission = 'pull' | 'push' | 'admin' | 'maintain' | 'triage'; type Collaborator = { access: Permission; username: string }; export function createPublishGithubAction(options: { integrations: ScmIntegrationRegistry; + config: Config; }) { - const { integrations } = options; + const { integrations, config } = options; const credentialsProviders = new Map( integrations.github.list().map(integration => { @@ -248,6 +250,11 @@ export function createPublishGithubAction(options: { const remoteUrl = newRepo.clone_url; const repoContentsUrl = `${newRepo.html_url}/blob/${defaultBranch}`; + const gitAuthorInfo = { + name: config.getOptionalString('scaffolder.git.author.name'), + email: config.getOptionalString('scaffolder.git.author.email'), + }; + await initRepoAndPush({ dir: getRepoSourceDirectory(ctx.workspacePath, ctx.input.sourcePath), remoteUrl, @@ -257,6 +264,7 @@ export function createPublishGithubAction(options: { password: token, }, logger: ctx.logger, + gitAuthorInfo, }); try { diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.test.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.test.ts index 67064efde7..427056454c 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.test.ts @@ -24,24 +24,24 @@ import { PassThrough } from 'stream'; import { initRepoAndPush } from '../../../stages/publish/helpers'; describe('publish:gitlab', () => { - const integrations = ScmIntegrations.fromConfig( - new ConfigReader({ - integrations: { - gitlab: [ - { - host: 'gitlab.com', - token: 'tokenlols', - apiBaseUrl: 'https://api.gitlab.com', - }, - { - host: 'hosted.gitlab.com', - apiBaseUrl: 'https://api.hosted.gitlab.com', - }, - ], - }, - }), - ); - const action = createPublishGitlabAction({ integrations }); + const config = new ConfigReader({ + integrations: { + gitlab: [ + { + host: 'gitlab.com', + token: 'tokenlols', + apiBaseUrl: 'https://api.gitlab.com', + }, + { + host: 'hosted.gitlab.com', + apiBaseUrl: 'https://api.hosted.gitlab.com', + }, + ], + }, + }); + + const integrations = ScmIntegrations.fromConfig(config); + const action = createPublishGitlabAction({ integrations, config }); const mockContext = { input: { repoUrl: 'gitlab.com?repo=repo&owner=owner', @@ -166,6 +166,7 @@ describe('publish:gitlab', () => { remoteUrl: 'http://mockurl.git', auth: { username: 'oauth2', password: 'tokenlols' }, logger: mockContext.logger, + gitAuthorInfo: {}, }); }); diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.ts index 57c7fdf752..6d7384294d 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.ts @@ -20,11 +20,13 @@ import { Gitlab } from '@gitbeaker/node'; import { initRepoAndPush } from '../../../stages/publish/helpers'; import { getRepoSourceDirectory, parseRepoUrl } from './util'; import { createTemplateAction } from '../../createTemplateAction'; +import { Config } from '@backstage/config'; export function createPublishGitlabAction(options: { integrations: ScmIntegrationRegistry; + config: Config; }) { - const { integrations } = options; + const { integrations, config } = options; return createTemplateAction<{ repoUrl: string; @@ -121,6 +123,11 @@ export function createPublishGitlabAction(options: { const remoteUrl = (http_url_to_repo as string).replace(/\.git$/, ''); const repoContentsUrl = `${remoteUrl}/-/blob/master`; + const gitAuthorInfo = { + name: config.getOptionalString('scaffolder.git.author.name'), + email: config.getOptionalString('scaffolder.git.author.email'), + }; + await initRepoAndPush({ dir: getRepoSourceDirectory(ctx.workspacePath, ctx.input.sourcePath), remoteUrl: http_url_to_repo as string, @@ -130,6 +137,7 @@ export function createPublishGitlabAction(options: { password: integrationConfig.config.token, }, logger: ctx.logger, + gitAuthorInfo, }); ctx.output('remoteUrl', remoteUrl); diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/publish/helpers.ts b/plugins/scaffolder-backend/src/scaffolder/stages/publish/helpers.ts index dff0feb5f2..c974c466d4 100644 --- a/plugins/scaffolder-backend/src/scaffolder/stages/publish/helpers.ts +++ b/plugins/scaffolder-backend/src/scaffolder/stages/publish/helpers.ts @@ -25,12 +25,14 @@ export async function initRepoAndPush({ auth, logger, defaultBranch = 'master', + gitAuthorInfo, }: { dir: string; remoteUrl: string; auth: { username: string; password: string }; logger: Logger; defaultBranch?: string; + gitAuthorInfo?: { name?: string; email?: string }; }): Promise { const git = Git.fromAuth({ username: auth.username, @@ -53,11 +55,17 @@ export async function initRepoAndPush({ await git.add({ dir, filepath }); } + // use provided info if possible, otherwise use fallbacks + const authorInfo = { + name: gitAuthorInfo?.name ?? 'Scaffolder', + email: gitAuthorInfo?.email ?? 'scaffolder@backstage.io', + }; + await git.commit({ dir, message: 'Initial commit', - author: { name: 'Scaffolder', email: 'scaffolder@backstage.io' }, - committer: { name: 'Scaffolder', email: 'scaffolder@backstage.io' }, + author: authorInfo, + committer: authorInfo, }); await git.addRemote({ diff --git a/plugins/scaffolder-backend/src/service/router.ts b/plugins/scaffolder-backend/src/service/router.ts index b0142d4b02..17304aefb1 100644 --- a/plugins/scaffolder-backend/src/service/router.ts +++ b/plugins/scaffolder-backend/src/service/router.ts @@ -129,6 +129,7 @@ export async function createRouter( catalogClient, templaters, reader, + config, }), ]; From b1aca39abe11bc22f0908fecf2d53dc95a1b58c5 Mon Sep 17 00:00:00 2001 From: Chase Rutherford-Jenkins Date: Fri, 2 Jul 2021 17:11:32 -0500 Subject: [PATCH 163/204] incorporate naming feedback; add tests Signed-off-by: Chase Rutherford-Jenkins --- app-config.yaml | 9 ++- plugins/scaffolder-backend/config.d.ts | 14 ++-- .../actions/builtin/publish/azure.test.ts | 39 +++++++++++ .../actions/builtin/publish/azure.ts | 4 +- .../actions/builtin/publish/bitbucket.test.ts | 69 +++++++++++++++++++ .../actions/builtin/publish/bitbucket.ts | 4 +- .../actions/builtin/publish/github.test.ts | 47 +++++++++++++ .../actions/builtin/publish/github.ts | 4 +- .../actions/builtin/publish/gitlab.test.ts | 47 +++++++++++++ .../actions/builtin/publish/gitlab.ts | 4 +- 10 files changed, 220 insertions(+), 21 deletions(-) diff --git a/app-config.yaml b/app-config.yaml index c0bea41b34..b50de963ed 100644 --- a/app-config.yaml +++ b/app-config.yaml @@ -250,11 +250,10 @@ catalog: target: ../catalog-model/examples/acme-corp.yaml scaffolder: - # Use to customize commit author info used when new components are created - # git: - # author: - # name: Scaffolder - # email: scaffolder@backstage.io + # Use to customize default commit author info used when new components are created + # defaultAuthor: + # name: Scaffolder + # email: scaffolder@backstage.io github: token: ${GITHUB_TOKEN} visibility: public # or 'internal' or 'private' diff --git a/plugins/scaffolder-backend/config.d.ts b/plugins/scaffolder-backend/config.d.ts index 07602b649a..795fe5b112 100644 --- a/plugins/scaffolder-backend/config.d.ts +++ b/plugins/scaffolder-backend/config.d.ts @@ -17,14 +17,12 @@ export interface Config { /** Configuration options for the scaffolder plugin */ scaffolder?: { - git?: { - /** - * The commit author info used when new components are created. - */ - author?: { - name?: string; - email?: string; - }; + /** + * The commit author info used when new components are created. + */ + defaultAuthor?: { + name?: string; + email?: string; }; github?: { [key: string]: string; diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/azure.test.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/azure.test.ts index 6a1c8fdc55..b5c9bdcd89 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/azure.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/azure.test.ts @@ -191,6 +191,45 @@ describe('publish:azure', () => { }); }); + it('should call initRepoAndPush with the configured defaultAuthor', async () => { + const customAuthorConfig = new ConfigReader({ + integrations: { + azure: [ + { host: 'dev.azure.com', token: 'tokenlols' }, + { host: 'myazurehostnotoken.com' }, + ], + }, + scaffolder: { + defaultAuthor: { + name: 'Test', + email: 'example@example.com', + }, + }, + }); + + const customAuthorIntegrations = ScmIntegrations.fromConfig( + customAuthorConfig, + ); + const customAuthorAction = createPublishAzureAction({ + integrations: customAuthorIntegrations, + config: customAuthorConfig, + }); + + mockGitClient.createRepository.mockImplementation(() => ({ + remoteUrl: 'https://dev.azure.com/organization/project/_git/repo', + })); + + await customAuthorAction.handler(mockContext); + + expect(initRepoAndPush).toHaveBeenCalledWith({ + dir: mockContext.workspacePath, + remoteUrl: 'https://dev.azure.com/organization/project/_git/repo', + auth: { username: 'notempty', password: 'tokenlols' }, + logger: mockContext.logger, + gitAuthorInfo: { name: 'Test', email: 'example@example.com' }, + }); + }); + it('should call output with the remoteUrl and the repoContentsUrl', async () => { mockGitClient.createRepository.mockImplementation(() => ({ remoteUrl: 'https://dev.azure.com/organization/project/_git/repo', diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/azure.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/azure.ts index 677abc3a08..8b8f6ce3e5 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/azure.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/azure.ts @@ -126,8 +126,8 @@ export function createPublishAzureAction(options: { const repoContentsUrl = remoteUrl; const gitAuthorInfo = { - name: config.getOptionalString('scaffolder.git.author.name'), - email: config.getOptionalString('scaffolder.git.author.email'), + name: config.getOptionalString('scaffolder.defaultAuthor.name'), + email: config.getOptionalString('scaffolder.defaultAuthor.email'), }; await initRepoAndPush({ diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/bitbucket.test.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/bitbucket.test.ts index f173959aa0..6a72cf1bc3 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/bitbucket.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/bitbucket.test.ts @@ -335,6 +335,75 @@ describe('publish:bitbucket', () => { }); }); + it('should call initAndPush with the configured defaultAuthor', async () => { + const customAuthorConfig = new ConfigReader({ + integrations: { + bitbucket: [ + { + host: 'bitbucket.org', + token: 'tokenlols', + }, + { + host: 'hosted.bitbucket.com', + token: 'thing', + apiBaseUrl: 'https://hosted.bitbucket.com/rest/api/1.0', + }, + { + host: 'notoken.bitbucket.com', + }, + ], + }, + scaffolder: { + defaultAuthor: { + name: 'Test', + email: 'example@example.com', + }, + }, + }); + + const customAuthorIntegrations = ScmIntegrations.fromConfig( + customAuthorConfig, + ); + const customAuthorAction = createPublishBitbucketAction({ + integrations: customAuthorIntegrations, + config: customAuthorConfig, + }); + + server.use( + rest.post( + 'https://api.bitbucket.org/2.0/repositories/owner/repo', + (_, res, ctx) => + res( + ctx.status(200), + ctx.set('Content-Type', 'application/json'), + ctx.json({ + links: { + html: { + href: 'https://bitbucket.org/owner/repo', + }, + clone: [ + { + name: 'https', + href: 'https://bitbucket.org/owner/cloneurl', + }, + ], + }, + }), + ), + ), + ); + + await customAuthorAction.handler(mockContext); + + expect(initRepoAndPush).toHaveBeenCalledWith({ + dir: mockContext.workspacePath, + remoteUrl: 'https://bitbucket.org/owner/cloneurl', + auth: { username: 'x-token-auth', password: 'tokenlols' }, + logger: mockContext.logger, + gitAuthorInfo: { name: 'Test', email: 'example@example.com' }, + }); + }); + it('should call outputs with the correct urls', async () => { server.use( rest.post( diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/bitbucket.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/bitbucket.ts index b05b51a7eb..1dc80f370c 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/bitbucket.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/bitbucket.ts @@ -287,8 +287,8 @@ export function createPublishBitbucketAction(options: { }); const gitAuthorInfo = { - name: config.getOptionalString('scaffolder.git.author.name'), - email: config.getOptionalString('scaffolder.git.author.email'), + name: config.getOptionalString('scaffolder.defaultAuthor.name'), + email: config.getOptionalString('scaffolder.defaultAuthor.email'), }; await initRepoAndPush({ diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/github.test.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/github.test.ts index 058168d666..0b277c4739 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/github.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/github.test.ts @@ -212,6 +212,53 @@ describe('publish:github', () => { }); }); + it('should call initRepoAndPush with the configured defaultAuthor', async () => { + const customAuthorConfig = new ConfigReader({ + integrations: { + github: [ + { host: 'github.com', token: 'tokenlols' }, + { host: 'ghe.github.com' }, + ], + }, + scaffolder: { + defaultAuthor: { + name: 'Test', + email: 'example@example.com', + }, + }, + }); + + const customAuthorIntegrations = ScmIntegrations.fromConfig( + customAuthorConfig, + ); + const customAuthorAction = createPublishGithubAction({ + integrations: customAuthorIntegrations, + config: customAuthorConfig, + }); + + mockGithubClient.users.getByUsername.mockResolvedValue({ + data: { type: 'User' }, + }); + + mockGithubClient.repos.createForAuthenticatedUser.mockResolvedValue({ + data: { + clone_url: 'https://github.com/clone/url.git', + html_url: 'https://github.com/html/url', + }, + }); + + await customAuthorAction.handler(mockContext); + + expect(initRepoAndPush).toHaveBeenCalledWith({ + dir: mockContext.workspacePath, + remoteUrl: 'https://github.com/clone/url.git', + defaultBranch: 'master', + auth: { username: 'x-access-token', password: 'tokenlols' }, + logger: mockContext.logger, + gitAuthorInfo: { name: 'Test', email: 'example@example.com' }, + }); + }); + it('should add access for the team when it starts with the owner', async () => { mockGithubClient.users.getByUsername.mockResolvedValue({ data: { type: 'User' }, diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/github.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/github.ts index f14dd817b0..9f693a96d8 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/github.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/github.ts @@ -251,8 +251,8 @@ export function createPublishGithubAction(options: { const repoContentsUrl = `${newRepo.html_url}/blob/${defaultBranch}`; const gitAuthorInfo = { - name: config.getOptionalString('scaffolder.git.author.name'), - email: config.getOptionalString('scaffolder.git.author.email'), + name: config.getOptionalString('scaffolder.defaultAuthor.name'), + email: config.getOptionalString('scaffolder.defaultAuthor.email'), }; await initRepoAndPush({ diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.test.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.test.ts index 427056454c..08ab87c271 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.test.ts @@ -170,6 +170,53 @@ describe('publish:gitlab', () => { }); }); + it('should call initRepoAndPush with the configured defaultAuthor', async () => { + const customAuthorConfig = new ConfigReader({ + integrations: { + gitlab: [ + { + host: 'gitlab.com', + token: 'tokenlols', + apiBaseUrl: 'https://api.gitlab.com', + }, + { + host: 'hosted.gitlab.com', + apiBaseUrl: 'https://api.hosted.gitlab.com', + }, + ], + }, + scaffolder: { + defaultAuthor: { + name: 'Test', + email: 'example@example.com', + }, + }, + }); + + const customAuthorIntegrations = ScmIntegrations.fromConfig( + customAuthorConfig, + ); + const customAuthorAction = createPublishGitlabAction({ + integrations: customAuthorIntegrations, + config: customAuthorConfig, + }); + + mockGitlabClient.Namespaces.show.mockResolvedValue({ id: 1234 }); + mockGitlabClient.Projects.create.mockResolvedValue({ + http_url_to_repo: 'http://mockurl.git', + }); + + await customAuthorAction.handler(mockContext); + + expect(initRepoAndPush).toHaveBeenCalledWith({ + dir: mockContext.workspacePath, + remoteUrl: 'http://mockurl.git', + auth: { username: 'oauth2', password: 'tokenlols' }, + logger: mockContext.logger, + gitAuthorInfo: { name: 'Test', email: 'example@example.com' }, + }); + }); + it('should call output with the remoteUrl and repoContentsUrl', async () => { mockGitlabClient.Namespaces.show.mockResolvedValue({ id: 1234 }); mockGitlabClient.Projects.create.mockResolvedValue({ diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.ts index 6d7384294d..1cd77ebe2a 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.ts @@ -124,8 +124,8 @@ export function createPublishGitlabAction(options: { const repoContentsUrl = `${remoteUrl}/-/blob/master`; const gitAuthorInfo = { - name: config.getOptionalString('scaffolder.git.author.name'), - email: config.getOptionalString('scaffolder.git.author.email'), + name: config.getOptionalString('scaffolder.defaultAuthor.name'), + email: config.getOptionalString('scaffolder.defaultAuthor.email'), }; await initRepoAndPush({ From 7cad18e2f039e71161af7aa582f1fd758b7d2546 Mon Sep 17 00:00:00 2001 From: Chase Rutherford-Jenkins Date: Tue, 6 Jul 2021 20:45:10 -0500 Subject: [PATCH 164/204] add changeset Signed-off-by: Chase Rutherford-Jenkins --- .changeset/moody-garlics-whisper.md | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 .changeset/moody-garlics-whisper.md diff --git a/.changeset/moody-garlics-whisper.md b/.changeset/moody-garlics-whisper.md new file mode 100644 index 0000000000..b2867bc016 --- /dev/null +++ b/.changeset/moody-garlics-whisper.md @@ -0,0 +1,24 @@ +--- +'@backstage/plugin-scaffolder-backend': patch +--- + +Adding `config: Config` as a required argument to `createBuiltinActions` and downstream methods in order to support configuration of the default git author used for Scaffolder commits. + +The affected methods are: + +- `createBuiltinActions` +- `createPublishGithubAction` +- `createPublishGitlabAction` +- `createPublishBitbucketAction` +- `createPublishAzureAction` + +Call sites to these methods will need to be migrated to include the new `config` argument. See `createRouter` in `plugins/scaffolder-backend/src/service/router.ts` for an example of adding this new argument. + +To configure the default git author, use the `defaultAuthor` key under `scaffolder` in `app-config.yaml`: + +```yaml +scaffolder: + defaultAuthor: + name: Example + email: example@example.com +``` From 3c19f1230f28d2465a83410fca6ed9dadbb9e9c0 Mon Sep 17 00:00:00 2001 From: Chase Rutherford-Jenkins Date: Tue, 6 Jul 2021 21:15:14 -0500 Subject: [PATCH 165/204] update tests Signed-off-by: Chase Rutherford-Jenkins --- .../src/scaffolder/actions/builtin/publish/azure.test.ts | 2 ++ .../src/scaffolder/actions/builtin/publish/bitbucket.test.ts | 2 ++ .../src/scaffolder/actions/builtin/publish/gitlab.test.ts | 2 ++ 3 files changed, 6 insertions(+) diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/azure.test.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/azure.test.ts index b5c9bdcd89..1dc29ea763 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/azure.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/azure.test.ts @@ -165,6 +165,7 @@ describe('publish:azure', () => { defaultBranch: 'master', auth: { username: 'notempty', password: 'tokenlols' }, logger: mockContext.logger, + gitAuthorInfo: {}, }); }); @@ -226,6 +227,7 @@ describe('publish:azure', () => { remoteUrl: 'https://dev.azure.com/organization/project/_git/repo', auth: { username: 'notempty', password: 'tokenlols' }, logger: mockContext.logger, + defaultBranch: 'master', gitAuthorInfo: { name: 'Test', email: 'example@example.com' }, }); }); diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/bitbucket.test.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/bitbucket.test.ts index 6a72cf1bc3..0e5f8df72b 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/bitbucket.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/bitbucket.test.ts @@ -289,6 +289,7 @@ describe('publish:bitbucket', () => { defaultBranch: 'master', auth: { username: 'x-token-auth', password: 'tokenlols' }, logger: mockContext.logger, + gitAuthorInfo: {}, }); }); @@ -400,6 +401,7 @@ describe('publish:bitbucket', () => { remoteUrl: 'https://bitbucket.org/owner/cloneurl', auth: { username: 'x-token-auth', password: 'tokenlols' }, logger: mockContext.logger, + defaultBranch: 'master', gitAuthorInfo: { name: 'Test', email: 'example@example.com' }, }); }); diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.test.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.test.ts index 08ab87c271..25a129d905 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.test.ts @@ -143,6 +143,7 @@ describe('publish:gitlab', () => { remoteUrl: 'http://mockurl.git', auth: { username: 'oauth2', password: 'tokenlols' }, logger: mockContext.logger, + gitAuthorInfo: {}, }); }); @@ -213,6 +214,7 @@ describe('publish:gitlab', () => { remoteUrl: 'http://mockurl.git', auth: { username: 'oauth2', password: 'tokenlols' }, logger: mockContext.logger, + defaultBranch: 'master', gitAuthorInfo: { name: 'Test', email: 'example@example.com' }, }); }); From ca46883c3a4a6a702ce8aa738575b524a6d4c8ff Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 7 Jul 2021 04:10:11 +0000 Subject: [PATCH 166/204] chore(deps): bump passport-oauth2 from 1.5.0 to 1.6.0 Bumps [passport-oauth2](https://github.com/jaredhanson/passport-oauth2) from 1.5.0 to 1.6.0. - [Release notes](https://github.com/jaredhanson/passport-oauth2/releases) - [Changelog](https://github.com/jaredhanson/passport-oauth2/blob/master/CHANGELOG.md) - [Commits](https://github.com/jaredhanson/passport-oauth2/compare/v1.5.0...v1.6.0) --- updated-dependencies: - dependency-name: passport-oauth2 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 27a6fcc250..3eb7874b4b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -20313,9 +20313,9 @@ passport-oauth2@1.2.0: uid2 "0.0.x" passport-oauth2@1.x.x, passport-oauth2@^1.4.0, passport-oauth2@^1.5.0: - version "1.5.0" - resolved "https://registry.npmjs.org/passport-oauth2/-/passport-oauth2-1.5.0.tgz#64babbb54ac46a4dcab35e7f266ed5294e3c4108" - integrity sha512-kqBt6vR/5VlCK8iCx1/KpY42kQ+NEHZwsSyt4Y6STiNjU+wWICG1i8ucc1FapXDGO15C5O5VZz7+7vRzrDPXXQ== + version "1.6.0" + resolved "https://registry.npmjs.org/passport-oauth2/-/passport-oauth2-1.6.0.tgz#5f599735e0ea40ea3027643785f81a3a9b4feb50" + integrity sha512-emXPLqLcVEcLFR/QvQXZcwLmfK8e9CqvMgmOFJxcNT3okSFMtUbRRKpY20x5euD+01uHsjjCa07DYboEeLXYiw== dependencies: base64url "3.x.x" oauth "0.9.x" From e056e9d88b8e93968ada74fd137a96cff70e1940 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 7 Jul 2021 04:13:40 +0000 Subject: [PATCH 167/204] chore(deps-dev): bump @graphql-codegen/cli from 1.21.5 to 1.21.6 Bumps [@graphql-codegen/cli](https://github.com/dotansimha/graphql-code-generator/tree/HEAD/packages/graphql-codegen-cli) from 1.21.5 to 1.21.6. - [Release notes](https://github.com/dotansimha/graphql-code-generator/releases) - [Changelog](https://github.com/dotansimha/graphql-code-generator/blob/master/packages/graphql-codegen-cli/CHANGELOG.md) - [Commits](https://github.com/dotansimha/graphql-code-generator/commits/@graphql-codegen/cli@1.21.6/packages/graphql-codegen-cli) --- updated-dependencies: - dependency-name: "@graphql-codegen/cli" dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- yarn.lock | 48 ++++++++++++++++++++++++++++-------------------- 1 file changed, 28 insertions(+), 20 deletions(-) diff --git a/yarn.lock b/yarn.lock index 27a6fcc250..a46e778db1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2015,9 +2015,9 @@ subscriptions-transport-ws "^0.9.18" "@graphql-codegen/cli@^1.21.3": - version "1.21.5" - resolved "https://registry.npmjs.org/@graphql-codegen/cli/-/cli-1.21.5.tgz#b9041553747cfb2dee7c3473a2e2461ec3e7ada5" - integrity sha512-w3SovNJ9qtMhFLAdPZeCdGvHXDgfdb53mueWDTyncOt04m+tohVnY4qExvyKLTN5zlGxrA/5ubp2x8Az0xQarA== + version "1.21.6" + resolved "https://registry.npmjs.org/@graphql-codegen/cli/-/cli-1.21.6.tgz#d06b5f6cb625541f3981d69f99966e520b958072" + integrity sha512-wtBk4lk/YxG6MrxnBOxE9nCfR9PNDjaqA8CF9hi6Q8jiSl4sV03tC2R+gE7+2EI8J6Xa1bxZe15LnBhVwb/mUA== dependencies: "@graphql-codegen/core" "1.17.10" "@graphql-codegen/plugin-helpers" "^1.18.7" @@ -2034,7 +2034,7 @@ ansi-escapes "^4.3.1" chalk "^4.1.0" change-case-all "1.0.14" - chokidar "^3.5.1" + chokidar "^3.5.2" common-tags "^1.8.0" cosmiconfig "^7.0.0" debounce "^1.2.0" @@ -2053,7 +2053,7 @@ mkdirp "^1.0.4" string-env-interpolation "^1.0.1" ts-log "^2.2.3" - tslib "~2.2.0" + tslib "~2.3.0" valid-url "^1.0.9" wrap-ansi "^7.0.0" yaml "^1.10.0" @@ -7448,7 +7448,7 @@ anymatch@^2.0.0: micromatch "^3.1.4" normalize-path "^2.1.1" -anymatch@^3.0.3, anymatch@~3.1.1: +anymatch@^3.0.3: version "3.1.1" resolved "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz#c55ecf02185e2469259399310c173ce31233b142" integrity sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg== @@ -7456,6 +7456,14 @@ anymatch@^3.0.3, anymatch@~3.1.1: normalize-path "^3.0.0" picomatch "^2.0.4" +anymatch@~3.1.2: + version "3.1.2" + resolved "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz#c0557c096af32f106198f4f4e2a383537e378716" + integrity sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg== + dependencies: + normalize-path "^3.0.0" + picomatch "^2.0.4" + apollo-cache-control@^0.14.0: version "0.14.0" resolved "https://registry.npmjs.org/apollo-cache-control/-/apollo-cache-control-0.14.0.tgz#95f20c3e03e7994e0d1bd48c59aeaeb575ed0ce7" @@ -9388,20 +9396,20 @@ chokidar@^2.1.8: optionalDependencies: fsevents "^1.2.7" -chokidar@^3.2.2, chokidar@^3.3.0, chokidar@^3.3.1, chokidar@^3.4.1, chokidar@^3.4.2, chokidar@^3.5.1: - version "3.5.1" - resolved "https://registry.npmjs.org/chokidar/-/chokidar-3.5.1.tgz#ee9ce7bbebd2b79f49f304799d5468e31e14e68a" - integrity sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw== +chokidar@^3.2.2, chokidar@^3.3.0, chokidar@^3.3.1, chokidar@^3.4.1, chokidar@^3.4.2, chokidar@^3.5.2: + version "3.5.2" + resolved "https://registry.npmjs.org/chokidar/-/chokidar-3.5.2.tgz#dba3976fcadb016f66fd365021d91600d01c1e75" + integrity sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ== dependencies: - anymatch "~3.1.1" + anymatch "~3.1.2" braces "~3.0.2" - glob-parent "~5.1.0" + glob-parent "~5.1.2" is-binary-path "~2.1.0" is-glob "~4.0.1" normalize-path "~3.0.0" - readdirp "~3.5.0" + readdirp "~3.6.0" optionalDependencies: - fsevents "~2.3.1" + fsevents "~2.3.2" chownr@^1.1.1: version "1.1.4" @@ -13552,7 +13560,7 @@ fsevents@^2.1.2: resolved "https://registry.npmjs.org/fsevents/-/fsevents-2.1.2.tgz#4c0a1fb34bc68e543b4b82a9ec392bfbda840805" integrity sha512-R4wDiBwZ0KzpgOWetKDug1FZcYhqYnUYKtfZYt4mD5SBz76q0KR4Q9o7GIPamsVPGmW3EYPPJ0dOOjvx32ldZA== -fsevents@~2.3.1: +fsevents@~2.3.1, fsevents@~2.3.2: version "2.3.2" resolved "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== @@ -13895,7 +13903,7 @@ glob-parent@^3.1.0: is-glob "^3.1.0" path-dirname "^1.0.0" -glob-parent@^5.1.0, glob-parent@^5.1.1, glob-parent@^5.1.2, glob-parent@~5.1.0: +glob-parent@^5.1.0, glob-parent@^5.1.1, glob-parent@^5.1.2, glob-parent@~5.1.2: version "5.1.2" resolved "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== @@ -22515,10 +22523,10 @@ readdirp@^2.2.1: micromatch "^3.1.10" readable-stream "^2.0.2" -readdirp@~3.5.0: - version "3.5.0" - resolved "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz#9ba74c019b15d365278d2e91bb8c48d7b4d42c9e" - integrity sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ== +readdirp@~3.6.0: + version "3.6.0" + resolved "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" + integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== dependencies: picomatch "^2.2.1" From d9c6637b385ed5dd8d65a1c5cef6eca23765142d Mon Sep 17 00:00:00 2001 From: Ben Lambert Date: Wed, 7 Jul 2021 10:28:47 +0200 Subject: [PATCH 168/204] Update sweet-terms-approve.md Signed-off-by: Ben Lambert --- .changeset/sweet-terms-approve.md | 1 - 1 file changed, 1 deletion(-) diff --git a/.changeset/sweet-terms-approve.md b/.changeset/sweet-terms-approve.md index 56297f694d..e8daa06673 100644 --- a/.changeset/sweet-terms-approve.md +++ b/.changeset/sweet-terms-approve.md @@ -1,5 +1,4 @@ --- -'example-backend': patch '@backstage/plugin-scaffolder-backend': patch --- From 313aa8b926c718dfc0be667075588085878a654b Mon Sep 17 00:00:00 2001 From: Ben Lambert Date: Wed, 7 Jul 2021 10:30:04 +0200 Subject: [PATCH 169/204] Update healthy-colts-watch.md Signed-off-by: Ben Lambert --- .changeset/healthy-colts-watch.md | 1 - 1 file changed, 1 deletion(-) diff --git a/.changeset/healthy-colts-watch.md b/.changeset/healthy-colts-watch.md index 763f2a9828..2b24621f20 100644 --- a/.changeset/healthy-colts-watch.md +++ b/.changeset/healthy-colts-watch.md @@ -1,5 +1,4 @@ --- -'example-backend': patch '@backstage/backend-test-utils': patch '@backstage/create-app': patch '@backstage/plugin-catalog-backend': patch From b254ebff8176b7464166414814016f4c4e61eefb Mon Sep 17 00:00:00 2001 From: Ben Lambert Date: Wed, 7 Jul 2021 10:43:11 +0200 Subject: [PATCH 170/204] Update moody-garlics-whisper.md Signed-off-by: Ben Lambert --- .changeset/moody-garlics-whisper.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/moody-garlics-whisper.md b/.changeset/moody-garlics-whisper.md index b2867bc016..b9683e4637 100644 --- a/.changeset/moody-garlics-whisper.md +++ b/.changeset/moody-garlics-whisper.md @@ -1,5 +1,5 @@ --- -'@backstage/plugin-scaffolder-backend': patch +'@backstage/plugin-scaffolder-backend': minor --- Adding `config: Config` as a required argument to `createBuiltinActions` and downstream methods in order to support configuration of the default git author used for Scaffolder commits. From 538ada54efa0e38e9af333348da73715c002ea8c Mon Sep 17 00:00:00 2001 From: Jos Craw Date: Wed, 7 Jul 2021 21:21:01 +1200 Subject: [PATCH 171/204] fix: add uiSchema support for dependent forms Signed-off-by: Jos Craw --- .../MultistepJsonForm/schema.test.ts | 60 +++++++++++++++++++ .../components/MultistepJsonForm/schema.ts | 12 +++- 2 files changed, 71 insertions(+), 1 deletion(-) diff --git a/plugins/scaffolder/src/components/MultistepJsonForm/schema.test.ts b/plugins/scaffolder/src/components/MultistepJsonForm/schema.test.ts index 1031dfffe3..b51d01f719 100644 --- a/plugins/scaffolder/src/components/MultistepJsonForm/schema.test.ts +++ b/plugins/scaffolder/src/components/MultistepJsonForm/schema.test.ts @@ -286,4 +286,64 @@ describe('transformSchemaToProps', () => { uiSchema: expectedUiSchema, }); }); + + it('transforms schema with dependencies', () => { + const inputSchema = { + type: 'object', + properties: { + name: { + type: 'string', + }, + credit_card: { + type: 'number', + }, + }, + required: ['name'], + dependencies: { + credit_card: { + properties: { + billing_address: { + type: 'string', + 'ui:widget': 'textarea', + }, + }, + required: ['billing_address'], + }, + }, + }; + const expectedSchema = { + type: 'object', + properties: { + name: { + type: 'string', + }, + credit_card: { + type: 'number', + }, + }, + required: ['name'], + dependencies: { + credit_card: { + properties: { + billing_address: { + type: 'string', + }, + }, + required: ['billing_address'], + }, + }, + }; + const expectedUiSchema = { + billing_address: { + 'ui:widget': 'textarea', + }, + credit_card: {}, + name: {}, + }; + + expect(transformSchemaToProps(inputSchema)).toEqual({ + schema: expectedSchema, + uiSchema: expectedUiSchema, + }); + }); }); diff --git a/plugins/scaffolder/src/components/MultistepJsonForm/schema.ts b/plugins/scaffolder/src/components/MultistepJsonForm/schema.ts index 3342e3a046..ee2dbce406 100644 --- a/plugins/scaffolder/src/components/MultistepJsonForm/schema.ts +++ b/plugins/scaffolder/src/components/MultistepJsonForm/schema.ts @@ -26,7 +26,7 @@ function extractUiSchema(schema: JsonObject, uiSchema: JsonObject) { return; } - const { properties, anyOf, oneOf, allOf } = schema; + const { properties, anyOf, oneOf, allOf, dependencies } = schema; for (const propName in schema) { if (!schema.hasOwnProperty(propName)) { @@ -81,6 +81,16 @@ function extractUiSchema(schema: JsonObject, uiSchema: JsonObject) { extractUiSchema(schemaNode, uiSchema); } } + + if (isObject(dependencies)) { + for (const depName of Object.keys(dependencies)) { + const schemaNode = dependencies[depName]; + if (!isObject(schemaNode)) { + continue; + } + extractUiSchema(schemaNode, uiSchema); + } + } } export function transformSchemaToProps( From 6a09ed555d092aec01700375bc18b89d35f08b51 Mon Sep 17 00:00:00 2001 From: blam Date: Sat, 19 Jun 2021 02:17:01 +0200 Subject: [PATCH 172/204] breaking: removing alphav1 support for templates Signed-off-by: blam --- packages/backend/src/plugins/scaffolder.ts | 30 +- .../src/kinds/TemplateEntityV1alpha1.test.ts | 106 ------ .../src/kinds/TemplateEntityV1alpha1.ts | 36 -- packages/catalog-model/src/kinds/index.ts | 5 - .../kinds/Template.v1alpha1.schema.json | 99 ------ .../src/ingestion/LocationReaders.ts | 1 + .../BuiltinKindsEntityProcessor.test.ts | 19 +- .../processors/BuiltinKindsEntityProcessor.ts | 6 +- .../DefaultCatalogProcessingOrchestrator.ts | 1 + .../sample-templates/remote-templates.yaml | 2 +- .../src/lib/catalog/CatalogEntityClient.ts | 9 +- .../actions/builtin/createBuiltinActions.ts | 18 +- .../actions/builtin/fetch/cookiecutter.ts | 110 +++++- .../publish => actions/builtin}/helpers.ts | 41 +++ .../actions/builtin/publish/azure.ts | 2 +- .../actions/builtin/publish/bitbucket.ts | 2 +- .../actions/builtin/publish/github.ts | 2 +- .../actions/builtin/publish/gitlab.ts | 2 +- .../src/scaffolder/index.ts | 3 - .../src/scaffolder/jobs/index.ts | 17 - .../src/scaffolder/jobs/logger.test.ts | 49 --- .../src/scaffolder/jobs/logger.ts | 48 --- .../src/scaffolder/jobs/processor.test.ts | 329 ----------------- .../src/scaffolder/jobs/processor.ts | 180 ---------- .../src/scaffolder/jobs/types.ts | 68 ---- .../src/scaffolder/stages/helpers.test.ts | 332 ------------------ .../src/scaffolder/stages/helpers.ts | 62 ---- .../src/scaffolder/stages/index.ts | 19 - .../src/scaffolder/stages/legacy.ts | 105 ------ .../scaffolder/stages/prepare/azure.test.ts | 116 ------ .../src/scaffolder/stages/prepare/azure.ts | 63 ---- .../stages/prepare/bitbucket.test.ts | 113 ------ .../scaffolder/stages/prepare/bitbucket.ts | 82 ----- .../scaffolder/stages/prepare/file.test.ts | 79 ----- .../src/scaffolder/stages/prepare/file.ts | 37 -- .../scaffolder/stages/prepare/github.test.ts | 97 ----- .../src/scaffolder/stages/prepare/github.ts | 71 ---- .../scaffolder/stages/prepare/gitlab.test.ts | 82 ----- .../src/scaffolder/stages/prepare/gitlab.ts | 62 ---- .../src/scaffolder/stages/prepare/index.ts | 23 -- .../stages/prepare/preparers.test.ts | 50 --- .../scaffolder/stages/prepare/preparers.ts | 81 ----- .../src/scaffolder/stages/prepare/types.ts | 40 --- .../scaffolder/stages/publish/azure.test.ts | 89 ----- .../src/scaffolder/stages/publish/azure.ts | 83 ----- .../stages/publish/bitbucket.test.ts | 228 ------------ .../scaffolder/stages/publish/bitbucket.ts | 207 ----------- .../scaffolder/stages/publish/github.test.ts | 315 ----------------- .../src/scaffolder/stages/publish/github.ts | 178 ---------- .../scaffolder/stages/publish/gitlab.test.ts | 151 -------- .../src/scaffolder/stages/publish/gitlab.ts | 106 ------ .../src/scaffolder/stages/publish/index.ts | 27 -- .../stages/publish/publishers.test.ts | 127 ------- .../scaffolder/stages/publish/publishers.ts | 113 ------ .../src/scaffolder/stages/publish/types.ts | 47 --- .../stages/templater/cookiecutter.test.ts | 279 --------------- .../stages/templater/cookiecutter.ts | 107 ------ .../scaffolder/stages/templater/cra/index.ts | 159 --------- .../scaffolder/stages/templater/helpers.ts | 75 ---- .../src/scaffolder/stages/templater/index.ts | 20 -- .../stages/templater/templaters.test.ts | 43 --- .../scaffolder/stages/templater/templaters.ts | 39 -- .../src/scaffolder/stages/templater/types.ts | 73 ---- .../src/scaffolder/tasks/TemplateConverter.ts | 101 ------ .../scaffolder-backend/src/service/router.ts | 113 +----- 65 files changed, 194 insertions(+), 5185 deletions(-) delete mode 100644 packages/catalog-model/src/kinds/TemplateEntityV1alpha1.test.ts delete mode 100644 packages/catalog-model/src/kinds/TemplateEntityV1alpha1.ts delete mode 100644 packages/catalog-model/src/schema/kinds/Template.v1alpha1.schema.json rename plugins/scaffolder-backend/src/scaffolder/{stages/publish => actions/builtin}/helpers.ts (77%) delete mode 100644 plugins/scaffolder-backend/src/scaffolder/jobs/index.ts delete mode 100644 plugins/scaffolder-backend/src/scaffolder/jobs/logger.test.ts delete mode 100644 plugins/scaffolder-backend/src/scaffolder/jobs/logger.ts delete mode 100644 plugins/scaffolder-backend/src/scaffolder/jobs/processor.test.ts delete mode 100644 plugins/scaffolder-backend/src/scaffolder/jobs/processor.ts delete mode 100644 plugins/scaffolder-backend/src/scaffolder/jobs/types.ts delete mode 100644 plugins/scaffolder-backend/src/scaffolder/stages/helpers.test.ts delete mode 100644 plugins/scaffolder-backend/src/scaffolder/stages/helpers.ts delete mode 100644 plugins/scaffolder-backend/src/scaffolder/stages/index.ts delete mode 100644 plugins/scaffolder-backend/src/scaffolder/stages/legacy.ts delete mode 100644 plugins/scaffolder-backend/src/scaffolder/stages/prepare/azure.test.ts delete mode 100644 plugins/scaffolder-backend/src/scaffolder/stages/prepare/azure.ts delete mode 100644 plugins/scaffolder-backend/src/scaffolder/stages/prepare/bitbucket.test.ts delete mode 100644 plugins/scaffolder-backend/src/scaffolder/stages/prepare/bitbucket.ts delete mode 100644 plugins/scaffolder-backend/src/scaffolder/stages/prepare/file.test.ts delete mode 100644 plugins/scaffolder-backend/src/scaffolder/stages/prepare/file.ts delete mode 100644 plugins/scaffolder-backend/src/scaffolder/stages/prepare/github.test.ts delete mode 100644 plugins/scaffolder-backend/src/scaffolder/stages/prepare/github.ts delete mode 100644 plugins/scaffolder-backend/src/scaffolder/stages/prepare/gitlab.test.ts delete mode 100644 plugins/scaffolder-backend/src/scaffolder/stages/prepare/gitlab.ts delete mode 100644 plugins/scaffolder-backend/src/scaffolder/stages/prepare/index.ts delete mode 100644 plugins/scaffolder-backend/src/scaffolder/stages/prepare/preparers.test.ts delete mode 100644 plugins/scaffolder-backend/src/scaffolder/stages/prepare/preparers.ts delete mode 100644 plugins/scaffolder-backend/src/scaffolder/stages/prepare/types.ts delete mode 100644 plugins/scaffolder-backend/src/scaffolder/stages/publish/azure.test.ts delete mode 100644 plugins/scaffolder-backend/src/scaffolder/stages/publish/azure.ts delete mode 100644 plugins/scaffolder-backend/src/scaffolder/stages/publish/bitbucket.test.ts delete mode 100644 plugins/scaffolder-backend/src/scaffolder/stages/publish/bitbucket.ts delete mode 100644 plugins/scaffolder-backend/src/scaffolder/stages/publish/github.test.ts delete mode 100644 plugins/scaffolder-backend/src/scaffolder/stages/publish/github.ts delete mode 100644 plugins/scaffolder-backend/src/scaffolder/stages/publish/gitlab.test.ts delete mode 100644 plugins/scaffolder-backend/src/scaffolder/stages/publish/gitlab.ts delete mode 100644 plugins/scaffolder-backend/src/scaffolder/stages/publish/index.ts delete mode 100644 plugins/scaffolder-backend/src/scaffolder/stages/publish/publishers.test.ts delete mode 100644 plugins/scaffolder-backend/src/scaffolder/stages/publish/publishers.ts delete mode 100644 plugins/scaffolder-backend/src/scaffolder/stages/publish/types.ts delete mode 100644 plugins/scaffolder-backend/src/scaffolder/stages/templater/cookiecutter.test.ts delete mode 100644 plugins/scaffolder-backend/src/scaffolder/stages/templater/cookiecutter.ts delete mode 100644 plugins/scaffolder-backend/src/scaffolder/stages/templater/cra/index.ts delete mode 100644 plugins/scaffolder-backend/src/scaffolder/stages/templater/helpers.ts delete mode 100644 plugins/scaffolder-backend/src/scaffolder/stages/templater/index.ts delete mode 100644 plugins/scaffolder-backend/src/scaffolder/stages/templater/templaters.test.ts delete mode 100644 plugins/scaffolder-backend/src/scaffolder/stages/templater/templaters.ts delete mode 100644 plugins/scaffolder-backend/src/scaffolder/stages/templater/types.ts delete mode 100644 plugins/scaffolder-backend/src/scaffolder/tasks/TemplateConverter.ts diff --git a/packages/backend/src/plugins/scaffolder.ts b/packages/backend/src/plugins/scaffolder.ts index 09b3732301..619134a990 100644 --- a/packages/backend/src/plugins/scaffolder.ts +++ b/packages/backend/src/plugins/scaffolder.ts @@ -14,19 +14,9 @@ * limitations under the License. */ -import { - DockerContainerRunner, - SingleHostDiscovery, -} from '@backstage/backend-common'; +import { DockerContainerRunner } from '@backstage/backend-common'; import { CatalogClient } from '@backstage/catalog-client'; -import { - CookieCutter, - CreateReactAppTemplater, - createRouter, - Preparers, - Publishers, - Templaters, -} from '@backstage/plugin-scaffolder-backend'; +import { createRouter } from '@backstage/plugin-scaffolder-backend'; import Docker from 'dockerode'; import { Router } from 'express'; import type { PluginEnvironment } from '../types'; @@ -36,27 +26,15 @@ export default async function createPlugin({ config, database, reader, + discovery, }: PluginEnvironment): Promise { const dockerClient = new Docker(); const containerRunner = new DockerContainerRunner({ dockerClient }); - const cookiecutterTemplater = new CookieCutter({ containerRunner }); - const craTemplater = new CreateReactAppTemplater({ containerRunner }); - const templaters = new Templaters(); - - templaters.register('cookiecutter', cookiecutterTemplater); - templaters.register('cra', craTemplater); - - const preparers = await Preparers.fromConfig(config, { logger }); - const publishers = await Publishers.fromConfig(config, { logger }); - - const discovery = SingleHostDiscovery.fromConfig(config); const catalogClient = new CatalogClient({ discoveryApi: discovery }); return await createRouter({ - preparers, - templaters, - publishers, + containerRunner, logger, config, database, diff --git a/packages/catalog-model/src/kinds/TemplateEntityV1alpha1.test.ts b/packages/catalog-model/src/kinds/TemplateEntityV1alpha1.test.ts deleted file mode 100644 index f03519a3c6..0000000000 --- a/packages/catalog-model/src/kinds/TemplateEntityV1alpha1.test.ts +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { - TemplateEntityV1alpha1, - templateEntityV1alpha1Validator as validator, -} from './TemplateEntityV1alpha1'; - -describe('templateEntityV1alpha1Validator', () => { - let entity: TemplateEntityV1alpha1; - - beforeEach(() => { - entity = { - apiVersion: 'backstage.io/v1alpha1', - kind: 'Template', - metadata: { - name: 'test', - }, - spec: { - type: 'website', - templater: 'cookiecutter', - schema: { - $schema: 'http://json-schema.org/draft-07/schema#', - required: ['storePath', 'owner'], - properties: { - owner: { - type: 'string', - title: 'Owner', - description: 'Who is going to own this component', - }, - storePath: { - type: 'string', - title: 'Store path', - description: 'GitHub store path in org/repo format', - }, - }, - }, - owner: 'team-a@example.com', - }, - }; - }); - - it('happy path: accepts valid data', async () => { - await expect(validator.check(entity)).resolves.toBe(true); - }); - - it('silently accepts v1beta1 as well', async () => { - (entity as any).apiVersion = 'backstage.io/v1beta1'; - await expect(validator.check(entity)).resolves.toBe(true); - }); - - it('ignores unknown apiVersion', async () => { - (entity as any).apiVersion = 'backstage.io/v1beta0'; - await expect(validator.check(entity)).resolves.toBe(false); - }); - - it('ignores unknown kind', async () => { - (entity as any).kind = 'Wizard'; - await expect(validator.check(entity)).resolves.toBe(false); - }); - - it('rejects missing type', async () => { - delete (entity as any).spec.type; - await expect(validator.check(entity)).rejects.toThrow(/type/); - }); - - it('accepts any other type', async () => { - (entity as any).spec.type = 'hallo'; - await expect(validator.check(entity)).resolves.toBe(true); - }); - - it('rejects empty type', async () => { - (entity as any).spec.type = ''; - await expect(validator.check(entity)).rejects.toThrow(/type/); - }); - - it('rejects missing templater', async () => { - (entity as any).spec.templater = ''; - await expect(validator.check(entity)).rejects.toThrow(/templater/); - }); - it('accepts missing owner', async () => { - delete (entity as any).spec.owner; - await expect(validator.check(entity)).resolves.toBe(true); - }); - it('rejects empty owner', async () => { - (entity as any).spec.owner = ''; - await expect(validator.check(entity)).rejects.toThrow(/owner/); - }); - it('rejects wrong type owner', async () => { - (entity as any).spec.owner = 5; - await expect(validator.check(entity)).rejects.toThrow(/owner/); - }); -}); diff --git a/packages/catalog-model/src/kinds/TemplateEntityV1alpha1.ts b/packages/catalog-model/src/kinds/TemplateEntityV1alpha1.ts deleted file mode 100644 index bdc6f35df2..0000000000 --- a/packages/catalog-model/src/kinds/TemplateEntityV1alpha1.ts +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import type { Entity } from '../entity/Entity'; -import schema from '../schema/kinds/Template.v1alpha1.schema.json'; -import type { JSONSchema } from '../types'; -import { ajvCompiledJsonSchemaValidator } from './util'; - -export interface TemplateEntityV1alpha1 extends Entity { - apiVersion: 'backstage.io/v1alpha1' | 'backstage.io/v1beta1'; - kind: 'Template'; - spec: { - type: string; - templater: string; - path?: string; - schema: JSONSchema; - owner?: string; - }; -} - -export const templateEntityV1alpha1Validator = ajvCompiledJsonSchemaValidator( - schema, -); diff --git a/packages/catalog-model/src/kinds/index.ts b/packages/catalog-model/src/kinds/index.ts index ccdf0051db..be9f7a0d6a 100644 --- a/packages/catalog-model/src/kinds/index.ts +++ b/packages/catalog-model/src/kinds/index.ts @@ -50,11 +50,6 @@ export type { SystemEntityV1alpha1 as SystemEntity, SystemEntityV1alpha1, } from './SystemEntityV1alpha1'; -export { templateEntityV1alpha1Validator } from './TemplateEntityV1alpha1'; -export type { - TemplateEntityV1alpha1 as TemplateEntity, - TemplateEntityV1alpha1, -} from './TemplateEntityV1alpha1'; export { templateEntityV1beta2Validator } from './TemplateEntityV1beta2'; export type { TemplateEntityV1beta2 } from './TemplateEntityV1beta2'; export type { KindValidator } from './types'; diff --git a/packages/catalog-model/src/schema/kinds/Template.v1alpha1.schema.json b/packages/catalog-model/src/schema/kinds/Template.v1alpha1.schema.json deleted file mode 100644 index 5a0c0efa73..0000000000 --- a/packages/catalog-model/src/schema/kinds/Template.v1alpha1.schema.json +++ /dev/null @@ -1,99 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema", - "$id": "TemplateV1alpha1", - "description": "A Template describes a skeleton for use with the Scaffolder. It is used for describing what templating library is supported, and also for documenting the variables that the template requires using JSON Forms Schema.", - "examples": [ - { - "apiVersion": "backstage.io/v1alpha1", - "kind": "Template", - "metadata": { - "name": "react-ssr-template", - "title": "React SSR Template", - "description": "Next.js application skeleton for creating isomorphic web applications.", - "tags": ["recommended", "react"] - }, - "spec": { - "owner": "artist-relations-team", - "templater": "cookiecutter", - "type": "website", - "path": ".", - "schema": { - "required": ["component-id", "description"], - "properties": { - "component_id": { - "title": "Name", - "type": "string", - "description": "Unique name of the component" - }, - "description": { - "title": "Description", - "type": "string", - "description": "Description of the component" - } - } - } - } - } - ], - "allOf": [ - { - "$ref": "Entity" - }, - { - "type": "object", - "required": ["spec"], - "properties": { - "apiVersion": { - "enum": ["backstage.io/v1alpha1", "backstage.io/v1beta1"] - }, - "kind": { - "enum": ["Template"] - }, - "metadata": { - "type": "object", - "properties": { - "title": { - "type": "string", - "description": "The nice display name for the template. This field is required as is used to reference the template to the user instead of the metadata.name field.", - "examples": ["React SSR Template"], - "minLength": 1 - } - } - }, - "spec": { - "type": "object", - "required": ["type", "templater", "schema"], - "properties": { - "type": { - "type": "string", - "description": "The type of component created by the template. The software catalog accepts any type value, but an organization should take great care to establish a proper taxonomy for these. Tools including Backstage itself may read this field and behave differently depending on its value. For example, a website type component may present tooling in the Backstage interface that is specific to just websites.", - "examples": ["service", "website", "library"], - "minLength": 1 - }, - "templater": { - "type": "string", - "description": "The templating library that is supported by the template skeleton.", - "examples": ["cookiecutter"], - "minLength": 1 - }, - "path": { - "type": "string", - "description": "The string location where the templater should be run if it is not on the same level as the template.yaml definition.", - "examples": ["./cookiecutter/skeleton"], - "minLength": 1 - }, - "schema": { - "type": "object", - "description": "The JSONSchema describing the inputs for the template." - }, - "owner": { - "type": "string", - "description": "The user (or group) owner of the template", - "minLength": 1 - } - } - } - } - } - ] -} diff --git a/plugins/catalog-backend/src/ingestion/LocationReaders.ts b/plugins/catalog-backend/src/ingestion/LocationReaders.ts index 624c7aaa61..86a8ebb9f2 100644 --- a/plugins/catalog-backend/src/ingestion/LocationReaders.ts +++ b/plugins/catalog-backend/src/ingestion/LocationReaders.ts @@ -265,6 +265,7 @@ export class LocationReaders implements LocationReader { )}, ${e}`; emit(result.inputError(item.location, message)); logger.warn(message); + logger.debug(e.stack); return undefined; } } diff --git a/plugins/catalog-backend/src/ingestion/processors/BuiltinKindsEntityProcessor.test.ts b/plugins/catalog-backend/src/ingestion/processors/BuiltinKindsEntityProcessor.test.ts index bdc6d463c2..33beffed0d 100644 --- a/plugins/catalog-backend/src/ingestion/processors/BuiltinKindsEntityProcessor.test.ts +++ b/plugins/catalog-backend/src/ingestion/processors/BuiltinKindsEntityProcessor.test.ts @@ -21,7 +21,7 @@ import { GroupEntity, ResourceEntity, SystemEntity, - TemplateEntity, + TemplateEntityV1beta2, UserEntity, } from '@backstage/catalog-model'; import { BuiltinKindsEntityProcessor } from './BuiltinKindsEntityProcessor'; @@ -522,22 +522,13 @@ describe('BuiltinKindsEntityProcessor', () => { }); }); it('generates relations for template entities', async () => { - const entity: TemplateEntity = { - apiVersion: 'backstage.io/v1alpha1', + const entity: TemplateEntityV1beta2 = { + apiVersion: 'backstage.io/v1beta2', kind: 'Template', metadata: { name: 'n' }, spec: { - schema: { - properties: { - description: { - title: 'd', - type: 'string', - description: 'des', - }, - }, - }, - templater: 'cookiecutter', - path: '.', + parameters: {}, + steps: [], type: 'service', owner: 'o', }, diff --git a/plugins/catalog-backend/src/ingestion/processors/BuiltinKindsEntityProcessor.ts b/plugins/catalog-backend/src/ingestion/processors/BuiltinKindsEntityProcessor.ts index b8805ab9ba..bcabc00f32 100644 --- a/plugins/catalog-backend/src/ingestion/processors/BuiltinKindsEntityProcessor.ts +++ b/plugins/catalog-backend/src/ingestion/processors/BuiltinKindsEntityProcessor.ts @@ -46,8 +46,7 @@ import { resourceEntityV1alpha1Validator, SystemEntity, systemEntityV1alpha1Validator, - TemplateEntity, - templateEntityV1alpha1Validator, + TemplateEntityV1beta2, templateEntityV1beta2Validator, UserEntity, userEntityV1alpha1Validator, @@ -62,7 +61,6 @@ export class BuiltinKindsEntityProcessor implements CatalogProcessor { resourceEntityV1alpha1Validator, groupEntityV1alpha1Validator, locationEntityV1alpha1Validator, - templateEntityV1alpha1Validator, templateEntityV1beta2Validator, userEntityV1alpha1Validator, systemEntityV1alpha1Validator, @@ -136,7 +134,7 @@ export class BuiltinKindsEntityProcessor implements CatalogProcessor { * Emit relations for the Template kind */ if (entity.kind === 'Template') { - const template = entity as TemplateEntity; + const template = entity as TemplateEntityV1beta2; doEmit( template.spec.owner, { defaultKind: 'Group', defaultNamespace: selfRef.namespace }, diff --git a/plugins/catalog-backend/src/next/processing/DefaultCatalogProcessingOrchestrator.ts b/plugins/catalog-backend/src/next/processing/DefaultCatalogProcessingOrchestrator.ts index bb23b6afb3..235673db03 100644 --- a/plugins/catalog-backend/src/next/processing/DefaultCatalogProcessingOrchestrator.ts +++ b/plugins/catalog-backend/src/next/processing/DefaultCatalogProcessingOrchestrator.ts @@ -124,6 +124,7 @@ export class DefaultCatalogProcessingOrchestrator }; } catch (error) { this.options.logger.warn(error.message); + this.options.logger.debug(error.stack); return { ok: false, errors: collector.results().errors.concat(error), diff --git a/plugins/scaffolder-backend/sample-templates/remote-templates.yaml b/plugins/scaffolder-backend/sample-templates/remote-templates.yaml index 7846a0994e..b89b21d5e3 100644 --- a/plugins/scaffolder-backend/sample-templates/remote-templates.yaml +++ b/plugins/scaffolder-backend/sample-templates/remote-templates.yaml @@ -6,4 +6,4 @@ metadata: spec: type: url targets: - - https://github.com/spotify/cookiecutter-golang/blob/master/template.yaml + # - https://github.com/spotify/cookiecutter-golang/blob/master/template.yaml diff --git a/plugins/scaffolder-backend/src/lib/catalog/CatalogEntityClient.ts b/plugins/scaffolder-backend/src/lib/catalog/CatalogEntityClient.ts index 9f3a754485..430afa5b5d 100644 --- a/plugins/scaffolder-backend/src/lib/catalog/CatalogEntityClient.ts +++ b/plugins/scaffolder-backend/src/lib/catalog/CatalogEntityClient.ts @@ -14,10 +14,7 @@ * limitations under the License. */ -import { - TemplateEntityV1alpha1, - TemplateEntityV1beta2, -} from '@backstage/catalog-model'; +import { TemplateEntityV1beta2 } from '@backstage/catalog-model'; import { CatalogApi } from '@backstage/catalog-client'; import { ConflictError, NotFoundError } from '@backstage/errors'; @@ -35,7 +32,7 @@ export class CatalogEntityClient { async findTemplate( templateName: string, options?: { token?: string }, - ): Promise { + ): Promise { const { items: templates } = (await this.catalogClient.getEntities( { filter: { @@ -44,7 +41,7 @@ export class CatalogEntityClient { }, }, options, - )) as { items: (TemplateEntityV1alpha1 | TemplateEntityV1beta2)[] }; + )) as { items: TemplateEntityV1beta2[] }; if (templates.length !== 1) { if (templates.length > 1) { diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/createBuiltinActions.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/createBuiltinActions.ts index b3757571ff..08d7bbf824 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/createBuiltinActions.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/createBuiltinActions.ts @@ -14,15 +14,15 @@ * limitations under the License. */ -import { UrlReader } from '@backstage/backend-common'; +import { ContainerRunner, UrlReader } from '@backstage/backend-common'; import { CatalogApi } from '@backstage/catalog-client'; import { ScmIntegrations } from '@backstage/integration'; import { Config } from '@backstage/config'; -import { TemplaterBuilder } from '../../stages'; import { - createCatalogRegisterAction, createCatalogWriteAction, + createCatalogRegisterAction, } from './catalog'; + import { createDebugLogAction } from './debug'; import { createFetchCookiecutterAction, createFetchPlainAction } from './fetch'; import { @@ -41,10 +41,16 @@ export const createBuiltinActions = (options: { reader: UrlReader; integrations: ScmIntegrations; catalogClient: CatalogApi; - templaters: TemplaterBuilder; + containerRunner: ContainerRunner; config: Config; }) => { - const { reader, integrations, templaters, catalogClient, config } = options; + const { + reader, + integrations, + containerRunner, + catalogClient, + config, + } = options; return [ createFetchPlainAction({ @@ -54,7 +60,7 @@ export const createBuiltinActions = (options: { createFetchCookiecutterAction({ reader, integrations, - templaters, + containerRunner, }), createPublishGithubAction({ integrations, diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/cookiecutter.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/cookiecutter.ts index 62dfc20125..e5720204c7 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/cookiecutter.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/cookiecutter.ts @@ -14,22 +14,116 @@ * limitations under the License. */ -import { UrlReader, resolveSafeChildPath } from '@backstage/backend-common'; -import { JsonObject } from '@backstage/config'; +import { + ContainerRunner, + UrlReader, + resolveSafeChildPath, +} from '@backstage/backend-common'; +import { JsonObject, JsonValue } from '@backstage/config'; import { InputError } from '@backstage/errors'; import { ScmIntegrations } from '@backstage/integration'; +import commandExists from 'command-exists'; import fs from 'fs-extra'; -import { resolve as resolvePath } from 'path'; -import { TemplaterBuilder, TemplaterValues } from '../../../stages/templater'; +import path, { resolve as resolvePath } from 'path'; +import { Writable } from 'stream'; +import { runCommand } from '../helpers'; import { createTemplateAction } from '../../createTemplateAction'; import { fetchContents } from './helpers'; +export class CookiecutterRunner { + private readonly containerRunner: ContainerRunner; + + constructor({ containerRunner }: { containerRunner: ContainerRunner }) { + this.containerRunner = containerRunner; + } + + private async fetchTemplateCookieCutter( + directory: string, + ): Promise> { + try { + return await fs.readJSON(path.join(directory, 'cookiecutter.json')); + } catch (ex) { + if (ex.code !== 'ENOENT') { + throw ex; + } + + return {}; + } + } + + public async run({ + workspacePath, + values, + logStream, + }: { + workspacePath: string; + values: JsonObject; + logStream: Writable; + }): Promise { + const templateDir = path.join(workspacePath, 'template'); + const intermediateDir = path.join(workspacePath, 'intermediate'); + await fs.ensureDir(intermediateDir); + const resultDir = path.join(workspacePath, 'result'); + + // First lets grab the default cookiecutter.json file + const cookieCutterJson = await this.fetchTemplateCookieCutter(templateDir); + + const { imageName, ...valuesForCookieCutterJson } = values; + const cookieInfo = { + ...cookieCutterJson, + ...valuesForCookieCutterJson, + }; + + await fs.writeJSON(path.join(templateDir, 'cookiecutter.json'), cookieInfo); + + // Directories to bind on container + const mountDirs = { + [templateDir]: '/input', + [intermediateDir]: '/output', + }; + + // the command-exists package returns `true` or throws an error + const cookieCutterInstalled = await commandExists('cookiecutter').catch( + () => false, + ); + if (cookieCutterInstalled) { + await runCommand({ + command: 'cookiecutter', + args: ['--no-input', '-o', intermediateDir, templateDir, '--verbose'], + logStream, + }); + } else { + await this.containerRunner.runContainer({ + imageName: (imageName as string) ?? 'spotify/backstage-cookiecutter', + command: 'cookiecutter', + args: ['--no-input', '-o', '/output', '/input', '--verbose'], + mountDirs, + workingDir: '/input', + // Set the home directory inside the container as something that applications can + // write to, otherwise they will just fail trying to write to / + envVars: { HOME: '/tmp' }, + logStream, + }); + } + + // if cookiecutter was successful, intermediateDir will contain + // exactly one directory. + const [generated] = await fs.readdir(intermediateDir); + + if (generated === undefined) { + throw new Error('No data generated by cookiecutter'); + } + + await fs.move(path.join(intermediateDir, generated), resultDir); + } +} + export function createFetchCookiecutterAction(options: { reader: UrlReader; integrations: ScmIntegrations; - templaters: TemplaterBuilder; + containerRunner: ContainerRunner; }) { - const { reader, templaters, integrations } = options; + const { reader, containerRunner, integrations } = options; return createTemplateAction<{ url: string; @@ -121,9 +215,9 @@ export function createFetchCookiecutterAction(options: { outputPath: templateContentsDir, }); - const cookiecutter = templaters.get('cookiecutter'); + const cookiecutter = new CookiecutterRunner({ containerRunner }); const values = { - ...(ctx.input.values as TemplaterValues), + ...ctx.input.values, _copy_without_render: ctx.input.copyWithoutRender, _extensions: ctx.input.extensions, imageName: ctx.input.imageName, diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/publish/helpers.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/helpers.ts similarity index 77% rename from plugins/scaffolder-backend/src/scaffolder/stages/publish/helpers.ts rename to plugins/scaffolder-backend/src/scaffolder/actions/builtin/helpers.ts index c974c466d4..a024be4f67 100644 --- a/plugins/scaffolder-backend/src/scaffolder/stages/publish/helpers.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/helpers.ts @@ -1,5 +1,9 @@ /* +<<<<<<< HEAD:plugins/scaffolder-backend/src/scaffolder/stages/publish/helpers.ts * Copyright 2020 The Backstage Authors +======= + * Copyright 2021 The Backstage Authors +>>>>>>> breaking: removing alphav1 support for templates:plugins/scaffolder-backend/src/scaffolder/actions/builtin/helpers.ts * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,11 +18,48 @@ * limitations under the License. */ +import { spawn } from 'child_process'; +import { PassThrough, Writable } from 'stream'; import globby from 'globby'; import { Logger } from 'winston'; import { Git } from '@backstage/backend-common'; import { Octokit } from '@octokit/rest'; +export type RunCommandOptions = { + command: string; + args: string[]; + logStream?: Writable; +}; + +export const runCommand = async ({ + command, + args, + logStream = new PassThrough(), +}: RunCommandOptions) => { + await new Promise((resolve, reject) => { + const process = spawn(command, args); + + process.stdout.on('data', stream => { + logStream.write(stream); + }); + + process.stderr.on('data', stream => { + logStream.write(stream); + }); + + process.on('error', error => { + return reject(error); + }); + + process.on('close', code => { + if (code !== 0) { + return reject(`Command ${command} failed, exit code: ${code}`); + } + return resolve(); + }); + }); +}; + export async function initRepoAndPush({ dir, remoteUrl, diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/azure.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/azure.ts index 8b8f6ce3e5..c58dd69424 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/azure.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/azure.ts @@ -16,7 +16,7 @@ import { InputError } from '@backstage/errors'; import { ScmIntegrationRegistry } from '@backstage/integration'; -import { initRepoAndPush } from '../../../stages/publish/helpers'; +import { initRepoAndPush } from '../helpers'; import { GitRepositoryCreateOptions } from 'azure-devops-node-api/interfaces/GitInterfaces'; import { getPersonalAccessTokenHandler, WebApi } from 'azure-devops-node-api'; import { getRepoSourceDirectory, parseRepoUrl } from './util'; diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/bitbucket.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/bitbucket.ts index 1dc80f370c..ffd2e4d6a7 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/bitbucket.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/bitbucket.ts @@ -20,7 +20,7 @@ import { ScmIntegrationRegistry, } from '@backstage/integration'; import fetch from 'cross-fetch'; -import { initRepoAndPush } from '../../../stages/publish/helpers'; +import { initRepoAndPush } from '../helpers'; import { createTemplateAction } from '../../createTemplateAction'; import { getRepoSourceDirectory, parseRepoUrl } from './util'; import { Config } from '@backstage/config'; diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/github.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/github.ts index 9f693a96d8..05301bda85 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/github.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/github.ts @@ -22,7 +22,7 @@ import { Octokit } from '@octokit/rest'; import { enableBranchProtectionOnDefaultRepoBranch, initRepoAndPush, -} from '../../../stages/publish/helpers'; +} from '../helpers'; import { getRepoSourceDirectory, parseRepoUrl } from './util'; import { createTemplateAction } from '../../createTemplateAction'; import { Config } from '@backstage/config'; diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.ts index 1cd77ebe2a..b99d40b1f7 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.ts @@ -17,7 +17,7 @@ import { InputError } from '@backstage/errors'; import { ScmIntegrationRegistry } from '@backstage/integration'; import { Gitlab } from '@gitbeaker/node'; -import { initRepoAndPush } from '../../../stages/publish/helpers'; +import { initRepoAndPush } from '../helpers'; import { getRepoSourceDirectory, parseRepoUrl } from './util'; import { createTemplateAction } from '../../createTemplateAction'; import { Config } from '@backstage/config'; diff --git a/plugins/scaffolder-backend/src/scaffolder/index.ts b/plugins/scaffolder-backend/src/scaffolder/index.ts index 038873b42c..284e372b4c 100644 --- a/plugins/scaffolder-backend/src/scaffolder/index.ts +++ b/plugins/scaffolder-backend/src/scaffolder/index.ts @@ -13,7 +13,4 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -export { createLegacyActions } from './stages/legacy'; -export * from './stages'; -export * from './jobs'; export * from './actions'; diff --git a/plugins/scaffolder-backend/src/scaffolder/jobs/index.ts b/plugins/scaffolder-backend/src/scaffolder/jobs/index.ts deleted file mode 100644 index 8ebffa2026..0000000000 --- a/plugins/scaffolder-backend/src/scaffolder/jobs/index.ts +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -export * from './processor'; -export * from './types'; diff --git a/plugins/scaffolder-backend/src/scaffolder/jobs/logger.test.ts b/plugins/scaffolder-backend/src/scaffolder/jobs/logger.test.ts deleted file mode 100644 index e5d298163b..0000000000 --- a/plugins/scaffolder-backend/src/scaffolder/jobs/logger.test.ts +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -import { makeLogStream } from './logger'; - -describe('Logger', () => { - const mockMeta = { test: 'blob' }; - - it('should return empty log lines by default', async () => { - const { log } = makeLogStream(mockMeta); - - expect(log).toEqual([]); - }); - it('should add lines to the log when using the logger that is returned', async () => { - const { logger, log } = makeLogStream(mockMeta); - - logger.info('TEST LINE'); - logger.warn('WARN LINE'); - - const [first, second] = log; - expect(log.length).toBe(2); - - expect(first).toContain('info'); - expect(first).toContain('TEST LINE'); - - expect(second).toContain('warn'); - expect(second).toContain('WARN LINE'); - }); - - it('should add lines from writing to the stream that is returned', async () => { - const { stream, log } = makeLogStream(mockMeta); - const textLine = 'SOMETHING'; - stream.write(textLine); - - expect(log).toContain(textLine); - }); -}); diff --git a/plugins/scaffolder-backend/src/scaffolder/jobs/logger.ts b/plugins/scaffolder-backend/src/scaffolder/jobs/logger.ts deleted file mode 100644 index 9ffdb33f37..0000000000 --- a/plugins/scaffolder-backend/src/scaffolder/jobs/logger.ts +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -import { PassThrough } from 'stream'; -import * as winston from 'winston'; -import { JsonValue } from '@backstage/config'; - -export const makeLogStream = (meta: Record) => { - const log: string[] = []; - - // Create an empty stream to collect all the log lines into - // one variable for the API. - const stream = new PassThrough(); - stream.on('data', chunk => { - const textValue = chunk.toString().trim(); - if (textValue?.length > 1) log.push(textValue); - }); - - const logger = winston.createLogger({ - level: process.env.LOG_LEVEL || 'info', - format: winston.format.combine( - winston.format.colorize(), - winston.format.timestamp(), - winston.format.simple(), - ), - defaultMeta: meta, - }); - - logger.add(new winston.transports.Stream({ stream })); - - return { - log, - stream, - logger, - }; -}; diff --git a/plugins/scaffolder-backend/src/scaffolder/jobs/processor.test.ts b/plugins/scaffolder-backend/src/scaffolder/jobs/processor.test.ts deleted file mode 100644 index 2bb2171899..0000000000 --- a/plugins/scaffolder-backend/src/scaffolder/jobs/processor.test.ts +++ /dev/null @@ -1,329 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -import { TemplateEntityV1alpha1 } from '@backstage/catalog-model'; -import parseGitUrl from 'git-url-parse'; -import mockFs from 'mock-fs'; -import os from 'os'; -import { RequiredTemplateValues } from '../stages/templater'; -import { makeLogStream } from './logger'; -import { JobProcessor } from './processor'; -import { StageInput } from './types'; - -describe('JobProcessor', () => { - const mockEntity: TemplateEntityV1alpha1 = { - apiVersion: 'backstage.io/v1alpha1', - kind: 'Template', - metadata: { - annotations: { - 'backstage.io/managed-by-location': - 'github:https://github.com/benjdlambert/backstage-graphql-template/blob/master/template.yaml', - }, - name: 'graphql-starter', - title: 'GraphQL Service', - description: - 'A GraphQL starter template for backstage to get you up and running\nthe best practices with GraphQL\n', - uid: '9cf16bad-16e0-4213-b314-c4eec773c50b', - etag: 'ZTkxMjUxMjUtYWY3Yi00MjU2LWFkYWMtZTZjNjU5ZjJhOWM2', - - generation: 1, - }, - spec: { - type: 'website', - templater: 'cookiecutter', - path: './template', - schema: { - $schema: 'http://json-schema.org/draft-07/schema#', - required: ['storePath', 'owner'], - properties: { - owner: { - type: 'string', - title: 'Owner', - description: 'Who is going to own this component', - }, - storePath: { - type: 'string', - title: 'Store path', - description: 'GitHub store path in org/repo format', - }, - }, - }, - owner: 'example@email.com', - }, - }; - - const mockValues: RequiredTemplateValues = { - owner: 'blobby', - storePath: 'https://github.com/backstage/mock-repo', - destination: { - git: parseGitUrl('https://github.com/backstage/mock-repo'), - }, - }; - - const workingDirectory = os.platform() === 'win32' ? 'C:\\tmp' : '/tmp'; - - // NOTE(freben): Without this line, mock-fs makes winston/logform break. - // There are a number of reported issues with logform and its use of dynamic - // strings for imports. It confuses webpack. The basic fix is to trigger - // those imports before mock-fs runs. I wanted to add a mock dir - // 'node_modules': mockFs.passthrough(), but that doesn't seem to be a thing - // in mock-fs 4. - // Probable REAL fix: https://github.com/winstonjs/logform/pull/117 - makeLogStream({}); - - beforeEach(() => { - mockFs({ - [workingDirectory]: mockFs.directory(), - }); - }); - - afterEach(() => { - mockFs.restore(); - }); - - describe('create', () => { - it('creates should create a new job with a unique id', async () => { - const processor = new JobProcessor(workingDirectory); - - const job = processor.create({ - entity: mockEntity, - values: mockValues, - stages: [], - }); - - expect(job.id).toMatch( - /^[0-9A-F]{8}-[0-9A-F]{4}-4[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i, - ); - }); - - it('should setup the correct context for the job', async () => { - const processor = new JobProcessor(workingDirectory); - - const job = processor.create({ - entity: mockEntity, - values: mockValues, - stages: [], - }); - - expect(job.context.entity).toBe(mockEntity); - expect(job.context.values).toBe(mockValues); - }); - - it('should set the status as pending', async () => { - const processor = new JobProcessor(workingDirectory); - - const job = processor.create({ - entity: mockEntity, - values: mockValues, - stages: [], - }); - - expect(job.status).toBe('PENDING'); - }); - - it('should create the correct stages', async () => { - const stages: StageInput[] = [ - { - name: 'Do something cool step 1', - handler: jest.fn(), - }, - { - name: 'Do something cool step 2', - handler: jest.fn(), - }, - ]; - - const processor = new JobProcessor(workingDirectory); - - const job = processor.create({ - entity: mockEntity, - values: mockValues, - stages, - }); - - expect(job.stages).toHaveLength(stages.length); - - for (let i = 0; i < job.stages.length; i++) { - expect(job.stages[i].name).toBe(stages[i].name); - expect(job.stages[i].status).toBe('PENDING'); - } - }); - }); - - describe('get', () => { - it('return undefined for when the job does not exist', () => { - const processor = new JobProcessor(workingDirectory); - expect(processor.get('123')).not.toBeDefined(); - }); - - it('should return the exact same instance of the job when one is created', async () => { - const processor = new JobProcessor(workingDirectory); - const job = processor.create({ - entity: mockEntity, - values: mockValues, - stages: [], - }); - - expect(processor.get(job.id)).toBe(job); - }); - }); - - describe('process', () => { - it('throws an error when the status of the job is not in pending state', async () => { - const processor = new JobProcessor(workingDirectory); - const job = processor.create({ - entity: mockEntity, - values: mockValues, - stages: [], - }); - - job.status = 'STARTED'; - - await expect(processor.run(job)).rejects.toThrow( - /Job is not in a 'PENDING' state/, - ); - }); - - it('will call each of the handlers in the stages', async () => { - const stages: StageInput[] = [ - { - name: 'c/o', - handler: jest.fn(), - }, - { - name: 'g/p', - handler: jest.fn(), - }, - ]; - - const processor = new JobProcessor(workingDirectory); - const job = processor.create({ - entity: mockEntity, - values: mockValues, - stages, - }); - - await processor.run(job); - - for (const stage of stages) { - expect(stage.handler).toHaveBeenCalled(); - } - }); - - it('should set all stages to complete and the job to complete when finishes without errors', async () => { - const stages: StageInput[] = [ - { - name: 'c/o', - handler: jest.fn(), - }, - { - name: 'g/p', - handler: jest.fn(), - }, - ]; - - const processor = new JobProcessor(workingDirectory); - const job = processor.create({ - entity: mockEntity, - values: mockValues, - stages, - }); - - await processor.run(job); - - for (const stage of job.stages) { - expect(stage.status).toBe('COMPLETED'); - } - - expect(job.status).toBe('COMPLETED'); - }); - - it('should merge the return value from previous steps into the context of the next step', async () => { - const stages: StageInput[] = [ - { - name: 'c/o', - handler: jest - .fn() - .mockResolvedValue({ first: 'ben', second: 'lambert' }), - }, - { - name: 'g/p', - handler: jest - .fn() - .mockResolvedValue({ second: 'linus', third: 'lambert' }), - }, - { - name: 'go', - handler: jest.fn(), - }, - ]; - - const processor = new JobProcessor(workingDirectory); - const job = processor.create({ - entity: mockEntity, - values: mockValues, - stages, - }); - - await processor.run(job); - - expect(stages[1].handler).toHaveBeenCalledWith( - expect.objectContaining({ first: 'ben', second: 'lambert' }), - ); - - expect(stages[2].handler).toHaveBeenCalledWith( - expect.objectContaining({ - first: 'ben', - second: 'linus', - third: 'lambert', - }), - ); - }); - - it('should fail the job and the step if one of them fails', async () => { - const fail = new Error('something went wrong here'); - const stages: StageInput[] = [ - { - name: 'c/o', - handler: jest.fn(), - }, - { - name: 'g/p', - handler: jest.fn().mockRejectedValue(fail), - }, - { - name: 'go', - handler: jest.fn(), - }, - ]; - - const processor = new JobProcessor(workingDirectory); - const job = processor.create({ - entity: mockEntity, - values: mockValues, - stages, - }); - - await processor.run(job); - - expect(job.status).toBe('FAILED'); - expect(job.stages[0].status).toBe('COMPLETED'); - expect(job.stages[1].status).toBe('FAILED'); - expect(job.stages[2].status).toBe('PENDING'); - expect(job.error?.message).toBe('something went wrong here'); - expect(job.stages[1].log.join()).toContain('something went wrong here'); - }); - }); -}); diff --git a/plugins/scaffolder-backend/src/scaffolder/jobs/processor.ts b/plugins/scaffolder-backend/src/scaffolder/jobs/processor.ts deleted file mode 100644 index ef603477c1..0000000000 --- a/plugins/scaffolder-backend/src/scaffolder/jobs/processor.ts +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import os from 'os'; -import fs from 'fs-extra'; -import { Processor, Job, StageContext, StageInput } from './types'; -import { TemplateEntityV1alpha1 } from '@backstage/catalog-model'; -import * as uuid from 'uuid'; -import path from 'path'; -import { TemplaterValues } from '../stages/templater'; -import { makeLogStream } from './logger'; -import { Logger } from 'winston'; -import { Config } from '@backstage/config'; - -export type JobAndDirectoryTuple = { - job: Job; - directory: string; -}; - -export class JobProcessor implements Processor { - private readonly workingDirectory: string; - private readonly jobs: Map; - - static async fromConfig({ - config, - logger, - }: { - config: Config; - logger: Logger; - }) { - 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; - } - } else { - workingDirectory = os.tmpdir(); - } - - return new JobProcessor(workingDirectory); - } - - constructor(workingDirectory: string) { - this.workingDirectory = workingDirectory; - this.jobs = new Map(); - } - - create({ - entity, - values, - stages, - }: { - entity: TemplateEntityV1alpha1; - values: TemplaterValues; - stages: StageInput[]; - }): Job { - const id = uuid.v4(); - const { logger, stream } = makeLogStream({ id }); - - const context: StageContext = { - entity, - values, - logger, - logStream: stream, - workspacePath: path.join(this.workingDirectory, id), - }; - - const job: Job = { - id, - context, - stages: stages.map(stage => ({ - handler: stage.handler, - log: [], - name: stage.name, - status: 'PENDING', - })), - status: 'PENDING', - }; - - this.jobs.set(job.id, job); - - return job; - } - - get(id: string): Job | undefined { - return this.jobs.get(id); - } - - async run(job: Job): Promise { - if (job.status !== 'PENDING') { - throw new Error("Job is not in a 'PENDING' state"); - } - - await fs.mkdir(job.context.workspacePath); - - job.status = 'STARTED'; - - try { - for (const stage of job.stages) { - // Create a logger for each stage so we can create separate - // Streams for each step. - const { logger, log, stream } = makeLogStream({ - id: job.id, - stage: stage.name, - }); - // Attach the logger to the stage, and setup some timestamps. - stage.log = log; - stage.startedAt = Date.now(); - - try { - // Run the handler with the context created for the Job and some - // Additional logging helpers. - stage.status = 'STARTED'; - const handlerResponse = await stage.handler({ - ...job.context, - logger, - logStream: stream, - }); - - // If the handler returns something, then let's merge this onto the - // context for the next stage to use as it might be relevant. - if (handlerResponse) { - job.context = { - ...job.context, - ...handlerResponse, - }; - } - - // Complete the current stage - stage.status = 'COMPLETED'; - } catch (error) { - // Log to the current stage the error that occurred and fail the stage. - stage.status = 'FAILED'; - logger.error(`Stage failed with error: ${error.message}`); - logger.debug(error.stack); - // Throw the error so the job can be failed too. - throw error; - } finally { - // Always set the stage end timestamp. - stage.endedAt = Date.now(); - } - } - - // If all went to plan, complete the job. - job.status = 'COMPLETED'; - } catch (error) { - // If something went wrong, fail the job, and set the error property on the job. - job.error = { name: error.name, message: error.message }; - job.status = 'FAILED'; - } finally { - await fs.remove(job.context.workspacePath); - } - } -} diff --git a/plugins/scaffolder-backend/src/scaffolder/jobs/types.ts b/plugins/scaffolder-backend/src/scaffolder/jobs/types.ts deleted file mode 100644 index 84509a6c0f..0000000000 --- a/plugins/scaffolder-backend/src/scaffolder/jobs/types.ts +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -import type { Writable } from 'stream'; -import { TemplateEntityV1alpha1 } from '@backstage/catalog-model'; -import { TemplaterValues } from '../stages/templater'; -import { Logger } from 'winston'; - -// Context will be a mutable object which is passed between stages -// To share data, but also thinking that we can pass in functions here too -// To maybe create sub steps or fail the entire thing, or skip stages down the line. -export type StageContext = { - values: TemplaterValues; - entity: TemplateEntityV1alpha1; - logger: Logger; - logStream: Writable; - workspacePath: string; -} & T; - -export type ProcessorStatus = 'PENDING' | 'STARTED' | 'COMPLETED' | 'FAILED'; - -export interface StageResult extends StageInput { - log: string[]; - status: ProcessorStatus; - startedAt?: number; - endedAt?: number; -} - -export interface StageInput { - name: string; - handler(ctx: StageContext): Promise; -} - -export type Job = { - id: string; - context: StageContext; - status: ProcessorStatus; - stages: StageResult[]; - error?: Error; -}; - -export type Processor = { - create({ - entity, - values, - stages, - }: { - entity: TemplateEntityV1alpha1; - values: TemplaterValues; - stages: StageInput[]; - }): Job; - - get(id: string): Job | undefined; - - run(job: Job): Promise; -}; diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/helpers.test.ts b/plugins/scaffolder-backend/src/scaffolder/stages/helpers.test.ts deleted file mode 100644 index 8f21485f64..0000000000 --- a/plugins/scaffolder-backend/src/scaffolder/stages/helpers.test.ts +++ /dev/null @@ -1,332 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -import { - LOCATION_ANNOTATION, - TemplateEntityV1alpha1, -} from '@backstage/catalog-model'; -import { joinGitUrlPath, parseLocationAnnotation } from './helpers'; - -describe('Helpers', () => { - describe('parseLocationAnnotation', () => { - it('throws an exception when no annotation location', () => { - const mockEntity: TemplateEntityV1alpha1 = { - apiVersion: 'backstage.io/v1alpha1', - kind: 'Template', - metadata: { - annotations: {}, - name: 'graphql-starter', - title: 'GraphQL Service', - description: - 'A GraphQL starter template for backstage to get you up and running\nthe best practices with GraphQL\n', - uid: '9cf16bad-16e0-4213-b314-c4eec773c50b', - etag: 'ZTkxMjUxMjUtYWY3Yi00MjU2LWFkYWMtZTZjNjU5ZjJhOWM2', - generation: 1, - }, - spec: { - type: 'website', - templater: 'cookiecutter', - path: './template', - schema: { - $schema: 'http://json-schema.org/draft-07/schema#', - required: ['storePath', 'owner'], - properties: { - owner: { - type: 'string', - title: 'Owner', - description: 'Who is going to own this component', - }, - storePath: { - type: 'string', - title: 'Store path', - description: 'GitHub store path in org/repo format', - }, - }, - }, - owner: 'team-d@example.com', - }, - }; - - expect(() => parseLocationAnnotation(mockEntity)).toThrow( - expect.objectContaining({ - name: 'InputError', - message: `No location annotation provided in entity: ${mockEntity.metadata.name}`, - }), - ); - }); - - it('should throw an error when the protocol part is not set in the location annotation', () => { - const mockEntity: TemplateEntityV1alpha1 = { - apiVersion: 'backstage.io/v1alpha1', - kind: 'Template', - metadata: { - annotations: { - [LOCATION_ANNOTATION]: - ':https://github.com/o/r/blob/master/template.yaml', - }, - name: 'graphql-starter', - title: 'GraphQL Service', - description: - 'A GraphQL starter template for backstage to get you up and running\nthe best practices with GraphQL\n', - uid: '9cf16bad-16e0-4213-b314-c4eec773c50b', - etag: 'ZTkxMjUxMjUtYWY3Yi00MjU2LWFkYWMtZTZjNjU5ZjJhOWM2', - generation: 1, - }, - spec: { - type: 'website', - templater: 'cookiecutter', - path: './template', - schema: { - $schema: 'http://json-schema.org/draft-07/schema#', - required: ['storePath', 'owner'], - properties: { - owner: { - type: 'string', - title: 'Owner', - description: 'Who is going to own this component', - }, - storePath: { - type: 'string', - title: 'Store path', - description: 'GitHub store path in org/repo format', - }, - }, - }, - owner: 'team-b@example.com', - }, - }; - - expect(() => parseLocationAnnotation(mockEntity)).toThrow( - expect.objectContaining({ - name: 'TypeError', - message: - "Unable to parse location reference ':https://github.com/o/r/blob/master/template.yaml', expected ':', e.g. 'url:https://host/path'", - }), - ); - }); - - it('should throw an error when the location part is not set in the location annotation', () => { - const mockEntity: TemplateEntityV1alpha1 = { - apiVersion: 'backstage.io/v1alpha1', - kind: 'Template', - metadata: { - annotations: { - [LOCATION_ANNOTATION]: 'github:', - }, - name: 'graphql-starter', - title: 'GraphQL Service', - description: - 'A GraphQL starter template for backstage to get you up and running\nthe best practices with GraphQL\n', - uid: '9cf16bad-16e0-4213-b314-c4eec773c50b', - etag: 'ZTkxMjUxMjUtYWY3Yi00MjU2LWFkYWMtZTZjNjU5ZjJhOWM2', - generation: 1, - }, - spec: { - type: 'website', - templater: 'cookiecutter', - path: './template', - schema: { - $schema: 'http://json-schema.org/draft-07/schema#', - required: ['storePath', 'owner'], - properties: { - owner: { - type: 'string', - title: 'Owner', - description: 'Who is going to own this component', - }, - storePath: { - type: 'string', - title: 'Store path', - description: 'GitHub store path in org/repo format', - }, - }, - }, - owner: 'team-a@example.com', - }, - }; - - expect(() => parseLocationAnnotation(mockEntity)).toThrow( - expect.objectContaining({ - name: 'TypeError', - message: `Unable to parse location reference 'github:', expected ':', e.g. 'url:https://host/path'`, - }), - ); - }); - - it('should parse the location and protocol correctly for simple locations', () => { - const mockEntity: TemplateEntityV1alpha1 = { - apiVersion: 'backstage.io/v1alpha1', - kind: 'Template', - metadata: { - annotations: { - [LOCATION_ANNOTATION]: 'file:./path', - }, - name: 'graphql-starter', - title: 'GraphQL Service', - description: - 'A GraphQL starter template for backstage to get you up and running\nthe best pracices with GraphQL\n', - uid: '9cf16bad-16e0-4213-b314-c4eec773c50b', - etag: 'ZTkxMjUxMjUtYWY3Yi00MjU2LWFkYWMtZTZjNjU5ZjJhOWM2', - generation: 1, - }, - spec: { - type: 'website', - templater: 'cookiecutter', - path: './template', - schema: { - $schema: 'http://json-schema.org/draft-07/schema#', - required: ['storePath', 'owner'], - properties: { - owner: { - type: 'string', - title: 'Owner', - description: 'Who is going to own this component', - }, - storePath: { - type: 'string', - title: 'Store path', - description: 'GitHub store path in org/repo format', - }, - }, - }, - owner: 'team-b@example.com', - }, - }; - - expect(parseLocationAnnotation(mockEntity)).toEqual({ - protocol: 'file', - location: './path', - }); - }); - - it('should parse the location and protocol correctly for complex with unescaped locations', () => { - const mockEntity: TemplateEntityV1alpha1 = { - apiVersion: 'backstage.io/v1alpha1', - kind: 'Template', - metadata: { - annotations: { - [LOCATION_ANNOTATION]: 'github:https://lol.com/:something/shello', - }, - name: 'graphql-starter', - title: 'GraphQL Service', - description: - 'A GraphQL starter template for backstage to get you up and running\nthe best practices with GraphQL\n', - uid: '9cf16bad-16e0-4213-b314-c4eec773c50b', - etag: 'ZTkxMjUxMjUtYWY3Yi00MjU2LWFkYWMtZTZjNjU5ZjJhOWM2', - generation: 1, - }, - spec: { - type: 'website', - templater: 'cookiecutter', - path: './template', - schema: { - $schema: 'http://json-schema.org/draft-07/schema#', - required: ['storePath', 'owner'], - properties: { - owner: { - type: 'string', - title: 'Owner', - description: 'Who is going to own this component', - }, - storePath: { - type: 'string', - title: 'Store path', - description: 'GitHub store path in org/repo format', - }, - }, - }, - owner: 'team-c@example.com', - }, - }; - - expect(parseLocationAnnotation(mockEntity)).toEqual({ - protocol: 'github', - location: 'https://lol.com/:something/shello', - }); - }); - }); - - describe('joinGitUrlPath', () => { - it.each([ - [ - 'https://github.com/o/r/blob/master/template.yaml', - 'template', - 'https://github.com/o/r/blob/master/template', - ], - [ - 'https://dev.azure.com/o/p/_git/template-repo?path=%2Ftemplate.yaml', - undefined, - 'https://dev.azure.com/o/p/_git/template-repo?path=%2F', - ], - [ - 'https://dev.azure.com/o/p/_git/template-repo?path=%2Ftemplate.yaml', - 'a', - 'https://dev.azure.com/o/p/_git/template-repo?path=%2Fa', - ], - [ - 'https://dev.azure.com/o/p/_git/template-repo?path=%2Fa%2Ftemplate.yaml', - 'b', - 'https://dev.azure.com/o/p/_git/template-repo?path=%2Fa%2Fb', - ], - [ - 'https://github.com/o/r/blob/master/template.yaml', - undefined, - 'https://github.com/o/r/blob/master', - ], - [ - 'https://github.com/o/r/blob/master/template.yaml', - 'template', - 'https://github.com/o/r/blob/master/template', - ], - [ - 'https://github.com/o/r/blob/master/templates/graphql-starter/template.yaml', - 'template', - 'https://github.com/o/r/blob/master/templates/graphql-starter/template', - ], - [ - 'https://gitlab.com/o/r/-/blob/master/template.yaml', - undefined, - 'https://gitlab.com/o/r/-/blob/master', - ], - [ - 'https://gitlab.com/o/r/-/blob/master/template.yaml', - 'template', - 'https://gitlab.com/o/r/-/blob/master/template', - ], - [ - 'https://gitlab.com/o/r/-/blob/master/a/b/c/template.yaml', - '../../c', - 'https://gitlab.com/o/r/-/blob/master/a/c', - ], - [ - 'https://bitbucket.org/p/r/src/master/a/b/template.yaml', - undefined, - 'https://bitbucket.org/p/r/src/master/a/b', - ], - [ - 'https://bitbucket.org/p/r/src/master/a/b/template.yaml', - 'c', - 'https://bitbucket.org/p/r/src/master/a/b/c', - ], - [ - 'https://bitbucket.org/p/r/src/master/a/b/template.yaml', - '../c', - 'https://bitbucket.org/p/r/src/master/a/c', - ], - ])('should join git url %s with path %s', (url, path, result) => { - expect(joinGitUrlPath(url, path)).toBe(result); - }); - }); -}); diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/helpers.ts b/plugins/scaffolder-backend/src/scaffolder/stages/helpers.ts deleted file mode 100644 index 8085277030..0000000000 --- a/plugins/scaffolder-backend/src/scaffolder/stages/helpers.ts +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { InputError } from '@backstage/errors'; -import { - LOCATION_ANNOTATION, - parseLocationReference, - TemplateEntityV1alpha1, -} from '@backstage/catalog-model'; -import { posix as posixPath } from 'path'; - -export type ParsedLocationAnnotation = { - protocol: 'file' | 'url'; - location: string; -}; - -export const parseLocationAnnotation = ( - entity: TemplateEntityV1alpha1, -): ParsedLocationAnnotation => { - const annotation = entity.metadata.annotations?.[LOCATION_ANNOTATION]; - if (!annotation) { - throw new InputError( - `No location annotation provided in entity: ${entity.metadata.name}`, - ); - } - - const { type, target } = parseLocationReference(annotation); - return { - protocol: type as 'file' | 'url', - location: target, - }; -}; - -export function joinGitUrlPath(repoUrl: string, path?: string): string { - const parsed = new URL(repoUrl); - - if (parsed.hostname.endsWith('azure.com')) { - const templatePath = posixPath.normalize( - posixPath.join( - posixPath.dirname(parsed.searchParams.get('path') || '/'), - path || '.', - ), - ); - parsed.searchParams.set('path', templatePath); - return parsed.toString(); - } - - return new URL(path || '.', repoUrl).toString().replace(/\/$/, ''); -} diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/index.ts b/plugins/scaffolder-backend/src/scaffolder/stages/index.ts deleted file mode 100644 index c6f824a139..0000000000 --- a/plugins/scaffolder-backend/src/scaffolder/stages/index.ts +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -export * from './prepare'; -export * from './publish'; -export * from './templater'; -export * from './helpers'; diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/legacy.ts b/plugins/scaffolder-backend/src/scaffolder/stages/legacy.ts deleted file mode 100644 index efbb241470..0000000000 --- a/plugins/scaffolder-backend/src/scaffolder/stages/legacy.ts +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright 2021 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { createTemplateAction } from '../actions'; -import { FilePreparer, PreparerBuilder } from './prepare'; -import { PublisherBuilder } from './publish'; -import { TemplaterBuilder, TemplaterValues } from './templater'; - -type Options = { - preparers: PreparerBuilder; - templaters: TemplaterBuilder; - publishers: PublisherBuilder; -}; - -export function createLegacyActions(options: Options) { - const { preparers, templaters, publishers } = options; - - return [ - createTemplateAction({ - id: 'legacy:prepare', - async handler(ctx) { - ctx.logger.info('Preparing the skeleton'); - const { protocol, url } = ctx.input; - const preparer = - protocol === 'file' - ? new FilePreparer() - : preparers.get(url as string); - - await preparer.prepare({ - url: url as string, - logger: ctx.logger, - workspacePath: ctx.workspacePath, - }); - }, - }), - createTemplateAction({ - id: 'legacy:template', - async handler(ctx) { - ctx.logger.info('Running the templater'); - const templater = templaters.get(ctx.input.templater as string); - await templater.run({ - workspacePath: ctx.workspacePath, - logStream: ctx.logStream, - values: ctx.input.values as TemplaterValues, - }); - }, - }), - createTemplateAction({ - id: 'legacy:publish', - async handler(ctx) { - const { values } = ctx.input; - if ( - typeof values !== 'object' || - values === null || - Array.isArray(values) - ) { - throw new Error( - `Invalid values passed to publish, got ${typeof values}`, - ); - } - const storePath = values.storePath as unknown; - if (typeof storePath !== 'string') { - throw new Error( - `Invalid store path passed to publish, got ${typeof storePath}`, - ); - } - const owner = values.owner as unknown; - if (typeof owner !== 'string') { - throw new Error( - `Invalid owner passed to publish, got ${typeof owner}`, - ); - } - - const publisher = publishers.get(storePath); - ctx.logger.info('Will now store the template'); - const { remoteUrl, catalogInfoUrl } = await publisher.publish({ - values: { - ...values, - owner, - storePath, - }, - workspacePath: ctx.workspacePath, - logger: ctx.logger, - }); - ctx.output('remoteUrl', remoteUrl); - if (catalogInfoUrl) { - ctx.output('catalogInfoUrl', catalogInfoUrl); - } - }, - }), - ]; -} diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/azure.test.ts b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/azure.test.ts deleted file mode 100644 index 74a21e0833..0000000000 --- a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/azure.test.ts +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import fs from 'fs-extra'; -import os from 'os'; -import path from 'path'; -import { AzurePreparer } from './azure'; -import { getVoidLogger, Git } from '@backstage/backend-common'; - -jest.mock('fs-extra'); - -describe('AzurePreparer', () => { - const mockGitClient = { - clone: jest.fn(), - }; - - const logger = getVoidLogger(); - - jest.spyOn(Git, 'fromAuth').mockReturnValue(mockGitClient as any); - - const preparer = AzurePreparer.fromConfig({ - host: 'dev.azure.com', - token: 'fake-azure-token', - }); - - const workspacePath = os.platform() === 'win32' ? 'C:\\tmp' : '/tmp'; - const checkoutPath = path.resolve(workspacePath, 'checkout'); - const templatePath = path.resolve(workspacePath, 'template'); - const prepareOptions = { - url: - 'https://dev.azure.com/backstage-org/backstage-project/_git/template-repo', - workspacePath, - logger, - }; - - it('calls the clone command with token from integrations config', async () => { - await preparer.prepare(prepareOptions); - expect(Git.fromAuth).toHaveBeenCalledWith({ - logger, - password: 'fake-azure-token', - username: 'notempty', - }); - expect(fs.move).toHaveBeenCalledWith(checkoutPath, templatePath); - expect(fs.rmdir).toHaveBeenCalledWith(path.resolve(templatePath, '.git')); - }); - - it('calls the clone command with the correct arguments for a repository', async () => { - await preparer.prepare(prepareOptions); - - expect(mockGitClient.clone).toHaveBeenCalledWith({ - url: - 'https://dev.azure.com/backstage-org/backstage-project/_git/template-repo', - dir: checkoutPath, - }); - }); - - it('calls the clone command with the correct arguments for a repository with a specified branch', async () => { - await preparer.prepare({ - url: - 'https://dev.azure.com/backstage-org/backstage-project/_git/template-repo?path=%2Ftemplate.yaml&version=GBmaster', - logger, - workspacePath, - }); - - expect(mockGitClient.clone).toHaveBeenCalledWith({ - url: - 'https://dev.azure.com/backstage-org/backstage-project/_git/template-repo', - dir: checkoutPath, - ref: 'master', - }); - }); - - it('calls the clone command with the correct arguments for a repository when no path is provided', async () => { - await preparer.prepare({ - url: - 'https://dev.azure.com/backstage-org/backstage-project/_git/template-repo', - workspacePath, - logger, - }); - - expect(mockGitClient.clone).toHaveBeenCalledWith({ - url: - 'https://dev.azure.com/backstage-org/backstage-project/_git/template-repo', - dir: checkoutPath, - }); - expect(fs.move).toHaveBeenCalledWith(checkoutPath, templatePath); - }); - - it('moves the template from path if it is specified', async () => { - await preparer.prepare({ - url: `https://dev.azure.com/backstage-org/backstage-project/_git/template-repo?path=${encodeURIComponent( - './subdir', - )}`, - logger, - workspacePath, - }); - - expect(fs.move).toHaveBeenCalledWith( - path.resolve(checkoutPath, 'subdir'), - templatePath, - ); - }); -}); diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/azure.ts b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/azure.ts deleted file mode 100644 index a405288f9f..0000000000 --- a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/azure.ts +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -import fs from 'fs-extra'; -import path from 'path'; -import { Git } from '@backstage/backend-common'; -import { PreparerBase, PreparerOptions } from './types'; -import parseGitUrl from 'git-url-parse'; -import { AzureIntegrationConfig } from '@backstage/integration'; - -export class AzurePreparer implements PreparerBase { - static fromConfig(config: AzureIntegrationConfig) { - return new AzurePreparer({ token: config.token }); - } - - constructor(private readonly config: { token?: string }) {} - - async prepare({ url, workspacePath, logger }: PreparerOptions) { - const parsedGitUrl = parseGitUrl(url); - const checkoutPath = path.join(workspacePath, 'checkout'); - const targetPath = path.join(workspacePath, 'template'); - const fullPathToTemplate = path.resolve( - checkoutPath, - parsedGitUrl.filepath ?? '', - ); - - // Username can be anything but the empty string according to: - // https://docs.microsoft.com/en-us/azure/devops/organizations/accounts/use-personal-access-tokens-to-authenticate?view=azure-devops&tabs=preview-page#use-a-pat - const git = this.config.token - ? Git.fromAuth({ - password: this.config.token, - username: 'notempty', - logger, - }) - : Git.fromAuth({ logger }); - - await git.clone({ - url: parsedGitUrl.toString('https'), - ref: parsedGitUrl.ref, - dir: checkoutPath, - }); - - await fs.move(fullPathToTemplate, targetPath); - - try { - await fs.rmdir(path.join(targetPath, '.git')); - } catch { - // Ignore intentionally - } - } -} diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/bitbucket.test.ts b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/bitbucket.test.ts deleted file mode 100644 index 2c4e24fed0..0000000000 --- a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/bitbucket.test.ts +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import fs from 'fs-extra'; -import { BitbucketPreparer } from './bitbucket'; -import { getVoidLogger, Git } from '@backstage/backend-common'; -import path from 'path'; -import os from 'os'; - -jest.mock('fs-extra'); - -describe('BitbucketPreparer', () => { - const logger = getVoidLogger(); - const mockGitClient = { - clone: jest.fn(), - }; - - jest.spyOn(Git, 'fromAuth').mockReturnValue(mockGitClient as any); - - beforeEach(() => { - jest.clearAllMocks(); - }); - - const preparer = BitbucketPreparer.fromConfig({ - host: 'bitbucket.org', - username: 'fake-user', - appPassword: 'fake-password', - }); - - const workspacePath = os.platform() === 'win32' ? 'C:\\tmp' : '/tmp'; - const checkoutPath = path.resolve(workspacePath, 'checkout'); - const templatePath = path.resolve(workspacePath, 'template'); - - const prepareOptions = { - url: 'https://bitbucket.org/backstage-project/backstage-repo', - logger, - workspacePath, - }; - - it('calls the clone command with the correct arguments for a repository', async () => { - await preparer.prepare(prepareOptions); - expect(mockGitClient.clone).toHaveBeenCalledWith({ - url: 'https://bitbucket.org/backstage-project/backstage-repo', - dir: checkoutPath, - ref: expect.any(String), - }); - expect(fs.move).toHaveBeenCalledWith(checkoutPath, templatePath); - expect(fs.rmdir).toHaveBeenCalledWith(path.resolve(templatePath, '.git')); - }); - - it('calls the clone command with the correct arguments if an app password is provided for a repository', async () => { - const preparerCheck = BitbucketPreparer.fromConfig({ - host: 'bitbucket.org', - username: 'fake-user', - appPassword: 'fake-password', - }); - await preparerCheck.prepare(prepareOptions); - - expect(Git.fromAuth).toHaveBeenCalledWith({ - logger, - username: 'fake-user', - password: 'fake-password', - }); - }); - - it('calls the clone command with the correct arguments for a repository when no path is provided', async () => { - await preparer.prepare(prepareOptions); - expect(mockGitClient.clone).toHaveBeenCalledWith({ - url: 'https://bitbucket.org/backstage-project/backstage-repo', - dir: checkoutPath, - ref: expect.any(String), - }); - }); - - it('moves a template subdirectory to checkout if specified', async () => { - await preparer.prepare({ - url: 'https://bitbucket.org/foo/bar/src/master/1/2/3', - logger, - workspacePath, - }); - expect(fs.move).toHaveBeenCalledWith( - path.resolve(checkoutPath, '1', '2', '3'), - templatePath, - ); - }); - - it('calls the clone command with with token for auth method', async () => { - const preparerCheck = BitbucketPreparer.fromConfig({ - host: 'bitbucket.org', - token: 'fake-token', - }); - await preparerCheck.prepare(prepareOptions); - - expect(Git.fromAuth).toHaveBeenCalledWith({ - logger, - username: 'x-token-auth', - password: 'fake-token', - }); - }); -}); diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/bitbucket.ts b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/bitbucket.ts deleted file mode 100644 index 36f6b07750..0000000000 --- a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/bitbucket.ts +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -import fs from 'fs-extra'; -import path from 'path'; -import { Git } from '@backstage/backend-common'; -import { PreparerBase, PreparerOptions } from './types'; -import { BitbucketIntegrationConfig } from '@backstage/integration'; -import parseGitUrl from 'git-url-parse'; - -export class BitbucketPreparer implements PreparerBase { - static fromConfig(config: BitbucketIntegrationConfig) { - return new BitbucketPreparer({ - username: config.username, - token: config.token, - appPassword: config.appPassword, - }); - } - - constructor( - private readonly config: { - username?: string; - token?: string; - appPassword?: string; - }, - ) {} - - async prepare({ url, workspacePath, logger }: PreparerOptions) { - const parsedGitUrl = parseGitUrl(url); - const checkoutPath = path.join(workspacePath, 'checkout'); - const targetPath = path.join(workspacePath, 'template'); - const fullPathToTemplate = path.resolve( - checkoutPath, - parsedGitUrl.filepath ?? '', - ); - - const git = Git.fromAuth({ logger, ...this.getAuth() }); - - await git.clone({ - url: parsedGitUrl.toString('https'), - dir: checkoutPath, - ref: parsedGitUrl.ref, - }); - - await fs.move(fullPathToTemplate, targetPath); - - try { - await fs.rmdir(path.join(targetPath, '.git')); - } catch { - // Ignore intentionally - } - } - - private getAuth(): { username: string; password: string } | undefined { - const { username, token, appPassword } = this.config; - - if (username && appPassword) { - return { username: username, password: appPassword }; - } - - if (token) { - return { - username: 'x-token-auth', - password: token! || appPassword!, - }; - } - - return undefined; - } -} diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/file.test.ts b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/file.test.ts deleted file mode 100644 index 73d944db67..0000000000 --- a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/file.test.ts +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { getVoidLogger } from '@backstage/backend-common'; -import fs from 'fs-extra'; -import { FilePreparer } from './file'; -import os from 'os'; -import path from 'path'; - -jest.mock('fs-extra'); - -describe('File preparer', () => { - it('prepares templates from a file path', async () => { - const logger = getVoidLogger(); - const preparer = new FilePreparer(); - const root = os.platform() === 'win32' ? 'C:\\' : '/'; - const workspacePath = path.join(root, 'tmp'); - const targetPath = path.resolve(workspacePath, 'template'); - - await preparer.prepare({ - url: `file://${root}path/to/template`, - logger, - workspacePath, - }); - expect(fs.copy).toHaveBeenCalledWith( - path.join(root, 'path', 'to', 'template'), - targetPath, - { - recursive: true, - }, - ); - expect(fs.ensureDir).toHaveBeenCalledWith(targetPath); - - await expect( - preparer.prepare({ - url: 'http://not/file/path', - logger, - workspacePath, - }), - ).rejects.toThrow( - "Wrong location protocol, should be 'file', http://not/file/path", - ); - - if (os.platform() === 'win32') { - // eslint-disable-next-line jest/no-conditional-expect - await expect( - preparer.prepare({ - url: 'file:///unix/file/path', - logger, - workspacePath, - }), - ).rejects.toThrow('File URL path must be absolute'); - } else { - // eslint-disable-next-line jest/no-conditional-expect - await expect( - preparer.prepare({ - url: 'file://not/full/path', - logger, - workspacePath, - }), - ).rejects.toThrow( - `File URL host must be "localhost" or empty on ${os.platform()}`, - ); - } - }); -}); diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/file.ts b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/file.ts deleted file mode 100644 index 92ee93511c..0000000000 --- a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/file.ts +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -import fs from 'fs-extra'; -import path from 'path'; -import { fileURLToPath } from 'url'; -import { InputError } from '@backstage/errors'; -import { PreparerBase, PreparerOptions } from './types'; - -export class FilePreparer implements PreparerBase { - async prepare({ url, workspacePath }: PreparerOptions) { - if (!url.startsWith('file://')) { - throw new InputError(`Wrong location protocol, should be 'file', ${url}`); - } - - const templatePath = fileURLToPath(url); - - const targetDir = path.join(workspacePath, 'template'); - await fs.ensureDir(targetDir); - - await fs.copy(templatePath, targetDir, { - recursive: true, - }); - } -} diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/github.test.ts b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/github.test.ts deleted file mode 100644 index 0438e28f01..0000000000 --- a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/github.test.ts +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import fs from 'fs-extra'; -import os from 'os'; -import path from 'path'; -import { GithubPreparer } from './github'; -import { getVoidLogger, Git } from '@backstage/backend-common'; - -jest.mock('fs-extra'); - -describe('GitHubPreparer', () => { - const workspacePath = os.platform() === 'win32' ? 'C:\\tmp' : '/tmp'; - const checkoutPath = path.resolve(workspacePath, 'checkout'); - const templatePath = path.resolve(workspacePath, 'template'); - - const mockGitClient = { - clone: jest.fn(), - }; - const logger = getVoidLogger(); - - jest.spyOn(Git, 'fromAuth').mockReturnValue(mockGitClient as any); - - beforeEach(() => { - jest.clearAllMocks(); - }); - - const preparer = GithubPreparer.fromConfig({ - host: 'github.com', - token: 'fake-token', - }); - - it('calls the clone command with the correct arguments for a repository', async () => { - await preparer.prepare({ - url: - 'https://github.com/benjdlambert/backstage-graphql-template/blob/master/templates/graphql-starter/template', - logger, - workspacePath, - }); - - expect(mockGitClient.clone).toHaveBeenCalledWith({ - url: 'https://github.com/benjdlambert/backstage-graphql-template', - dir: checkoutPath, - ref: expect.any(String), - }); - expect(fs.move).toHaveBeenCalledWith( - path.resolve(checkoutPath, 'templates', 'graphql-starter', 'template'), - templatePath, - ); - expect(fs.rmdir).toHaveBeenCalledWith(path.resolve(templatePath, '.git')); - }); - - it('calls the clone command with the correct arguments for a repository when no path is provided', async () => { - await preparer.prepare({ - url: - 'https://github.com/benjdlambert/backstage-graphql-template/blob/master', - logger, - workspacePath, - }); - - expect(mockGitClient.clone).toHaveBeenCalledWith({ - url: 'https://github.com/benjdlambert/backstage-graphql-template', - dir: checkoutPath, - ref: 'master', - }); - expect(fs.move).toHaveBeenCalledWith(checkoutPath, templatePath); - expect(fs.rmdir).toHaveBeenCalledWith(path.resolve(templatePath, '.git')); - }); - - it('calls the clone command with token', async () => { - await preparer.prepare({ - url: - 'https://github.com/benjdlambert/backstage-graphql-template/blob/master', - logger, - workspacePath, - }); - - expect(Git.fromAuth).toHaveBeenCalledWith({ - logger, - username: 'x-access-token', - password: 'fake-token', - }); - }); -}); diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/github.ts b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/github.ts deleted file mode 100644 index dec7fc06c2..0000000000 --- a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/github.ts +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -import fs from 'fs-extra'; -import path from 'path'; -import { Git } from '@backstage/backend-common'; -import { PreparerBase, PreparerOptions } from './types'; -import parseGitUrl from 'git-url-parse'; -import { - GitHubIntegrationConfig, - GithubCredentialsProvider, -} from '@backstage/integration'; - -export class GithubPreparer implements PreparerBase { - static fromConfig(config: GitHubIntegrationConfig) { - const credentialsProvider = GithubCredentialsProvider.create(config); - return new GithubPreparer({ credentialsProvider }); - } - - constructor( - private readonly config: { credentialsProvider: GithubCredentialsProvider }, - ) {} - - async prepare({ url, workspacePath, logger }: PreparerOptions) { - const parsedGitUrl = parseGitUrl(url); - const checkoutPath = path.join(workspacePath, 'checkout'); - const targetPath = path.join(workspacePath, 'template'); - const fullPathToTemplate = path.resolve( - checkoutPath, - parsedGitUrl.filepath ?? '', - ); - - const { token } = await this.config.credentialsProvider.getCredentials({ - url, - }); - - const git = token - ? Git.fromAuth({ - username: 'x-access-token', - password: token, - logger, - }) - : Git.fromAuth({ logger }); - - await git.clone({ - url: parsedGitUrl.toString('https'), - dir: checkoutPath, - ref: parsedGitUrl.ref, - }); - - await fs.move(fullPathToTemplate, targetPath); - - try { - await fs.rmdir(path.join(targetPath, '.git')); - } catch { - // Ignore intentionally - } - } -} diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/gitlab.test.ts b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/gitlab.test.ts deleted file mode 100644 index fa76c74bd7..0000000000 --- a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/gitlab.test.ts +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -import fs from 'fs-extra'; -import os from 'os'; -import path from 'path'; -import { GitlabPreparer } from './gitlab'; -import { getVoidLogger, Git } from '@backstage/backend-common'; - -jest.mock('fs-extra'); - -describe('GitLabPreparer', () => { - const workspacePath = os.platform() === 'win32' ? 'C:\\tmp' : '/tmp'; - const checkoutPath = path.resolve(workspacePath, 'checkout'); - const templatePath = path.resolve(workspacePath, 'template'); - - const mockGitClient = { - clone: jest.fn(), - }; - const logger = getVoidLogger(); - - jest.spyOn(Git, 'fromAuth').mockReturnValue(mockGitClient as any); - - beforeEach(() => { - jest.clearAllMocks(); - }); - const preparer = GitlabPreparer.fromConfig({ - host: '', - token: 'fake-token', - apiBaseUrl: '', - baseUrl: '', - }); - - it(`calls the clone command with the correct arguments for a repository`, async () => { - await preparer.prepare({ - url: - 'https://gitlab.com/benjdlambert/backstage-graphql-template/-/blob/master', - logger, - workspacePath, - }); - - expect(mockGitClient.clone).toHaveBeenCalledWith({ - url: 'https://gitlab.com/benjdlambert/backstage-graphql-template.git', - dir: checkoutPath, - ref: expect.any(String), - }); - - expect(Git.fromAuth).toHaveBeenCalledWith({ - logger, - username: 'oauth2', - password: 'fake-token', - }); - - expect(fs.move).toHaveBeenCalledWith(checkoutPath, templatePath); - expect(fs.rmdir).toHaveBeenCalledWith(path.resolve(templatePath, '.git')); - }); - - it(`clones the template from a sub directory if specified`, async () => { - await preparer.prepare({ - url: - 'https://gitlab.com/benjdlambert/backstage-graphql-template/-/blob/master/1/2/3', - logger, - workspacePath, - }); - expect(fs.move).toHaveBeenCalledWith( - path.resolve(checkoutPath, '1', '2', '3'), - templatePath, - ); - }); -}); diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/gitlab.ts b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/gitlab.ts deleted file mode 100644 index 582214606b..0000000000 --- a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/gitlab.ts +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -import { Git } from '@backstage/backend-common'; -import { GitLabIntegrationConfig } from '@backstage/integration'; -import fs from 'fs-extra'; -import parseGitUrl from 'git-url-parse'; -import path from 'path'; -import { PreparerBase, PreparerOptions } from './types'; - -export class GitlabPreparer implements PreparerBase { - static fromConfig(config: GitLabIntegrationConfig) { - return new GitlabPreparer({ token: config.token }); - } - - constructor(private readonly config: { token?: string }) {} - - async prepare({ url, workspacePath, logger }: PreparerOptions) { - const parsedGitUrl = parseGitUrl(url); - const checkoutPath = path.join(workspacePath, 'checkout'); - const targetPath = path.join(workspacePath, 'template'); - const fullPathToTemplate = path.resolve( - checkoutPath, - parsedGitUrl.filepath ?? '', - ); - parsedGitUrl.git_suffix = true; - - const git = this.config.token - ? Git.fromAuth({ - password: this.config.token, - username: 'oauth2', - logger, - }) - : Git.fromAuth({ logger }); - - await git.clone({ - url: parsedGitUrl.toString('https'), - dir: checkoutPath, - ref: parsedGitUrl.ref, - }); - - await fs.move(fullPathToTemplate, targetPath); - - try { - await fs.rmdir(path.join(targetPath, '.git')); - } catch { - // Ignore intentionally - } - } -} diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/index.ts b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/index.ts deleted file mode 100644 index 060b99b3a8..0000000000 --- a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/index.ts +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -export { AzurePreparer } from './azure'; -export { BitbucketPreparer } from './bitbucket'; -export { FilePreparer } from './file'; -export { GithubPreparer } from './github'; -export { GitlabPreparer } from './gitlab'; -export { Preparers } from './preparers'; -export type { PreparerBase, PreparerBuilder, PreparerOptions } from './types'; diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/preparers.test.ts b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/preparers.test.ts deleted file mode 100644 index 20dfad924b..0000000000 --- a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/preparers.test.ts +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { GithubPreparer } from './github'; -import { Preparers } from './preparers'; - -describe('Preparers', () => { - it('should return the correct preparer based on the hostname', async () => { - const preparer = await GithubPreparer.fromConfig({ - host: 'github.com', - apiBaseUrl: 'lols', - token: 'something else yo', - }); - - const preparers = new Preparers(); - preparers.register('github.com', preparer); - - expect( - preparers.get('https://github.com/please/find/me/something/from/github'), - ).toBe(preparer); - }); - - it('should throw an error if there is nothing that will match the url provided', async () => { - const preparer = await GithubPreparer.fromConfig({ - host: 'github.com', - apiBaseUrl: 'lols', - token: 'something else yo', - }); - - const preparers = new Preparers(); - preparers.register('github.com', preparer); - - expect(() => preparers.get('https://404.com')).toThrow( - `Unable to find a preparer for URL: https://404.com. Please make sure to register this host under an integration in app-config`, - ); - }); -}); diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/preparers.ts b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/preparers.ts deleted file mode 100644 index 98ca984c17..0000000000 --- a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/preparers.ts +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { Config } from '@backstage/config'; -import { PreparerBase, PreparerBuilder } from './types'; -import { Logger } from 'winston'; - -import { GitlabPreparer } from './gitlab'; -import { AzurePreparer } from './azure'; -import { GithubPreparer } from './github'; -import { BitbucketPreparer } from './bitbucket'; -import { ScmIntegrations } from '@backstage/integration'; - -export class Preparers implements PreparerBuilder { - private preparerMap = new Map(); - - register(host: string, preparer: PreparerBase) { - this.preparerMap.set(host, preparer); - } - - get(url: string): PreparerBase { - const preparer = this.preparerMap.get(new URL(url).host); - if (!preparer) { - throw new Error( - `Unable to find a preparer for URL: ${url}. Please make sure to register this host under an integration in app-config`, - ); - } - return preparer; - } - - static async fromConfig( - config: Config, - // eslint-disable-next-line - _: { logger: Logger }, - ): Promise { - const preparers = new Preparers(); - const scm = ScmIntegrations.fromConfig(config); - for (const integration of scm.azure.list()) { - preparers.register( - integration.config.host, - AzurePreparer.fromConfig(integration.config), - ); - } - - for (const integration of scm.github.list()) { - preparers.register( - integration.config.host, - GithubPreparer.fromConfig(integration.config), - ); - } - - for (const integration of scm.gitlab.list()) { - preparers.register( - integration.config.host, - GitlabPreparer.fromConfig(integration.config), - ); - } - - for (const integration of scm.bitbucket.list()) { - preparers.register( - integration.config.host, - BitbucketPreparer.fromConfig(integration.config), - ); - } - - return preparers; - } -} diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/types.ts b/plugins/scaffolder-backend/src/scaffolder/stages/prepare/types.ts deleted file mode 100644 index 1b6b4380f7..0000000000 --- a/plugins/scaffolder-backend/src/scaffolder/stages/prepare/types.ts +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -import { Logger } from 'winston'; - -export type PreparerOptions = { - /** - * Full URL to the directory containg template data - */ - url: string; - /** - * The workspace path that will eventually be the the root of the new repo - */ - workspacePath: string; - logger: Logger; -}; - -export interface PreparerBase { - /** - * Prepare a directory with contents from the remote location - */ - prepare(opts: PreparerOptions): Promise; -} - -export type PreparerBuilder = { - register(host: string, preparer: PreparerBase): void; - get(url: string): PreparerBase; -}; diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/publish/azure.test.ts b/plugins/scaffolder-backend/src/scaffolder/stages/publish/azure.test.ts deleted file mode 100644 index 3eecab33b5..0000000000 --- a/plugins/scaffolder-backend/src/scaffolder/stages/publish/azure.test.ts +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -jest.mock('./helpers'); - -jest.mock('azure-devops-node-api', () => ({ - WebApi: jest.fn(), - getPersonalAccessTokenHandler: jest.fn().mockReturnValue(() => {}), -})); - -import os from 'os'; -import { resolve } from 'path'; -import { AzurePublisher } from './azure'; -import { WebApi } from 'azure-devops-node-api'; -import * as helpers from './helpers'; -import { getVoidLogger } from '@backstage/backend-common'; - -describe('Azure Publisher', () => { - const logger = getVoidLogger(); - - const workspacePath = os.platform() === 'win32' ? 'C:\\tmp' : '/tmp'; - const resultPath = resolve(workspacePath, 'result'); - - describe('publish: createRemoteInAzure', () => { - it('should use azure-devops-node-api to create a repo in the given project', async () => { - const mockGitClient = { - createRepository: jest.fn(), - }; - const mockGitApi = { - getGitApi: jest.fn().mockReturnValue(mockGitClient), - }; - - ((WebApi as unknown) as jest.Mock).mockImplementation(() => mockGitApi); - - const publisher = await AzurePublisher.fromConfig({ - host: 'dev.azure.com', - token: 'fake-azure-token', - }); - - mockGitClient.createRepository.mockResolvedValue({ - remoteUrl: 'https://dev.azure.com/organization/project/_git/repo', - } as { remoteUrl: string }); - - const result = await publisher!.publish({ - values: { - storePath: 'https://dev.azure.com/organisation/project/_git/repo', - owner: 'bob', - }, - workspacePath, - logger, - }); - - expect(WebApi).toHaveBeenCalledWith( - 'https://dev.azure.com/organisation', - expect.any(Function), - ); - - expect(result).toEqual({ - remoteUrl: 'https://dev.azure.com/organization/project/_git/repo', - catalogInfoUrl: - 'https://dev.azure.com/organization/project/_git/repo?path=%2Fcatalog-info.yaml', - }); - expect(mockGitClient.createRepository).toHaveBeenCalledWith( - { - name: 'repo', - }, - 'project', - ); - expect(helpers.initRepoAndPush).toHaveBeenCalledWith({ - dir: resultPath, - remoteUrl: 'https://dev.azure.com/organization/project/_git/repo', - auth: { username: 'notempty', password: 'fake-azure-token' }, - logger, - }); - }); - }); -}); diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/publish/azure.ts b/plugins/scaffolder-backend/src/scaffolder/stages/publish/azure.ts deleted file mode 100644 index 921c139a2e..0000000000 --- a/plugins/scaffolder-backend/src/scaffolder/stages/publish/azure.ts +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { PublisherBase, PublisherOptions, PublisherResult } from './types'; -import { IGitApi } from 'azure-devops-node-api/GitApi'; -import { GitRepositoryCreateOptions } from 'azure-devops-node-api/interfaces/GitInterfaces'; -import { initRepoAndPush } from './helpers'; -import { AzureIntegrationConfig } from '@backstage/integration'; -import parseGitUrl from 'git-url-parse'; -import { getPersonalAccessTokenHandler, WebApi } from 'azure-devops-node-api'; -import path from 'path'; - -export class AzurePublisher implements PublisherBase { - static async fromConfig(config: AzureIntegrationConfig) { - if (!config.token) { - return undefined; - } - return new AzurePublisher({ token: config.token }); - } - - constructor(private readonly config: { token: string }) {} - - async publish({ - values, - workspacePath, - logger, - }: PublisherOptions): Promise { - const { owner, name, organization, resource } = parseGitUrl( - values.storePath, - ); - const authHandler = getPersonalAccessTokenHandler(this.config.token); - const webApi = new WebApi( - `https://${resource}/${organization}`, - authHandler, - ); - const client = await webApi.getGitApi(); - - const remoteUrl = await this.createRemote({ - project: owner, - name, - client, - }); - - const catalogInfoUrl = `${remoteUrl}?path=%2Fcatalog-info.yaml`; - - await initRepoAndPush({ - dir: path.join(workspacePath, 'result'), - remoteUrl, - auth: { - username: 'notempty', - password: this.config.token, - }, - logger, - }); - - return { remoteUrl, catalogInfoUrl }; - } - - private async createRemote(opts: { - name: string; - project: string; - client: IGitApi; - }) { - const { name, project, client } = opts; - const createOptions: GitRepositoryCreateOptions = { name }; - const repo = await client.createRepository(createOptions, project); - - return repo.remoteUrl || ''; - } -} diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/publish/bitbucket.test.ts b/plugins/scaffolder-backend/src/scaffolder/stages/publish/bitbucket.test.ts deleted file mode 100644 index a3f02e2c89..0000000000 --- a/plugins/scaffolder-backend/src/scaffolder/stages/publish/bitbucket.test.ts +++ /dev/null @@ -1,228 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -jest.mock('./helpers'); - -import os from 'os'; -import { resolve } from 'path'; -import { BitbucketPublisher } from './bitbucket'; -import { initRepoAndPush } from './helpers'; -import { getVoidLogger } from '@backstage/backend-common'; -import { rest } from 'msw'; -import { setupServer } from 'msw/node'; -import { msw } from '@backstage/test-utils'; - -describe('Bitbucket Publisher', () => { - const logger = getVoidLogger(); - const server = setupServer(); - msw.setupDefaultHandlers(server); - - beforeEach(() => { - jest.clearAllMocks(); - }); - - const workspacePath = os.platform() === 'win32' ? 'C:\\tmp' : '/tmp'; - const resultPath = resolve(workspacePath, 'result'); - - describe('publish: createRemoteInBitbucketCloud', () => { - it('should create repo in bitbucket cloud', async () => { - server.use( - rest.post( - 'https://api.bitbucket.org/2.0/repositories/project/repo', - (_, res, ctx) => - res( - ctx.status(200), - ctx.set('Content-Type', 'application/json'), - ctx.json({ - links: { - html: { - href: 'https://bitbucket.org/project/repo', - }, - clone: [ - { - name: 'https', - href: 'https://bitbucket.org/project/repo', - }, - ], - }, - }), - ), - ), - ); - - const publisher = await BitbucketPublisher.fromConfig( - { - host: 'bitbucket.org', - username: 'fake-user', - appPassword: 'fake-token', - }, - { repoVisibility: 'private' }, - ); - - const result = await publisher.publish({ - values: { - storePath: 'https://bitbucket.org/project/repo', - owner: 'bob', - }, - workspacePath, - logger: logger, - }); - - expect(result).toEqual({ - remoteUrl: 'https://bitbucket.org/project/repo', - catalogInfoUrl: - 'https://bitbucket.org/project/repo/src/master/catalog-info.yaml', - }); - - expect(initRepoAndPush).toHaveBeenCalledWith({ - dir: resultPath, - remoteUrl: 'https://bitbucket.org/project/repo', - auth: { username: 'fake-user', password: 'fake-token' }, - logger: logger, - }); - }); - }); - - describe('publish: createRemoteInBitbucketServer', () => { - it('should throw an error if no username present', async () => { - await expect( - BitbucketPublisher.fromConfig( - { - host: 'bitbucket.mycompany.com', - token: 'fake-token', - }, - { repoVisibility: 'private' }, - ), - ).rejects.toThrow( - 'Bitbucket server requires the username to be set in your config', - ); - }); - it('should create repo in bitbucket server', async () => { - server.use( - rest.post( - 'https://bitbucket.mycompany.com/rest/api/1.0/projects/project/repos', - (_, res, ctx) => - res( - ctx.status(201), - ctx.set('Content-Type', 'application/json'), - ctx.json({ - links: { - self: [ - { - href: - 'https://bitbucket.mycompany.com/projects/project/repos/repo', - }, - ], - clone: [ - { - name: 'http', - href: 'https://bitbucket.mycompany.com/scm/project/repo', - }, - ], - }, - }), - ), - ), - ); - - const publisher = await BitbucketPublisher.fromConfig( - { - host: 'bitbucket.mycompany.com', - username: 'foo', - token: 'fake-token', - }, - { repoVisibility: 'private' }, - ); - - const result = await publisher.publish({ - values: { - storePath: 'https://bitbucket.mycompany.com/project/repo', - owner: 'bob', - }, - workspacePath, - logger: logger, - }); - - expect(result).toEqual({ - remoteUrl: 'https://bitbucket.mycompany.com/scm/project/repo', - catalogInfoUrl: - 'https://bitbucket.mycompany.com/projects/project/repos/repo/catalog-info.yaml', - }); - - expect(initRepoAndPush).toHaveBeenCalledWith({ - dir: resultPath, - remoteUrl: 'https://bitbucket.mycompany.com/scm/project/repo', - auth: { username: 'foo', password: 'fake-token' }, - logger: logger, - }); - }); - }); - - it('should use apiBaseUrl to create the repository if it is set', async () => { - server.use( - rest.post( - 'https://bitbucket.mycompany.com/bitbucket/rest/api/1.0/projects/project/repos', - (_, res, ctx) => - res( - ctx.status(201), - ctx.set('Content-Type', 'application/json'), - ctx.json({ - links: { - self: [ - { - href: - 'https://bitbucket.mycompany.com/bitbucket/projects/project/repos/repo', - }, - ], - clone: [ - { - name: 'http', - href: - 'https://bitbucket.mycompany.com/bitbucket/scm/project/repo', - }, - ], - }, - }), - ), - ), - ); - - const publisher = await BitbucketPublisher.fromConfig( - { - host: 'bitbucket.mycompany.com', - username: 'foo', - token: 'fake-token', - apiBaseUrl: 'https://bitbucket.mycompany.com/bitbucket/rest/api/1.0', - }, - { repoVisibility: 'private' }, - ); - - const result = await publisher.publish({ - values: { - storePath: 'https://bitbucket.mycompany.com/project/repo', - owner: 'bob', - }, - workspacePath, - logger: logger, - }); - - expect(result).toEqual({ - remoteUrl: 'https://bitbucket.mycompany.com/bitbucket/scm/project/repo', - catalogInfoUrl: - 'https://bitbucket.mycompany.com/bitbucket/projects/project/repos/repo/catalog-info.yaml', - }); - }); -}); diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/publish/bitbucket.ts b/plugins/scaffolder-backend/src/scaffolder/stages/publish/bitbucket.ts deleted file mode 100644 index a85518eeae..0000000000 --- a/plugins/scaffolder-backend/src/scaffolder/stages/publish/bitbucket.ts +++ /dev/null @@ -1,207 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { PublisherBase, PublisherOptions, PublisherResult } from './types'; -import { initRepoAndPush } from './helpers'; -import fetch from 'cross-fetch'; -import { BitbucketIntegrationConfig } from '@backstage/integration'; -import parseGitUrl from 'git-url-parse'; -import path from 'path'; - -export type RepoVisibilityOptions = 'private' | 'public'; - -// TODO(blam): We should probably start to use a bitbucket client here that we can change -// the baseURL to point at on-prem or public bitbucket versions like we do for -// github and ghe. There's to much logic and not enough types here for us to say that this way is better than using -// a supported bitbucket client if one exists. -export class BitbucketPublisher implements PublisherBase { - static async fromConfig( - config: BitbucketIntegrationConfig, - { repoVisibility }: { repoVisibility: RepoVisibilityOptions }, - ) { - if (config.host !== 'bitbucket.org' && !config.username) - throw new Error( - 'Bitbucket server requires the username to be set in your config', - ); - - return new BitbucketPublisher({ - host: config.host, - token: config.token, - appPassword: config.appPassword, - username: config.username, - apiBaseUrl: config.apiBaseUrl, - repoVisibility, - }); - } - - constructor( - private readonly config: { - host: string; - token?: string; - appPassword?: string; - username?: string; - apiBaseUrl?: string; - repoVisibility: RepoVisibilityOptions; - }, - ) {} - - async publish({ - values, - workspacePath, - logger, - }: PublisherOptions): Promise { - const { owner: project, name } = parseGitUrl(values.storePath); - - const description = values.description as string; - const result = await this.createRemote({ - project, - name, - description, - }); - - await initRepoAndPush({ - dir: path.join(workspacePath, 'result'), - remoteUrl: result.remoteUrl, - auth: { - username: this.config.username ? this.config.username : 'x-token-auth', - password: this.config.appPassword - ? this.config.appPassword - : this.config.token ?? '', - }, - logger, - }); - return result; - } - - private async createRemote(opts: { - project: string; - name: string; - description: string; - }): Promise { - if (this.config.host === 'bitbucket.org') { - return this.createBitbucketCloudRepository(opts); - } - return this.createBitbucketServerRepository(opts); - } - - private async createBitbucketCloudRepository(opts: { - project: string; - name: string; - description: string; - }): Promise { - const { project, name, description } = opts; - - let response: Response; - - const options: RequestInit = { - method: 'POST', - body: JSON.stringify({ - scm: 'git', - description: description, - is_private: this.config.repoVisibility === 'private', - }), - headers: { - Authorization: this.getAuthorizationHeader(), - 'Content-Type': 'application/json', - }, - }; - try { - response = await fetch( - `https://api.bitbucket.org/2.0/repositories/${project}/${name}`, - options, - ); - } catch (e) { - throw new Error(`Unable to create repository, ${e}`); - } - if (response.status === 200) { - const r = await response.json(); - let remoteUrl = ''; - for (const link of r.links.clone) { - if (link.name === 'https') { - remoteUrl = link.href; - } - } - - // TODO use the urlReader to get the default branch - const catalogInfoUrl = `${r.links.html.href}/src/master/catalog-info.yaml`; - return { remoteUrl, catalogInfoUrl }; - } - throw new Error(`Not a valid response code ${await response.text()}`); - } - - private getAuthorizationHeader(): string { - if (this.config.username && this.config.appPassword) { - const buffer = Buffer.from( - `${this.config.username}:${this.config.appPassword}`, - 'utf8', - ); - - return `Basic ${buffer.toString('base64')}`; - } - - if (this.config.token) { - return `Bearer ${this.config.token}`; - } - - throw new Error( - `Authorization has not been provided for Bitbucket. Please add either username + appPassword or token to the Integrations config`, - ); - } - - private async createBitbucketServerRepository(opts: { - project: string; - name: string; - description: string; - }): Promise { - const { project, name, description } = opts; - - let response: Response; - const options: RequestInit = { - method: 'POST', - body: JSON.stringify({ - name: name, - description: description, - public: this.config.repoVisibility === 'public', - }), - headers: { - Authorization: this.getAuthorizationHeader(), - 'Content-Type': 'application/json', - }, - }; - - try { - const baseUrl = this.config.apiBaseUrl - ? this.config.apiBaseUrl - : `https://${this.config.host}/rest/api/1.0`; - - response = await fetch(`${baseUrl}/projects/${project}/repos`, options); - } catch (e) { - throw new Error(`Unable to create repository, ${e}`); - } - if (response.status === 201) { - const r = await response.json(); - let remoteUrl = ''; - for (const link of r.links.clone) { - if (link.name === 'http') { - remoteUrl = link.href; - } - } - const catalogInfoUrl = `${r.links.self[0].href}/catalog-info.yaml`; - return { remoteUrl, catalogInfoUrl }; - } - throw new Error(`Not a valid response code ${await response.text()}`); - } -} diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/publish/github.test.ts b/plugins/scaffolder-backend/src/scaffolder/stages/publish/github.test.ts deleted file mode 100644 index fd4256dc86..0000000000 --- a/plugins/scaffolder-backend/src/scaffolder/stages/publish/github.test.ts +++ /dev/null @@ -1,315 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -jest.mock('@octokit/rest'); -jest.mock('./helpers'); - -import os from 'os'; -import { resolve } from 'path'; - -import { getVoidLogger } from '@backstage/backend-common'; -import { Octokit, RestEndpointMethodTypes } from '@octokit/rest'; -import { GithubPublisher } from './github'; -import { initRepoAndPush } from './helpers'; - -const { mockGithubClient } = require('@octokit/rest') as { - mockGithubClient: { - repos: jest.Mocked; - users: jest.Mocked; - teams: jest.Mocked; - }; -}; - -describe('GitHub Publisher', () => { - const logger = getVoidLogger(); - beforeEach(() => { - jest.clearAllMocks(); - }); - - const workspacePath = os.platform() === 'win32' ? 'C:\\tmp' : '/tmp'; - const resultPath = resolve(workspacePath, 'result'); - - describe('with public repo visibility', () => { - describe('publish: createRemoteInGithub', () => { - it('should use octokit to create a repo in an organisation if the organisation property is set', async () => { - const publisher = await GithubPublisher.fromConfig( - { - token: 'fake-token', - host: 'github.com', - }, - { repoVisibility: 'public' }, - ); - - mockGithubClient.repos.createInOrg.mockResolvedValue({ - data: { - clone_url: 'https://github.com/backstage/backstage.git', - }, - } as RestEndpointMethodTypes['repos']['createInOrg']['response']); - mockGithubClient.users.getByUsername.mockResolvedValue({ - data: { - type: 'Organization', - }, - } as RestEndpointMethodTypes['users']['getByUsername']['response']); - - const result = await publisher!.publish({ - values: { - storePath: 'https://github.com/blam/test', - owner: 'bob', - access: 'blam/team', - }, - workspacePath, - logger, - }); - - expect(result).toEqual({ - remoteUrl: 'https://github.com/backstage/backstage.git', - catalogInfoUrl: - 'https://github.com/backstage/backstage/blob/master/catalog-info.yaml', - }); - expect(mockGithubClient.repos.createInOrg).toHaveBeenCalledWith({ - org: 'blam', - name: 'test', - private: false, - visibility: 'public', - }); - expect( - mockGithubClient.teams.addOrUpdateRepoPermissionsInOrg, - ).toHaveBeenCalledWith({ - org: 'blam', - team_slug: 'team', - owner: 'blam', - repo: 'test', - permission: 'admin', - }); - expect(initRepoAndPush).toHaveBeenCalledWith({ - dir: resultPath, - remoteUrl: 'https://github.com/backstage/backstage.git', - auth: { username: 'x-access-token', password: 'fake-token' }, - logger, - }); - }); - - it('should use octokit to create a repo in the authed user if the organisation property is not set', async () => { - const publisher = await GithubPublisher.fromConfig( - { - token: 'fake-token', - host: 'github.com', - }, - { repoVisibility: 'public' }, - ); - - mockGithubClient.repos.createForAuthenticatedUser.mockResolvedValue({ - data: { - clone_url: 'https://github.com/backstage/backstage.git', - }, - } as RestEndpointMethodTypes['repos']['createForAuthenticatedUser']['response']); - mockGithubClient.users.getByUsername.mockResolvedValue({ - data: { - type: 'User', - }, - } as RestEndpointMethodTypes['users']['getByUsername']['response']); - - const result = await publisher!.publish({ - values: { - storePath: 'https://github.com/blam/test', - owner: 'bob', - access: 'blam', - }, - workspacePath, - logger, - }); - - expect(result).toEqual({ - remoteUrl: 'https://github.com/backstage/backstage.git', - catalogInfoUrl: - 'https://github.com/backstage/backstage/blob/master/catalog-info.yaml', - }); - expect( - mockGithubClient.repos.createForAuthenticatedUser, - ).toHaveBeenCalledWith({ - name: 'test', - private: false, - }); - expect(mockGithubClient.repos.addCollaborator).not.toHaveBeenCalled(); - - expect(initRepoAndPush).toHaveBeenCalledWith({ - dir: resultPath, - remoteUrl: 'https://github.com/backstage/backstage.git', - auth: { username: 'x-access-token', password: 'fake-token' }, - logger, - }); - }); - }); - - it('should invite other user in the authed user', async () => { - const publisher = await GithubPublisher.fromConfig( - { - token: 'fake-token', - host: 'github.com', - }, - { repoVisibility: 'public' }, - ); - - mockGithubClient.repos.createForAuthenticatedUser.mockResolvedValue({ - data: { - clone_url: 'https://github.com/backstage/backstage.git', - }, - } as RestEndpointMethodTypes['repos']['createForAuthenticatedUser']['response']); - mockGithubClient.users.getByUsername.mockResolvedValue({ - data: { - type: 'User', - }, - } as RestEndpointMethodTypes['users']['getByUsername']['response']); - - const result = await publisher!.publish({ - values: { - storePath: 'https://github.com/blam/test', - owner: 'bob', - access: 'bob', - description: 'description', - }, - workspacePath, - logger, - }); - - expect(result).toEqual({ - remoteUrl: 'https://github.com/backstage/backstage.git', - catalogInfoUrl: - 'https://github.com/backstage/backstage/blob/master/catalog-info.yaml', - }); - expect( - mockGithubClient.repos.createForAuthenticatedUser, - ).toHaveBeenCalledWith({ - description: 'description', - name: 'test', - private: false, - }); - expect(mockGithubClient.repos.addCollaborator).toHaveBeenCalledWith({ - owner: 'blam', - repo: 'test', - username: 'bob', - permission: 'admin', - }); - expect(initRepoAndPush).toHaveBeenCalledWith({ - dir: resultPath, - remoteUrl: 'https://github.com/backstage/backstage.git', - auth: { username: 'x-access-token', password: 'fake-token' }, - logger, - }); - }); - }); - - describe('with internal repo visibility', () => { - it('creates a private repository in the organization with visibility set to internal', async () => { - const publisher = await GithubPublisher.fromConfig( - { - token: 'fake-token', - host: 'github.com', - }, - { repoVisibility: 'internal' }, - ); - - mockGithubClient.repos.createInOrg.mockResolvedValue({ - data: { - clone_url: 'https://github.com/backstage/backstage.git', - }, - } as RestEndpointMethodTypes['repos']['createInOrg']['response']); - mockGithubClient.users.getByUsername.mockResolvedValue({ - data: { - type: 'Organization', - }, - } as RestEndpointMethodTypes['users']['getByUsername']['response']); - - const result = await publisher!.publish({ - values: { - isOrg: true, - storePath: 'https://github.com/blam/test', - owner: 'bob', - }, - workspacePath, - logger, - }); - - expect(result).toEqual({ - remoteUrl: 'https://github.com/backstage/backstage.git', - catalogInfoUrl: - 'https://github.com/backstage/backstage/blob/master/catalog-info.yaml', - }); - expect(mockGithubClient.repos.createInOrg).toHaveBeenCalledWith({ - org: 'blam', - name: 'test', - private: true, - visibility: 'internal', - }); - expect(initRepoAndPush).toHaveBeenCalledWith({ - dir: resultPath, - remoteUrl: 'https://github.com/backstage/backstage.git', - auth: { username: 'x-access-token', password: 'fake-token' }, - logger, - }); - }); - }); - - describe('private visibility in a user account', () => { - it('creates a private repository', async () => { - const publisher = await GithubPublisher.fromConfig( - { - token: 'fake-token', - host: 'github.com', - }, - { repoVisibility: 'private' }, - ); - - mockGithubClient.repos.createForAuthenticatedUser.mockResolvedValue({ - data: { - clone_url: 'https://github.com/backstage/backstage.git', - }, - } as RestEndpointMethodTypes['repos']['createForAuthenticatedUser']['response']); - mockGithubClient.users.getByUsername.mockResolvedValue({ - data: { - type: 'User', - }, - } as RestEndpointMethodTypes['users']['getByUsername']['response']); - - const result = await publisher!.publish({ - values: { - storePath: 'https://github.com/blam/test', - owner: 'bob', - }, - workspacePath, - logger, - }); - - expect(result).toEqual({ - remoteUrl: 'https://github.com/backstage/backstage.git', - catalogInfoUrl: - 'https://github.com/backstage/backstage/blob/master/catalog-info.yaml', - }); - expect( - mockGithubClient.repos.createForAuthenticatedUser, - ).toHaveBeenCalledWith({ - name: 'test', - private: true, - }); - expect(initRepoAndPush).toHaveBeenCalledWith({ - dir: resultPath, - remoteUrl: 'https://github.com/backstage/backstage.git', - auth: { username: 'x-access-token', password: 'fake-token' }, - logger, - }); - }); - }); -}); diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/publish/github.ts b/plugins/scaffolder-backend/src/scaffolder/stages/publish/github.ts deleted file mode 100644 index 9b4b1d48f5..0000000000 --- a/plugins/scaffolder-backend/src/scaffolder/stages/publish/github.ts +++ /dev/null @@ -1,178 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { PublisherBase, PublisherOptions, PublisherResult } from './types'; -import { - enableBranchProtectionOnDefaultRepoBranch, - initRepoAndPush, -} from './helpers'; -import { - GitHubIntegrationConfig, - GithubCredentialsProvider, -} from '@backstage/integration'; -import parseGitUrl from 'git-url-parse'; -import { Octokit } from '@octokit/rest'; -import path from 'path'; - -export type RepoVisibilityOptions = 'private' | 'internal' | 'public'; - -/** @deprecated use createPublishGithubAction instead */ -export class GithubPublisher implements PublisherBase { - static async fromConfig( - config: GitHubIntegrationConfig, - { repoVisibility }: { repoVisibility: RepoVisibilityOptions }, - ) { - if (!config.token && !config.apps) { - return undefined; - } - - const credentialsProvider = GithubCredentialsProvider.create(config); - - return new GithubPublisher({ - credentialsProvider, - repoVisibility, - apiBaseUrl: config.apiBaseUrl, - }); - } - - constructor( - private readonly config: { - credentialsProvider: GithubCredentialsProvider; - repoVisibility: RepoVisibilityOptions; - apiBaseUrl: string | undefined; - }, - ) {} - - async publish({ - values, - workspacePath, - logger, - }: PublisherOptions): Promise { - const { owner, name } = parseGitUrl(values.storePath); - - const { token } = await this.config.credentialsProvider.getCredentials({ - url: values.storePath, - }); - - if (!token) { - throw new Error( - `No token could be acquired for URL: ${values.storePath}`, - ); - } - - const client = new Octokit({ - auth: token, - baseUrl: this.config.apiBaseUrl, - previews: ['nebula-preview'], - }); - - const description = values.description as string; - const access = values.access as string; - const remoteUrl = await this.createRemote({ - client, - description, - access, - name, - owner, - }); - - await initRepoAndPush({ - dir: path.join(workspacePath, 'result'), - remoteUrl, - auth: { - username: 'x-access-token', - password: token, - }, - logger, - }); - - const catalogInfoUrl = remoteUrl.replace( - /\.git$/, - '/blob/master/catalog-info.yaml', - ); - - try { - await enableBranchProtectionOnDefaultRepoBranch({ - owner, - client, - repoName: name, - logger, - }); - } catch (e) { - throw new Error(`Failed to add branch protection to '${name}', ${e}`); - } - - return { remoteUrl, catalogInfoUrl }; - } - - private async createRemote(opts: { - client: Octokit; - access: string; - name: string; - owner: string; - description: string; - }) { - const { client, access, description, owner, name } = opts; - - const user = await client.users.getByUsername({ - username: owner, - }); - - const repoCreationPromise = - user.data.type === 'Organization' - ? client.repos.createInOrg({ - name, - org: owner, - private: this.config.repoVisibility !== 'public', - visibility: this.config.repoVisibility, - description, - }) - : client.repos.createForAuthenticatedUser({ - name, - private: this.config.repoVisibility === 'private', - description, - }); - - const { data: newRepo } = await repoCreationPromise; - - try { - if (access?.startsWith(`${owner}/`)) { - const [, team] = access.split('/'); - await client.teams.addOrUpdateRepoPermissionsInOrg({ - org: owner, - team_slug: team, - owner, - repo: name, - permission: 'admin', - }); - // no need to add access if it's the person who owns the personal account - } else if (access && access !== owner) { - await client.repos.addCollaborator({ - owner, - repo: name, - username: access, - permission: 'admin', - }); - } - } catch (e) { - throw new Error( - `Failed to add access to '${access}'. Status ${e.status} ${e.message}`, - ); - } - - return newRepo.clone_url; - } -} diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/publish/gitlab.test.ts b/plugins/scaffolder-backend/src/scaffolder/stages/publish/gitlab.test.ts deleted file mode 100644 index 5c6a01afc8..0000000000 --- a/plugins/scaffolder-backend/src/scaffolder/stages/publish/gitlab.test.ts +++ /dev/null @@ -1,151 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -jest.mock('@gitbeaker/node', () => ({ - Gitlab: jest.fn(), -})); - -jest.mock('./helpers'); - -import os from 'os'; -import path from 'path'; -import { GitlabPublisher } from './gitlab'; -import { Gitlab } from '@gitbeaker/node'; -import { initRepoAndPush } from './helpers'; -import { getVoidLogger } from '@backstage/backend-common'; - -describe('GitLab Publisher', () => { - const logger = getVoidLogger(); - const mockGitlabClient = { - Namespaces: { - show: jest.fn(), - }, - Projects: { - create: jest.fn(), - }, - Users: { - current: jest.fn(), - }, - }; - - beforeEach(() => { - jest.clearAllMocks(); - - ((Gitlab as unknown) as jest.Mock).mockImplementation( - () => mockGitlabClient, - ); - }); - - const workspacePath = os.platform() === 'win32' ? 'C:\\tmp' : '/tmp'; - const resultPath = path.resolve(workspacePath, 'result'); - - describe('publish: createRemoteInGitLab', () => { - it('should use gitbeaker to create a repo in a namespace if the namespace property is set', async () => { - const publisher = await GitlabPublisher.fromConfig( - { - host: 'gitlab.com', - apiBaseUrl: 'https://gitlab.com/api/v4', - token: 'fake-token', - baseUrl: 'https://gitlab.hosted.com', - }, - { repoVisibility: 'public' }, - ); - - mockGitlabClient.Namespaces.show.mockResolvedValue({ - id: 42, - } as { id: number }); - mockGitlabClient.Projects.create.mockResolvedValue({ - http_url_to_repo: 'mockclone', - } as { http_url_to_repo: string }); - - const result = await publisher!.publish({ - values: { - isOrg: true, - storePath: 'https://gitlab.com/blam/test', - owner: 'bob', - }, - workspacePath, - logger, - }); - - expect(Gitlab).toHaveBeenCalledWith({ - token: 'fake-token', - host: 'https://gitlab.hosted.com', - }); - expect(result).toEqual({ - remoteUrl: 'mockclone', - catalogInfoUrl: 'mockclone', - }); - expect(mockGitlabClient.Projects.create).toHaveBeenCalledWith({ - namespace_id: 42, - name: 'test', - visibility: 'public', - }); - expect(initRepoAndPush).toHaveBeenCalledWith({ - dir: resultPath, - remoteUrl: 'mockclone', - auth: { username: 'oauth2', password: 'fake-token' }, - logger, - }); - }); - - it('should use gitbeaker to create a repo in the authed user if the namespace property is not set', async () => { - const publisher = await GitlabPublisher.fromConfig( - { - host: 'gitlab.com', - apiBaseUrl: 'https://gitlab.com/api/v4', - token: 'fake-token', - baseUrl: 'https://gitlab.com', - }, - { repoVisibility: 'public' }, - ); - - mockGitlabClient.Namespaces.show.mockResolvedValue({}); - mockGitlabClient.Users.current.mockResolvedValue({ - id: 21, - } as { id: number }); - mockGitlabClient.Projects.create.mockResolvedValue({ - http_url_to_repo: 'mockclone', - } as { http_url_to_repo: string }); - - const result = await publisher!.publish({ - values: { - storePath: 'https://gitlab.com/blam/test', - owner: 'bob', - }, - workspacePath, - logger, - }); - - expect(result).toEqual({ - remoteUrl: 'mockclone', - catalogInfoUrl: 'mockclone', - }); - expect(mockGitlabClient.Users.current).toHaveBeenCalled(); - expect(mockGitlabClient.Projects.create).toHaveBeenCalledWith({ - namespace_id: 21, - name: 'test', - visibility: 'public', - }); - expect(initRepoAndPush).toHaveBeenCalledWith({ - dir: resultPath, - remoteUrl: 'mockclone', - auth: { username: 'oauth2', password: 'fake-token' }, - logger, - }); - }); - }); -}); diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/publish/gitlab.ts b/plugins/scaffolder-backend/src/scaffolder/stages/publish/gitlab.ts deleted file mode 100644 index d2f58900a8..0000000000 --- a/plugins/scaffolder-backend/src/scaffolder/stages/publish/gitlab.ts +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { PublisherBase, PublisherOptions, PublisherResult } from './types'; -import { Gitlab } from '@gitbeaker/node'; -import { Gitlab as GitlabClient } from '@gitbeaker/core'; -import { initRepoAndPush } from './helpers'; -import parseGitUrl from 'git-url-parse'; -import path from 'path'; -import { GitLabIntegrationConfig } from '@backstage/integration'; - -export type RepoVisibilityOptions = 'private' | 'internal' | 'public'; - -export class GitlabPublisher implements PublisherBase { - static async fromConfig( - config: GitLabIntegrationConfig, - { repoVisibility }: { repoVisibility: RepoVisibilityOptions }, - ) { - if (!config.token) { - return undefined; - } - - const client = new Gitlab({ host: config.baseUrl, token: config.token }); - return new GitlabPublisher({ - token: config.token, - client, - repoVisibility, - }); - } - - constructor( - private readonly config: { - token: string; - client: GitlabClient; - repoVisibility: RepoVisibilityOptions; - }, - ) {} - - async publish({ - values, - workspacePath, - logger, - }: PublisherOptions): Promise { - const { owner, name } = parseGitUrl(values.storePath); - - const remoteUrl = await this.createRemote({ - owner, - name, - }); - - await initRepoAndPush({ - dir: path.join(workspacePath, 'result'), - remoteUrl, - auth: { - username: 'oauth2', - password: this.config.token, - }, - logger, - }); - - const catalogInfoUrl = remoteUrl.replace( - /\.git$/, - '/-/blob/master/catalog-info.yaml', - ); - return { remoteUrl, catalogInfoUrl }; - } - - private async createRemote(opts: { name: string; owner: string }) { - const { owner, name } = opts; - - // TODO(blam): this needs cleaning up to be nicer. The amount of brackets is too damn high! - // Shouldn't have to cast things now - let targetNamespace = ((await this.config.client.Namespaces.show( - owner, - )) as { - id: number; - }).id; - - if (!targetNamespace) { - targetNamespace = ((await this.config.client.Users.current()) as { - id: number; - }).id; - } - - const project = (await this.config.client.Projects.create({ - namespace_id: targetNamespace, - name: name, - visibility: this.config.repoVisibility, - })) as { http_url_to_repo: string }; - - return project?.http_url_to_repo; - } -} diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/publish/index.ts b/plugins/scaffolder-backend/src/scaffolder/stages/publish/index.ts deleted file mode 100644 index 7a384f1657..0000000000 --- a/plugins/scaffolder-backend/src/scaffolder/stages/publish/index.ts +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -export { AzurePublisher } from './azure'; -export { BitbucketPublisher } from './bitbucket'; -export { GithubPublisher } from './github'; -export type { RepoVisibilityOptions } from './github'; -export { GitlabPublisher } from './gitlab'; -export { Publishers } from './publishers'; -export type { - PublisherBase, - PublisherBuilder, - PublisherOptions, - PublisherResult, -} from './types'; diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/publish/publishers.test.ts b/plugins/scaffolder-backend/src/scaffolder/stages/publish/publishers.test.ts deleted file mode 100644 index c7ca832752..0000000000 --- a/plugins/scaffolder-backend/src/scaffolder/stages/publish/publishers.test.ts +++ /dev/null @@ -1,127 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -import { Publishers } from './publishers'; -import { GithubPublisher } from './github'; -import { getVoidLogger } from '@backstage/backend-common'; -import { ConfigReader } from '@backstage/config'; -import { AzurePublisher } from './azure'; -import { GitlabPublisher } from './gitlab'; -import { BitbucketPublisher } from './bitbucket'; - -jest.mock('@octokit/rest'); -jest.mock('azure-devops-node-api'); - -describe('Publishers', () => { - const logger = getVoidLogger(); - - it('should throw an error when the publisher for the source location is not registered', () => { - const publishers = new Publishers(); - - expect(() => publishers.get('https://github.com/org/repo')).toThrow( - expect.objectContaining({ - message: - 'Unable to find a publisher for URL: https://github.com/org/repo. Please make sure to register this host under an integration in app-config', - }), - ); - }); - - it('should return the correct preparer when the source matches for github', async () => { - const publishers = await Publishers.fromConfig( - new ConfigReader({ - integrations: { - github: [{ host: 'github.com', token: 'blob' }], - }, - }), - { - logger, - }, - ); - - expect(publishers.get('https://github.com/org/repo')).toBeInstanceOf( - GithubPublisher, - ); - }); - - it('should return the correct preparer when the source matches for azure', async () => { - const publishers = await Publishers.fromConfig( - new ConfigReader({ - integrations: { - azure: [{ host: 'dev.azure.com', token: 'blob' }], - }, - }), - { - logger, - }, - ); - - expect( - publishers.get('https://dev.azure.com/org/project/_git/repo'), - ).toBeInstanceOf(AzurePublisher); - }); - - it('should return the correct preparer when the source matches for bitbucket', async () => { - const publishers = await Publishers.fromConfig( - new ConfigReader({ - integrations: { - bitbucket: [ - { host: 'bitbucket.com', username: 'foo', token: 'blob' }, - ], - }, - }), - { - logger, - }, - ); - expect(publishers.get('https://bitbucket.org/owner/repo')).toBeInstanceOf( - BitbucketPublisher, - ); - }); - - it('should return the correct preparer when the source matches for gitlab', async () => { - const publishers = await Publishers.fromConfig( - new ConfigReader({ - integrations: { - gitlab: [{ host: 'gitlab.com', token: 'blob' }], - }, - }), - { - logger, - }, - ); - expect(publishers.get('https://gitlab.com/owner/repo')).toBeInstanceOf( - GitlabPublisher, - ); - }); - - it('should respect registrations for custom URLs for providers using the integrations config', async () => { - const publishers = await Publishers.fromConfig( - new ConfigReader({ - integrations: { - github: [ - { host: 'my.special.github.enterprise.thing', token: 'lolghe' }, - ], - }, - }), - { - logger, - }, - ); - - expect( - publishers.get('https://my.special.github.enterprise.thing/org/repo'), - ).toBeInstanceOf(GithubPublisher); - }); -}); diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/publish/publishers.ts b/plugins/scaffolder-backend/src/scaffolder/stages/publish/publishers.ts deleted file mode 100644 index 9c34ab5783..0000000000 --- a/plugins/scaffolder-backend/src/scaffolder/stages/publish/publishers.ts +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { Config } from '@backstage/config'; -import { PublisherBase, PublisherBuilder } from './types'; -import { - GithubPublisher, - RepoVisibilityOptions as GithubRepoVisibilityOptions, -} from './github'; -import { - GitlabPublisher, - RepoVisibilityOptions as GitlabRepoVisibilityOptions, -} from './gitlab'; -import { AzurePublisher } from './azure'; -import { - BitbucketPublisher, - RepoVisibilityOptions as BitbucketRepoVisibilityOptions, -} from './bitbucket'; -import { Logger } from 'winston'; -import { ScmIntegrations } from '@backstage/integration'; - -export class Publishers implements PublisherBuilder { - private publisherMap = new Map(); - - register(host: string, preparer: PublisherBase | undefined) { - this.publisherMap.set(host, preparer); - } - - get(url: string): PublisherBase { - const preparer = this.publisherMap.get(new URL(url).host); - if (!preparer) { - throw new Error( - `Unable to find a publisher for URL: ${url}. Please make sure to register this host under an integration in app-config`, - ); - } - return preparer; - } - - static async fromConfig( - config: Config, - _options: { logger: Logger }, - ): Promise { - const publishers = new Publishers(); - - const scm = ScmIntegrations.fromConfig(config); - - for (const integration of scm.azure.list()) { - const publisher = await AzurePublisher.fromConfig(integration.config); - if (publisher) { - publishers.register(integration.config.host, publisher); - } - } - - for (const integration of scm.github.list()) { - const repoVisibility = (config.getOptionalString( - 'scaffolder.github.visibility', - ) ?? 'public') as GithubRepoVisibilityOptions; - - const publisher = await GithubPublisher.fromConfig(integration.config, { - repoVisibility, - }); - if (publisher) { - publishers.register(integration.config.host, publisher); - } - } - - for (const integration of scm.gitlab.list()) { - const repoVisibility = (config.getOptionalString( - 'scaffolder.gitlab.visibility', - ) ?? 'public') as GitlabRepoVisibilityOptions; - - const publisher = await GitlabPublisher.fromConfig(integration.config, { - repoVisibility, - }); - - if (publisher) { - publishers.register(integration.config.host, publisher); - } - } - - for (const integration of scm.bitbucket.list()) { - const repoVisibility = (config.getOptionalString( - 'scaffolder.bitbucket.visibility', - ) ?? 'public') as BitbucketRepoVisibilityOptions; - - const publisher = await BitbucketPublisher.fromConfig( - integration.config, - { - repoVisibility, - }, - ); - - if (publisher) { - publishers.register(integration.config.host, publisher); - } - } - - return publishers; - } -} diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/publish/types.ts b/plugins/scaffolder-backend/src/scaffolder/stages/publish/types.ts deleted file mode 100644 index 725816c918..0000000000 --- a/plugins/scaffolder-backend/src/scaffolder/stages/publish/types.ts +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -import { TemplaterValues } from '../templater'; -import { Logger } from 'winston'; - -/** - * Publisher is in charge of taking a folder created by - * the templater, and pushing it to a remote storage - */ -export type PublisherBase = { - /** - * - * @param opts object containing the template entity from the service - * catalog, plus the values from the form and the directory that has - * been templated - */ - publish(opts: PublisherOptions): Promise; -}; - -export type PublisherOptions = { - values: TemplaterValues; - workspacePath: string; - logger: Logger; -}; - -export type PublisherResult = { - remoteUrl: string; - catalogInfoUrl?: string; -}; - -export type PublisherBuilder = { - register(host: string, publisher: PublisherBase): void; - get(storePath: string): PublisherBase; -}; diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/templater/cookiecutter.test.ts b/plugins/scaffolder-backend/src/scaffolder/stages/templater/cookiecutter.test.ts deleted file mode 100644 index 1db5b52ffa..0000000000 --- a/plugins/scaffolder-backend/src/scaffolder/stages/templater/cookiecutter.test.ts +++ /dev/null @@ -1,279 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -const runCommand = jest.fn(); -const commandExists = jest.fn(); - -jest.mock('./helpers', () => ({ runCommand })); -jest.mock('command-exists', () => commandExists); -jest.mock('fs-extra'); - -import { ContainerRunner } from '@backstage/backend-common'; -import fs from 'fs-extra'; -import parseGitUrl from 'git-url-parse'; -import path from 'path'; -import { PassThrough } from 'stream'; -import { CookieCutter } from './cookiecutter'; - -describe('CookieCutter Templater', () => { - const containerRunner: jest.Mocked = { - runContainer: jest.fn(), - }; - - beforeEach(() => { - jest.clearAllMocks(); - commandExists.mockRejectedValue(null); - }); - - it('should write a cookiecutter.json file with the values from the entity', async () => { - const values = { - owner: 'blobby', - storePath: 'https://github.com/org/repo', - description: 'description', - component_id: 'newthing', - destination: { - git: parseGitUrl('https://github.com/org/repo'), - }, - }; - - jest.spyOn(fs, 'readdir').mockResolvedValueOnce(['newthing'] as any); - - const templater = new CookieCutter({ containerRunner }); - await templater.run({ - workspacePath: 'tempdir', - values, - }); - - expect(fs.ensureDir).toBeCalledWith(path.join('tempdir', 'intermediate')); - expect(fs.writeJson).toBeCalledWith( - path.join('tempdir', 'template', 'cookiecutter.json'), - expect.objectContaining(values), - ); - }); - - it('should merge any value that is in the cookiecutter.json path already', async () => { - const existingJson = { - _copy_without_render: ['./github/workflows/*'], - }; - - jest - .spyOn(fs, 'readJSON') - .mockImplementationOnce(() => Promise.resolve(existingJson)); - jest.spyOn(fs, 'readdir').mockResolvedValueOnce(['newthing'] as any); - - const values = { - owner: 'blobby', - storePath: 'https://github.com/org/repo', - component_id: 'something', - destination: { - git: parseGitUrl('https://github.com/org/repo'), - }, - }; - - const templater = new CookieCutter({ containerRunner }); - await templater.run({ - workspacePath: 'tempdir', - values, - }); - - expect(fs.writeJSON).toBeCalledWith( - path.join('tempdir', 'template', 'cookiecutter.json'), - { - ...existingJson, - ...values, - destination: { - git: expect.objectContaining({ organization: 'org', name: 'repo' }), - }, - }, - ); - }); - - it('should throw an error if the cookiecutter json is malformed and not missing', async () => { - jest.spyOn(fs, 'readJSON').mockImplementationOnce(() => { - throw new Error('BAM'); - }); - - const values = { - owner: 'blobby', - storePath: 'https://github.com/org/repo', - destination: { - git: parseGitUrl('https://github.com/org/repo'), - }, - }; - - const templater = new CookieCutter({ containerRunner }); - await expect( - templater.run({ - workspacePath: 'tempdir', - values, - }), - ).rejects.toThrow('BAM'); - }); - - it('should run the correct docker container with the correct bindings for the volumes', async () => { - const values = { - owner: 'blobby', - storePath: 'https://github.com/org/repo', - component_id: 'newthing', - destination: { - git: parseGitUrl('https://github.com/org/repo'), - }, - }; - - jest.spyOn(fs, 'readdir').mockResolvedValueOnce(['newthing'] as any); - jest - .spyOn(fs, 'realpath') - .mockImplementation(x => Promise.resolve(x.toString())); - - const templater = new CookieCutter({ containerRunner }); - await templater.run({ - workspacePath: 'tempdir', - values, - }); - - expect(containerRunner.runContainer).toHaveBeenCalledWith({ - imageName: 'spotify/backstage-cookiecutter', - command: 'cookiecutter', - args: ['--no-input', '-o', '/output', '/input', '--verbose'], - envVars: { HOME: '/tmp' }, - mountDirs: { - [path.join('tempdir', 'template')]: '/input', - [path.join('tempdir', 'intermediate')]: '/output', - }, - workingDir: '/input', - logStream: undefined, - }); - }); - - it('should run the docker container mentioned in configs, overriding the default', async () => { - const values = { - owner: 'blobby', - storePath: 'https://github.com/org/repo', - imageName: 'foo/cookiecutter-image-with-extensions', - }; - - jest.spyOn(fs, 'readdir').mockResolvedValueOnce(['newthing'] as any); - - const templater = new CookieCutter({ containerRunner }); - await templater.run({ - workspacePath: 'tempdir', - values, - }); - - expect(containerRunner.runContainer).toHaveBeenCalledWith( - expect.objectContaining({ - imageName: 'foo/cookiecutter-image-with-extensions', - }), - ); - }); - - it('should pass through the streamer to the run docker helper', async () => { - const stream = new PassThrough(); - - const values = { - owner: 'blobby', - storePath: 'https://github.com/org/repo', - component_id: 'newthing', - destination: { - git: parseGitUrl('https://github.com/org/repo'), - }, - }; - - jest.spyOn(fs, 'readdir').mockResolvedValueOnce(['newthing'] as any); - - const templater = new CookieCutter({ containerRunner }); - await templater.run({ - workspacePath: 'tempdir', - values, - logStream: stream, - }); - - expect(containerRunner.runContainer).toHaveBeenCalledWith({ - imageName: 'spotify/backstage-cookiecutter', - command: 'cookiecutter', - args: ['--no-input', '-o', '/output', '/input', '--verbose'], - envVars: { HOME: '/tmp' }, - mountDirs: { - [path.join('tempdir', 'template')]: '/input', - [path.join('tempdir', 'intermediate')]: '/output', - }, - workingDir: '/input', - logStream: stream, - }); - }); - - describe('when cookiecutter is available', () => { - it('use the binary', async () => { - const stream = new PassThrough(); - - const values = { - owner: 'blobby', - storePath: 'https://github.com/org/repo', - component_id: 'newthing', - destination: { - git: parseGitUrl('https://github.com/org/repo'), - }, - }; - - jest.spyOn(fs, 'readdir').mockResolvedValueOnce(['newthing'] as any); - commandExists.mockResolvedValueOnce(true); - - const templater = new CookieCutter({ containerRunner }); - await templater.run({ - workspacePath: 'tempdir', - values, - logStream: stream, - }); - - expect(runCommand).toHaveBeenCalledWith({ - command: 'cookiecutter', - args: expect.arrayContaining([ - '--no-input', - '-o', - path.join('tempdir', 'intermediate'), - path.join('tempdir', 'template'), - '--verbose', - ]), - logStream: stream, - }); - }); - }); - - describe('when nothing was generated', () => { - it('throws an error', async () => { - const stream = new PassThrough(); - - jest - .spyOn(fs, 'readdir') - .mockImplementationOnce(() => Promise.resolve([])); - - const templater = new CookieCutter({ containerRunner }); - await expect( - templater.run({ - workspacePath: 'tempdir', - values: { - owner: 'blobby', - storePath: 'https://github.com/org/repo', - destination: { - git: parseGitUrl('https://github.com/org/repo'), - }, - }, - logStream: stream, - }), - ).rejects.toThrow(/No data generated by cookiecutter/); - }); - }); -}); diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/templater/cookiecutter.ts b/plugins/scaffolder-backend/src/scaffolder/stages/templater/cookiecutter.ts deleted file mode 100644 index ef51fc20a9..0000000000 --- a/plugins/scaffolder-backend/src/scaffolder/stages/templater/cookiecutter.ts +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { ContainerRunner } from '@backstage/backend-common'; -import { JsonValue } from '@backstage/config'; -import commandExists from 'command-exists'; -import fs from 'fs-extra'; -import path from 'path'; -import { runCommand } from './helpers'; -import { TemplaterBase, TemplaterRunOptions } from './types'; - -export class CookieCutter implements TemplaterBase { - private readonly containerRunner: ContainerRunner; - - constructor({ containerRunner }: { containerRunner: ContainerRunner }) { - this.containerRunner = containerRunner; - } - - private async fetchTemplateCookieCutter( - directory: string, - ): Promise> { - try { - return await fs.readJSON(path.join(directory, 'cookiecutter.json')); - } catch (ex) { - if (ex.code !== 'ENOENT') { - throw ex; - } - - return {}; - } - } - - public async run({ - workspacePath, - values, - logStream, - }: TemplaterRunOptions): Promise { - const templateDir = path.join(workspacePath, 'template'); - const intermediateDir = path.join(workspacePath, 'intermediate'); - await fs.ensureDir(intermediateDir); - const resultDir = path.join(workspacePath, 'result'); - - // First lets grab the default cookiecutter.json file - const cookieCutterJson = await this.fetchTemplateCookieCutter(templateDir); - - const { imageName, ...valuesForCookieCutterJson } = values; - const cookieInfo = { - ...cookieCutterJson, - ...valuesForCookieCutterJson, - }; - - await fs.writeJSON(path.join(templateDir, 'cookiecutter.json'), cookieInfo); - - // Directories to bind on container - const mountDirs = { - [templateDir]: '/input', - [intermediateDir]: '/output', - }; - - // the command-exists package returns `true` or throws an error - const cookieCutterInstalled = await commandExists('cookiecutter').catch( - () => false, - ); - if (cookieCutterInstalled) { - await runCommand({ - command: 'cookiecutter', - args: ['--no-input', '-o', intermediateDir, templateDir, '--verbose'], - logStream, - }); - } else { - await this.containerRunner.runContainer({ - imageName: imageName || 'spotify/backstage-cookiecutter', - command: 'cookiecutter', - args: ['--no-input', '-o', '/output', '/input', '--verbose'], - mountDirs, - workingDir: '/input', - // Set the home directory inside the container as something that applications can - // write to, otherwise they will just fail trying to write to / - envVars: { HOME: '/tmp' }, - logStream, - }); - } - - // if cookiecutter was successful, intermediateDir will contain - // exactly one directory. - const [generated] = await fs.readdir(intermediateDir); - - if (generated === undefined) { - throw new Error('No data generated by cookiecutter'); - } - - await fs.move(path.join(intermediateDir, generated), resultDir); - } -} diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/templater/cra/index.ts b/plugins/scaffolder-backend/src/scaffolder/stages/templater/cra/index.ts deleted file mode 100644 index 46bd9094ac..0000000000 --- a/plugins/scaffolder-backend/src/scaffolder/stages/templater/cra/index.ts +++ /dev/null @@ -1,159 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { ContainerRunner } from '@backstage/backend-common'; -import fs from 'fs-extra'; -import path from 'path'; -import * as yaml from 'yaml'; -import { TemplaterBase, TemplaterRunOptions } from '../types'; - -// TODO(blam): Replace with the universal import from github-actions after a release -// As it will break the E2E without it -const GITHUB_ACTIONS_ANNOTATION = 'github.com/project-slug'; - -export class CreateReactAppTemplater implements TemplaterBase { - private readonly containerRunner: ContainerRunner; - - constructor({ containerRunner }: { containerRunner: ContainerRunner }) { - this.containerRunner = containerRunner; - } - - public async run({ - workspacePath, - values, - logStream, - }: TemplaterRunOptions): Promise { - const { - component_id: componentName, - use_typescript: withTypescript, - use_github_actions: withGithubActions, - description, - owner, - } = values; - const intermediateDir = path.join(workspacePath, 'template'); - await fs.ensureDir(intermediateDir); - - const mountDirs = { - [intermediateDir]: '/template', - [intermediateDir]: '/result', - }; - - await this.containerRunner.runContainer({ - imageName: 'node:lts-alpine', - command: ['npx'], - args: [ - 'create-react-app', - componentName as string, - withTypescript ? ' --template typescript' : '', - ], - mountDirs, - workingDir: '/result', - logStream: logStream, - // Set the home directory inside the container as something that applications can - // write to, otherwise they will just fail trying to write to / - envVars: { HOME: '/tmp' }, - }); - - // if cookiecutter was successful, intermediateDir will contain - // exactly one directory. - const [generated] = await fs.readdir(intermediateDir); - - if (generated === undefined) { - throw new Error('No data generated by cookiecutter'); - } - - const resultDir = path.join(workspacePath, 'result'); - await fs.move(path.join(intermediateDir, generated), resultDir); - - const extraAnnotations: Record = {}; - if (withGithubActions) { - await fs.mkdir(`${resultDir}/.github`); - await fs.mkdir(`${resultDir}/.github/workflows`); - const githubActionsYaml = ` -name: CRA Build - -on: - push: - branches: [ master ] - pull_request: - branches: [ master ] - -jobs: - build: - runs-on: ubuntu-latest - - strategy: - matrix: - node-version: [12.x] - - steps: - - name: checkout code - uses: actions/checkout@v1 - - name: get yarn cache - id: yarn-cache - run: echo "::set-output name=dir::$(yarn cache dir)" - - uses: actions/cache@v2 - with: - path: \${{ steps.yarn-cache.outputs.dir }} - key: \${{ runner.os }}-yarn-\${{ hashFiles('**/yarn.lock') }} - restore-keys: | - \${{ runner.os }}-yarn- - - name: use node.js \${{ matrix.node-version }} - uses: actions/setup-node@v1 - with: - node-version: \${{ matrix.node-version }} - - name: yarn install, build, and test - working-directory: . - run: | - yarn install - yarn build - yarn test - env: - CI: true - `; - await fs.writeFile( - `${resultDir}/.github/workflows/main.yml`, - githubActionsYaml, - ); - - extraAnnotations[ - GITHUB_ACTIONS_ANNOTATION - ] = `${values?.destination?.git?.owner}/${values?.destination?.git?.name}`; - } - - const componentInfo = { - apiVersion: 'backstage.io/v1alpha1', - kind: 'Component', - metadata: { - name: componentName, - description, - annotations: { - ...extraAnnotations, - }, - }, - spec: { - type: 'website', - lifecycle: 'experimental', - owner, - }, - }; - - await fs.writeFile( - `${resultDir}/catalog-info.yaml`, - yaml.stringify(componentInfo), - ); - } -} diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/templater/helpers.ts b/plugins/scaffolder-backend/src/scaffolder/stages/templater/helpers.ts deleted file mode 100644 index c2742428a5..0000000000 --- a/plugins/scaffolder-backend/src/scaffolder/stages/templater/helpers.ts +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -import { InputError } from '@backstage/errors'; -import { TemplateEntityV1alpha1 } from '@backstage/catalog-model'; -import { spawn } from 'child_process'; -import { PassThrough, Writable } from 'stream'; - -export type RunCommandOptions = { - command: string; - args: string[]; - logStream?: Writable; -}; - -/** - * Gets the templater key to use for templating from the entity - * @param entity Template entity - */ -export const getTemplaterKey = (entity: TemplateEntityV1alpha1): string => { - const { templater } = entity.spec; - - if (!templater) { - throw new InputError('Template does not have a required templating key'); - } - - return templater; -}; - -/** - * - * @param options the options object - * @param options.command the command to run - * @param options.args the arguments to pass the command - * @param options.logStream the log streamer to capture log messages - */ -export const runCommand = async ({ - command, - args, - logStream = new PassThrough(), -}: RunCommandOptions) => { - await new Promise((resolve, reject) => { - const process = spawn(command, args); - - process.stdout.on('data', stream => { - logStream.write(stream); - }); - - process.stderr.on('data', stream => { - logStream.write(stream); - }); - - process.on('error', error => { - return reject(error); - }); - - process.on('close', code => { - if (code !== 0) { - return reject(`Command ${command} failed, exit code: ${code}`); - } - return resolve(); - }); - }); -}; diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/templater/index.ts b/plugins/scaffolder-backend/src/scaffolder/stages/templater/index.ts deleted file mode 100644 index 4d80f86946..0000000000 --- a/plugins/scaffolder-backend/src/scaffolder/stages/templater/index.ts +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -export * from './cookiecutter'; -export * from './types'; -export * from './helpers'; -export * from './templaters'; -export * from './cra'; diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/templater/templaters.test.ts b/plugins/scaffolder-backend/src/scaffolder/stages/templater/templaters.test.ts deleted file mode 100644 index ae3890c092..0000000000 --- a/plugins/scaffolder-backend/src/scaffolder/stages/templater/templaters.test.ts +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { ContainerRunner } from '@backstage/backend-common'; -import { CookieCutter } from './cookiecutter'; -import { Templaters } from './templaters'; - -describe('Templaters', () => { - const containerRunner: jest.Mocked = { - runContainer: jest.fn(), - }; - - it('should throw an error when the templater is not registered', () => { - const templaters = new Templaters(); - - expect(() => templaters.get('cookiecutter')).toThrow( - expect.objectContaining({ - message: 'No templater registered for template: "cookiecutter"', - }), - ); - }); - it('should return the correct templater when the templater matches', () => { - const templaters = new Templaters(); - const templater = new CookieCutter({ containerRunner }); - - templaters.register('cookiecutter', templater); - - expect(templaters.get('cookiecutter')).toBe(templater); - }); -}); diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/templater/templaters.ts b/plugins/scaffolder-backend/src/scaffolder/stages/templater/templaters.ts deleted file mode 100644 index a977502a01..0000000000 --- a/plugins/scaffolder-backend/src/scaffolder/stages/templater/templaters.ts +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { - TemplaterBase, - SupportedTemplatingKey, - TemplaterBuilder, -} from './types'; - -export class Templaters implements TemplaterBuilder { - private templaterMap = new Map(); - - register(templaterKey: SupportedTemplatingKey, templater: TemplaterBase) { - this.templaterMap.set(templaterKey, templater); - } - - get(templaterId: string): TemplaterBase { - const templater = this.templaterMap.get(templaterId); - - if (!templater) { - throw new Error(`No templater registered for template: "${templaterId}"`); - } - - return templater; - } -} diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/templater/types.ts b/plugins/scaffolder-backend/src/scaffolder/stages/templater/types.ts deleted file mode 100644 index 4d6b96c776..0000000000 --- a/plugins/scaffolder-backend/src/scaffolder/stages/templater/types.ts +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import gitUrlParse from 'git-url-parse'; -import type { Writable } from 'stream'; - -/** - * Currently the required template values. The owner - * and where to store the result from templating - */ -export type RequiredTemplateValues = { - owner: string; - storePath: string; - destination?: { - git?: gitUrlParse.GitUrl; - }; -}; - -export type TemplaterValues = RequiredTemplateValues & Record; - -/** - * The returned directory from the templater which is ready - * to pass to the next stage of the scaffolder which is publishing - */ -export type TemplaterRunResult = { - resultDir: string; -}; - -/** - * The values that the templater will receive. The directory of the - * skeleton, with the values from the frontend. A dedicated log stream and a docker - * client to run any templater on top of your directory. - */ -export type TemplaterRunOptions = { - workspacePath: string; - values: TemplaterValues; - logStream?: Writable; -}; - -export type TemplaterBase = { - // runs the templating with the values and returns the directory to push the VCS - run(opts: TemplaterRunOptions): Promise; -}; - -export type TemplaterConfig = { - templater?: TemplaterBase; -}; - -/** - * List of supported templating options - */ -export type SupportedTemplatingKey = 'cookiecutter' | string; - -/** - * The templater builder holds the templaters ready for run time - */ -export type TemplaterBuilder = { - register(protocol: SupportedTemplatingKey, templater: TemplaterBase): void; - get(templater: string): TemplaterBase; -}; diff --git a/plugins/scaffolder-backend/src/scaffolder/tasks/TemplateConverter.ts b/plugins/scaffolder-backend/src/scaffolder/tasks/TemplateConverter.ts deleted file mode 100644 index fef92d081f..0000000000 --- a/plugins/scaffolder-backend/src/scaffolder/tasks/TemplateConverter.ts +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright 2021 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { resolve as resolvePath, dirname } from 'path'; -import { TemplateEntityV1alpha1 } from '@backstage/catalog-model'; -import parseGitUrl from 'git-url-parse'; -import { TaskSpec } from './types'; -import { - getTemplaterKey, - joinGitUrlPath, - parseLocationAnnotation, - TemplaterValues, -} from '../stages'; - -export function templateEntityToSpec( - template: TemplateEntityV1alpha1, - inputValues: TemplaterValues, -): TaskSpec { - const steps: TaskSpec['steps'] = []; - - const { protocol, location } = parseLocationAnnotation(template); - - let url: string; - if (protocol === 'file') { - const path = resolvePath(dirname(location), template.spec.path || '.'); - - url = `file://${path}`; - } else { - url = joinGitUrlPath(location, template.spec.path); - } - const templater = getTemplaterKey(template); - - const values = { - ...inputValues, - destination: { - git: parseGitUrl(inputValues.storePath), - }, - } as TemplaterValues; - - steps.push({ - id: 'prepare', - name: 'Prepare', - action: 'legacy:prepare', - input: { - protocol, - url, - }, - }); - - steps.push({ - id: 'template', - name: 'Template', - action: 'legacy:template', - input: { - templater, - values, - }, - }); - - steps.push({ - id: 'publish', - name: 'Publish', - action: 'legacy:publish', - input: { - values, - }, - }); - - steps.push({ - id: 'register', - name: 'Register', - action: 'catalog:register', - input: { - catalogInfoUrl: '{{ steps.publish.output.catalogInfoUrl }}', - }, - }); - - return { - baseUrl: undefined, // not used by legacy actions - values: {}, - steps, - output: { - remoteUrl: '{{ steps.publish.output.remoteUrl }}', - catalogInfoUrl: '{{ steps.register.output.catalogInfoUrl }}', - entityRef: '{{ steps.register.output.entityRef }}', - }, - }; -} diff --git a/plugins/scaffolder-backend/src/service/router.ts b/plugins/scaffolder-backend/src/service/router.ts index 17304aefb1..3ad4646b01 100644 --- a/plugins/scaffolder-backend/src/service/router.ts +++ b/plugins/scaffolder-backend/src/service/router.ts @@ -18,12 +18,6 @@ import { Config } from '@backstage/config'; import express from 'express'; import Router from 'express-promise-router'; import { Logger } from 'winston'; -import { - PreparerBuilder, - TemplaterBuilder, - TemplaterValues, - PublisherBuilder, -} from '../scaffolder'; import { CatalogEntityClient } from '../lib/catalog'; import { validate } from 'jsonschema'; import { @@ -31,27 +25,21 @@ import { StorageTaskBroker, TaskWorker, } from '../scaffolder/tasks'; -import { templateEntityToSpec } from '../scaffolder/tasks/TemplateConverter'; import { TemplateActionRegistry } from '../scaffolder/actions/TemplateActionRegistry'; -import { createLegacyActions } from '../scaffolder/stages/legacy'; import { getEntityBaseUrl, getWorkingDirectory } from './helpers'; -import { PluginDatabaseManager, UrlReader } from '@backstage/backend-common'; +import { + ContainerRunner, + PluginDatabaseManager, + UrlReader, +} from '@backstage/backend-common'; import { InputError, NotFoundError } from '@backstage/errors'; import { CatalogApi } from '@backstage/catalog-client'; -import { - TemplateEntityV1alpha1, - TemplateEntityV1beta2, - Entity, -} from '@backstage/catalog-model'; +import { TemplateEntityV1beta2, Entity } from '@backstage/catalog-model'; import { ScmIntegrations } from '@backstage/integration'; import { TemplateAction } from '../scaffolder/actions'; import { createBuiltinActions } from '../scaffolder/actions/builtin/createBuiltinActions'; export interface RouterOptions { - preparers: PreparerBuilder; - templaters: TemplaterBuilder; - publishers: PublisherBuilder; - logger: Logger; config: Config; reader: UrlReader; @@ -59,19 +47,11 @@ export interface RouterOptions { catalogClient: CatalogApi; actions?: TemplateAction[]; taskWorkers?: number; -} - -function isAlpha1Template( - entity: TemplateEntityV1alpha1 | TemplateEntityV1beta2, -): entity is TemplateEntityV1alpha1 { - return ( - entity.apiVersion === 'backstage.io/v1alpha1' || - entity.apiVersion === 'backstage.io/v1beta1' - ); + containerRunner: ContainerRunner; } function isBeta2Template( - entity: TemplateEntityV1alpha1 | TemplateEntityV1beta2, + entity: TemplateEntityV1beta2, ): entity is TemplateEntityV1beta2 { return entity.apiVersion === 'backstage.io/v1beta2'; } @@ -83,15 +63,13 @@ export async function createRouter( router.use(express.json()); const { - preparers, - templaters, - publishers, logger: parentLogger, config, reader, database, catalogClient, actions, + containerRunner, taskWorkers, } = options; @@ -118,20 +96,13 @@ export async function createRouter( const actionsToRegister = Array.isArray(actions) ? actions - : [ - ...createLegacyActions({ - preparers, - publishers, - templaters, - }), - ...createBuiltinActions({ - integrations, - catalogClient, - templaters, - reader, - config, - }), - ]; + : createBuiltinActions({ + integrations, + catalogClient, + containerRunner, + reader, + config, + }); actionsToRegister.forEach(action => actionRegistry.register(action)); workers.forEach(worker => worker.start()); @@ -165,42 +136,6 @@ export async function createRouter( schema, })), }); - } else if (isAlpha1Template(template)) { - res.json({ - title: template.metadata.title ?? template.metadata.name, - steps: [ - { - title: 'Fill in template parameters', - schema: template.spec.schema, - }, - { - title: 'Choose owner and repo', - schema: { - type: 'object', - required: ['storePath', 'owner'], - properties: { - owner: { - type: 'string', - title: 'Owner', - description: 'Who is going to own this component', - }, - storePath: { - type: 'string', - title: 'Store path', - description: - 'A full URL to the repository that should be created. e.g https://github.com/backstage/new-repo', - }, - access: { - type: 'string', - title: 'Access', - description: - 'Who should have access, in org/team or user format', - }, - }, - }, - }, - ], - }); } else { throw new InputError( `Unsupported apiVersion field in schema entity, ${ @@ -222,26 +157,14 @@ export async function createRouter( }) .post('/v2/tasks', async (req, res) => { const templateName: string = req.body.templateName; - const values: TemplaterValues = req.body.values; + const values = req.body.values; const token = getBearerToken(req.headers.authorization); const template = await entityClient.findTemplate(templateName, { token, }); let taskSpec; - if (isAlpha1Template(template)) { - logger.warn( - `[DEPRECATION] - Template: ${template.metadata.name} has version ${template.apiVersion} which is going to be deprecated. Please refer to https://backstage.io/docs/features/software-templates/migrating-from-v1alpha1-to-v1beta2 for help on migrating`, - ); - - const result = validate(values, template.spec.schema); - if (!result.valid) { - res.status(400).json({ errors: result.errors }); - return; - } - - taskSpec = templateEntityToSpec(template, values); - } else if (isBeta2Template(template)) { + if (isBeta2Template(template)) { for (const parameters of [template.spec.parameters ?? []].flat()) { const result = validate(values, parameters); From a02ea1e4e121c1d2f26b534488cc44d0c87f7efa Mon Sep 17 00:00:00 2001 From: blam Date: Sat, 19 Jun 2021 02:39:44 +0200 Subject: [PATCH 173/204] breaking: some more changes in the frontend. removing support for v1alpha1 Signed-off-by: blam --- .../sample-templates/remote-templates.yaml | 2 +- .../ScaffolderPage/ScaffolderPage.tsx | 32 ++++++-------- .../components/TemplatePage/TemplatePage.tsx | 43 ------------------- .../src/filter/EntityFilterGroupsProvider.tsx | 14 +++--- plugins/scaffolder/src/filter/context.ts | 4 +- 5 files changed, 23 insertions(+), 72 deletions(-) diff --git a/plugins/scaffolder-backend/sample-templates/remote-templates.yaml b/plugins/scaffolder-backend/sample-templates/remote-templates.yaml index b89b21d5e3..7846a0994e 100644 --- a/plugins/scaffolder-backend/sample-templates/remote-templates.yaml +++ b/plugins/scaffolder-backend/sample-templates/remote-templates.yaml @@ -6,4 +6,4 @@ metadata: spec: type: url targets: - # - https://github.com/spotify/cookiecutter-golang/blob/master/template.yaml + - https://github.com/spotify/cookiecutter-golang/blob/master/template.yaml diff --git a/plugins/scaffolder/src/components/ScaffolderPage/ScaffolderPage.tsx b/plugins/scaffolder/src/components/ScaffolderPage/ScaffolderPage.tsx index 1d16e50568..29758f4ac3 100644 --- a/plugins/scaffolder/src/components/ScaffolderPage/ScaffolderPage.tsx +++ b/plugins/scaffolder/src/components/ScaffolderPage/ScaffolderPage.tsx @@ -14,7 +14,17 @@ * limitations under the License. */ -import { EntityMeta, TemplateEntityV1alpha1 } from '@backstage/catalog-model'; +import { EntityMeta, TemplateEntityV1beta2 } from '@backstage/catalog-model'; +import { + Content, + ContentHeader, + Header, + ItemCardGrid, + Lifecycle, + Page, + Progress, + SupportButton, +} from '@backstage/core-components'; import { useStarredEntities } from '@backstage/plugin-catalog-react'; import { Button, Link, makeStyles, Typography } from '@material-ui/core'; import StarIcon from '@material-ui/icons/Star'; @@ -30,18 +40,6 @@ import { TemplateCard } from '../TemplateCard'; import { configApiRef, useApi, useRouteRef } from '@backstage/core-plugin-api'; -import { - Content, - ContentHeader, - Header, - ItemCardGrid, - Lifecycle, - Page, - Progress, - SupportButton, - WarningPanel, -} from '@backstage/core-components'; - const useStyles = makeStyles(theme => ({ contentWrapper: { display: 'grid', @@ -90,7 +88,7 @@ export const ScaffolderPageContents = () => { ); const [search, setSearch] = useState(''); const [matchingEntities, setMatchingEntities] = useState( - [] as TemplateEntityV1alpha1[], + [] as TemplateEntityV1beta2[], ); const matchesQuery = (metadata: EntityMeta, query: string) => @@ -175,11 +173,7 @@ export const ScaffolderPageContents = () => { {matchingEntities && matchingEntities?.length > 0 && matchingEntities.map((template, i) => ( - + ))} diff --git a/plugins/scaffolder/src/components/TemplatePage/TemplatePage.tsx b/plugins/scaffolder/src/components/TemplatePage/TemplatePage.tsx index 3caece4878..b6cab5b620 100644 --- a/plugins/scaffolder/src/components/TemplatePage/TemplatePage.tsx +++ b/plugins/scaffolder/src/components/TemplatePage/TemplatePage.tsx @@ -16,7 +16,6 @@ import { JsonObject, JsonValue } from '@backstage/config'; import { LinearProgress } from '@material-ui/core'; import { FieldValidation, FormValidation, IChangeEvent } from '@rjsf/core'; -import parseGitUrl from 'git-url-parse'; import React, { useCallback, useState } from 'react'; import { generatePath, Navigate, useNavigate } from 'react-router'; import { useParams } from 'react-router-dom'; @@ -99,39 +98,6 @@ export const createValidator = ( }; }; -const storePathValidator = ( - formData: { storePath?: string }, - errors: FormValidation, -) => { - const { storePath } = formData; - if (!storePath) { - errors.storePath.addError('Store path is required and not present'); - return errors; - } - - try { - const parsedUrl = parseGitUrl(storePath); - - if (!parsedUrl.resource || !parsedUrl.owner || !parsedUrl.name) { - if (parsedUrl.resource === 'dev.azure.com') { - errors.storePath.addError( - "The store path should be formatted like https://dev.azure.com/{org}/{project}/_git/{repo} for Azure URL's", - ); - } else { - errors.storePath.addError( - 'The store path should be a complete Git URL to the new repository location. For example: https://github.com/{owner}/{repo}', - ); - } - } - } catch (ex) { - errors.storePath.addError( - `Failed validation of the store path with message ${ex.message}`, - ); - } - - return errors; -}; - export const TemplatePage = ({ customFieldExtensions = [], }: { @@ -203,15 +169,6 @@ export const TemplatePage = ({ onReset={handleFormReset} onFinish={handleCreate} steps={schema.steps.map(step => { - // TODO: Can delete this function when the migration from v1 to v2 beta is completed - // And just have the default validator for all fields. - if ((step.schema as any)?.properties?.storePath) { - return { - ...step, - validate: (a, b) => storePathValidator(a, b), - }; - } - return { ...step, validate: createValidator(step.schema, customFieldValidators), diff --git a/plugins/scaffolder/src/filter/EntityFilterGroupsProvider.tsx b/plugins/scaffolder/src/filter/EntityFilterGroupsProvider.tsx index 7aa1a21643..a5be11380f 100644 --- a/plugins/scaffolder/src/filter/EntityFilterGroupsProvider.tsx +++ b/plugins/scaffolder/src/filter/EntityFilterGroupsProvider.tsx @@ -14,7 +14,7 @@ * limitations under the License. */ -import { TemplateEntityV1alpha1 } from '@backstage/catalog-model'; +import { TemplateEntityV1beta2 } from '@backstage/catalog-model'; import { catalogApiRef } from '@backstage/plugin-catalog-react'; import React, { useCallback, useEffect, useRef, useState } from 'react'; import { useAsyncFn } from 'react-use'; @@ -50,7 +50,7 @@ function useProvideEntityFilters(): FilterGroupsContext { const response = await catalogApi.getEntities({ filter: { kind: 'Template' }, }); - return response.items as TemplateEntityV1alpha1[]; + return response.items as TemplateEntityV1beta2[]; }); const filterGroups = useRef<{ @@ -64,7 +64,7 @@ function useProvideEntityFilters(): FilterGroupsContext { [filterGroupId: string]: FilterGroupStates; }>({}); const [filteredEntities, setFilteredEntities] = useState< - TemplateEntityV1alpha1[] + TemplateEntityV1beta2[] >([]); const [availableCategories, setAvailableCategories] = useState([]); const [isCatalogEmpty, setCatalogEmpty] = useState(false); @@ -161,7 +161,7 @@ function buildStates( filterGroups: { [filterGroupId: string]: FilterGroup }, selectedFilterKeys: { [filterGroupId: string]: Set }, selectedCategories: string[], - entities?: TemplateEntityV1alpha1[], + entities?: TemplateEntityV1beta2[], error?: Error, ): { [filterGroupId: string]: FilterGroupStates } { // On error - all entries are an error state @@ -208,7 +208,7 @@ function buildStates( } // Given all entites, find all possible categories and provide them in a sorted list. -function collectCategories(entities?: TemplateEntityV1alpha1[]): string[] { +function collectCategories(entities?: TemplateEntityV1beta2[]): string[] { const categories = new Set(); (entities || []).forEach(e => { if (e.spec?.type) { @@ -224,9 +224,9 @@ function buildMatchingEntities( filterGroups: { [filterGroupId: string]: FilterGroup }, selectedFilterKeys: { [filterGroupId: string]: Set }, selectedCategories: string[], - entities?: TemplateEntityV1alpha1[], + entities?: TemplateEntityV1beta2[], excludeFilterGroupId?: string, -): TemplateEntityV1alpha1[] { +): TemplateEntityV1beta2[] { // Build one filter fn per filter group const allFilters: EntityFilterFn[] = []; for (const [filterGroupId, filterGroup] of Object.entries(filterGroups)) { diff --git a/plugins/scaffolder/src/filter/context.ts b/plugins/scaffolder/src/filter/context.ts index ee66e3d9da..385d3f6eb5 100644 --- a/plugins/scaffolder/src/filter/context.ts +++ b/plugins/scaffolder/src/filter/context.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { TemplateEntityV1alpha1 } from '@backstage/catalog-model'; +import { TemplateEntityV1beta2 } from '@backstage/catalog-model'; import { createContext } from 'react'; import { FilterGroup, FilterGroupStates } from './types'; @@ -32,7 +32,7 @@ export type FilterGroupsContext = { loading: boolean; error?: Error; filterGroupStates: { [filterGroupId: string]: FilterGroupStates }; - filteredEntities: TemplateEntityV1alpha1[]; + filteredEntities: TemplateEntityV1beta2[]; availableCategories: string[]; isCatalogEmpty: boolean; }; From 18660e933765f2b93c328bc15f04af7c637cd050 Mon Sep 17 00:00:00 2001 From: blam Date: Wed, 30 Jun 2021 20:53:50 +0200 Subject: [PATCH 174/204] chore: fixing merge conflict Signed-off-by: blam --- .../src/scaffolder/actions/builtin/helpers.ts | 4 ---- 1 file changed, 4 deletions(-) diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/helpers.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/helpers.ts index a024be4f67..e2459a8ca7 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/helpers.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/helpers.ts @@ -1,9 +1,5 @@ /* -<<<<<<< HEAD:plugins/scaffolder-backend/src/scaffolder/stages/publish/helpers.ts - * Copyright 2020 The Backstage Authors -======= * Copyright 2021 The Backstage Authors ->>>>>>> breaking: removing alphav1 support for templates:plugins/scaffolder-backend/src/scaffolder/actions/builtin/helpers.ts * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. From a41b024a0f092276104b92fdfcc84faf68aa8d87 Mon Sep 17 00:00:00 2001 From: blam Date: Wed, 30 Jun 2021 21:18:39 +0200 Subject: [PATCH 175/204] feat: removing the last parts of v1alpha1 and fixing up TypeScript Signed-off-by: blam --- .../builtin/fetch/cookiecutter.test.ts | 186 ------------------ .../actions/builtin/publish/azure.test.ts | 7 +- .../actions/builtin/publish/bitbucket.test.ts | 5 +- .../actions/builtin/publish/github.test.ts | 7 +- .../actions/builtin/publish/gitlab.test.ts | 6 +- .../src/service/router.test.ts | 36 +--- .../ScaffolderPage/ScaffolderPage.tsx | 1 + .../components/TemplateCard/TemplateCard.tsx | 6 +- 8 files changed, 25 insertions(+), 229 deletions(-) delete mode 100644 plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/cookiecutter.test.ts diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/cookiecutter.test.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/cookiecutter.test.ts deleted file mode 100644 index 3ce3052956..0000000000 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/cookiecutter.test.ts +++ /dev/null @@ -1,186 +0,0 @@ -/* - * Copyright 2021 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -jest.mock('./helpers'); - -import { getVoidLogger, UrlReader } from '@backstage/backend-common'; -import { ConfigReader } from '@backstage/config'; -import { ScmIntegrations } from '@backstage/integration'; -import mock from 'mock-fs'; -import os from 'os'; -import { resolve as resolvePath } from 'path'; -import { PassThrough } from 'stream'; -import { Templaters } from '../../../stages/templater'; -import { createFetchCookiecutterAction } from './cookiecutter'; -import { fetchContents } from './helpers'; - -describe('fetch:cookiecutter', () => { - const integrations = ScmIntegrations.fromConfig( - new ConfigReader({ - integrations: { - azure: [ - { host: 'dev.azure.com', token: 'tokenlols' }, - { host: 'myazurehostnotoken.com' }, - ], - }, - }), - ); - - const templaters = new Templaters(); - const cookiecutterTemplater = { run: jest.fn() }; - const mockTmpDir = os.tmpdir(); - const mockContext = { - input: { - url: 'https://google.com/cookie/cutter', - targetPath: 'something', - values: { - help: 'me', - }, - }, - baseUrl: 'somebase', - workspacePath: mockTmpDir, - logger: getVoidLogger(), - logStream: new PassThrough(), - output: jest.fn(), - createTemporaryDirectory: jest.fn().mockResolvedValue(mockTmpDir), - }; - - const mockReader: UrlReader = { - read: jest.fn(), - readTree: jest.fn(), - search: jest.fn(), - }; - - const action = createFetchCookiecutterAction({ - integrations, - templaters, - reader: mockReader, - }); - - templaters.register('cookiecutter', cookiecutterTemplater); - - beforeEach(() => { - mock({ [`${mockContext.workspacePath}/result`]: {} }); - jest.restoreAllMocks(); - }); - - afterEach(() => { - mock.restore(); - }); - - it('should call fetchContents with the correct values', async () => { - await action.handler(mockContext); - - expect(fetchContents).toHaveBeenCalledWith({ - reader: mockReader, - integrations, - baseUrl: mockContext.baseUrl, - fetchUrl: mockContext.input.url, - outputPath: resolvePath( - mockContext.workspacePath, - `template/{{cookiecutter and 'contents'}}`, - ), - }); - }); - - it('should execute the cookiecutter templater with the correct values', async () => { - await action.handler(mockContext); - - expect(cookiecutterTemplater.run).toHaveBeenCalledWith({ - workspacePath: mockTmpDir, - logStream: mockContext.logStream, - values: mockContext.input.values, - }); - }); - - it('should execute the cookiecutter templater with optional inputs if they are present and valid', async () => { - await action.handler({ - ...mockContext, - input: { - ...mockContext.input, - copyWithoutRender: ['goreleaser.yml'], - extensions: [ - 'jinja2_custom_filters_extension.string_filters_extension.StringFilterExtension', - ], - imageName: 'foo/cookiecutter-image-with-extensions', - }, - }); - - expect(cookiecutterTemplater.run).toHaveBeenCalledWith({ - workspacePath: mockTmpDir, - logStream: mockContext.logStream, - values: { - ...mockContext.input.values, - _copy_without_render: ['goreleaser.yml'], - _extensions: [ - 'jinja2_custom_filters_extension.string_filters_extension.StringFilterExtension', - ], - imageName: 'foo/cookiecutter-image-with-extensions', - }, - }); - }); - - it('should throw if copyWithoutRender is not an Array', async () => { - await expect( - action.handler({ - ...mockContext, - input: { - ...mockContext.input, - copyWithoutRender: 'xyz', - }, - }), - ).rejects.toThrow(/copyWithoutRender must be an Array/); - }); - - it('should throw if extensions is not an Array', async () => { - await expect( - action.handler({ - ...mockContext, - input: { - ...mockContext.input, - extensions: 'xyz', - }, - }), - ).rejects.toThrow(/extensions must be an Array/); - }); - - it('should throw if there is no cookiecutter templater initialized', async () => { - const templatersWithoutCookiecutter = new Templaters(); - - const newAction = createFetchCookiecutterAction({ - integrations, - templaters: templatersWithoutCookiecutter, - reader: mockReader, - }); - - await expect(newAction.handler(mockContext)).rejects.toThrow( - /No templater registered/, - ); - }); - - it('should throw if the target directory is outside of the workspace path', async () => { - await expect( - action.handler({ - ...mockContext, - input: { - ...mockContext.input, - targetPath: '/foo', - }, - }), - ).rejects.toThrow( - /Relative path is not allowed to refer to a directory outside its parent/, - ); - }); -}); diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/azure.test.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/azure.test.ts index 1dc29ea763..30995dee38 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/azure.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/azure.test.ts @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Backstage Authors + * Copyright 2021 The Backstage Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,19 +13,20 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -jest.mock('../../../stages/publish/helpers'); jest.mock('azure-devops-node-api', () => ({ WebApi: jest.fn(), getPersonalAccessTokenHandler: jest.fn().mockReturnValue(() => {}), })); +jest.mock('../helpers'); + import { createPublishAzureAction } from './azure'; import { ScmIntegrations } from '@backstage/integration'; import { ConfigReader } from '@backstage/config'; import { getVoidLogger } from '@backstage/backend-common'; import { WebApi } from 'azure-devops-node-api'; import { PassThrough } from 'stream'; -import { initRepoAndPush } from '../../../stages/publish/helpers'; +import { initRepoAndPush } from '../helpers'; describe('publish:azure', () => { const config = new ConfigReader({ diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/bitbucket.test.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/bitbucket.test.ts index 0e5f8df72b..9fe245935b 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/bitbucket.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/bitbucket.test.ts @@ -13,7 +13,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -jest.mock('../../../stages/publish/helpers'); + +jest.mock('../helpers'); import { createPublishBitbucketAction } from './bitbucket'; import { rest } from 'msw'; @@ -23,7 +24,7 @@ import { ScmIntegrations } from '@backstage/integration'; import { ConfigReader } from '@backstage/config'; import { getVoidLogger } from '@backstage/backend-common'; import { PassThrough } from 'stream'; -import { initRepoAndPush } from '../../../stages/publish/helpers'; +import { initRepoAndPush } from '../helpers'; describe('publish:bitbucket', () => { const config = new ConfigReader({ diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/github.test.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/github.test.ts index 0b277c4739..f0725d6e8e 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/github.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/github.test.ts @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Backstage Authors + * Copyright 2021 The Backstage Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -jest.mock('../../../stages/publish/helpers'); + +jest.mock('../helpers'); jest.mock('@octokit/rest'); import { createPublishGithubAction } from './github'; @@ -21,7 +22,7 @@ import { ScmIntegrations } from '@backstage/integration'; import { ConfigReader } from '@backstage/config'; import { getVoidLogger } from '@backstage/backend-common'; import { PassThrough } from 'stream'; -import { initRepoAndPush } from '../../../stages/publish/helpers'; +import { initRepoAndPush } from '../helpers'; import { when } from 'jest-when'; describe('publish:github', () => { diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.test.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.test.ts index 25a129d905..5150205a08 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.test.ts @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Backstage Authors + * Copyright 2021 The Backstage Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -jest.mock('../../../stages/publish/helpers'); +jest.mock('../helpers'); jest.mock('@gitbeaker/node'); import { createPublishGitlabAction } from './gitlab'; @@ -21,7 +21,7 @@ import { ScmIntegrations } from '@backstage/integration'; import { ConfigReader } from '@backstage/config'; import { getVoidLogger } from '@backstage/backend-common'; import { PassThrough } from 'stream'; -import { initRepoAndPush } from '../../../stages/publish/helpers'; +import { initRepoAndPush } from '../helpers'; describe('publish:gitlab', () => { const config = new ConfigReader({ diff --git a/plugins/scaffolder-backend/src/service/router.test.ts b/plugins/scaffolder-backend/src/service/router.test.ts index b43b62a413..d91ec2b7d0 100644 --- a/plugins/scaffolder-backend/src/service/router.test.ts +++ b/plugins/scaffolder-backend/src/service/router.test.ts @@ -33,12 +33,13 @@ import { PluginDatabaseManager, DatabaseManager, UrlReaders, + DockerContainerRunner, } from '@backstage/backend-common'; import { CatalogApi } from '@backstage/catalog-client'; import { ConfigReader } from '@backstage/config'; import express from 'express'; import request from 'supertest'; -import { Preparers, Publishers, Templaters } from '../scaffolder'; +import { TemplateEntityV1beta2 } from '../../../../packages/catalog-model/src'; import { createRouter } from './router'; const createCatalogClient = (templates: any[] = []) => @@ -66,8 +67,8 @@ const mockUrlReader = UrlReaders.default({ describe('createRouter', () => { let app: express.Express; - const template = { - apiVersion: 'backstage.io/v1alpha1', + const template: TemplateEntityV1beta2 = { + apiVersion: 'backstage.io/v1beta2', kind: 'Template', metadata: { description: 'Create a new CRA website project', @@ -80,42 +81,19 @@ describe('createRouter', () => { }, spec: { owner: 'web@example.com', - path: '.', - schema: { - properties: { - component_id: { - description: 'Unique name of the component', - title: 'Name', - type: 'string', - }, - description: { - description: 'Description of the component', - title: 'Description', - type: 'string', - }, - use_typescript: { - default: true, - description: 'Include TypeScript', - title: 'Use TypeScript', - type: 'boolean', - }, - }, - required: ['component_id', 'use_typescript'], - }, - templater: 'cra', type: 'website', + steps: [], + parameters: [], }, }; beforeAll(async () => { const router = await createRouter({ logger: getVoidLogger(), - preparers: new Preparers(), - templaters: new Templaters(), - publishers: new Publishers(), config: new ConfigReader({}), database: createDatabase(), catalogClient: createCatalogClient([template]), + containerRunner: new DockerContainerRunner({} as any), reader: mockUrlReader, }); app = express().use(router); diff --git a/plugins/scaffolder/src/components/ScaffolderPage/ScaffolderPage.tsx b/plugins/scaffolder/src/components/ScaffolderPage/ScaffolderPage.tsx index 29758f4ac3..65386b60b3 100644 --- a/plugins/scaffolder/src/components/ScaffolderPage/ScaffolderPage.tsx +++ b/plugins/scaffolder/src/components/ScaffolderPage/ScaffolderPage.tsx @@ -21,6 +21,7 @@ import { Header, ItemCardGrid, Lifecycle, + WarningPanel, Page, Progress, SupportButton, diff --git a/plugins/scaffolder/src/components/TemplateCard/TemplateCard.tsx b/plugins/scaffolder/src/components/TemplateCard/TemplateCard.tsx index ad91fc6cfd..9d2e827be9 100644 --- a/plugins/scaffolder/src/components/TemplateCard/TemplateCard.tsx +++ b/plugins/scaffolder/src/components/TemplateCard/TemplateCard.tsx @@ -16,7 +16,7 @@ import { Entity, RELATION_OWNED_BY, - TemplateEntityV1alpha1, + TemplateEntityV1beta2, } from '@backstage/catalog-model'; import { ScmIntegrationIcon, @@ -93,7 +93,7 @@ const useDeprecationStyles = makeStyles(theme => ({ })); export type TemplateCardProps = { - template: TemplateEntityV1alpha1; + template: TemplateEntityV1beta2; deprecated?: boolean; }; @@ -106,7 +106,7 @@ type TemplateProps = { }; const getTemplateCardProps = ( - template: TemplateEntityV1alpha1, + template: TemplateEntityV1beta2, ): TemplateProps & { key: string } => { return { key: template.metadata.uid!, From 7632873678f0360cabd0744614a5a37ec50f4ee8 Mon Sep 17 00:00:00 2001 From: blam Date: Fri, 2 Jul 2021 11:02:31 +0200 Subject: [PATCH 176/204] chore: updating api-reports Signed-off-by: blam --- packages/catalog-model/api-report.md | 23 ----------------------- 1 file changed, 23 deletions(-) diff --git a/packages/catalog-model/api-report.md b/packages/catalog-model/api-report.md index 68644bef87..5d055566be 100644 --- a/packages/catalog-model/api-report.md +++ b/packages/catalog-model/api-report.md @@ -492,29 +492,6 @@ export { SystemEntityV1alpha1 } // @public (undocumented) export const systemEntityV1alpha1Validator: KindValidator; -// @public (undocumented) -interface TemplateEntityV1alpha1 extends Entity { - // (undocumented) - apiVersion: 'backstage.io/v1alpha1' | 'backstage.io/v1beta1'; - // (undocumented) - kind: 'Template'; - // (undocumented) - spec: { - type: string; - templater: string; - path?: string; - schema: JSONSchema; - owner?: string; - }; -} - -export { TemplateEntityV1alpha1 as TemplateEntity } - -export { TemplateEntityV1alpha1 } - -// @public (undocumented) -export const templateEntityV1alpha1Validator: KindValidator; - // @public (undocumented) export interface TemplateEntityV1beta2 extends Entity { // (undocumented) From 70bb2a711f04b0bdc213add414556cd6776b6aff Mon Sep 17 00:00:00 2001 From: blam Date: Fri, 2 Jul 2021 14:26:07 +0200 Subject: [PATCH 177/204] chore: fix up some code review comments Signed-off-by: blam --- plugins/catalog-backend/src/ingestion/LocationReaders.ts | 1 - .../src/next/processing/DefaultCatalogProcessingOrchestrator.ts | 1 - plugins/scaffolder-backend/src/service/router.test.ts | 2 +- 3 files changed, 1 insertion(+), 3 deletions(-) diff --git a/plugins/catalog-backend/src/ingestion/LocationReaders.ts b/plugins/catalog-backend/src/ingestion/LocationReaders.ts index 86a8ebb9f2..624c7aaa61 100644 --- a/plugins/catalog-backend/src/ingestion/LocationReaders.ts +++ b/plugins/catalog-backend/src/ingestion/LocationReaders.ts @@ -265,7 +265,6 @@ export class LocationReaders implements LocationReader { )}, ${e}`; emit(result.inputError(item.location, message)); logger.warn(message); - logger.debug(e.stack); return undefined; } } diff --git a/plugins/catalog-backend/src/next/processing/DefaultCatalogProcessingOrchestrator.ts b/plugins/catalog-backend/src/next/processing/DefaultCatalogProcessingOrchestrator.ts index 235673db03..bb23b6afb3 100644 --- a/plugins/catalog-backend/src/next/processing/DefaultCatalogProcessingOrchestrator.ts +++ b/plugins/catalog-backend/src/next/processing/DefaultCatalogProcessingOrchestrator.ts @@ -124,7 +124,6 @@ export class DefaultCatalogProcessingOrchestrator }; } catch (error) { this.options.logger.warn(error.message); - this.options.logger.debug(error.stack); return { ok: false, errors: collector.results().errors.concat(error), diff --git a/plugins/scaffolder-backend/src/service/router.test.ts b/plugins/scaffolder-backend/src/service/router.test.ts index d91ec2b7d0..c693573c4f 100644 --- a/plugins/scaffolder-backend/src/service/router.test.ts +++ b/plugins/scaffolder-backend/src/service/router.test.ts @@ -39,7 +39,7 @@ import { CatalogApi } from '@backstage/catalog-client'; import { ConfigReader } from '@backstage/config'; import express from 'express'; import request from 'supertest'; -import { TemplateEntityV1beta2 } from '../../../../packages/catalog-model/src'; +import { TemplateEntityV1beta2 } from '@backstage/catalog-model'; import { createRouter } from './router'; const createCatalogClient = (templates: any[] = []) => From f0928d674fdd0f0336c13f0d6420a43cb7050d88 Mon Sep 17 00:00:00 2001 From: blam Date: Fri, 2 Jul 2021 14:50:39 +0200 Subject: [PATCH 178/204] chore: fix e2e tests as they no longer need all of the Templaters and Publishers Signed-off-by: blam --- .../packages/backend/src/plugins/scaffolder.ts | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) 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 333ffa11df..ee40b06320 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 @@ -24,23 +24,11 @@ export default async function createPlugin({ const dockerClient = new Docker(); const containerRunner = new DockerContainerRunner({ dockerClient }); - const cookiecutterTemplater = new CookieCutter({ containerRunner }); - const craTemplater = new CreateReactAppTemplater({ containerRunner }); - const templaters = new Templaters(); - - templaters.register('cookiecutter', cookiecutterTemplater); - templaters.register('cra', craTemplater); - - const preparers = await Preparers.fromConfig(config, { logger }); - const publishers = await Publishers.fromConfig(config, { logger }); - const discovery = SingleHostDiscovery.fromConfig(config); const catalogClient = new CatalogClient({ discoveryApi: discovery }); return await createRouter({ - preparers, - templaters, - publishers, + containerRunner, logger, config, database, From 350555727fcb85c6ace5728b0977e590d6fb2f4c Mon Sep 17 00:00:00 2001 From: blam Date: Fri, 2 Jul 2021 14:56:18 +0200 Subject: [PATCH 179/204] chore: dont need to export this dep any more Signed-off-by: blam --- plugins/scaffolder-backend/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/scaffolder-backend/package.json b/plugins/scaffolder-backend/package.json index 0a0ccd36b1..7173f865c5 100644 --- a/plugins/scaffolder-backend/package.json +++ b/plugins/scaffolder-backend/package.json @@ -39,7 +39,6 @@ "@gitbeaker/node": "^30.2.0", "@octokit/rest": "^18.5.3", "@types/express": "^4.17.6", - "@types/git-url-parse": "^9.0.0", "azure-devops-node-api": "^10.2.2", "command-exists": "^1.2.9", "compression": "^1.7.4", @@ -68,6 +67,7 @@ "@backstage/test-utils": "^0.1.14", "@types/command-exists": "^1.2.0", "@types/fs-extra": "^9.0.1", + "@types/git-url-parse": "^9.0.0", "@types/mock-fs": "^4.13.0", "@types/supertest": "^2.0.8", "jest-when": "^3.1.0", From b9cba53a05c85d442e6a6961b7ca1a857e8577d3 Mon Sep 17 00:00:00 2001 From: blam Date: Fri, 2 Jul 2021 15:08:36 +0200 Subject: [PATCH 180/204] chore: removing the extra deps Signed-off-by: blam --- .../default-app/packages/backend/src/plugins/scaffolder.ts | 5 ----- 1 file changed, 5 deletions(-) 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 ee40b06320..a0201cec01 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 @@ -4,12 +4,7 @@ import { } from '@backstage/backend-common'; import { CatalogClient } from '@backstage/catalog-client'; import { - CookieCutter, - CreateReactAppTemplater, createRouter, - Preparers, - Publishers, - Templaters, } from '@backstage/plugin-scaffolder-backend'; import Docker from 'dockerode'; import { Router } from 'express'; From 4c689b0fae738935be3b5659e7524f244bc68dd7 Mon Sep 17 00:00:00 2001 From: blam Date: Fri, 2 Jul 2021 16:18:22 +0200 Subject: [PATCH 181/204] chore: making the failing test pass because of parameter validation Signed-off-by: blam --- .../scaffolder-backend/src/service/router.test.ts | 13 +++++++++++-- plugins/scaffolder-backend/src/service/router.ts | 1 + 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/plugins/scaffolder-backend/src/service/router.test.ts b/plugins/scaffolder-backend/src/service/router.test.ts index c693573c4f..227f6d3c88 100644 --- a/plugins/scaffolder-backend/src/service/router.test.ts +++ b/plugins/scaffolder-backend/src/service/router.test.ts @@ -83,7 +83,16 @@ describe('createRouter', () => { owner: 'web@example.com', type: 'website', steps: [], - parameters: [], + parameters: { + type: 'object', + required: ['required'], + properties: { + required: { + type: 'string', + description: 'Required parameter', + }, + }, + }, }, }; @@ -117,7 +126,7 @@ describe('createRouter', () => { const response = await request(app) .post('/v2/tasks') .send({ - templateName: '', + templateName: 'create-react-app-template', values: { storePath: 'https://github.com/backstage/backstage', }, diff --git a/plugins/scaffolder-backend/src/service/router.ts b/plugins/scaffolder-backend/src/service/router.ts index 3ad4646b01..2b5bdb3bf8 100644 --- a/plugins/scaffolder-backend/src/service/router.ts +++ b/plugins/scaffolder-backend/src/service/router.ts @@ -164,6 +164,7 @@ export async function createRouter( }); let taskSpec; + if (isBeta2Template(template)) { for (const parameters of [template.spec.parameters ?? []].flat()) { const result = validate(values, parameters); From 2529ec28a6bad75a9c8e617873af491edea9a2ec Mon Sep 17 00:00:00 2001 From: blam Date: Fri, 2 Jul 2021 16:21:49 +0200 Subject: [PATCH 182/204] chore: fixing all tests Signed-off-by: blam --- plugins/scaffolder-backend/src/service/router.test.ts | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/plugins/scaffolder-backend/src/service/router.test.ts b/plugins/scaffolder-backend/src/service/router.test.ts index 227f6d3c88..c0fdcb2ef7 100644 --- a/plugins/scaffolder-backend/src/service/router.test.ts +++ b/plugins/scaffolder-backend/src/service/router.test.ts @@ -141,10 +141,7 @@ describe('createRouter', () => { .send({ templateName: 'create-react-app-template', values: { - storePath: 'https://github.com/backstage/backstage', - component_id: '123', - name: 'test', - use_typescript: false, + required: 'required-value', }, }); @@ -161,10 +158,7 @@ describe('createRouter', () => { .send({ templateName: 'create-react-app-template', values: { - storePath: 'https://github.com/backstage/backstage', - component_id: '123', - name: 'test', - use_typescript: false, + required: 'required-value', }, }); From b658d339442f30ac3ee209c8118fcdcb3139183f Mon Sep 17 00:00:00 2001 From: blam Date: Mon, 5 Jul 2021 20:38:27 +0200 Subject: [PATCH 183/204] chore: added some tests for cookiecutter but they need re-writing Signed-off-by: blam --- .../builtin/fetch/cookiecutter.test.ts | 194 ++++++++++++++++++ .../actions/builtin/fetch/cookiecutter.ts | 1 + 2 files changed, 195 insertions(+) create mode 100644 plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/cookiecutter.test.ts diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/cookiecutter.test.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/cookiecutter.test.ts new file mode 100644 index 0000000000..53f255a639 --- /dev/null +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/cookiecutter.test.ts @@ -0,0 +1,194 @@ +/* + * Copyright 2021 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +const runCommand = jest.fn(); +const commandExists = jest.fn(); +const fetchContents = jest.fn(); +jest.mock('./helpers', () => ({ runCommand, fetchContents })); +jest.mock('command-exists', () => commandExists); +jest.mock('./helpers'); +jest.mock('fs-extra'); + +import fs from 'fs-extra'; +import { + getVoidLogger, + UrlReader, + ContainerRunner, +} from '@backstage/backend-common'; +import { ConfigReader } from '@backstage/config'; +import { ScmIntegrations } from '@backstage/integration'; +import mock from 'mock-fs'; +import os from 'os'; +import { resolve as resolvePath } from 'path'; +import { PassThrough } from 'stream'; +import { createFetchCookiecutterAction } from './cookiecutter'; + +describe('fetch:cookiecutter', () => { + const integrations = ScmIntegrations.fromConfig( + new ConfigReader({ + integrations: { + azure: [ + { host: 'dev.azure.com', token: 'tokenlols' }, + { host: 'myazurehostnotoken.com' }, + ], + }, + }), + ); + + const mockTmpDir = os.tmpdir(); + const mockContext = { + input: { + url: 'https://google.com/cookie/cutter', + targetPath: 'something', + values: { + help: 'me', + }, + }, + baseUrl: 'somebase', + workspacePath: mockTmpDir, + logger: getVoidLogger(), + logStream: new PassThrough(), + output: jest.fn(), + createTemporaryDirectory: jest.fn().mockResolvedValue(mockTmpDir), + }; + + const containerRunner: jest.Mocked = { + runContainer: jest.fn(), + }; + + const mockReader: UrlReader = { + read: jest.fn(), + readTree: jest.fn(), + search: jest.fn(), + }; + + const action = createFetchCookiecutterAction({ + integrations, + containerRunner, + reader: mockReader, + }); + + beforeEach(() => { + (fs.readdir as jest.Mock).mockReturnValueOnce(['cookiecutter.json']); + + mock({ + [`${mockContext.workspacePath}/template`]: { 'cookiecutter.json': '{}' }, + }); + mock({ [`${mockContext.workspacePath}/result`]: {} }); + mock({ + [`${mockContext.workspacePath}/intermediate`]: {}, + }); + jest.restoreAllMocks(); + commandExists.mockRejectedValue(null); + }); + + afterEach(() => { + mock.restore(); + }); + + it('should call fetchContents with the correct values', async () => { + await action.handler(mockContext); + + expect(fetchContents).toHaveBeenCalledWith({ + reader: mockReader, + integrations, + baseUrl: mockContext.baseUrl, + fetchUrl: mockContext.input.url, + outputPath: resolvePath( + mockContext.workspacePath, + `template/{{cookiecutter and 'contents'}}`, + ), + }); + }); + + it('should execute the cookiecutter templater with optional inputs if they are present and valid', async () => { + await action.handler({ + ...mockContext, + input: { + ...mockContext.input, + copyWithoutRender: ['goreleaser.yml'], + extensions: [ + 'jinja2_custom_filters_extension.string_filters_extension.StringFilterExtension', + ], + imageName: 'foo/cookiecutter-image-with-extensions', + }, + }); + + expect(cookiecutterTemplater.run).toHaveBeenCalledWith({ + workspacePath: mockTmpDir, + logStream: mockContext.logStream, + values: { + ...mockContext.input.values, + _copy_without_render: ['goreleaser.yml'], + _extensions: [ + 'jinja2_custom_filters_extension.string_filters_extension.StringFilterExtension', + ], + imageName: 'foo/cookiecutter-image-with-extensions', + }, + }); + }); + + // it('should throw if copyWithoutRender is not an Array', async () => { + // await expect( + // action.handler({ + // ...mockContext, + // input: { + // ...mockContext.input, + // copyWithoutRender: 'xyz', + // }, + // }), + // ).rejects.toThrow(/copyWithoutRender must be an Array/); + // }); + + // it('should throw if extensions is not an Array', async () => { + // await expect( + // action.handler({ + // ...mockContext, + // input: { + // ...mockContext.input, + // extensions: 'xyz', + // }, + // }), + // ).rejects.toThrow(/extensions must be an Array/); + // }); + + // it('should throw if there is no cookiecutter templater initialized', async () => { + // const templatersWithoutCookiecutter = new Templaters(); + + // const newAction = createFetchCookiecutterAction({ + // integrations, + // templaters: templatersWithoutCookiecutter, + // reader: mockReader, + // }); + + // await expect(newAction.handler(mockContext)).rejects.toThrow( + // /No templater registered/, + // ); + // }); + + // it('should throw if the target directory is outside of the workspace path', async () => { + // await expect( + // action.handler({ + // ...mockContext, + // input: { + // ...mockContext.input, + // targetPath: '/foo', + // }, + // }), + // ).rejects.toThrow( + // /Relative path is not allowed to refer to a directory outside its parent/, + // ); + // }); +}); diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/cookiecutter.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/cookiecutter.ts index e5720204c7..2bf22ce4fd 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/cookiecutter.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/cookiecutter.ts @@ -108,6 +108,7 @@ export class CookiecutterRunner { // if cookiecutter was successful, intermediateDir will contain // exactly one directory. + const [generated] = await fs.readdir(intermediateDir); if (generated === undefined) { From 2ed57f31c76a22358da80d5b5e9959d26d8e2036 Mon Sep 17 00:00:00 2001 From: blam Date: Tue, 6 Jul 2021 20:20:49 +0200 Subject: [PATCH 184/204] chore: write some tests for the cookiecutter templater Signed-off-by: blam --- .../builtin/fetch/cookiecutter.test.ts | 252 ++++++++++-------- 1 file changed, 138 insertions(+), 114 deletions(-) diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/cookiecutter.test.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/cookiecutter.test.ts index 53f255a639..8bd205be1d 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/cookiecutter.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/cookiecutter.test.ts @@ -16,24 +16,26 @@ const runCommand = jest.fn(); const commandExists = jest.fn(); const fetchContents = jest.fn(); -jest.mock('./helpers', () => ({ runCommand, fetchContents })); -jest.mock('command-exists', () => commandExists); -jest.mock('./helpers'); -jest.mock('fs-extra'); -import fs from 'fs-extra'; +jest.mock('./helpers', () => ({ fetchContents })); +jest.mock('command-exists', () => commandExists); +jest.mock('../helpers', () => ({ runCommand })); + import { getVoidLogger, UrlReader, ContainerRunner, } from '@backstage/backend-common'; -import { ConfigReader } from '@backstage/config'; +import { ConfigReader, JsonObject } from '@backstage/config'; import { ScmIntegrations } from '@backstage/integration'; import mock from 'mock-fs'; import os from 'os'; -import { resolve as resolvePath } from 'path'; import { PassThrough } from 'stream'; import { createFetchCookiecutterAction } from './cookiecutter'; +import { join } from 'path'; +import { ActionContext } from '../../types'; + +import fs from 'fs-extra'; describe('fetch:cookiecutter', () => { const integrations = ScmIntegrations.fromConfig( @@ -48,21 +50,15 @@ describe('fetch:cookiecutter', () => { ); const mockTmpDir = os.tmpdir(); - const mockContext = { - input: { - url: 'https://google.com/cookie/cutter', - targetPath: 'something', - values: { - help: 'me', - }, - }, - baseUrl: 'somebase', - workspacePath: mockTmpDir, - logger: getVoidLogger(), - logStream: new PassThrough(), - output: jest.fn(), - createTemporaryDirectory: jest.fn().mockResolvedValue(mockTmpDir), - }; + + let mockContext: ActionContext<{ + url: string; + targetPath?: string; + values: JsonObject; + copyWithoutRender?: string[]; + extensions?: string[]; + imageName?: string; + }>; const containerRunner: jest.Mocked = { runContainer: jest.fn(), @@ -81,114 +77,142 @@ describe('fetch:cookiecutter', () => { }); beforeEach(() => { - (fs.readdir as jest.Mock).mockReturnValueOnce(['cookiecutter.json']); + jest.resetAllMocks(); - mock({ - [`${mockContext.workspacePath}/template`]: { 'cookiecutter.json': '{}' }, + mockContext = { + input: { + url: 'https://google.com/cookie/cutter', + targetPath: 'something', + values: { + help: 'me', + }, + }, + baseUrl: 'somebase', + workspacePath: mockTmpDir, + logger: getVoidLogger(), + logStream: new PassThrough(), + output: jest.fn(), + createTemporaryDirectory: jest.fn().mockResolvedValue(mockTmpDir), + }; + + // mock the temp directory + mock({ [mockTmpDir]: {} }); + mock({ [`${join(mockTmpDir, 'template')}`]: {} }); + + commandExists.mockResolvedValue(null); + + // Mock when run container is called it creates some new files in the mock filesystem + containerRunner.runContainer.mockImplementation(async () => { + mock({ + [`${join(mockTmpDir, 'intermediate')}`]: { + 'testfile.json': '{}', + }, + }); }); - mock({ [`${mockContext.workspacePath}/result`]: {} }); - mock({ - [`${mockContext.workspacePath}/intermediate`]: {}, + + // Mock when runCommand is called it creats some new files in the mock filesystem + runCommand.mockImplementation(async () => { + mock({ + [`${join(mockTmpDir, 'intermediate')}`]: { + 'testfile.json': '{}', + }, + }); }); - jest.restoreAllMocks(); - commandExists.mockRejectedValue(null); }); afterEach(() => { mock.restore(); }); - it('should call fetchContents with the correct values', async () => { + it('should throw an error when copyWithoutRender is not an array', async () => { + (mockContext.input as any).copyWithoutRender = 'not an array'; + + await expect( + action.handler(mockContext), + ).rejects.toThrowErrorMatchingInlineSnapshot( + `"Fetch action input copyWithoutRender must be an Array"`, + ); + }); + + it('should throw an error when extensions is not an array', async () => { + (mockContext.input as any).extensions = 'not an array'; + + await expect( + action.handler(mockContext), + ).rejects.toThrowErrorMatchingInlineSnapshot( + `"Fetch action input extensions must be an Array"`, + ); + }); + + it('should call fetchContents with the correct variables', async () => { + fetchContents.mockImplementation(() => Promise.resolve()); + await action.handler(mockContext); + expect(fetchContents).toHaveBeenCalledWith( + expect.objectContaining({ + reader: mockReader, + integrations, + baseUrl: mockContext.baseUrl, + fetchUrl: mockContext.input.url, + outputPath: join( + mockTmpDir, + 'template', + "{{cookiecutter and 'contents'}}", + ), + }), + ); + }); + + it('should call out to cookiecutter using runCommand when cookiecutter is installed', async () => { + commandExists.mockResolvedValue(true); + await action.handler(mockContext); - expect(fetchContents).toHaveBeenCalledWith({ - reader: mockReader, - integrations, - baseUrl: mockContext.baseUrl, - fetchUrl: mockContext.input.url, - outputPath: resolvePath( - mockContext.workspacePath, - `template/{{cookiecutter and 'contents'}}`, - ), - }); + expect(runCommand).toHaveBeenCalledWith( + expect.objectContaining({ + command: 'cookiecutter', + args: [ + '--no-input', + '-o', + join(mockTmpDir, 'intermediate'), + join(mockTmpDir, 'template'), + '--verbose', + ], + logStream: mockContext.logStream, + }), + ); }); - it('should execute the cookiecutter templater with optional inputs if they are present and valid', async () => { - await action.handler({ - ...mockContext, - input: { - ...mockContext.input, - copyWithoutRender: ['goreleaser.yml'], - extensions: [ - 'jinja2_custom_filters_extension.string_filters_extension.StringFilterExtension', - ], - imageName: 'foo/cookiecutter-image-with-extensions', - }, - }); + it('should call out to the containerRunner when there is no cookiecutter installed', async () => { + commandExists.mockResolvedValue(false); - expect(cookiecutterTemplater.run).toHaveBeenCalledWith({ - workspacePath: mockTmpDir, - logStream: mockContext.logStream, - values: { - ...mockContext.input.values, - _copy_without_render: ['goreleaser.yml'], - _extensions: [ - 'jinja2_custom_filters_extension.string_filters_extension.StringFilterExtension', - ], - imageName: 'foo/cookiecutter-image-with-extensions', - }, - }); + await action.handler(mockContext); + + expect(containerRunner.runContainer).toHaveBeenCalledWith( + expect.objectContaining({ + imageName: 'spotify/backstage-cookiecutter', + command: 'cookiecutter', + args: ['--no-input', '-o', '/output', '/input', '--verbose'], + mountDirs: { + [join(mockTmpDir, 'intermediate')]: '/output', + [join(mockTmpDir, 'template')]: '/input', + }, + workingDir: '/input', + envVars: { HOME: '/tmp' }, + logStream: mockContext.logStream, + }), + ); }); - // it('should throw if copyWithoutRender is not an Array', async () => { - // await expect( - // action.handler({ - // ...mockContext, - // input: { - // ...mockContext.input, - // copyWithoutRender: 'xyz', - // }, - // }), - // ).rejects.toThrow(/copyWithoutRender must be an Array/); - // }); + it('should use a custom imageName when there is an image supplied to the context', async () => { + const imageName = 'test-image'; + mockContext.input.imageName = imageName; - // it('should throw if extensions is not an Array', async () => { - // await expect( - // action.handler({ - // ...mockContext, - // input: { - // ...mockContext.input, - // extensions: 'xyz', - // }, - // }), - // ).rejects.toThrow(/extensions must be an Array/); - // }); + await action.handler(mockContext); - // it('should throw if there is no cookiecutter templater initialized', async () => { - // const templatersWithoutCookiecutter = new Templaters(); - - // const newAction = createFetchCookiecutterAction({ - // integrations, - // templaters: templatersWithoutCookiecutter, - // reader: mockReader, - // }); - - // await expect(newAction.handler(mockContext)).rejects.toThrow( - // /No templater registered/, - // ); - // }); - - // it('should throw if the target directory is outside of the workspace path', async () => { - // await expect( - // action.handler({ - // ...mockContext, - // input: { - // ...mockContext.input, - // targetPath: '/foo', - // }, - // }), - // ).rejects.toThrow( - // /Relative path is not allowed to refer to a directory outside its parent/, - // ); - // }); + expect(containerRunner.runContainer).toHaveBeenCalledWith( + expect.objectContaining({ + imageName, + }), + ); + }); }); From fd5ec6d304d3f4f6bc0846a8ae8e6e6866402786 Mon Sep 17 00:00:00 2001 From: blam Date: Tue, 6 Jul 2021 20:29:58 +0200 Subject: [PATCH 185/204] chore: some api-docs changed Signed-off-by: blam --- .../src/scaffolder/actions/builtin/fetch/cookiecutter.test.ts | 2 -- plugins/sentry/api-report.md | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/cookiecutter.test.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/cookiecutter.test.ts index 8bd205be1d..1ef1e1a940 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/cookiecutter.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/cookiecutter.test.ts @@ -35,8 +35,6 @@ import { createFetchCookiecutterAction } from './cookiecutter'; import { join } from 'path'; import { ActionContext } from '../../types'; -import fs from 'fs-extra'; - describe('fetch:cookiecutter', () => { const integrations = ScmIntegrations.fromConfig( new ConfigReader({ diff --git a/plugins/sentry/api-report.md b/plugins/sentry/api-report.md index c3cce9ed7c..f140fc8b60 100644 --- a/plugins/sentry/api-report.md +++ b/plugins/sentry/api-report.md @@ -81,7 +81,7 @@ export type SentryIssue = { // @public (undocumented) export const SentryIssuesWidget: ({ entity, statsFor, variant, }: { entity: Entity; - statsFor?: "12h" | "24h" | undefined; + statsFor?: "24h" | "12h" | undefined; variant?: InfoCardVariants | undefined; }) => JSX.Element; From 4d9264f0fcacff87095e9cb4b81ccb719c5580dd Mon Sep 17 00:00:00 2001 From: blam Date: Tue, 6 Jul 2021 20:37:39 +0200 Subject: [PATCH 186/204] chore: fixing api-reports again Signed-off-by: blam --- plugins/sentry/api-report.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/sentry/api-report.md b/plugins/sentry/api-report.md index f140fc8b60..c3cce9ed7c 100644 --- a/plugins/sentry/api-report.md +++ b/plugins/sentry/api-report.md @@ -81,7 +81,7 @@ export type SentryIssue = { // @public (undocumented) export const SentryIssuesWidget: ({ entity, statsFor, variant, }: { entity: Entity; - statsFor?: "24h" | "12h" | undefined; + statsFor?: "12h" | "24h" | undefined; variant?: InfoCardVariants | undefined; }) => JSX.Element; From 8e183acc9cee145f665b4c0c9d2ca997e2171b50 Mon Sep 17 00:00:00 2001 From: blam Date: Wed, 7 Jul 2021 11:02:31 +0200 Subject: [PATCH 187/204] chore: code review comments Signed-off-by: blam --- .../builtin/fetch/cookiecutter.test.ts | 24 ++++++++----------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/cookiecutter.test.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/cookiecutter.test.ts index 1ef1e1a940..86f953a6a5 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/cookiecutter.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/cookiecutter.test.ts @@ -28,7 +28,7 @@ import { } from '@backstage/backend-common'; import { ConfigReader, JsonObject } from '@backstage/config'; import { ScmIntegrations } from '@backstage/integration'; -import mock from 'mock-fs'; +import mockFs from 'mock-fs'; import os from 'os'; import { PassThrough } from 'stream'; import { createFetchCookiecutterAction } from './cookiecutter'; @@ -94,14 +94,14 @@ describe('fetch:cookiecutter', () => { }; // mock the temp directory - mock({ [mockTmpDir]: {} }); - mock({ [`${join(mockTmpDir, 'template')}`]: {} }); + mockFs({ [mockTmpDir]: {} }); + mockFs({ [`${join(mockTmpDir, 'template')}`]: {} }); commandExists.mockResolvedValue(null); // Mock when run container is called it creates some new files in the mock filesystem containerRunner.runContainer.mockImplementation(async () => { - mock({ + mockFs({ [`${join(mockTmpDir, 'intermediate')}`]: { 'testfile.json': '{}', }, @@ -110,7 +110,7 @@ describe('fetch:cookiecutter', () => { // Mock when runCommand is called it creats some new files in the mock filesystem runCommand.mockImplementation(async () => { - mock({ + mockFs({ [`${join(mockTmpDir, 'intermediate')}`]: { 'testfile.json': '{}', }, @@ -119,26 +119,22 @@ describe('fetch:cookiecutter', () => { }); afterEach(() => { - mock.restore(); + mockFs.restore(); }); it('should throw an error when copyWithoutRender is not an array', async () => { (mockContext.input as any).copyWithoutRender = 'not an array'; - await expect( - action.handler(mockContext), - ).rejects.toThrowErrorMatchingInlineSnapshot( - `"Fetch action input copyWithoutRender must be an Array"`, + await expect(action.handler(mockContext)).rejects.toThrowError( + /Fetch action input copyWithoutRender must be an Array/, ); }); it('should throw an error when extensions is not an array', async () => { (mockContext.input as any).extensions = 'not an array'; - await expect( - action.handler(mockContext), - ).rejects.toThrowErrorMatchingInlineSnapshot( - `"Fetch action input extensions must be an Array"`, + await expect(action.handler(mockContext)).rejects.toThrowError( + /Fetch action input extensions must be an Array/, ); }); From 60e8302222987ae3832efbcb777cba105bb6934c Mon Sep 17 00:00:00 2001 From: blam Date: Wed, 7 Jul 2021 11:21:46 +0200 Subject: [PATCH 188/204] chore: made a lovely changeset Signed-off-by: blam --- .changeset/fresh-elephants-tease.md | 68 +++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 .changeset/fresh-elephants-tease.md diff --git a/.changeset/fresh-elephants-tease.md b/.changeset/fresh-elephants-tease.md new file mode 100644 index 0000000000..5141f96be7 --- /dev/null +++ b/.changeset/fresh-elephants-tease.md @@ -0,0 +1,68 @@ +--- +'@backstage/catalog-model': minor +'@backstage/plugin-catalog-backend': minor +'@backstage/plugin-scaffolder': minor +'@backstage/plugin-scaffolder-backend': minor +'@backstage/create-app': patch +--- + +Support for `Template` kinds with version `backstage.io/v1alpha1` has now been removed. This means that the old method of running templates with `Preparers`, `Templaters` and `Publishers` has also been removed. If you had any logic in these abstractions, they should now be moved to `actions` instead, and you can find out more about those in the [documentation](https://backstage.io/docs/features/software-templates/writing-custom-actions) + +If you need any help migrating existing templates, there's a [migration guide](https://backstage.io/docs/features/software-templates/migrating-from-v1alpha1-to-v1beta2). Reach out to us on Discord in the #support channel if you're having problems. + +The `scaffolder-backend` now no longer requires these `Preparers`, `Templaters`, and `Publishers` to be passed in, now all it needs is the `containerRunner`. + +Please update your `packages/backend/src/plugins/scaffolder.ts` like the following + +```diff +- import { +- DockerContainerRunner, +- SingleHostDiscovery, +- } from '@backstage/backend-common'; ++ import { DockerContainerRunner } from '@backstage/backend-common'; + import { CatalogClient } from '@backstage/catalog-client'; +- import { +- CookieCutter, +- CreateReactAppTemplater, +- createRouter, +- Preparers, +- Publishers, +- Templaters, +- } from '@backstage/plugin-scaffolder-backend'; ++ import { createRouter } from '@backstage/plugin-scaffolder-backend'; + import Docker from 'dockerode'; + import { Router } from 'express'; + import type { PluginEnvironment } from '../types'; + + export default async function createPlugin({ + config, + database, + reader, ++ discovery, + }: PluginEnvironment): Promise { + const dockerClient = new Docker(); + const containerRunner = new DockerContainerRunner({ dockerClient }); + +- const cookiecutterTemplater = new CookieCutter({ containerRunner }); +- const craTemplater = new CreateReactAppTemplater({ containerRunner }); +- const templaters = new Templaters(); + +- templaters.register('cookiecutter', cookiecutterTemplater); +- templaters.register('cra', craTemplater); +- +- const preparers = await Preparers.fromConfig(config, { logger }); +- const publishers = await Publishers.fromConfig(config, { logger }); + +- const discovery = SingleHostDiscovery.fromConfig(config); + const catalogClient = new CatalogClient({ discoveryApi: discovery }); + + return await createRouter({ +- preparers, +- templaters, +- publishers, ++ containerRunner, + logger, + config, + database, + +``` From e922a9952830474e1431330bf46d0a1c601df93d Mon Sep 17 00:00:00 2001 From: blam Date: Wed, 7 Jul 2021 11:27:55 +0200 Subject: [PATCH 189/204] chore: updating api-docs Signed-off-by: blam --- plugins/scaffolder-backend/api-report.md | 377 +---------------------- 1 file changed, 5 insertions(+), 372 deletions(-) diff --git a/plugins/scaffolder-backend/api-report.md b/plugins/scaffolder-backend/api-report.md index 21c6e03b0f..ab3ea433c6 100644 --- a/plugins/scaffolder-backend/api-report.md +++ b/plugins/scaffolder-backend/api-report.md @@ -4,18 +4,11 @@ ```ts -import { AzureIntegrationConfig } from '@backstage/integration'; -import { BitbucketIntegrationConfig } from '@backstage/integration'; import { CatalogApi } from '@backstage/catalog-client'; import { Config } from '@backstage/config'; import { ContainerRunner } from '@backstage/backend-common'; import { createPullRequest } from 'octokit-plugin-create-pull-request'; import express from 'express'; -import { GithubCredentialsProvider } from '@backstage/integration'; -import { GitHubIntegrationConfig } from '@backstage/integration'; -import { Gitlab } from '@gitbeaker/core'; -import { GitLabIntegrationConfig } from '@backstage/integration'; -import gitUrlParse from 'git-url-parse'; import { JsonObject } from '@backstage/config'; import { JsonValue } from '@backstage/config'; import { Logger } from 'winston'; @@ -23,7 +16,6 @@ import { PluginDatabaseManager } from '@backstage/backend-common'; import { Schema } from 'jsonschema'; import { ScmIntegrationRegistry } from '@backstage/integration'; import { ScmIntegrations } from '@backstage/integration'; -import { TemplateEntityV1alpha1 } from '@backstage/catalog-model'; import { TemplateEntityV1beta2 } from '@backstage/catalog-model'; import { UrlReader } from '@backstage/backend-common'; import { Writable } from 'stream'; @@ -40,74 +32,12 @@ export type ActionContext = { createTemporaryDirectory(): Promise; }; -// @public (undocumented) -export class AzurePreparer implements PreparerBase { - constructor(config: { - token?: string; - }); - // (undocumented) - static fromConfig(config: AzureIntegrationConfig): AzurePreparer; - // (undocumented) - prepare({ url, workspacePath, logger }: PreparerOptions): Promise; -} - -// @public (undocumented) -export class AzurePublisher implements PublisherBase { - constructor(config: { - token: string; - }); - // (undocumented) - static fromConfig(config: AzureIntegrationConfig): Promise; - // (undocumented) - publish({ values, workspacePath, logger, }: PublisherOptions): Promise; -} - -// @public (undocumented) -export class BitbucketPreparer implements PreparerBase { - constructor(config: { - username?: string; - token?: string; - appPassword?: string; - }); - // (undocumented) - static fromConfig(config: BitbucketIntegrationConfig): BitbucketPreparer; - // (undocumented) - prepare({ url, workspacePath, logger }: PreparerOptions): Promise; -} - -// @public (undocumented) -export class BitbucketPublisher implements PublisherBase { - constructor(config: { - host: string; - token?: string; - appPassword?: string; - username?: string; - apiBaseUrl?: string; - repoVisibility: RepoVisibilityOptions_2; - }); - // (undocumented) - static fromConfig(config: BitbucketIntegrationConfig, { repoVisibility }: { - repoVisibility: RepoVisibilityOptions_2; - }): Promise; - // (undocumented) - publish({ values, workspacePath, logger, }: PublisherOptions): Promise; -} - // @public export class CatalogEntityClient { constructor(catalogClient: CatalogApi); findTemplate(templateName: string, options?: { token?: string; - }): Promise; -} - -// @public (undocumented) -export class CookieCutter implements TemplaterBase { - constructor({ containerRunner }: { - containerRunner: ContainerRunner; - }); - // (undocumented) - run({ workspacePath, values, logStream, }: TemplaterRunOptions): Promise; + }): Promise; } // @public (undocumented) @@ -115,7 +45,7 @@ export const createBuiltinActions: (options: { reader: UrlReader; integrations: ScmIntegrations; catalogClient: CatalogApi; - templaters: TemplaterBuilder; + containerRunner: ContainerRunner; config: Config; }) => TemplateAction[]; @@ -135,7 +65,7 @@ export function createDebugLogAction(): TemplateAction; export function createFetchCookiecutterAction(options: { reader: UrlReader; integrations: ScmIntegrations; - templaters: TemplaterBuilder; + containerRunner: ContainerRunner; }): TemplateAction; // @public (undocumented) @@ -150,9 +80,6 @@ export const createFilesystemDeleteAction: () => TemplateAction; // @public (undocumented) export const createFilesystemRenameAction: () => TemplateAction; -// @public (undocumented) -export function createLegacyActions(options: Options): TemplateAction[]; - // @public (undocumented) export function createPublishAzureAction(options: { integrations: ScmIntegrationRegistry; @@ -183,15 +110,6 @@ export function createPublishGitlabAction(options: { config: Config; }): TemplateAction; -// @public (undocumented) -export class CreateReactAppTemplater implements TemplaterBase { - constructor({ containerRunner }: { - containerRunner: ContainerRunner; - }); - // (undocumented) - run({ workspacePath, values, logStream, }: TemplaterRunOptions): Promise; -} - // @public (undocumented) export function createRouter(options: RouterOptions): Promise; @@ -200,206 +118,6 @@ export const createTemplateAction: | undefined; }>>(templateAction: TemplateAction) => TemplateAction; -// @public (undocumented) -export class FilePreparer implements PreparerBase { - // (undocumented) - prepare({ url, workspacePath }: PreparerOptions): Promise; -} - -// @public -export const getTemplaterKey: (entity: TemplateEntityV1alpha1) => string; - -// @public (undocumented) -export class GithubPreparer implements PreparerBase { - constructor(config: { - credentialsProvider: GithubCredentialsProvider; - }); - // (undocumented) - static fromConfig(config: GitHubIntegrationConfig): GithubPreparer; - // (undocumented) - prepare({ url, workspacePath, logger }: PreparerOptions): Promise; -} - -// @public @deprecated (undocumented) -export class GithubPublisher implements PublisherBase { - constructor(config: { - credentialsProvider: GithubCredentialsProvider; - repoVisibility: RepoVisibilityOptions; - apiBaseUrl: string | undefined; - }); - // (undocumented) - static fromConfig(config: GitHubIntegrationConfig, { repoVisibility }: { - repoVisibility: RepoVisibilityOptions; - }): Promise; - // (undocumented) - publish({ values, workspacePath, logger, }: PublisherOptions): Promise; -} - -// @public (undocumented) -export class GitlabPreparer implements PreparerBase { - constructor(config: { - token?: string; - }); - // (undocumented) - static fromConfig(config: GitLabIntegrationConfig): GitlabPreparer; - // (undocumented) - prepare({ url, workspacePath, logger }: PreparerOptions): Promise; -} - -// @public (undocumented) -export class GitlabPublisher implements PublisherBase { - constructor(config: { - token: string; - client: Gitlab; - repoVisibility: RepoVisibilityOptions_3; - }); - // (undocumented) - static fromConfig(config: GitLabIntegrationConfig, { repoVisibility }: { - repoVisibility: RepoVisibilityOptions_3; - }): Promise; - // (undocumented) - publish({ values, workspacePath, logger, }: PublisherOptions): Promise; -} - -// @public (undocumented) -export type Job = { - id: string; - context: StageContext; - status: ProcessorStatus; - stages: StageResult[]; - error?: Error; -}; - -// @public (undocumented) -export type JobAndDirectoryTuple = { - job: Job; - directory: string; -}; - -// @public (undocumented) -export class JobProcessor implements Processor { - constructor(workingDirectory: string); - // (undocumented) - create({ entity, values, stages, }: { - entity: TemplateEntityV1alpha1; - values: TemplaterValues; - stages: StageInput[]; - }): Job; - // (undocumented) - static fromConfig({ config, logger, }: { - config: Config; - logger: Logger; - }): Promise; - // (undocumented) - get(id: string): Job | undefined; - // (undocumented) - run(job: Job): Promise; - } - -// @public (undocumented) -export function joinGitUrlPath(repoUrl: string, path?: string): string; - -// @public (undocumented) -export type ParsedLocationAnnotation = { - protocol: 'file' | 'url'; - location: string; -}; - -// @public (undocumented) -export const parseLocationAnnotation: (entity: TemplateEntityV1alpha1) => ParsedLocationAnnotation; - -// @public (undocumented) -export interface PreparerBase { - prepare(opts: PreparerOptions): Promise; -} - -// @public (undocumented) -export type PreparerBuilder = { - register(host: string, preparer: PreparerBase): void; - get(url: string): PreparerBase; -}; - -// @public (undocumented) -export type PreparerOptions = { - url: string; - workspacePath: string; - logger: Logger; -}; - -// @public (undocumented) -export class Preparers implements PreparerBuilder { - // (undocumented) - static fromConfig(config: Config, _: { - logger: Logger; - }): Promise; - // (undocumented) - get(url: string): PreparerBase; - // (undocumented) - register(host: string, preparer: PreparerBase): void; -} - -// @public (undocumented) -export type Processor = { - create({ entity, values, stages, }: { - entity: TemplateEntityV1alpha1; - values: TemplaterValues; - stages: StageInput[]; - }): Job; - get(id: string): Job | undefined; - run(job: Job): Promise; -}; - -// @public (undocumented) -export type ProcessorStatus = 'PENDING' | 'STARTED' | 'COMPLETED' | 'FAILED'; - -// @public -export type PublisherBase = { - publish(opts: PublisherOptions): Promise; -}; - -// @public (undocumented) -export type PublisherBuilder = { - register(host: string, publisher: PublisherBase): void; - get(storePath: string): PublisherBase; -}; - -// @public (undocumented) -export type PublisherOptions = { - values: TemplaterValues; - workspacePath: string; - logger: Logger; -}; - -// @public (undocumented) -export type PublisherResult = { - remoteUrl: string; - catalogInfoUrl?: string; -}; - -// @public (undocumented) -export class Publishers implements PublisherBuilder { - // (undocumented) - static fromConfig(config: Config, _options: { - logger: Logger; - }): Promise; - // (undocumented) - get(url: string): PublisherBase; - // (undocumented) - register(host: string, preparer: PublisherBase | undefined): void; -} - -// @public (undocumented) -export type RepoVisibilityOptions = 'private' | 'internal' | 'public'; - -// @public -export type RequiredTemplateValues = { - owner: string; - storePath: string; - destination?: { - git?: gitUrlParse.GitUrl; - }; -}; - // @public (undocumented) export interface RouterOptions { // (undocumented) @@ -409,63 +127,17 @@ export interface RouterOptions { // (undocumented) config: Config; // (undocumented) + containerRunner: ContainerRunner; + // (undocumented) database: PluginDatabaseManager; // (undocumented) logger: Logger; // (undocumented) - preparers: PreparerBuilder; - // (undocumented) - publishers: PublisherBuilder; - // (undocumented) reader: UrlReader; // (undocumented) taskWorkers?: number; - // (undocumented) - templaters: TemplaterBuilder; } -// @public (undocumented) -export const runCommand: ({ command, args, logStream, }: RunCommandOptions) => Promise; - -// @public (undocumented) -export type RunCommandOptions = { - command: string; - args: string[]; - logStream?: Writable; -}; - -// @public (undocumented) -export type StageContext = { - values: TemplaterValues; - entity: TemplateEntityV1alpha1; - logger: Logger; - logStream: Writable; - workspacePath: string; -} & T; - -// @public (undocumented) -export interface StageInput { - // (undocumented) - handler(ctx: StageContext): Promise; - // (undocumented) - name: string; -} - -// @public (undocumented) -export interface StageResult extends StageInput { - // (undocumented) - endedAt?: number; - // (undocumented) - log: string[]; - // (undocumented) - startedAt?: number; - // (undocumented) - status: ProcessorStatus; -} - -// @public -export type SupportedTemplatingKey = 'cookiecutter' | string; - // @public (undocumented) export type TemplateAction = { id: string; @@ -487,45 +159,6 @@ export class TemplateActionRegistry { register(action: TemplateAction): void; } -// @public (undocumented) -export type TemplaterBase = { - run(opts: TemplaterRunOptions): Promise; -}; - -// @public -export type TemplaterBuilder = { - register(protocol: SupportedTemplatingKey, templater: TemplaterBase): void; - get(templater: string): TemplaterBase; -}; - -// @public (undocumented) -export type TemplaterConfig = { - templater?: TemplaterBase; -}; - -// @public -export type TemplaterRunOptions = { - workspacePath: string; - values: TemplaterValues; - logStream?: Writable; -}; - -// @public -export type TemplaterRunResult = { - resultDir: string; -}; - -// @public (undocumented) -export class Templaters implements TemplaterBuilder { - // (undocumented) - get(templaterId: string): TemplaterBase; - // (undocumented) - register(templaterKey: SupportedTemplatingKey, templater: TemplaterBase): void; - } - -// @public (undocumented) -export type TemplaterValues = RequiredTemplateValues & Record; - // (No @packageDocumentation comment for this package) From 0adfae5c812655cf886dda0140e4a04d77aeaf80 Mon Sep 17 00:00:00 2001 From: Jos Craw Date: Wed, 7 Jul 2021 21:37:52 +1200 Subject: [PATCH 190/204] added changeset Signed-off-by: Jos Craw --- .changeset/red-ladybugs-promise.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/red-ladybugs-promise.md diff --git a/.changeset/red-ladybugs-promise.md b/.changeset/red-ladybugs-promise.md new file mode 100644 index 0000000000..dbfbf2bbd4 --- /dev/null +++ b/.changeset/red-ladybugs-promise.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder': patch +--- + +add support for uiSchema on dependent form fields From 7a3ad92b525354993908d52af27c9f7984085070 Mon Sep 17 00:00:00 2001 From: Rogerio Angeliski Date: Fri, 11 Jun 2021 11:01:53 -0300 Subject: [PATCH 191/204] feat: added rails templater to scaffolder-backend Signed-off-by: Rogerio Angeliski --- .changeset/twelve-deers-explode.md | 5 + plugins/scaffolder-backend/package.json | 6 +- .../sample-templates/local-templates.yaml | 1 + .../sample-templates/rails-demo/template.yaml | 174 ++++++++++++ .../template/rails-template-file.rb | 14 + .../scripts/Rails.dockerfile | 9 + .../actions/builtin/createBuiltinActions.ts | 10 +- .../scaffolder/actions/builtin/fetch/index.ts | 1 + .../actions/builtin/fetch/rails.test.ts | 140 ++++++++++ .../scaffolder/actions/builtin/fetch/rails.ts | 182 +++++++++++++ .../src/scaffolder/stages/templater/index.ts | 21 ++ .../stages/templater/rails/index.test.ts | 257 ++++++++++++++++++ .../stages/templater/rails/index.ts | 96 +++++++ .../rails/railsArgumentResolver.test.ts | 50 ++++ .../templater/rails/railsArgumentResolver.ts | 106 ++++++++ 15 files changed, 1070 insertions(+), 2 deletions(-) create mode 100644 .changeset/twelve-deers-explode.md create mode 100644 plugins/scaffolder-backend/sample-templates/rails-demo/template.yaml create mode 100644 plugins/scaffolder-backend/sample-templates/rails-demo/template/rails-template-file.rb create mode 100644 plugins/scaffolder-backend/scripts/Rails.dockerfile create mode 100644 plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/rails.test.ts create mode 100644 plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/rails.ts create mode 100644 plugins/scaffolder-backend/src/scaffolder/stages/templater/index.ts create mode 100644 plugins/scaffolder-backend/src/scaffolder/stages/templater/rails/index.test.ts create mode 100644 plugins/scaffolder-backend/src/scaffolder/stages/templater/rails/index.ts create mode 100644 plugins/scaffolder-backend/src/scaffolder/stages/templater/rails/railsArgumentResolver.test.ts create mode 100644 plugins/scaffolder-backend/src/scaffolder/stages/templater/rails/railsArgumentResolver.ts diff --git a/.changeset/twelve-deers-explode.md b/.changeset/twelve-deers-explode.md new file mode 100644 index 0000000000..c5ce1318a6 --- /dev/null +++ b/.changeset/twelve-deers-explode.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder-backend': patch +--- + +Created a Rails templater to scaffold apps diff --git a/plugins/scaffolder-backend/package.json b/plugins/scaffolder-backend/package.json index 7173f865c5..0bc4c62ea6 100644 --- a/plugins/scaffolder-backend/package.json +++ b/plugins/scaffolder-backend/package.json @@ -40,6 +40,9 @@ "@octokit/rest": "^18.5.3", "@types/express": "^4.17.6", "azure-devops-node-api": "^10.2.2", + "@types/git-url-parse": "^9.0.0", + "@types/dockerode": "^3.2.1", + "azure-devops-node-api": "^10.1.1", "command-exists": "^1.2.9", "compression": "^1.7.4", "cors": "^2.8.5", @@ -60,7 +63,8 @@ "octokit-plugin-create-pull-request": "^3.9.3", "uuid": "^8.2.0", "winston": "^3.2.1", - "yaml": "^1.10.0" + "yaml": "^1.10.0", + "dockerode": "^3.2.1" }, "devDependencies": { "@backstage/cli": "^0.7.3", diff --git a/plugins/scaffolder-backend/sample-templates/local-templates.yaml b/plugins/scaffolder-backend/sample-templates/local-templates.yaml index 3b3acbae7e..59a55b3cd9 100644 --- a/plugins/scaffolder-backend/sample-templates/local-templates.yaml +++ b/plugins/scaffolder-backend/sample-templates/local-templates.yaml @@ -10,4 +10,5 @@ spec: - ./create-react-app/template.yaml - ./springboot-grpc-template/template.yaml - ./v1beta2-demo/template.yaml + - ./rails-demo/template.yaml - ./pull-request/template.yaml diff --git a/plugins/scaffolder-backend/sample-templates/rails-demo/template.yaml b/plugins/scaffolder-backend/sample-templates/rails-demo/template.yaml new file mode 100644 index 0000000000..174c58741b --- /dev/null +++ b/plugins/scaffolder-backend/sample-templates/rails-demo/template.yaml @@ -0,0 +1,174 @@ +apiVersion: backstage.io/v1beta2 +kind: Template +metadata: + name: rails-demo + title: Rails template + description: scaffolder Rails app +spec: + owner: backstage/techdocs-core + type: service + + parameters: + - title: Fill in some steps + required: + - name + - owner + properties: + name: + title: Name + type: string + description: Unique name of the component + ui:autofocus: true + ui:options: + rows: 5 + owner: + title: Owner + type: string + description: Owner of the component + ui:field: OwnerPicker + ui:options: + allowedKinds: + - Group + system: + title: System + type: string + description: System of the component + ui:field: EntityPicker + ui:options: + allowedKinds: + - System + defaultKind: System + + - title: Choose a location + required: + - repoUrl + - dryRun + properties: + repoUrl: + title: Repository Location + type: string + ui:field: RepoUrlPicker + ui:options: + allowedHosts: + - github.com + dryRun: + title: Only perform a dry run, don't publish anything + type: boolean + default: false + railsArguments: + title: arguments to run the rails new command + type: object + properties: + minimal: + title: minimal + description: Preconfigure a minimal rails app + type: boolean + skipBundle: + title: skipBundle + description: Don't run bundle install + type: boolean + skipWebpackInstall: + title: skipWebpackInstall + description: Don't run Webpack install + type: boolean + api: + title: api + description: Preconfigure smaller stack for API only apps + type: boolean + template: + title: template + description: Path to some application template (can be a filesystem path or URL) + type: string + default: './rails-template-file.rb' + webpacker: + title: webpacker + description: 'Preconfigure Webpack with a particular framework (options: react, + vue, angular, elm, stimulus)' + type: string + enum: + - react + - vue + - angular + - elm + - stimulus + database: + title: database + description: 'Preconfigure for selected database (options: mysql/postgresql/sqlite3/oracle/sqlserver/jdbcmysql/jdbcsqlite3/jdbcpostgresql/jdbc)' + type: string + enum: + - mysql + - postgresql + - sqlite3 + - oracle + - sqlserver + - jdbcmysql + - jdbcsqlite3 + - jdbcpostgresql + - jdbc + railsVersion: + title: Rails version in Gemfile + description: 'Set up the application with Gemfile pointing to a specific version + (options: dev, edge, master)' + type: string + enum: + - dev + - edge + - master + + steps: + - id: fetch-base + name: Fetch Base + action: fetch:rails + input: + url: ./template + values: + name: '{{ parameters.name }}' + owner: '{{ parameters.owner }}' + system: '{{ parameters.system }}' + railsArguments: '{{ json parameters.railsArguments }}' + + - name: Write Catalog information + action: catalog:write + input: + component: + apiVersion: 'backstage.io/v1alpha1' + kind: Component + metadata: + name: '{{ parameters.name }}' + annotations: + github.com/project-slug: '{{ projectSlug parameters.repoUrl }}' + spec: + type: service + lifecycle: production + owner: '{{ parameters.owner }}' + + - id: publish + if: '{{ not parameters.dryRun }}' + name: Publish + action: publish:github + input: + allowedHosts: ['github.com'] + description: 'This is {{ parameters.name }}' + repoUrl: '{{ parameters.repoUrl }}' + + - id: register + if: '{{ not parameters.dryRun }}' + name: Register + action: catalog:register + input: + repoContentsUrl: '{{ steps.publish.output.repoContentsUrl }}' + catalogInfoPath: '/catalog-info.yaml' + + - name: Results + if: '{{ parameters.dryRun }}' + action: debug:log + input: + listWorkspace: true + + output: + links: + - title: Repository + url: '{{ steps.publish.output.remoteUrl }}' + - title: Open in catalog + icon: 'catalog' + entityRef: '{{ steps.register.output.entityRef }}' diff --git a/plugins/scaffolder-backend/sample-templates/rails-demo/template/rails-template-file.rb b/plugins/scaffolder-backend/sample-templates/rails-demo/template/rails-template-file.rb new file mode 100644 index 0000000000..90c0d53ddc --- /dev/null +++ b/plugins/scaffolder-backend/sample-templates/rails-demo/template/rails-template-file.rb @@ -0,0 +1,14 @@ +gem_group :development, :test do + gem "rspec" + gem "rspec-rails" +end + +rakefile("example.rake") do + <<-TASK + namespace :example do + task :backstage do + puts "i like backstage!" + end + end + TASK +end diff --git a/plugins/scaffolder-backend/scripts/Rails.dockerfile b/plugins/scaffolder-backend/scripts/Rails.dockerfile new file mode 100644 index 0000000000..3cec0e7668 --- /dev/null +++ b/plugins/scaffolder-backend/scripts/Rails.dockerfile @@ -0,0 +1,9 @@ +FROM ruby:3.0 + +RUN apt-get update -qq && \ + apt-get install -y \ + nodejs \ + postgresql-client \ + git + +RUN gem install rails diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/createBuiltinActions.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/createBuiltinActions.ts index 08d7bbf824..fa2fcbfcee 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/createBuiltinActions.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/createBuiltinActions.ts @@ -24,7 +24,11 @@ import { } from './catalog'; import { createDebugLogAction } from './debug'; -import { createFetchCookiecutterAction, createFetchPlainAction } from './fetch'; +import { + createFetchCookiecutterAction, + createFetchPlainAction, + createFetchRailsAction, +} from './fetch'; import { createFilesystemDeleteAction, createFilesystemRenameAction, @@ -62,6 +66,10 @@ export const createBuiltinActions = (options: { integrations, containerRunner, }), + createFetchRailsAction({ + reader, + integrations, + }), createPublishGithubAction({ integrations, config, diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/index.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/index.ts index 8e0f93f3ab..9557a88a4c 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/index.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/index.ts @@ -16,3 +16,4 @@ export { createFetchPlainAction } from './plain'; export { createFetchCookiecutterAction } from './cookiecutter'; +export { createFetchRailsAction } from './rails'; diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/rails.test.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/rails.test.ts new file mode 100644 index 0000000000..ebc62e9277 --- /dev/null +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/rails.test.ts @@ -0,0 +1,140 @@ +/* + * Copyright 2021 Spotify AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +const mockRailsTemplater = { run: jest.fn() }; +jest.mock('./helpers'); +jest.mock('../../../stages/templater', () => { + return { + Rails: jest.fn().mockImplementation(() => { + return mockRailsTemplater; + }), + }; +}); + +import { getVoidLogger, UrlReader } from '@backstage/backend-common'; +import { ConfigReader } from '@backstage/config'; +import { ScmIntegrations } from '@backstage/integration'; +import mock from 'mock-fs'; +import os from 'os'; +import { resolve as resolvePath } from 'path'; +import { PassThrough } from 'stream'; +import { createFetchRailsAction } from './rails'; +import { fetchContents } from './helpers'; + +describe('fetch:rails', () => { + const integrations = ScmIntegrations.fromConfig( + new ConfigReader({ + integrations: { + azure: [ + { host: 'dev.azure.com', token: 'tokenlols' }, + { host: 'myazurehostnotoken.com' }, + ], + }, + }), + ); + + const mockTmpDir = os.tmpdir(); + const mockContext = { + input: { + url: 'https://rubyonrails.org/generator', + targetPath: 'something', + values: { + help: 'me', + }, + }, + baseUrl: 'somebase', + workspacePath: mockTmpDir, + logger: getVoidLogger(), + logStream: new PassThrough(), + output: jest.fn(), + createTemporaryDirectory: jest.fn().mockResolvedValue(mockTmpDir), + }; + + const mockReader: UrlReader = { + read: jest.fn(), + readTree: jest.fn(), + search: jest.fn(), + }; + + const action = createFetchRailsAction({ + integrations, + reader: mockReader, + }); + + beforeEach(() => { + mock({ [`${mockContext.workspacePath}/result`]: {} }); + jest.restoreAllMocks(); + }); + + afterEach(() => { + mock.restore(); + }); + + it('should call fetchContents with the correct values', async () => { + await action.handler(mockContext); + + expect(fetchContents).toHaveBeenCalledWith({ + reader: mockReader, + integrations, + baseUrl: mockContext.baseUrl, + fetchUrl: mockContext.input.url, + outputPath: resolvePath(mockContext.workspacePath), + }); + }); + + it('should execute the rails templater with the correct values', async () => { + await action.handler(mockContext); + + expect(mockRailsTemplater.run).toHaveBeenCalledWith({ + workspacePath: mockTmpDir, + logStream: mockContext.logStream, + values: mockContext.input.values, + }); + }); + + it('should execute the rails templater with optional inputs if they are present and valid', async () => { + await action.handler({ + ...mockContext, + input: { + ...mockContext.input, + imageName: 'foo/rails-custom-image', + }, + }); + + expect(mockRailsTemplater.run).toHaveBeenCalledWith({ + workspacePath: mockTmpDir, + logStream: mockContext.logStream, + values: { + ...mockContext.input.values, + imageName: 'foo/rails-custom-image', + }, + }); + }); + + it('should throw if the target directory is outside of the workspace path', async () => { + await expect( + action.handler({ + ...mockContext, + input: { + ...mockContext.input, + targetPath: '/foo', + }, + }), + ).rejects.toThrow( + /targetPath may not specify a path outside the working directory/, + ); + }); +}); diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/rails.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/rails.ts new file mode 100644 index 0000000000..203db5004e --- /dev/null +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/rails.ts @@ -0,0 +1,182 @@ +/* + * Copyright 2021 Spotify AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { DockerContainerRunner, UrlReader } from '@backstage/backend-common'; +import { JsonObject } from '@backstage/config'; +import { InputError } from '@backstage/errors'; +import { ScmIntegrations } from '@backstage/integration'; +import fs from 'fs-extra'; +import { resolve as resolvePath } from 'path'; +import { Rails, TemplaterValues } from '../../../stages/templater'; +import { createTemplateAction } from '../../createTemplateAction'; +import { fetchContents } from './helpers'; +import Docker from 'dockerode'; + +export function createFetchRailsAction(options: { + reader: UrlReader; + integrations: ScmIntegrations; +}) { + const { reader, integrations } = options; + + return createTemplateAction<{ + url: string; + targetPath?: string; + values: JsonObject; + imageName?: string; + }>({ + id: 'fetch:rails', + description: + 'Downloads a template from the given URL into the workspace, and runs a rails generator on it.', + schema: { + input: { + type: 'object', + required: ['url'], + properties: { + url: { + title: 'Fetch URL', + description: + 'Relative path or absolute URL pointing to the directory tree to fetch', + type: 'string', + }, + targetPath: { + title: 'Target Path', + description: + 'Target path within the working directory to download the contents to.', + type: 'string', + }, + values: { + title: 'Template Values', + description: 'Values to pass on to rails for templating', + type: 'object', + properties: { + railsArguments: { + title: 'Arguments to pass to new command', + description: + 'You can provide some arguments to create a custom app', + type: 'object', + properties: { + minimal: { + title: 'minimal', + description: 'Preconfigure a minimal rails app', + type: 'boolean', + }, + skipBundle: { + title: 'skipBundle', + description: "Don't run bundle install", + type: 'boolean', + }, + skipWebpackInstall: { + title: 'skipWebpackInstall', + description: "Don't run Webpack install", + type: 'boolean', + }, + api: { + title: 'api', + description: 'Preconfigure smaller stack for API only apps', + type: 'boolean', + }, + template: { + title: 'template', + description: + 'Path to some application template (can be a filesystem path or URL)', + type: 'string', + }, + webpacker: { + title: 'webpacker', + description: + 'Preconfigure Webpack with a particular framework (options: react, vue, angular, elm, stimulus)', + type: 'string', + enum: ['react', 'vue', 'angular', 'elm', 'stimulus'], + }, + database: { + title: 'database', + description: + 'Preconfigure for selected database (options: mysql/postgresql/sqlite3/oracle/sqlserver/jdbcmysql/jdbcsqlite3/jdbcpostgresql/jdbc)', + type: 'string', + enum: [ + 'mysql', + 'postgresql', + 'sqlite3', + 'oracle', + 'sqlserver', + 'jdbcmysql', + 'jdbcsqlite3', + 'jdbcpostgresql', + 'jdbc', + ], + }, + railsVersion: { + title: 'Rails version in Gemfile', + description: + 'Set up the application with Gemfile pointing to a specific version (options: fromImage, dev, edge, master)', + type: 'string', + enum: ['dev', 'edge', 'master', 'fromImage'], + }, + }, + }, + }, + }, + imageName: { + title: 'Rails Docker image', + description: + 'Specify a Docker image to run rails new. Used only when a local rails is not found.', + type: 'string', + }, + }, + }, + }, + async handler(ctx) { + ctx.logger.info('Fetching and then templating using rails'); + + const workDir = await ctx.createTemporaryDirectory(); + const resultDir = resolvePath(workDir, 'result'); + + await fetchContents({ + reader, + integrations, + baseUrl: ctx.baseUrl, + fetchUrl: ctx.input.url, + outputPath: workDir, + }); + + const dockerClient = new Docker(); + const containerRunner = new DockerContainerRunner({ dockerClient }); + const templateRunner = new Rails({ containerRunner }); + + const values = { + ...(ctx.input.values as TemplaterValues), + imageName: ctx.input.imageName, + }; + + // Will execute the template in ./template and put the result in ./result + await templateRunner.run({ + workspacePath: workDir, + logStream: ctx.logStream, + values, + }); + + // Finally move the template result into the task workspace + const targetPath = ctx.input.targetPath ?? './'; + const outputPath = resolvePath(ctx.workspacePath, targetPath); + if (!outputPath.startsWith(ctx.workspacePath)) { + throw new InputError( + `Fetch action targetPath may not specify a path outside the working directory`, + ); + } + await fs.copy(resultDir, outputPath); + }, + }); +} diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/templater/index.ts b/plugins/scaffolder-backend/src/scaffolder/stages/templater/index.ts new file mode 100644 index 0000000000..139ff2207e --- /dev/null +++ b/plugins/scaffolder-backend/src/scaffolder/stages/templater/index.ts @@ -0,0 +1,21 @@ +/* + * Copyright 2020 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +export * from './cookiecutter'; +export * from './types'; +export * from './helpers'; +export * from './templaters'; +export * from './cra'; +export * from './rails'; diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/templater/rails/index.test.ts b/plugins/scaffolder-backend/src/scaffolder/stages/templater/rails/index.test.ts new file mode 100644 index 0000000000..534899eec1 --- /dev/null +++ b/plugins/scaffolder-backend/src/scaffolder/stages/templater/rails/index.test.ts @@ -0,0 +1,257 @@ +/* + * Copyright 2021 Spotify AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +const runCommand = jest.fn(); +const commandExists = jest.fn(); + +jest.mock('../helpers', () => ({ runCommand })); +jest.mock('command-exists', () => commandExists); +jest.mock('fs-extra'); + +import { ContainerRunner } from '@backstage/backend-common'; +import fs from 'fs-extra'; + +import path from 'path'; +import { PassThrough } from 'stream'; + +import { Rails } from './index'; + +describe('Rails Templater', () => { + const containerRunner: jest.Mocked = { + runContainer: jest.fn(), + }; + + beforeEach(() => { + jest.clearAllMocks(); + }); + + describe('when running on docker', () => { + it('should run the correct bindings for the volumes', async () => { + const values = { + owner: 'angeliski', + storePath: 'https://github.com/angeliski/rails-project', + name: 'rails-project', + imageName: 'foo/rails-custom-image', + }; + + jest.spyOn(fs, 'readdir').mockResolvedValueOnce(['newthing'] as any); + jest + .spyOn(fs, 'realpath') + .mockImplementation(x => Promise.resolve(x.toString())); + + const templater = new Rails({ containerRunner }); + await templater.run({ + workspacePath: 'tempdir', + values, + }); + + expect(containerRunner.runContainer).toHaveBeenCalledWith({ + imageName: 'foo/rails-custom-image', + command: 'rails', + args: ['new', '/output/rails-project'], + envVars: { HOME: '/tmp' }, + mountDirs: { + ['tempdir']: '/input', + [path.join('tempdir', 'intermediate')]: '/output', + }, + workingDir: '/input', + logStream: undefined, + }); + }); + + it('should use the provided imageName', async () => { + const values = { + owner: 'angeliski', + storePath: 'https://github.com/angeliski/rails-project', + name: 'rails-project', + imageName: 'foo/rails-custom-image', + }; + + jest.spyOn(fs, 'readdir').mockResolvedValueOnce(['newthing'] as any); + + const templater = new Rails({ containerRunner }); + await templater.run({ + workspacePath: 'tempdir', + values, + }); + + expect(containerRunner.runContainer).toHaveBeenCalledWith( + expect.objectContaining({ + imageName: 'foo/rails-custom-image', + }), + ); + }); + + it('should pass through the streamer to the run docker helper', async () => { + const stream = new PassThrough(); + + const values = { + owner: 'angeliski', + storePath: 'https://github.com/angeliski/rails-project', + name: 'rails-project', + imageName: 'foo/rails-custom-image', + }; + + jest.spyOn(fs, 'readdir').mockResolvedValueOnce(['newthing'] as any); + + const templater = new Rails({ containerRunner }); + await templater.run({ + workspacePath: 'tempdir', + values, + logStream: stream, + }); + + expect(containerRunner.runContainer).toHaveBeenCalledWith({ + imageName: 'foo/rails-custom-image', + command: 'rails', + args: ['new', '/output/rails-project'], + envVars: { HOME: '/tmp' }, + mountDirs: { + ['tempdir']: '/input', + [path.join('tempdir', 'intermediate')]: '/output', + }, + workingDir: '/input', + logStream: stream, + }); + }); + + it('update the template path to correct location', async () => { + const values = { + owner: 'angeliski', + storePath: 'https://github.com/angeliski/rails-project', + name: 'rails-project', + railsArguments: { template: './something.rb' }, + imageName: 'foo/rails-custom-image', + }; + + jest.spyOn(fs, 'readdir').mockResolvedValueOnce(['newthing'] as any); + jest + .spyOn(fs, 'realpath') + .mockImplementation(x => Promise.resolve(x.toString())); + + const templater = new Rails({ containerRunner }); + await templater.run({ + workspacePath: 'tempdir', + values, + }); + + expect(containerRunner.runContainer).toHaveBeenCalledWith({ + imageName: 'foo/rails-custom-image', + command: 'rails', + args: [ + 'new', + '/output/rails-project', + '--template', + '/input/something.rb', + ], + envVars: { HOME: '/tmp' }, + mountDirs: { + ['tempdir']: '/input', + [path.join('tempdir', 'intermediate')]: '/output', + }, + workingDir: '/input', + logStream: undefined, + }); + }); + }); + + describe('when rails is available', () => { + it('use the binary', async () => { + const stream = new PassThrough(); + + const values = { + owner: 'angeliski', + storePath: 'https://github.com/angeliski/rails-project', + name: 'rails-project', + imageName: 'foo/rails-custom-image', + }; + + jest.spyOn(fs, 'readdir').mockResolvedValueOnce(['newthing'] as any); + commandExists.mockImplementationOnce(() => () => true); + + const templater = new Rails({ containerRunner }); + await templater.run({ + workspacePath: 'tempdir', + values, + logStream: stream, + }); + + expect(runCommand).toHaveBeenCalledWith({ + command: 'rails', + args: expect.arrayContaining([ + 'new', + path.join('tempdir', 'intermediate', 'rails-project'), + ]), + logStream: stream, + }); + }); + it('update the template path to correct location', async () => { + const stream = new PassThrough(); + + const values = { + owner: 'angeliski', + storePath: 'https://github.com/angeliski/rails-project', + name: 'rails-project', + railsArguments: { template: './something.rb' }, + imageName: 'foo/rails-custom-image', + }; + + jest.spyOn(fs, 'readdir').mockResolvedValueOnce(['newthing'] as any); + commandExists.mockImplementationOnce(() => () => true); + + const templater = new Rails({ containerRunner }); + await templater.run({ + workspacePath: 'tempdir', + values, + logStream: stream, + }); + + expect(runCommand).toHaveBeenCalledWith({ + command: 'rails', + args: expect.arrayContaining([ + 'new', + path.join('tempdir', 'intermediate', 'rails-project'), + '--template', + path.join('tempdir', './something.rb'), + ]), + logStream: stream, + }); + }); + }); + + describe('when nothing was generated', () => { + it('throws an error', async () => { + const stream = new PassThrough(); + + jest + .spyOn(fs, 'readdir') + .mockImplementationOnce(() => Promise.resolve([])); + + const templater = new Rails({ containerRunner }); + await expect( + templater.run({ + workspacePath: 'tempdir', + values: { + owner: 'angeliski', + storePath: 'https://github.com/angeliski/rails-project', + name: 'rails-project', + imageName: 'foo/rails-custom-image', + }, + logStream: stream, + }), + ).rejects.toThrow(/No data generated by rails/); + }); + }); +}); diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/templater/rails/index.ts b/plugins/scaffolder-backend/src/scaffolder/stages/templater/rails/index.ts new file mode 100644 index 0000000000..57ee26e106 --- /dev/null +++ b/plugins/scaffolder-backend/src/scaffolder/stages/templater/rails/index.ts @@ -0,0 +1,96 @@ +/* + * Copyright 2021 Spotify AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ContainerRunner } from '@backstage/backend-common'; +import fs from 'fs-extra'; +import path from 'path'; +import { runCommand } from '../helpers'; +import commandExists from 'command-exists'; +import { TemplaterBase, TemplaterRunOptions } from '../types'; +import { railsArgumentResolver } from './railsArgumentResolver'; + +export class Rails implements TemplaterBase { + private readonly containerRunner: ContainerRunner; + + constructor({ containerRunner }: { containerRunner: ContainerRunner }) { + this.containerRunner = containerRunner; + } + + public async run({ + workspacePath, + values, + logStream, + }: TemplaterRunOptions): Promise { + const intermediateDir = path.join(workspacePath, 'intermediate'); + await fs.ensureDir(intermediateDir); + const resultDir = path.join(workspacePath, 'result'); + + const { name, imageName, railsArguments } = values; + + // Directories to bind on container + const mountDirs = { + [workspacePath]: '/input', + [intermediateDir]: '/output', + }; + + const baseCommand = 'rails'; + const baseArguments = ['new']; + const commandExistsToRun = await commandExists(baseCommand); + + if (commandExistsToRun) { + const arrayExtraArguments = railsArgumentResolver( + workspacePath, + railsArguments, + ); + + await runCommand({ + command: baseCommand, + args: [ + ...baseArguments, + `${intermediateDir}/${name}`, + ...arrayExtraArguments, + ], + logStream, + }); + } else { + const arrayExtraArguments = railsArgumentResolver( + '/input', + railsArguments, + ); + await this.containerRunner.runContainer({ + imageName: imageName, + command: baseCommand, + args: [...baseArguments, `/output/${name}`, ...arrayExtraArguments], + mountDirs, + workingDir: '/input', + // Set the home directory inside the container as something that applications can + // write to, otherwise they will just fail trying to write to / + envVars: { HOME: '/tmp' }, + logStream, + }); + } + + // if command was successful, intermediateDir should contain + // exactly one directory. + const [generated] = await fs.readdir(intermediateDir); + + if (generated === undefined) { + throw new Error(`No data generated by ${baseCommand}`); + } + + await fs.move(path.join(intermediateDir, generated), resultDir); + } +} diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/templater/rails/railsArgumentResolver.test.ts b/plugins/scaffolder-backend/src/scaffolder/stages/templater/rails/railsArgumentResolver.test.ts new file mode 100644 index 0000000000..370d9de380 --- /dev/null +++ b/plugins/scaffolder-backend/src/scaffolder/stages/templater/rails/railsArgumentResolver.test.ts @@ -0,0 +1,50 @@ +/* + * Copyright 2021 Spotify AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { railsArgumentResolver } from './railsArgumentResolver'; +import { TemplaterValues } from '../types'; + +describe('railsArgumentResolver', () => { + describe('when provide the parameter', () => { + test.each([ + [{}, []], + [{ minimal: true }, ['--minimal']], + [{ api: true }, ['--api']], + [{ skipBundle: true }, ['--skip-bundle']], + [{ skipWebpackInstall: true }, ['--skip-webpack-install']], + [{ webpacker: 'vue' }, ['--webpack', 'vue']], + [{ database: 'postgresql' }, ['--database', 'postgresql']], + [{ railsVersion: 'dev' }, ['--dev']], + [{ template: './rails.rb' }, ['--template', '/tmp/rails.rb']], + ])( + 'should include the argument to execution %p -> %p', + (passedArguments: object, expected: Array) => { + // that step is to ensure the validation between the TemplaterValues and the resolver + const values: TemplaterValues = { + owner: 'r', + storePath: '', + railsArguments: passedArguments, + }; + + const { railsArguments } = values; + + const argumentsToRun = railsArgumentResolver('/tmp', railsArguments); + + expect(argumentsToRun).toEqual(expected); + }, + ); + }); +}); diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/templater/rails/railsArgumentResolver.ts b/plugins/scaffolder-backend/src/scaffolder/stages/templater/rails/railsArgumentResolver.ts new file mode 100644 index 0000000000..5ea2f70895 --- /dev/null +++ b/plugins/scaffolder-backend/src/scaffolder/stages/templater/rails/railsArgumentResolver.ts @@ -0,0 +1,106 @@ +/* + * Copyright 2021 Spotify AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +enum Webpacker { + react = 'react', + vue = 'vue', + angular = 'angular', + elm = 'elm', + stimulus = 'stimulus', +} + +enum Database { + mysql = 'mysql', + postgresql = 'postgresql', + sqlite3 = 'sqlite3', + oracle = 'oracle', + sqlserver = 'sqlserver', + jdbcmysql = 'jdbcmysql', + jdbcsqlite3 = 'jdbcsqlite3', + jdbcpostgresql = 'jdbcpostgresql', + jdbc = 'jdbc', +} + +enum RailsVersion { + dev = 'dev', + edge = 'edge', + master = 'master', + fromImage = 'fromImage', +} + +export type RailsRunOptions = { + minimal?: boolean; + api?: boolean; + template?: string; + webpacker?: Webpacker; + database?: Database; + railsVersion?: RailsVersion; + skipBundle?: boolean; + skipWebpackInstall?: boolean; +}; + +export const railsArgumentResolver = ( + projectRoot: string, + options: RailsRunOptions, +): string[] => { + const argumentsToRun: string[] = []; + + if (options?.minimal) { + argumentsToRun.push('--minimal'); + } + + if (options?.api) { + argumentsToRun.push('--api'); + } + + if (options?.skipBundle) { + argumentsToRun.push('--skip-bundle'); + } + + if (options?.skipWebpackInstall) { + argumentsToRun.push('--skip-webpack-install'); + } + + if ( + options?.webpacker && + Object.values(Webpacker).includes(options?.webpacker as Webpacker) + ) { + argumentsToRun.push('--webpack'); + argumentsToRun.push(options.webpacker); + } + + if ( + options?.database && + Object.values(Database).includes(options?.database as Database) + ) { + argumentsToRun.push('--database'); + argumentsToRun.push(options.database); + } + + if ( + options?.railsVersion !== RailsVersion.fromImage && + Object.values(RailsVersion).includes(options?.railsVersion as RailsVersion) + ) { + argumentsToRun.push(`--${options.railsVersion}`); + } + + if (options?.template) { + argumentsToRun.push('--template'); + argumentsToRun.push(options.template.replace('./', `${projectRoot}/`)); + } + + return argumentsToRun; +}; From aad73cf398fcc63ab4e182b3a38fd3b422da3cb9 Mon Sep 17 00:00:00 2001 From: Rogerio Angeliski Date: Fri, 18 Jun 2021 11:54:19 -0300 Subject: [PATCH 192/204] fix: move dep to correction location Signed-off-by: Rogerio Angeliski --- plugins/scaffolder-backend/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/scaffolder-backend/package.json b/plugins/scaffolder-backend/package.json index 0bc4c62ea6..a6db486594 100644 --- a/plugins/scaffolder-backend/package.json +++ b/plugins/scaffolder-backend/package.json @@ -41,7 +41,6 @@ "@types/express": "^4.17.6", "azure-devops-node-api": "^10.2.2", "@types/git-url-parse": "^9.0.0", - "@types/dockerode": "^3.2.1", "azure-devops-node-api": "^10.1.1", "command-exists": "^1.2.9", "compression": "^1.7.4", @@ -74,6 +73,7 @@ "@types/git-url-parse": "^9.0.0", "@types/mock-fs": "^4.13.0", "@types/supertest": "^2.0.8", + "@types/dockerode": "^3.2.1", "jest-when": "^3.1.0", "mock-fs": "^4.13.0", "msw": "^0.29.0", From c5e81eab43c5ecf5774d0780561867caff34f4bd Mon Sep 17 00:00:00 2001 From: Rogerio Angeliski Date: Thu, 24 Jun 2021 12:00:43 -0300 Subject: [PATCH 193/204] refactor to a isolated module Signed-off-by: Rogerio Angeliski --- .changeset/twelve-deers-explode.md | 2 +- .../scaffolder-backend-module-rails.yaml | 9 + microsite/static/img/rails-icon.png | Bin 0 -> 5439 bytes packages/backend/package.json | 2 + .../.eslintrc.js | 3 + .../scaffolder-backend-module-rails/README.md | 225 ++++++++++++++++++ .../Rails.dockerfile | 0 .../api-report.md | 22 ++ .../package.json | 44 ++++ .../src/actions/fetch/index.ts | 16 ++ .../src/actions/fetch/rails/index.test.ts} | 23 +- .../src/actions/fetch/rails/index.ts} | 23 +- .../rails/railsArgumentResolver.test.ts | 3 +- .../fetch}/rails/railsArgumentResolver.ts | 0 .../fetch/rails/railsNewRunner.test.ts} | 28 ++- .../actions/fetch/rails/railsNewRunner.ts} | 24 +- .../src/actions/index.ts | 16 ++ .../src/index.ts | 16 ++ plugins/scaffolder-backend/api-report.md | 6 +- plugins/scaffolder-backend/package.json | 4 +- .../actions/builtin/createBuiltinActions.ts | 10 +- .../scaffolder/actions/builtin/fetch/index.ts | 2 +- .../src/scaffolder/stages/templater/index.ts | 1 - 23 files changed, 423 insertions(+), 56 deletions(-) create mode 100644 microsite/data/plugins/scaffolder-backend-module-rails.yaml create mode 100644 microsite/static/img/rails-icon.png create mode 100644 plugins/scaffolder-backend-module-rails/.eslintrc.js create mode 100644 plugins/scaffolder-backend-module-rails/README.md rename plugins/{scaffolder-backend/scripts => scaffolder-backend-module-rails}/Rails.dockerfile (100%) create mode 100644 plugins/scaffolder-backend-module-rails/api-report.md create mode 100644 plugins/scaffolder-backend-module-rails/package.json create mode 100644 plugins/scaffolder-backend-module-rails/src/actions/fetch/index.ts rename plugins/{scaffolder-backend/src/scaffolder/actions/builtin/fetch/rails.test.ts => scaffolder-backend-module-rails/src/actions/fetch/rails/index.test.ts} (86%) rename plugins/{scaffolder-backend/src/scaffolder/actions/builtin/fetch/rails.ts => scaffolder-backend-module-rails/src/actions/fetch/rails/index.ts} (90%) rename plugins/{scaffolder-backend/src/scaffolder/stages/templater => scaffolder-backend-module-rails/src/actions/fetch}/rails/railsArgumentResolver.test.ts (95%) rename plugins/{scaffolder-backend/src/scaffolder/stages/templater => scaffolder-backend-module-rails/src/actions/fetch}/rails/railsArgumentResolver.ts (100%) rename plugins/{scaffolder-backend/src/scaffolder/stages/templater/rails/index.test.ts => scaffolder-backend-module-rails/src/actions/fetch/rails/railsNewRunner.test.ts} (89%) rename plugins/{scaffolder-backend/src/scaffolder/stages/templater/rails/index.ts => scaffolder-backend-module-rails/src/actions/fetch/rails/railsNewRunner.ts} (84%) create mode 100644 plugins/scaffolder-backend-module-rails/src/actions/index.ts create mode 100644 plugins/scaffolder-backend-module-rails/src/index.ts diff --git a/.changeset/twelve-deers-explode.md b/.changeset/twelve-deers-explode.md index c5ce1318a6..0d34392eab 100644 --- a/.changeset/twelve-deers-explode.md +++ b/.changeset/twelve-deers-explode.md @@ -2,4 +2,4 @@ '@backstage/plugin-scaffolder-backend': patch --- -Created a Rails templater to scaffold apps +Export the `fetchContents` from scaffolder-backend diff --git a/microsite/data/plugins/scaffolder-backend-module-rails.yaml b/microsite/data/plugins/scaffolder-backend-module-rails.yaml new file mode 100644 index 0000000000..5f5a29cf3c --- /dev/null +++ b/microsite/data/plugins/scaffolder-backend-module-rails.yaml @@ -0,0 +1,9 @@ +--- +title: Scaffolder Backend Module Rails +author: Rogerio Angeliski +authorUrl: https://angeliski.com.br/ +category: Scaffolder +description: Here you can find all Rails related features to improve your scaffolder. +documentation: https://github.com/backstage/backstage/blob/master/plugins/scaffolder-backend-module-rails/README.md +iconUrl: img/rails-icon.png +npmPackageName: '@backstage/plugin-scaffolder-backend-module-rails' diff --git a/microsite/static/img/rails-icon.png b/microsite/static/img/rails-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..f7b8b69bd9695a8dc98b7bb4b5f848e2ab6eccdf GIT binary patch literal 5439 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 literal 0 HcmV?d00001 diff --git a/packages/backend/package.json b/packages/backend/package.json index ed6fbd56b5..c3e693865f 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -31,6 +31,7 @@ "@backstage/catalog-client": "^0.3.15", "@backstage/catalog-model": "^0.8.2", "@backstage/config": "^0.1.5", + "@backstage/integration": "^0.5.6", "@backstage/plugin-app-backend": "^0.3.13", "@backstage/plugin-auth-backend": "^0.3.15", "@backstage/plugin-badges-backend": "^0.1.6", @@ -42,6 +43,7 @@ "@backstage/plugin-proxy-backend": "^0.2.9", "@backstage/plugin-rollbar-backend": "^0.1.11", "@backstage/plugin-scaffolder-backend": "^0.12.4", + "@backstage/plugin-scaffolder-backend-module-rails": "^0.1.1", "@backstage/plugin-search-backend": "^0.2.0", "@backstage/plugin-search-backend-node": "^0.2.0", "@backstage/plugin-techdocs-backend": "^0.8.5", diff --git a/plugins/scaffolder-backend-module-rails/.eslintrc.js b/plugins/scaffolder-backend-module-rails/.eslintrc.js new file mode 100644 index 0000000000..16a033dbc6 --- /dev/null +++ b/plugins/scaffolder-backend-module-rails/.eslintrc.js @@ -0,0 +1,3 @@ +module.exports = { + extends: [require.resolve('@backstage/cli/config/eslint.backend')], +}; diff --git a/plugins/scaffolder-backend-module-rails/README.md b/plugins/scaffolder-backend-module-rails/README.md new file mode 100644 index 0000000000..3c0c9da53e --- /dev/null +++ b/plugins/scaffolder-backend-module-rails/README.md @@ -0,0 +1,225 @@ +# scaffolder-backend-module-rails + +Welcome to the Rails Module for Scaffolder. + +Here you can find all Rails related features to improve your scaffolder: + +- Rails Action to use the `new` command +- More features are coming + +## Getting started + +You need to configure the action in your backend: + +``` +yarn add @backstage/plugin-scaffolder-backend-module-rails +``` + +Configure the action (you can check +the [docs](https://backstage.io/docs/features/software-templates/writing-custom-actions#registering-custom-actions) to +see all options): + +```typescript +const actions = [ + createFetchRailsAction({ + integrations, + reader, + containerRunner, + }), +]; + +return await createRouter({ + preparers, + templaters, + publishers, + logger, + config, + database, + catalogClient, + reader, + actions, +}); +``` + +After that you can use the action in your template: + +```yaml +apiVersion: backstage.io/v1beta2 +kind: Template +metadata: + name: rails-demo + title: Rails template + description: scaffolder Rails app +spec: + owner: backstage/techdocs-core + type: service + + parameters: + - title: Fill in some steps + required: + - name + - owner + properties: + name: + title: Name + type: string + description: Unique name of the component + ui:autofocus: true + ui:options: + rows: 5 + owner: + title: Owner + type: string + description: Owner of the component + ui:field: OwnerPicker + ui:options: + allowedKinds: + - Group + system: + title: System + type: string + description: System of the component + ui:field: EntityPicker + ui:options: + allowedKinds: + - System + defaultKind: System + + - title: Choose a location + required: + - repoUrl + - dryRun + properties: + repoUrl: + title: Repository Location + type: string + ui:field: RepoUrlPicker + ui:options: + allowedHosts: + - github.com + dryRun: + title: Only perform a dry run, don't publish anything + type: boolean + default: false + railsArguments: + title: arguments to run the rails new command + type: object + properties: + minimal: + title: minimal + description: Preconfigure a minimal rails app + type: boolean + skipBundle: + title: skipBundle + description: Don't run bundle install + type: boolean + skipWebpackInstall: + title: skipWebpackInstall + description: Don't run Webpack install + type: boolean + api: + title: api + description: Preconfigure smaller stack for API only apps + type: boolean + template: + title: template + description: Path to some application template (can be a filesystem path or URL) + type: string + default: './rails-template-file.rb' + webpacker: + title: webpacker + description: + 'Preconfigure Webpack with a particular framework (options: react, + vue, angular, elm, stimulus)' + type: string + enum: + - react + - vue + - angular + - elm + - stimulus + database: + title: database + description: 'Preconfigure for selected database (options: mysql/postgresql/sqlite3/oracle/sqlserver/jdbcmysql/jdbcsqlite3/jdbcpostgresql/jdbc)' + type: string + enum: + - mysql + - postgresql + - sqlite3 + - oracle + - sqlserver + - jdbcmysql + - jdbcsqlite3 + - jdbcpostgresql + - jdbc + railsVersion: + title: Rails version in Gemfile + description: + 'Set up the application with Gemfile pointing to a specific version + (options: dev, edge, master)' + type: string + enum: + - dev + - edge + - master + + steps: + - id: fetch-base + name: Fetch Base + action: fetch:rails + input: + url: ./template + values: + name: '{{ parameters.name }}' + owner: '{{ parameters.owner }}' + system: '{{ parameters.system }}' + railsArguments: '{{ json parameters.railsArguments }}' + + - name: Write Catalog information + action: catalog:write + input: + component: + apiVersion: 'backstage.io/v1alpha1' + kind: Component + metadata: + name: '{{ parameters.name }}' + annotations: + github.com/project-slug: '{{ projectSlug parameters.repoUrl }}' + spec: + type: service + lifecycle: production + owner: '{{ parameters.owner }}' + + - id: publish + if: '{{ not parameters.dryRun }}' + name: Publish + action: publish:github + input: + allowedHosts: ['github.com'] + description: 'This is {{ parameters.name }}' + repoUrl: '{{ parameters.repoUrl }}' + + - id: register + if: '{{ not parameters.dryRun }}' + name: Register + action: catalog:register + input: + repoContentsUrl: '{{ steps.publish.output.repoContentsUrl }}' + catalogInfoPath: '/catalog-info.yaml' + + - name: Results + if: '{{ parameters.dryRun }}' + action: debug:log + input: + listWorkspace: true + + output: + links: + - title: Repository + url: '{{ steps.publish.output.remoteUrl }}' + - title: Open in catalog + icon: 'catalog' + entityRef: '{{ steps.register.output.entityRef }}' +``` + +We have a [Docker image](https://github.com/backstage/backstage/blob/master/plugins/scaffolder-backend-module-rails/Rails.dockerfile) you can use to build your own. diff --git a/plugins/scaffolder-backend/scripts/Rails.dockerfile b/plugins/scaffolder-backend-module-rails/Rails.dockerfile similarity index 100% rename from plugins/scaffolder-backend/scripts/Rails.dockerfile rename to plugins/scaffolder-backend-module-rails/Rails.dockerfile diff --git a/plugins/scaffolder-backend-module-rails/api-report.md b/plugins/scaffolder-backend-module-rails/api-report.md new file mode 100644 index 0000000000..95d9c1bd9f --- /dev/null +++ b/plugins/scaffolder-backend-module-rails/api-report.md @@ -0,0 +1,22 @@ +## API Report File for "@backstage/plugin-scaffolder-backend-module-rails" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts + +import { ContainerRunner } from '@backstage/backend-common'; +import { ScmIntegrations } from '@backstage/integration'; +import { TemplateAction } from '@backstage/plugin-scaffolder-backend'; +import { UrlReader } from '@backstage/backend-common'; + +// @public (undocumented) +export function createFetchRailsAction(options: { + reader: UrlReader; + integrations: ScmIntegrations; + containerRunner: ContainerRunner; +}): TemplateAction; + + +// (No @packageDocumentation comment for this package) + +``` diff --git a/plugins/scaffolder-backend-module-rails/package.json b/plugins/scaffolder-backend-module-rails/package.json new file mode 100644 index 0000000000..79b123cdb6 --- /dev/null +++ b/plugins/scaffolder-backend-module-rails/package.json @@ -0,0 +1,44 @@ +{ + "name": "@backstage/plugin-scaffolder-backend-module-rails", + "version": "0.1.1", + "main": "src/index.ts", + "types": "src/index.ts", + "license": "Apache-2.0", + "publishConfig": { + "access": "public", + "main": "dist/index.esm.js", + "types": "dist/index.d.ts" + }, + "scripts": { + "build": "backstage-cli plugin:build", + "start": "backstage-cli plugin:serve", + "lint": "backstage-cli lint", + "test": "backstage-cli test", + "diff": "backstage-cli plugin:diff", + "prepack": "backstage-cli prepack", + "postpack": "backstage-cli postpack", + "clean": "backstage-cli clean" + }, + "dependencies": { + "@backstage/backend-common": "^0.8.3", + "@backstage/plugin-scaffolder-backend": "^0.12.2", + "@backstage/config": "^0.1.5", + "@backstage/errors": "^0.1.1", + "@backstage/integration": "^0.5.6", + "command-exists": "^1.2.9", + "fs-extra": "^9.0.0" + }, + "devDependencies": { + "@backstage/cli": "^0.7.1", + "@types/jest": "^26.0.7", + "@types/node": "^14.14.32", + "@types/command-exists": "^1.2.0", + "@types/fs-extra": "^9.0.1", + "@types/mock-fs": "^4.13.0", + "jest-when": "^3.1.0", + "mock-fs": "^4.13.0" + }, + "files": [ + "dist" + ] +} diff --git a/plugins/scaffolder-backend-module-rails/src/actions/fetch/index.ts b/plugins/scaffolder-backend-module-rails/src/actions/fetch/index.ts new file mode 100644 index 0000000000..7d590c9a1a --- /dev/null +++ b/plugins/scaffolder-backend-module-rails/src/actions/fetch/index.ts @@ -0,0 +1,16 @@ +/* + * Copyright 2021 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +export * from './rails'; diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/rails.test.ts b/plugins/scaffolder-backend-module-rails/src/actions/fetch/rails/index.test.ts similarity index 86% rename from plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/rails.test.ts rename to plugins/scaffolder-backend-module-rails/src/actions/fetch/rails/index.test.ts index ebc62e9277..cedc768f88 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/rails.test.ts +++ b/plugins/scaffolder-backend-module-rails/src/actions/fetch/rails/index.test.ts @@ -15,24 +15,31 @@ */ const mockRailsTemplater = { run: jest.fn() }; -jest.mock('./helpers'); -jest.mock('../../../stages/templater', () => { +jest.mock('@backstage/plugin-scaffolder-backend', () => ({ + ...jest.requireActual('@backstage/plugin-scaffolder-backend'), + fetchContents: jest.fn(), +})); +jest.mock('./railsNewRunner', () => { return { - Rails: jest.fn().mockImplementation(() => { + RailsNewRunner: jest.fn().mockImplementation(() => { return mockRailsTemplater; }), }; }); -import { getVoidLogger, UrlReader } from '@backstage/backend-common'; +import { + ContainerRunner, + getVoidLogger, + UrlReader, +} from '@backstage/backend-common'; import { ConfigReader } from '@backstage/config'; import { ScmIntegrations } from '@backstage/integration'; import mock from 'mock-fs'; import os from 'os'; import { resolve as resolvePath } from 'path'; import { PassThrough } from 'stream'; -import { createFetchRailsAction } from './rails'; -import { fetchContents } from './helpers'; +import { createFetchRailsAction } from './index'; +import { fetchContents } from '@backstage/plugin-scaffolder-backend'; describe('fetch:rails', () => { const integrations = ScmIntegrations.fromConfig( @@ -68,10 +75,14 @@ describe('fetch:rails', () => { readTree: jest.fn(), search: jest.fn(), }; + const containerRunner: ContainerRunner = { + runContainer: jest.fn(), + }; const action = createFetchRailsAction({ integrations, reader: mockReader, + containerRunner, }); beforeEach(() => { diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/rails.ts b/plugins/scaffolder-backend-module-rails/src/actions/fetch/rails/index.ts similarity index 90% rename from plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/rails.ts rename to plugins/scaffolder-backend-module-rails/src/actions/fetch/rails/index.ts index 203db5004e..e2dc8fd95a 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/rails.ts +++ b/plugins/scaffolder-backend-module-rails/src/actions/fetch/rails/index.ts @@ -14,22 +14,25 @@ * limitations under the License. */ -import { DockerContainerRunner, UrlReader } from '@backstage/backend-common'; +import { ContainerRunner, UrlReader } from '@backstage/backend-common'; import { JsonObject } from '@backstage/config'; import { InputError } from '@backstage/errors'; import { ScmIntegrations } from '@backstage/integration'; import fs from 'fs-extra'; +import { + createTemplateAction, + fetchContents, +} from '@backstage/plugin-scaffolder-backend'; + import { resolve as resolvePath } from 'path'; -import { Rails, TemplaterValues } from '../../../stages/templater'; -import { createTemplateAction } from '../../createTemplateAction'; -import { fetchContents } from './helpers'; -import Docker from 'dockerode'; +import { RailsNewRunner } from './railsNewRunner'; export function createFetchRailsAction(options: { reader: UrlReader; integrations: ScmIntegrations; + containerRunner: ContainerRunner; }) { - const { reader, integrations } = options; + const { reader, integrations, containerRunner } = options; return createTemplateAction<{ url: string; @@ -39,7 +42,7 @@ export function createFetchRailsAction(options: { }>({ id: 'fetch:rails', description: - 'Downloads a template from the given URL into the workspace, and runs a rails generator on it.', + 'Downloads a template from the given URL into the workspace, and runs a rails new generator on it.', schema: { input: { type: 'object', @@ -152,12 +155,10 @@ export function createFetchRailsAction(options: { outputPath: workDir, }); - const dockerClient = new Docker(); - const containerRunner = new DockerContainerRunner({ dockerClient }); - const templateRunner = new Rails({ containerRunner }); + const templateRunner = new RailsNewRunner({ containerRunner }); const values = { - ...(ctx.input.values as TemplaterValues), + ...ctx.input.values, imageName: ctx.input.imageName, }; diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/templater/rails/railsArgumentResolver.test.ts b/plugins/scaffolder-backend-module-rails/src/actions/fetch/rails/railsArgumentResolver.test.ts similarity index 95% rename from plugins/scaffolder-backend/src/scaffolder/stages/templater/rails/railsArgumentResolver.test.ts rename to plugins/scaffolder-backend-module-rails/src/actions/fetch/rails/railsArgumentResolver.test.ts index 370d9de380..a8c10625c2 100644 --- a/plugins/scaffolder-backend/src/scaffolder/stages/templater/rails/railsArgumentResolver.test.ts +++ b/plugins/scaffolder-backend-module-rails/src/actions/fetch/rails/railsArgumentResolver.test.ts @@ -15,7 +15,6 @@ */ import { railsArgumentResolver } from './railsArgumentResolver'; -import { TemplaterValues } from '../types'; describe('railsArgumentResolver', () => { describe('when provide the parameter', () => { @@ -33,7 +32,7 @@ describe('railsArgumentResolver', () => { 'should include the argument to execution %p -> %p', (passedArguments: object, expected: Array) => { // that step is to ensure the validation between the TemplaterValues and the resolver - const values: TemplaterValues = { + const values = { owner: 'r', storePath: '', railsArguments: passedArguments, diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/templater/rails/railsArgumentResolver.ts b/plugins/scaffolder-backend-module-rails/src/actions/fetch/rails/railsArgumentResolver.ts similarity index 100% rename from plugins/scaffolder-backend/src/scaffolder/stages/templater/rails/railsArgumentResolver.ts rename to plugins/scaffolder-backend-module-rails/src/actions/fetch/rails/railsArgumentResolver.ts diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/templater/rails/index.test.ts b/plugins/scaffolder-backend-module-rails/src/actions/fetch/rails/railsNewRunner.test.ts similarity index 89% rename from plugins/scaffolder-backend/src/scaffolder/stages/templater/rails/index.test.ts rename to plugins/scaffolder-backend-module-rails/src/actions/fetch/rails/railsNewRunner.test.ts index 534899eec1..dc3f824236 100644 --- a/plugins/scaffolder-backend/src/scaffolder/stages/templater/rails/index.test.ts +++ b/plugins/scaffolder-backend-module-rails/src/actions/fetch/rails/railsNewRunner.test.ts @@ -16,7 +16,7 @@ const runCommand = jest.fn(); const commandExists = jest.fn(); -jest.mock('../helpers', () => ({ runCommand })); +jest.mock('@backstage/plugin-scaffolder-backend', () => ({ runCommand })); jest.mock('command-exists', () => commandExists); jest.mock('fs-extra'); @@ -26,7 +26,7 @@ import fs from 'fs-extra'; import path from 'path'; import { PassThrough } from 'stream'; -import { Rails } from './index'; +import { RailsNewRunner } from './railsNewRunner'; describe('Rails Templater', () => { const containerRunner: jest.Mocked = { @@ -39,6 +39,7 @@ describe('Rails Templater', () => { describe('when running on docker', () => { it('should run the correct bindings for the volumes', async () => { + const logStream = new PassThrough(); const values = { owner: 'angeliski', storePath: 'https://github.com/angeliski/rails-project', @@ -51,10 +52,11 @@ describe('Rails Templater', () => { .spyOn(fs, 'realpath') .mockImplementation(x => Promise.resolve(x.toString())); - const templater = new Rails({ containerRunner }); + const templater = new RailsNewRunner({ containerRunner }); await templater.run({ workspacePath: 'tempdir', values, + logStream, }); expect(containerRunner.runContainer).toHaveBeenCalledWith({ @@ -67,11 +69,12 @@ describe('Rails Templater', () => { [path.join('tempdir', 'intermediate')]: '/output', }, workingDir: '/input', - logStream: undefined, + logStream: logStream, }); }); it('should use the provided imageName', async () => { + const logStream = new PassThrough(); const values = { owner: 'angeliski', storePath: 'https://github.com/angeliski/rails-project', @@ -81,10 +84,11 @@ describe('Rails Templater', () => { jest.spyOn(fs, 'readdir').mockResolvedValueOnce(['newthing'] as any); - const templater = new Rails({ containerRunner }); + const templater = new RailsNewRunner({ containerRunner }); await templater.run({ workspacePath: 'tempdir', values, + logStream, }); expect(containerRunner.runContainer).toHaveBeenCalledWith( @@ -106,7 +110,7 @@ describe('Rails Templater', () => { jest.spyOn(fs, 'readdir').mockResolvedValueOnce(['newthing'] as any); - const templater = new Rails({ containerRunner }); + const templater = new RailsNewRunner({ containerRunner }); await templater.run({ workspacePath: 'tempdir', values, @@ -128,6 +132,7 @@ describe('Rails Templater', () => { }); it('update the template path to correct location', async () => { + const logStream = new PassThrough(); const values = { owner: 'angeliski', storePath: 'https://github.com/angeliski/rails-project', @@ -141,10 +146,11 @@ describe('Rails Templater', () => { .spyOn(fs, 'realpath') .mockImplementation(x => Promise.resolve(x.toString())); - const templater = new Rails({ containerRunner }); + const templater = new RailsNewRunner({ containerRunner }); await templater.run({ workspacePath: 'tempdir', values, + logStream, }); expect(containerRunner.runContainer).toHaveBeenCalledWith({ @@ -162,7 +168,7 @@ describe('Rails Templater', () => { [path.join('tempdir', 'intermediate')]: '/output', }, workingDir: '/input', - logStream: undefined, + logStream: logStream, }); }); }); @@ -181,7 +187,7 @@ describe('Rails Templater', () => { jest.spyOn(fs, 'readdir').mockResolvedValueOnce(['newthing'] as any); commandExists.mockImplementationOnce(() => () => true); - const templater = new Rails({ containerRunner }); + const templater = new RailsNewRunner({ containerRunner }); await templater.run({ workspacePath: 'tempdir', values, @@ -211,7 +217,7 @@ describe('Rails Templater', () => { jest.spyOn(fs, 'readdir').mockResolvedValueOnce(['newthing'] as any); commandExists.mockImplementationOnce(() => () => true); - const templater = new Rails({ containerRunner }); + const templater = new RailsNewRunner({ containerRunner }); await templater.run({ workspacePath: 'tempdir', values, @@ -239,7 +245,7 @@ describe('Rails Templater', () => { .spyOn(fs, 'readdir') .mockImplementationOnce(() => Promise.resolve([])); - const templater = new Rails({ containerRunner }); + const templater = new RailsNewRunner({ containerRunner }); await expect( templater.run({ workspacePath: 'tempdir', diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/templater/rails/index.ts b/plugins/scaffolder-backend-module-rails/src/actions/fetch/rails/railsNewRunner.ts similarity index 84% rename from plugins/scaffolder-backend/src/scaffolder/stages/templater/rails/index.ts rename to plugins/scaffolder-backend-module-rails/src/actions/fetch/rails/railsNewRunner.ts index 57ee26e106..3e18490587 100644 --- a/plugins/scaffolder-backend/src/scaffolder/stages/templater/rails/index.ts +++ b/plugins/scaffolder-backend-module-rails/src/actions/fetch/rails/railsNewRunner.ts @@ -17,12 +17,16 @@ import { ContainerRunner } from '@backstage/backend-common'; import fs from 'fs-extra'; import path from 'path'; -import { runCommand } from '../helpers'; +import { runCommand } from '@backstage/plugin-scaffolder-backend'; import commandExists from 'command-exists'; -import { TemplaterBase, TemplaterRunOptions } from '../types'; -import { railsArgumentResolver } from './railsArgumentResolver'; +import { + railsArgumentResolver, + RailsRunOptions, +} from './railsArgumentResolver'; +import { JsonObject } from '@backstage/config'; +import { Writable } from 'stream'; -export class Rails implements TemplaterBase { +export class RailsNewRunner { private readonly containerRunner: ContainerRunner; constructor({ containerRunner }: { containerRunner: ContainerRunner }) { @@ -33,7 +37,11 @@ export class Rails implements TemplaterBase { workspacePath, values, logStream, - }: TemplaterRunOptions): Promise { + }: { + workspacePath: string; + values: JsonObject; + logStream: Writable; + }): Promise { const intermediateDir = path.join(workspacePath, 'intermediate'); await fs.ensureDir(intermediateDir); const resultDir = path.join(workspacePath, 'result'); @@ -53,7 +61,7 @@ export class Rails implements TemplaterBase { if (commandExistsToRun) { const arrayExtraArguments = railsArgumentResolver( workspacePath, - railsArguments, + railsArguments as RailsRunOptions, ); await runCommand({ @@ -68,10 +76,10 @@ export class Rails implements TemplaterBase { } else { const arrayExtraArguments = railsArgumentResolver( '/input', - railsArguments, + railsArguments as RailsRunOptions, ); await this.containerRunner.runContainer({ - imageName: imageName, + imageName: imageName as string, command: baseCommand, args: [...baseArguments, `/output/${name}`, ...arrayExtraArguments], mountDirs, diff --git a/plugins/scaffolder-backend-module-rails/src/actions/index.ts b/plugins/scaffolder-backend-module-rails/src/actions/index.ts new file mode 100644 index 0000000000..1b47db9e03 --- /dev/null +++ b/plugins/scaffolder-backend-module-rails/src/actions/index.ts @@ -0,0 +1,16 @@ +/* + * Copyright 2021 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +export * from './fetch'; diff --git a/plugins/scaffolder-backend-module-rails/src/index.ts b/plugins/scaffolder-backend-module-rails/src/index.ts new file mode 100644 index 0000000000..4f06b14a86 --- /dev/null +++ b/plugins/scaffolder-backend-module-rails/src/index.ts @@ -0,0 +1,16 @@ +/* + * Copyright 2021 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +export * from './actions'; diff --git a/plugins/scaffolder-backend/api-report.md b/plugins/scaffolder-backend/api-report.md index ab3ea433c6..e30542aca7 100644 --- a/plugins/scaffolder-backend/api-report.md +++ b/plugins/scaffolder-backend/api-report.md @@ -11,7 +11,7 @@ import { createPullRequest } from 'octokit-plugin-create-pull-request'; import express from 'express'; import { JsonObject } from '@backstage/config'; import { JsonValue } from '@backstage/config'; -import { Logger } from 'winston'; +import { Logger as Logger_2 } from 'winston'; import { PluginDatabaseManager } from '@backstage/backend-common'; import { Schema } from 'jsonschema'; import { ScmIntegrationRegistry } from '@backstage/integration'; @@ -23,7 +23,7 @@ import { Writable } from 'stream'; // @public (undocumented) export type ActionContext = { baseUrl?: string; - logger: Logger; + logger: Logger_2; logStream: Writable; token?: string | undefined; workspacePath: string; @@ -131,7 +131,7 @@ export interface RouterOptions { // (undocumented) database: PluginDatabaseManager; // (undocumented) - logger: Logger; + logger: Logger_2; // (undocumented) reader: UrlReader; // (undocumented) diff --git a/plugins/scaffolder-backend/package.json b/plugins/scaffolder-backend/package.json index a6db486594..a88413d611 100644 --- a/plugins/scaffolder-backend/package.json +++ b/plugins/scaffolder-backend/package.json @@ -62,8 +62,7 @@ "octokit-plugin-create-pull-request": "^3.9.3", "uuid": "^8.2.0", "winston": "^3.2.1", - "yaml": "^1.10.0", - "dockerode": "^3.2.1" + "yaml": "^1.10.0" }, "devDependencies": { "@backstage/cli": "^0.7.3", @@ -73,7 +72,6 @@ "@types/git-url-parse": "^9.0.0", "@types/mock-fs": "^4.13.0", "@types/supertest": "^2.0.8", - "@types/dockerode": "^3.2.1", "jest-when": "^3.1.0", "mock-fs": "^4.13.0", "msw": "^0.29.0", diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/createBuiltinActions.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/createBuiltinActions.ts index fa2fcbfcee..08d7bbf824 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/createBuiltinActions.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/createBuiltinActions.ts @@ -24,11 +24,7 @@ import { } from './catalog'; import { createDebugLogAction } from './debug'; -import { - createFetchCookiecutterAction, - createFetchPlainAction, - createFetchRailsAction, -} from './fetch'; +import { createFetchCookiecutterAction, createFetchPlainAction } from './fetch'; import { createFilesystemDeleteAction, createFilesystemRenameAction, @@ -66,10 +62,6 @@ export const createBuiltinActions = (options: { integrations, containerRunner, }), - createFetchRailsAction({ - reader, - integrations, - }), createPublishGithubAction({ integrations, config, diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/index.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/index.ts index 9557a88a4c..82bc387f26 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/index.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/index.ts @@ -16,4 +16,4 @@ export { createFetchPlainAction } from './plain'; export { createFetchCookiecutterAction } from './cookiecutter'; -export { createFetchRailsAction } from './rails'; +export * from './helpers'; diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/templater/index.ts b/plugins/scaffolder-backend/src/scaffolder/stages/templater/index.ts index 139ff2207e..4d80f86946 100644 --- a/plugins/scaffolder-backend/src/scaffolder/stages/templater/index.ts +++ b/plugins/scaffolder-backend/src/scaffolder/stages/templater/index.ts @@ -18,4 +18,3 @@ export * from './types'; export * from './helpers'; export * from './templaters'; export * from './cra'; -export * from './rails'; From 1cdc4ba0e2c36b1e1c0869cb6dbc9cfcb079d40f Mon Sep 17 00:00:00 2001 From: Rogerio Angeliski Date: Thu, 24 Jun 2021 12:49:32 -0300 Subject: [PATCH 194/204] docs: added generated files Signed-off-by: Rogerio Angeliski --- packages/backend-common/api-report.md | 10 +++++----- packages/techdocs-common/api-report.md | 20 +++++++++---------- plugins/app-backend/api-report.md | 4 ++-- plugins/auth-backend/api-report.md | 6 +++--- .../api-report.md | 6 +++--- plugins/catalog-graphql/api-report.md | 4 ++-- plugins/code-coverage-backend/api-report.md | 4 ++-- plugins/graphql/api-report.md | 4 ++-- plugins/kafka-backend/api-report.md | 2 +- plugins/kubernetes-backend/api-report.md | 6 +++--- plugins/proxy-backend/api-report.md | 2 +- plugins/rollbar-backend/api-report.md | 6 +++--- plugins/search-backend-node/api-report.md | 8 ++++---- plugins/search-backend/api-report.md | 2 +- plugins/techdocs-backend/api-report.md | 2 +- plugins/todo-backend/api-report.md | 2 +- 16 files changed, 44 insertions(+), 44 deletions(-) diff --git a/packages/backend-common/api-report.md b/packages/backend-common/api-report.md index a21aaef4a6..22eac06ed2 100644 --- a/packages/backend-common/api-report.md +++ b/packages/backend-common/api-report.md @@ -19,7 +19,7 @@ import * as http from 'http'; import { isChildPath } from '@backstage/cli-common'; import { JsonValue } from '@backstage/config'; import { Knex } from 'knex'; -import { Logger } from 'winston'; +import { Logger as Logger_2 } from 'winston'; import { MergeResult } from 'isomorphic-git'; import { PushResult } from 'isomorphic-git'; import { Readable } from 'stream'; @@ -129,7 +129,7 @@ export function errorHandler(options?: ErrorHandlerOptions): ErrorRequestHandler // @public (undocumented) export type ErrorHandlerOptions = { showStackTraces?: boolean; - logger?: Logger; + logger?: Logger_2; logClientErrors?: boolean; }; @@ -185,7 +185,7 @@ export class Git { static fromAuth: ({ username, password, logger, }: { username?: string | undefined; password?: string | undefined; - logger?: Logger | undefined; + logger?: Logger_2 | undefined; }) => Git; // (undocumented) init({ dir, defaultBranch, }: { @@ -301,7 +301,7 @@ export type ReadTreeResponseFile = { }; // @public -export function requestLoggingHandler(logger?: Logger): RequestHandler; +export function requestLoggingHandler(logger?: Logger_2): RequestHandler; // @public export function resolvePackagePath(name: string, ...paths: string[]): string; @@ -337,7 +337,7 @@ export type ServiceBuilder = { loadConfig(config: ConfigReader): ServiceBuilder; setPort(port: number): ServiceBuilder; setHost(host: string): ServiceBuilder; - setLogger(logger: Logger): ServiceBuilder; + setLogger(logger: Logger_2): ServiceBuilder; enableCors(options: cors.CorsOptions): ServiceBuilder; setHttpsSettings(settings: HttpsSettings): ServiceBuilder; addRouter(root: string, router: Router | RequestHandler): ServiceBuilder; diff --git a/packages/techdocs-common/api-report.md b/packages/techdocs-common/api-report.md index 3fff030eee..d25f55bf3a 100644 --- a/packages/techdocs-common/api-report.md +++ b/packages/techdocs-common/api-report.md @@ -12,17 +12,17 @@ import { EntityName } from '@backstage/catalog-model'; import express from 'express'; import { GitHubIntegrationConfig } from '@backstage/integration'; import { GitLabIntegrationConfig } from '@backstage/integration'; -import { Logger } from 'winston'; +import { Logger as Logger_2 } from 'winston'; import { PluginEndpointDiscovery } from '@backstage/backend-common'; import { UrlReader } from '@backstage/backend-common'; import { Writable } from 'stream'; // @public (undocumented) -export const checkoutGitRepository: (repoUrl: string, config: Config, logger: Logger) => Promise; +export const checkoutGitRepository: (repoUrl: string, config: Config, logger: Logger_2) => Promise; // @public (undocumented) export class CommonGitPreparer implements PreparerBase { - constructor(config: Config, logger: Logger); + constructor(config: Config, logger: Logger_2); // (undocumented) prepare(entity: Entity, options?: { etag?: string; @@ -31,7 +31,7 @@ export class CommonGitPreparer implements PreparerBase { // @public (undocumented) export class DirectoryPreparer implements PreparerBase { - constructor(config: Config, logger: Logger, reader: UrlReader); + constructor(config: Config, logger: Logger_2, reader: UrlReader); // (undocumented) prepare(entity: Entity): Promise; } @@ -51,7 +51,7 @@ export type GeneratorBuilder = { export class Generators implements GeneratorBuilder { // (undocumented) static fromConfig(config: Config, { logger, containerRunner, }: { - logger: Logger; + logger: Logger_2; containerRunner: ContainerRunner; }): Promise; // (undocumented) @@ -69,7 +69,7 @@ export const getDefaultBranch: (repositoryUrl: string, config: Config) => Promis // @public (undocumented) export const getDocFilesFromRepository: (reader: UrlReader, entity: Entity, opts?: { etag?: string | undefined; - logger?: Logger | undefined; + logger?: Logger_2 | undefined; } | undefined) => Promise; // @public (undocumented) @@ -88,7 +88,7 @@ export const getGitRepositoryTempFolder: (repositoryUrl: string, config: Config) export function getGitRepoType(url: string): string; // @public (undocumented) -export const getLastCommitTimestamp: (repositoryLocation: string, logger: Logger) => Promise; +export const getLastCommitTimestamp: (repositoryLocation: string, logger: Logger_2) => Promise; // @public (undocumented) export const getLocationForEntity: (entity: Entity) => ParsedLocationAnnotation; @@ -108,7 +108,7 @@ export const parseReferenceAnnotation: (annotationName: string, entity: Entity) // @public (undocumented) export type PreparerBase = { prepare(entity: Entity, options?: { - logger?: Logger; + logger?: Logger_2; etag?: string; }): Promise; }; @@ -153,7 +153,7 @@ export type RemoteProtocol = 'url' | 'dir' | 'github' | 'gitlab' | 'file' | 'azu // @public (undocumented) export class TechdocsGenerator implements GeneratorBase { constructor({ logger, containerRunner, config, }: { - logger: Logger; + logger: Logger_2; containerRunner: ContainerRunner; config: Config; }); @@ -170,7 +170,7 @@ export type TechDocsMetadata = { // @public (undocumented) export class UrlPreparer implements PreparerBase { - constructor(reader: UrlReader, logger: Logger); + constructor(reader: UrlReader, logger: Logger_2); // (undocumented) prepare(entity: Entity, options?: { etag?: string; diff --git a/plugins/app-backend/api-report.md b/plugins/app-backend/api-report.md index 4f59102265..93aba5596f 100644 --- a/plugins/app-backend/api-report.md +++ b/plugins/app-backend/api-report.md @@ -6,7 +6,7 @@ import { Config } from '@backstage/config'; import express from 'express'; -import { Logger } from 'winston'; +import { Logger as Logger_2 } from 'winston'; // @public (undocumented) export function createRouter(options: RouterOptions): Promise; @@ -18,7 +18,7 @@ export interface RouterOptions { config: Config; disableConfigInjection?: boolean; // (undocumented) - logger: Logger; + logger: Logger_2; staticFallbackHandler?: express.Handler; } diff --git a/plugins/auth-backend/api-report.md b/plugins/auth-backend/api-report.md index 6ae878accf..9f9a8d18ef 100644 --- a/plugins/auth-backend/api-report.md +++ b/plugins/auth-backend/api-report.md @@ -9,7 +9,7 @@ import { Config } from '@backstage/config'; import { Entity } from '@backstage/catalog-model'; import express from 'express'; import { JSONWebKey } from 'jose'; -import { Logger } from 'winston'; +import { Logger as Logger_2 } from 'winston'; import { PluginDatabaseManager } from '@backstage/backend-common'; import { PluginEndpointDiscovery } from '@backstage/backend-common'; import { Profile } from 'passport'; @@ -23,7 +23,7 @@ export type AuthProviderFactoryOptions = { providerId: string; globalConfig: AuthProviderConfig; config: Config; - logger: Logger; + logger: Logger_2; tokenIssuer: TokenIssuer; discovery: PluginEndpointDiscovery; catalogApi: CatalogApi; @@ -206,7 +206,7 @@ export interface RouterOptions { // (undocumented) discovery: PluginEndpointDiscovery; // (undocumented) - logger: Logger; + logger: Logger_2; // (undocumented) providerFactories?: ProviderFactories; } diff --git a/plugins/catalog-backend-module-msgraph/api-report.md b/plugins/catalog-backend-module-msgraph/api-report.md index f1e7e22c35..bac733ef53 100644 --- a/plugins/catalog-backend-module-msgraph/api-report.md +++ b/plugins/catalog-backend-module-msgraph/api-report.md @@ -9,7 +9,7 @@ import { CatalogProcessorEmit } from '@backstage/plugin-catalog-backend'; import { Config } from '@backstage/config'; import { GroupEntity } from '@backstage/catalog-model'; import { LocationSpec } from '@backstage/catalog-model'; -import { Logger } from 'winston'; +import { Logger as Logger_2 } from 'winston'; import * as MicrosoftGraph from '@microsoft/microsoft-graph-types'; import * as msal from '@azure/msal-node'; import { UserEntity } from '@backstage/catalog-model'; @@ -70,12 +70,12 @@ export class MicrosoftGraphClient { export class MicrosoftGraphOrgReaderProcessor implements CatalogProcessor { constructor(options: { providers: MicrosoftGraphProviderConfig[]; - logger: Logger; + logger: Logger_2; groupTransformer?: GroupTransformer; }); // (undocumented) static fromConfig(config: Config, options: { - logger: Logger; + logger: Logger_2; groupTransformer?: GroupTransformer; }): MicrosoftGraphOrgReaderProcessor; // (undocumented) diff --git a/plugins/catalog-graphql/api-report.md b/plugins/catalog-graphql/api-report.md index cbe325f4c5..40e8a19b66 100644 --- a/plugins/catalog-graphql/api-report.md +++ b/plugins/catalog-graphql/api-report.md @@ -6,7 +6,7 @@ import { Config } from '@backstage/config'; import { GraphQLModule } from '@graphql-modules/core'; -import { Logger } from 'winston'; +import { Logger as Logger_2 } from 'winston'; // @public (undocumented) export function createModule(options: ModuleOptions): Promise; @@ -16,7 +16,7 @@ export interface ModuleOptions { // (undocumented) config: Config; // (undocumented) - logger: Logger; + logger: Logger_2; } diff --git a/plugins/code-coverage-backend/api-report.md b/plugins/code-coverage-backend/api-report.md index f8f1575d0b..186b76fb39 100644 --- a/plugins/code-coverage-backend/api-report.md +++ b/plugins/code-coverage-backend/api-report.md @@ -6,7 +6,7 @@ import { Config } from '@backstage/config'; import express from 'express'; -import { Logger } from 'winston'; +import { Logger as Logger_2 } from 'winston'; import { PluginDatabaseManager } from '@backstage/backend-common'; import { PluginEndpointDiscovery } from '@backstage/backend-common'; import { UrlReader } from '@backstage/backend-common'; @@ -32,7 +32,7 @@ export interface RouterOptions { // (undocumented) discovery: PluginEndpointDiscovery; // (undocumented) - logger: Logger; + logger: Logger_2; // (undocumented) urlReader: UrlReader; } diff --git a/plugins/graphql/api-report.md b/plugins/graphql/api-report.md index 8109c94122..ef172afbd7 100644 --- a/plugins/graphql/api-report.md +++ b/plugins/graphql/api-report.md @@ -6,7 +6,7 @@ import { Config } from '@backstage/config'; import express from 'express'; -import { Logger } from 'winston'; +import { Logger as Logger_2 } from 'winston'; // @public (undocumented) export function createRouter(options: RouterOptions): Promise; @@ -16,7 +16,7 @@ export interface RouterOptions { // (undocumented) config: Config; // (undocumented) - logger: Logger; + logger: Logger_2; } diff --git a/plugins/kafka-backend/api-report.md b/plugins/kafka-backend/api-report.md index 47754ad572..6840bd7527 100644 --- a/plugins/kafka-backend/api-report.md +++ b/plugins/kafka-backend/api-report.md @@ -6,7 +6,7 @@ import { Config } from '@backstage/config'; import express from 'express'; -import { Logger } from 'winston'; +import { Logger as Logger_2 } from 'winston'; // @public (undocumented) export function createRouter(options: RouterOptions): Promise; diff --git a/plugins/kubernetes-backend/api-report.md b/plugins/kubernetes-backend/api-report.md index fe43e8888a..a9389b7e62 100644 --- a/plugins/kubernetes-backend/api-report.md +++ b/plugins/kubernetes-backend/api-report.md @@ -9,7 +9,7 @@ import express from 'express'; import { FetchResponse } from '@backstage/plugin-kubernetes-common'; import { KubernetesFetchError } from '@backstage/plugin-kubernetes-common'; import { KubernetesRequestBody } from '@backstage/plugin-kubernetes-common'; -import { Logger } from 'winston'; +import { Logger as Logger_2 } from 'winston'; // @public (undocumented) export interface ClusterDetails { @@ -68,7 +68,7 @@ export interface KubernetesServiceLocator { } // @public (undocumented) -export const makeRouter: (logger: Logger, kubernetesFanOutHandler: KubernetesFanOutHandler, clusterDetails: ClusterDetails[]) => express.Router; +export const makeRouter: (logger: Logger_2, kubernetesFanOutHandler: KubernetesFanOutHandler, clusterDetails: ClusterDetails[]) => express.Router; // @public (undocumented) export interface ObjectFetchParams { @@ -91,7 +91,7 @@ export interface RouterOptions { // (undocumented) config: Config; // (undocumented) - logger: Logger; + logger: Logger_2; } // @public (undocumented) diff --git a/plugins/proxy-backend/api-report.md b/plugins/proxy-backend/api-report.md index 1b1eba3b00..63469a2017 100644 --- a/plugins/proxy-backend/api-report.md +++ b/plugins/proxy-backend/api-report.md @@ -6,7 +6,7 @@ import { Config } from '@backstage/config'; import express from 'express'; -import { Logger } from 'winston'; +import { Logger as Logger_2 } from 'winston'; import { PluginEndpointDiscovery } from '@backstage/backend-common'; // @public (undocumented) diff --git a/plugins/rollbar-backend/api-report.md b/plugins/rollbar-backend/api-report.md index fa8c67d4f0..9fa525cfc3 100644 --- a/plugins/rollbar-backend/api-report.md +++ b/plugins/rollbar-backend/api-report.md @@ -6,7 +6,7 @@ import { Config } from '@backstage/config'; import express from 'express'; -import { Logger } from 'winston'; +import { Logger as Logger_2 } from 'winston'; // @public (undocumented) export function createRouter(options: RouterOptions): Promise; @@ -20,7 +20,7 @@ export function getRequestHeaders(token: string): { // @public (undocumented) export class RollbarApi { - constructor(accessToken: string, logger: Logger); + constructor(accessToken: string, logger: Logger_2); // (undocumented) getActivatedCounts(projectName: string, options?: { environment: string; @@ -49,7 +49,7 @@ export interface RouterOptions { // (undocumented) config: Config; // (undocumented) - logger: Logger; + logger: Logger_2; // (undocumented) rollbarApi?: RollbarApi; } diff --git a/plugins/search-backend-node/api-report.md b/plugins/search-backend-node/api-report.md index 03585b6b99..ccb7475573 100644 --- a/plugins/search-backend-node/api-report.md +++ b/plugins/search-backend-node/api-report.md @@ -7,7 +7,7 @@ import { DocumentCollator } from '@backstage/search-common'; import { DocumentDecorator } from '@backstage/search-common'; import { IndexableDocument } from '@backstage/search-common'; -import { Logger } from 'winston'; +import { Logger as Logger_2 } from 'winston'; import { default as lunr_2 } from 'lunr'; import { SearchQuery } from '@backstage/search-common'; import { SearchResultSet } from '@backstage/search-common'; @@ -27,14 +27,14 @@ export class IndexBuilder { // @public (undocumented) export class LunrSearchEngine implements SearchEngine { constructor({ logger }: { - logger: Logger; + logger: Logger_2; }); // (undocumented) protected docStore: Record; // (undocumented) index(type: string, documents: IndexableDocument[]): void; // (undocumented) - protected logger: Logger; + protected logger: Logger_2; // (undocumented) protected lunrIndices: Record; // (undocumented) @@ -48,7 +48,7 @@ export class LunrSearchEngine implements SearchEngine { // @public export class Scheduler { constructor({ logger }: { - logger: Logger; + logger: Logger_2; }); addToSchedule(task: Function, interval: number): void; start(): void; diff --git a/plugins/search-backend/api-report.md b/plugins/search-backend/api-report.md index 9e617b73ed..7eba677439 100644 --- a/plugins/search-backend/api-report.md +++ b/plugins/search-backend/api-report.md @@ -5,7 +5,7 @@ ```ts import express from 'express'; -import { Logger } from 'winston'; +import { Logger as Logger_2 } from 'winston'; import { SearchEngine } from '@backstage/plugin-search-backend-node'; // @public (undocumented) diff --git a/plugins/techdocs-backend/api-report.md b/plugins/techdocs-backend/api-report.md index d433d428e0..947439533a 100644 --- a/plugins/techdocs-backend/api-report.md +++ b/plugins/techdocs-backend/api-report.md @@ -8,7 +8,7 @@ import { Config } from '@backstage/config'; import express from 'express'; import { GeneratorBuilder } from '@backstage/techdocs-common'; import { Knex } from 'knex'; -import { Logger } from 'winston'; +import { Logger as Logger_2 } from 'winston'; import { PluginEndpointDiscovery } from '@backstage/backend-common'; import { PreparerBuilder } from '@backstage/techdocs-common'; import { PublisherBase } from '@backstage/techdocs-common'; diff --git a/plugins/todo-backend/api-report.md b/plugins/todo-backend/api-report.md index 8bcfe30aee..d203a52b36 100644 --- a/plugins/todo-backend/api-report.md +++ b/plugins/todo-backend/api-report.md @@ -8,7 +8,7 @@ import { CatalogApi } from '@backstage/catalog-client'; import { Config } from '@backstage/config'; import { EntityName } from '@backstage/catalog-model'; import express from 'express'; -import { Logger } from 'winston'; +import { Logger as Logger_2 } from 'winston'; import { ScmIntegrations } from '@backstage/integration'; import { UrlReader } from '@backstage/backend-common'; From c1a86b800a929c6deda00640535a240d07c7363c Mon Sep 17 00:00:00 2001 From: Rogerio Angeliski Date: Thu, 24 Jun 2021 13:27:44 -0300 Subject: [PATCH 195/204] chore: remove frontend plugin command Signed-off-by: Rogerio Angeliski --- plugins/scaffolder-backend-module-rails/package.json | 1 - 1 file changed, 1 deletion(-) diff --git a/plugins/scaffolder-backend-module-rails/package.json b/plugins/scaffolder-backend-module-rails/package.json index 79b123cdb6..b2765b04f5 100644 --- a/plugins/scaffolder-backend-module-rails/package.json +++ b/plugins/scaffolder-backend-module-rails/package.json @@ -14,7 +14,6 @@ "start": "backstage-cli plugin:serve", "lint": "backstage-cli lint", "test": "backstage-cli test", - "diff": "backstage-cli plugin:diff", "prepack": "backstage-cli prepack", "postpack": "backstage-cli postpack", "clean": "backstage-cli clean" From 93f8e8b423c633b4f7a535c2f5a1899bc1ae544b Mon Sep 17 00:00:00 2001 From: Rogerio Angeliski Date: Tue, 29 Jun 2021 18:51:02 -0300 Subject: [PATCH 196/204] Revert "docs: added generated files" This reverts commit b2cefb34e0d4640cc5bb675d05d0ea906d74eec8. Signed-off-by: Rogerio Angeliski --- packages/backend-common/api-report.md | 10 +++++----- packages/techdocs-common/api-report.md | 20 +++++++++---------- plugins/app-backend/api-report.md | 4 ++-- plugins/auth-backend/api-report.md | 6 +++--- .../api-report.md | 6 +++--- plugins/catalog-graphql/api-report.md | 4 ++-- plugins/code-coverage-backend/api-report.md | 4 ++-- plugins/graphql/api-report.md | 4 ++-- plugins/kafka-backend/api-report.md | 2 +- plugins/kubernetes-backend/api-report.md | 6 +++--- plugins/proxy-backend/api-report.md | 2 +- plugins/rollbar-backend/api-report.md | 6 +++--- plugins/search-backend-node/api-report.md | 8 ++++---- plugins/search-backend/api-report.md | 2 +- plugins/techdocs-backend/api-report.md | 2 +- plugins/todo-backend/api-report.md | 2 +- 16 files changed, 44 insertions(+), 44 deletions(-) diff --git a/packages/backend-common/api-report.md b/packages/backend-common/api-report.md index 22eac06ed2..a21aaef4a6 100644 --- a/packages/backend-common/api-report.md +++ b/packages/backend-common/api-report.md @@ -19,7 +19,7 @@ import * as http from 'http'; import { isChildPath } from '@backstage/cli-common'; import { JsonValue } from '@backstage/config'; import { Knex } from 'knex'; -import { Logger as Logger_2 } from 'winston'; +import { Logger } from 'winston'; import { MergeResult } from 'isomorphic-git'; import { PushResult } from 'isomorphic-git'; import { Readable } from 'stream'; @@ -129,7 +129,7 @@ export function errorHandler(options?: ErrorHandlerOptions): ErrorRequestHandler // @public (undocumented) export type ErrorHandlerOptions = { showStackTraces?: boolean; - logger?: Logger_2; + logger?: Logger; logClientErrors?: boolean; }; @@ -185,7 +185,7 @@ export class Git { static fromAuth: ({ username, password, logger, }: { username?: string | undefined; password?: string | undefined; - logger?: Logger_2 | undefined; + logger?: Logger | undefined; }) => Git; // (undocumented) init({ dir, defaultBranch, }: { @@ -301,7 +301,7 @@ export type ReadTreeResponseFile = { }; // @public -export function requestLoggingHandler(logger?: Logger_2): RequestHandler; +export function requestLoggingHandler(logger?: Logger): RequestHandler; // @public export function resolvePackagePath(name: string, ...paths: string[]): string; @@ -337,7 +337,7 @@ export type ServiceBuilder = { loadConfig(config: ConfigReader): ServiceBuilder; setPort(port: number): ServiceBuilder; setHost(host: string): ServiceBuilder; - setLogger(logger: Logger_2): ServiceBuilder; + setLogger(logger: Logger): ServiceBuilder; enableCors(options: cors.CorsOptions): ServiceBuilder; setHttpsSettings(settings: HttpsSettings): ServiceBuilder; addRouter(root: string, router: Router | RequestHandler): ServiceBuilder; diff --git a/packages/techdocs-common/api-report.md b/packages/techdocs-common/api-report.md index d25f55bf3a..3fff030eee 100644 --- a/packages/techdocs-common/api-report.md +++ b/packages/techdocs-common/api-report.md @@ -12,17 +12,17 @@ import { EntityName } from '@backstage/catalog-model'; import express from 'express'; import { GitHubIntegrationConfig } from '@backstage/integration'; import { GitLabIntegrationConfig } from '@backstage/integration'; -import { Logger as Logger_2 } from 'winston'; +import { Logger } from 'winston'; import { PluginEndpointDiscovery } from '@backstage/backend-common'; import { UrlReader } from '@backstage/backend-common'; import { Writable } from 'stream'; // @public (undocumented) -export const checkoutGitRepository: (repoUrl: string, config: Config, logger: Logger_2) => Promise; +export const checkoutGitRepository: (repoUrl: string, config: Config, logger: Logger) => Promise; // @public (undocumented) export class CommonGitPreparer implements PreparerBase { - constructor(config: Config, logger: Logger_2); + constructor(config: Config, logger: Logger); // (undocumented) prepare(entity: Entity, options?: { etag?: string; @@ -31,7 +31,7 @@ export class CommonGitPreparer implements PreparerBase { // @public (undocumented) export class DirectoryPreparer implements PreparerBase { - constructor(config: Config, logger: Logger_2, reader: UrlReader); + constructor(config: Config, logger: Logger, reader: UrlReader); // (undocumented) prepare(entity: Entity): Promise; } @@ -51,7 +51,7 @@ export type GeneratorBuilder = { export class Generators implements GeneratorBuilder { // (undocumented) static fromConfig(config: Config, { logger, containerRunner, }: { - logger: Logger_2; + logger: Logger; containerRunner: ContainerRunner; }): Promise; // (undocumented) @@ -69,7 +69,7 @@ export const getDefaultBranch: (repositoryUrl: string, config: Config) => Promis // @public (undocumented) export const getDocFilesFromRepository: (reader: UrlReader, entity: Entity, opts?: { etag?: string | undefined; - logger?: Logger_2 | undefined; + logger?: Logger | undefined; } | undefined) => Promise; // @public (undocumented) @@ -88,7 +88,7 @@ export const getGitRepositoryTempFolder: (repositoryUrl: string, config: Config) export function getGitRepoType(url: string): string; // @public (undocumented) -export const getLastCommitTimestamp: (repositoryLocation: string, logger: Logger_2) => Promise; +export const getLastCommitTimestamp: (repositoryLocation: string, logger: Logger) => Promise; // @public (undocumented) export const getLocationForEntity: (entity: Entity) => ParsedLocationAnnotation; @@ -108,7 +108,7 @@ export const parseReferenceAnnotation: (annotationName: string, entity: Entity) // @public (undocumented) export type PreparerBase = { prepare(entity: Entity, options?: { - logger?: Logger_2; + logger?: Logger; etag?: string; }): Promise; }; @@ -153,7 +153,7 @@ export type RemoteProtocol = 'url' | 'dir' | 'github' | 'gitlab' | 'file' | 'azu // @public (undocumented) export class TechdocsGenerator implements GeneratorBase { constructor({ logger, containerRunner, config, }: { - logger: Logger_2; + logger: Logger; containerRunner: ContainerRunner; config: Config; }); @@ -170,7 +170,7 @@ export type TechDocsMetadata = { // @public (undocumented) export class UrlPreparer implements PreparerBase { - constructor(reader: UrlReader, logger: Logger_2); + constructor(reader: UrlReader, logger: Logger); // (undocumented) prepare(entity: Entity, options?: { etag?: string; diff --git a/plugins/app-backend/api-report.md b/plugins/app-backend/api-report.md index 93aba5596f..4f59102265 100644 --- a/plugins/app-backend/api-report.md +++ b/plugins/app-backend/api-report.md @@ -6,7 +6,7 @@ import { Config } from '@backstage/config'; import express from 'express'; -import { Logger as Logger_2 } from 'winston'; +import { Logger } from 'winston'; // @public (undocumented) export function createRouter(options: RouterOptions): Promise; @@ -18,7 +18,7 @@ export interface RouterOptions { config: Config; disableConfigInjection?: boolean; // (undocumented) - logger: Logger_2; + logger: Logger; staticFallbackHandler?: express.Handler; } diff --git a/plugins/auth-backend/api-report.md b/plugins/auth-backend/api-report.md index 9f9a8d18ef..6ae878accf 100644 --- a/plugins/auth-backend/api-report.md +++ b/plugins/auth-backend/api-report.md @@ -9,7 +9,7 @@ import { Config } from '@backstage/config'; import { Entity } from '@backstage/catalog-model'; import express from 'express'; import { JSONWebKey } from 'jose'; -import { Logger as Logger_2 } from 'winston'; +import { Logger } from 'winston'; import { PluginDatabaseManager } from '@backstage/backend-common'; import { PluginEndpointDiscovery } from '@backstage/backend-common'; import { Profile } from 'passport'; @@ -23,7 +23,7 @@ export type AuthProviderFactoryOptions = { providerId: string; globalConfig: AuthProviderConfig; config: Config; - logger: Logger_2; + logger: Logger; tokenIssuer: TokenIssuer; discovery: PluginEndpointDiscovery; catalogApi: CatalogApi; @@ -206,7 +206,7 @@ export interface RouterOptions { // (undocumented) discovery: PluginEndpointDiscovery; // (undocumented) - logger: Logger_2; + logger: Logger; // (undocumented) providerFactories?: ProviderFactories; } diff --git a/plugins/catalog-backend-module-msgraph/api-report.md b/plugins/catalog-backend-module-msgraph/api-report.md index bac733ef53..f1e7e22c35 100644 --- a/plugins/catalog-backend-module-msgraph/api-report.md +++ b/plugins/catalog-backend-module-msgraph/api-report.md @@ -9,7 +9,7 @@ import { CatalogProcessorEmit } from '@backstage/plugin-catalog-backend'; import { Config } from '@backstage/config'; import { GroupEntity } from '@backstage/catalog-model'; import { LocationSpec } from '@backstage/catalog-model'; -import { Logger as Logger_2 } from 'winston'; +import { Logger } from 'winston'; import * as MicrosoftGraph from '@microsoft/microsoft-graph-types'; import * as msal from '@azure/msal-node'; import { UserEntity } from '@backstage/catalog-model'; @@ -70,12 +70,12 @@ export class MicrosoftGraphClient { export class MicrosoftGraphOrgReaderProcessor implements CatalogProcessor { constructor(options: { providers: MicrosoftGraphProviderConfig[]; - logger: Logger_2; + logger: Logger; groupTransformer?: GroupTransformer; }); // (undocumented) static fromConfig(config: Config, options: { - logger: Logger_2; + logger: Logger; groupTransformer?: GroupTransformer; }): MicrosoftGraphOrgReaderProcessor; // (undocumented) diff --git a/plugins/catalog-graphql/api-report.md b/plugins/catalog-graphql/api-report.md index 40e8a19b66..cbe325f4c5 100644 --- a/plugins/catalog-graphql/api-report.md +++ b/plugins/catalog-graphql/api-report.md @@ -6,7 +6,7 @@ import { Config } from '@backstage/config'; import { GraphQLModule } from '@graphql-modules/core'; -import { Logger as Logger_2 } from 'winston'; +import { Logger } from 'winston'; // @public (undocumented) export function createModule(options: ModuleOptions): Promise; @@ -16,7 +16,7 @@ export interface ModuleOptions { // (undocumented) config: Config; // (undocumented) - logger: Logger_2; + logger: Logger; } diff --git a/plugins/code-coverage-backend/api-report.md b/plugins/code-coverage-backend/api-report.md index 186b76fb39..f8f1575d0b 100644 --- a/plugins/code-coverage-backend/api-report.md +++ b/plugins/code-coverage-backend/api-report.md @@ -6,7 +6,7 @@ import { Config } from '@backstage/config'; import express from 'express'; -import { Logger as Logger_2 } from 'winston'; +import { Logger } from 'winston'; import { PluginDatabaseManager } from '@backstage/backend-common'; import { PluginEndpointDiscovery } from '@backstage/backend-common'; import { UrlReader } from '@backstage/backend-common'; @@ -32,7 +32,7 @@ export interface RouterOptions { // (undocumented) discovery: PluginEndpointDiscovery; // (undocumented) - logger: Logger_2; + logger: Logger; // (undocumented) urlReader: UrlReader; } diff --git a/plugins/graphql/api-report.md b/plugins/graphql/api-report.md index ef172afbd7..8109c94122 100644 --- a/plugins/graphql/api-report.md +++ b/plugins/graphql/api-report.md @@ -6,7 +6,7 @@ import { Config } from '@backstage/config'; import express from 'express'; -import { Logger as Logger_2 } from 'winston'; +import { Logger } from 'winston'; // @public (undocumented) export function createRouter(options: RouterOptions): Promise; @@ -16,7 +16,7 @@ export interface RouterOptions { // (undocumented) config: Config; // (undocumented) - logger: Logger_2; + logger: Logger; } diff --git a/plugins/kafka-backend/api-report.md b/plugins/kafka-backend/api-report.md index 6840bd7527..47754ad572 100644 --- a/plugins/kafka-backend/api-report.md +++ b/plugins/kafka-backend/api-report.md @@ -6,7 +6,7 @@ import { Config } from '@backstage/config'; import express from 'express'; -import { Logger as Logger_2 } from 'winston'; +import { Logger } from 'winston'; // @public (undocumented) export function createRouter(options: RouterOptions): Promise; diff --git a/plugins/kubernetes-backend/api-report.md b/plugins/kubernetes-backend/api-report.md index a9389b7e62..fe43e8888a 100644 --- a/plugins/kubernetes-backend/api-report.md +++ b/plugins/kubernetes-backend/api-report.md @@ -9,7 +9,7 @@ import express from 'express'; import { FetchResponse } from '@backstage/plugin-kubernetes-common'; import { KubernetesFetchError } from '@backstage/plugin-kubernetes-common'; import { KubernetesRequestBody } from '@backstage/plugin-kubernetes-common'; -import { Logger as Logger_2 } from 'winston'; +import { Logger } from 'winston'; // @public (undocumented) export interface ClusterDetails { @@ -68,7 +68,7 @@ export interface KubernetesServiceLocator { } // @public (undocumented) -export const makeRouter: (logger: Logger_2, kubernetesFanOutHandler: KubernetesFanOutHandler, clusterDetails: ClusterDetails[]) => express.Router; +export const makeRouter: (logger: Logger, kubernetesFanOutHandler: KubernetesFanOutHandler, clusterDetails: ClusterDetails[]) => express.Router; // @public (undocumented) export interface ObjectFetchParams { @@ -91,7 +91,7 @@ export interface RouterOptions { // (undocumented) config: Config; // (undocumented) - logger: Logger_2; + logger: Logger; } // @public (undocumented) diff --git a/plugins/proxy-backend/api-report.md b/plugins/proxy-backend/api-report.md index 63469a2017..1b1eba3b00 100644 --- a/plugins/proxy-backend/api-report.md +++ b/plugins/proxy-backend/api-report.md @@ -6,7 +6,7 @@ import { Config } from '@backstage/config'; import express from 'express'; -import { Logger as Logger_2 } from 'winston'; +import { Logger } from 'winston'; import { PluginEndpointDiscovery } from '@backstage/backend-common'; // @public (undocumented) diff --git a/plugins/rollbar-backend/api-report.md b/plugins/rollbar-backend/api-report.md index 9fa525cfc3..fa8c67d4f0 100644 --- a/plugins/rollbar-backend/api-report.md +++ b/plugins/rollbar-backend/api-report.md @@ -6,7 +6,7 @@ import { Config } from '@backstage/config'; import express from 'express'; -import { Logger as Logger_2 } from 'winston'; +import { Logger } from 'winston'; // @public (undocumented) export function createRouter(options: RouterOptions): Promise; @@ -20,7 +20,7 @@ export function getRequestHeaders(token: string): { // @public (undocumented) export class RollbarApi { - constructor(accessToken: string, logger: Logger_2); + constructor(accessToken: string, logger: Logger); // (undocumented) getActivatedCounts(projectName: string, options?: { environment: string; @@ -49,7 +49,7 @@ export interface RouterOptions { // (undocumented) config: Config; // (undocumented) - logger: Logger_2; + logger: Logger; // (undocumented) rollbarApi?: RollbarApi; } diff --git a/plugins/search-backend-node/api-report.md b/plugins/search-backend-node/api-report.md index ccb7475573..03585b6b99 100644 --- a/plugins/search-backend-node/api-report.md +++ b/plugins/search-backend-node/api-report.md @@ -7,7 +7,7 @@ import { DocumentCollator } from '@backstage/search-common'; import { DocumentDecorator } from '@backstage/search-common'; import { IndexableDocument } from '@backstage/search-common'; -import { Logger as Logger_2 } from 'winston'; +import { Logger } from 'winston'; import { default as lunr_2 } from 'lunr'; import { SearchQuery } from '@backstage/search-common'; import { SearchResultSet } from '@backstage/search-common'; @@ -27,14 +27,14 @@ export class IndexBuilder { // @public (undocumented) export class LunrSearchEngine implements SearchEngine { constructor({ logger }: { - logger: Logger_2; + logger: Logger; }); // (undocumented) protected docStore: Record; // (undocumented) index(type: string, documents: IndexableDocument[]): void; // (undocumented) - protected logger: Logger_2; + protected logger: Logger; // (undocumented) protected lunrIndices: Record; // (undocumented) @@ -48,7 +48,7 @@ export class LunrSearchEngine implements SearchEngine { // @public export class Scheduler { constructor({ logger }: { - logger: Logger_2; + logger: Logger; }); addToSchedule(task: Function, interval: number): void; start(): void; diff --git a/plugins/search-backend/api-report.md b/plugins/search-backend/api-report.md index 7eba677439..9e617b73ed 100644 --- a/plugins/search-backend/api-report.md +++ b/plugins/search-backend/api-report.md @@ -5,7 +5,7 @@ ```ts import express from 'express'; -import { Logger as Logger_2 } from 'winston'; +import { Logger } from 'winston'; import { SearchEngine } from '@backstage/plugin-search-backend-node'; // @public (undocumented) diff --git a/plugins/techdocs-backend/api-report.md b/plugins/techdocs-backend/api-report.md index 947439533a..d433d428e0 100644 --- a/plugins/techdocs-backend/api-report.md +++ b/plugins/techdocs-backend/api-report.md @@ -8,7 +8,7 @@ import { Config } from '@backstage/config'; import express from 'express'; import { GeneratorBuilder } from '@backstage/techdocs-common'; import { Knex } from 'knex'; -import { Logger as Logger_2 } from 'winston'; +import { Logger } from 'winston'; import { PluginEndpointDiscovery } from '@backstage/backend-common'; import { PreparerBuilder } from '@backstage/techdocs-common'; import { PublisherBase } from '@backstage/techdocs-common'; diff --git a/plugins/todo-backend/api-report.md b/plugins/todo-backend/api-report.md index d203a52b36..8bcfe30aee 100644 --- a/plugins/todo-backend/api-report.md +++ b/plugins/todo-backend/api-report.md @@ -8,7 +8,7 @@ import { CatalogApi } from '@backstage/catalog-client'; import { Config } from '@backstage/config'; import { EntityName } from '@backstage/catalog-model'; import express from 'express'; -import { Logger as Logger_2 } from 'winston'; +import { Logger } from 'winston'; import { ScmIntegrations } from '@backstage/integration'; import { UrlReader } from '@backstage/backend-common'; From 944640535ac8d6fdf5d8d936b132c7aef571525b Mon Sep 17 00:00:00 2001 From: Rogerio Angeliski Date: Thu, 1 Jul 2021 21:47:54 -0300 Subject: [PATCH 197/204] update with PR comments Signed-off-by: Rogerio Angeliski --- .../scaffolder-backend-module-rails/README.md | 26 ++++++++++++++++++- .../Rails.dockerfile | 6 ++--- .../package.json | 1 + .../src/actions/fetch/rails/index.test.ts | 6 ++--- .../fetch/rails/railsArgumentResolver.test.ts | 10 +++++-- .../fetch/rails/railsArgumentResolver.ts | 8 +++++- .../sample-templates/local-templates.yaml | 1 - .../scaffolder/actions/builtin/fetch/index.ts | 2 +- 8 files changed, 47 insertions(+), 13 deletions(-) diff --git a/plugins/scaffolder-backend-module-rails/README.md b/plugins/scaffolder-backend-module-rails/README.md index 3c0c9da53e..3da594dd75 100644 --- a/plugins/scaffolder-backend-module-rails/README.md +++ b/plugins/scaffolder-backend-module-rails/README.md @@ -11,7 +11,10 @@ Here you can find all Rails related features to improve your scaffolder: You need to configure the action in your backend: +## From your Backstage root directory + ``` +cd packages/backend yarn add @backstage/plugin-scaffolder-backend-module-rails ``` @@ -222,4 +225,25 @@ spec: entityRef: '{{ steps.register.output.entityRef }}' ``` -We have a [Docker image](https://github.com/backstage/backstage/blob/master/plugins/scaffolder-backend-module-rails/Rails.dockerfile) you can use to build your own. +### What you need to run that action + +The environment need to have a [rails](https://github.com/rails/rails#getting-started) installation, or you can build and provide a docker image in your template. + +We have a [Dockerfile](https://github.com/backstage/backstage/blob/master/plugins/scaffolder-backend-module-rails/Rails.dockerfile) that you can use to build your image. + +If you choose to provide a docker image, you need to update your template with `imageName` parameter: + +```yaml +steps: + - id: fetch-base + name: Fetch Base + action: fetch:rails + input: + url: ./template + imageName: repository/rails:tag + values: + name: '{{ parameters.name }}' + owner: '{{ parameters.owner }}' + system: '{{ parameters.system }}' + railsArguments: '{{ json parameters.railsArguments }}' +``` diff --git a/plugins/scaffolder-backend-module-rails/Rails.dockerfile b/plugins/scaffolder-backend-module-rails/Rails.dockerfile index 3cec0e7668..0774fdc975 100644 --- a/plugins/scaffolder-backend-module-rails/Rails.dockerfile +++ b/plugins/scaffolder-backend-module-rails/Rails.dockerfile @@ -1,9 +1,7 @@ FROM ruby:3.0 RUN apt-get update -qq && \ - apt-get install -y \ - nodejs \ - postgresql-client \ - git + apt-get install -y nodejs postgresql-client git && \ + rm -rf /var/lib/apt/lists/ RUN gem install rails diff --git a/plugins/scaffolder-backend-module-rails/package.json b/plugins/scaffolder-backend-module-rails/package.json index b2765b04f5..b513100f16 100644 --- a/plugins/scaffolder-backend-module-rails/package.json +++ b/plugins/scaffolder-backend-module-rails/package.json @@ -4,6 +4,7 @@ "main": "src/index.ts", "types": "src/index.ts", "license": "Apache-2.0", + "private": false, "publishConfig": { "access": "public", "main": "dist/index.esm.js", diff --git a/plugins/scaffolder-backend-module-rails/src/actions/fetch/rails/index.test.ts b/plugins/scaffolder-backend-module-rails/src/actions/fetch/rails/index.test.ts index cedc768f88..6b98dd86c6 100644 --- a/plugins/scaffolder-backend-module-rails/src/actions/fetch/rails/index.test.ts +++ b/plugins/scaffolder-backend-module-rails/src/actions/fetch/rails/index.test.ts @@ -34,7 +34,7 @@ import { } from '@backstage/backend-common'; import { ConfigReader } from '@backstage/config'; import { ScmIntegrations } from '@backstage/integration'; -import mock from 'mock-fs'; +import mockFs from 'mock-fs'; import os from 'os'; import { resolve as resolvePath } from 'path'; import { PassThrough } from 'stream'; @@ -86,12 +86,12 @@ describe('fetch:rails', () => { }); beforeEach(() => { - mock({ [`${mockContext.workspacePath}/result`]: {} }); + mockFs({ [`${mockContext.workspacePath}/result`]: {} }); jest.restoreAllMocks(); }); afterEach(() => { - mock.restore(); + mockFs.restore(); }); it('should call fetchContents with the correct values', async () => { diff --git a/plugins/scaffolder-backend-module-rails/src/actions/fetch/rails/railsArgumentResolver.test.ts b/plugins/scaffolder-backend-module-rails/src/actions/fetch/rails/railsArgumentResolver.test.ts index a8c10625c2..99a113f4f7 100644 --- a/plugins/scaffolder-backend-module-rails/src/actions/fetch/rails/railsArgumentResolver.test.ts +++ b/plugins/scaffolder-backend-module-rails/src/actions/fetch/rails/railsArgumentResolver.test.ts @@ -15,9 +15,12 @@ */ import { railsArgumentResolver } from './railsArgumentResolver'; +import { sep as separatorPath } from 'path'; +import os from 'os'; describe('railsArgumentResolver', () => { describe('when provide the parameter', () => { + const root = os.platform() === 'win32' ? 'C:\\' : '/'; test.each([ [{}, []], [{ minimal: true }, ['--minimal']], @@ -27,7 +30,10 @@ describe('railsArgumentResolver', () => { [{ webpacker: 'vue' }, ['--webpack', 'vue']], [{ database: 'postgresql' }, ['--database', 'postgresql']], [{ railsVersion: 'dev' }, ['--dev']], - [{ template: './rails.rb' }, ['--template', '/tmp/rails.rb']], + [ + { template: `.${separatorPath}rails.rb` }, + ['--template', `${root}${separatorPath}rails.rb`], + ], ])( 'should include the argument to execution %p -> %p', (passedArguments: object, expected: Array) => { @@ -40,7 +46,7 @@ describe('railsArgumentResolver', () => { const { railsArguments } = values; - const argumentsToRun = railsArgumentResolver('/tmp', railsArguments); + const argumentsToRun = railsArgumentResolver(root, railsArguments); expect(argumentsToRun).toEqual(expected); }, diff --git a/plugins/scaffolder-backend-module-rails/src/actions/fetch/rails/railsArgumentResolver.ts b/plugins/scaffolder-backend-module-rails/src/actions/fetch/rails/railsArgumentResolver.ts index 5ea2f70895..b1ddadc6d9 100644 --- a/plugins/scaffolder-backend-module-rails/src/actions/fetch/rails/railsArgumentResolver.ts +++ b/plugins/scaffolder-backend-module-rails/src/actions/fetch/rails/railsArgumentResolver.ts @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +import { sep as separatorPath } from 'path'; enum Webpacker { react = 'react', @@ -99,7 +100,12 @@ export const railsArgumentResolver = ( if (options?.template) { argumentsToRun.push('--template'); - argumentsToRun.push(options.template.replace('./', `${projectRoot}/`)); + argumentsToRun.push( + options.template.replace( + `.${separatorPath}`, + `${projectRoot}${separatorPath}`, + ), + ); } return argumentsToRun; diff --git a/plugins/scaffolder-backend/sample-templates/local-templates.yaml b/plugins/scaffolder-backend/sample-templates/local-templates.yaml index 59a55b3cd9..3b3acbae7e 100644 --- a/plugins/scaffolder-backend/sample-templates/local-templates.yaml +++ b/plugins/scaffolder-backend/sample-templates/local-templates.yaml @@ -10,5 +10,4 @@ spec: - ./create-react-app/template.yaml - ./springboot-grpc-template/template.yaml - ./v1beta2-demo/template.yaml - - ./rails-demo/template.yaml - ./pull-request/template.yaml diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/index.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/index.ts index 82bc387f26..fa6d23c032 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/index.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/index.ts @@ -16,4 +16,4 @@ export { createFetchPlainAction } from './plain'; export { createFetchCookiecutterAction } from './cookiecutter'; -export * from './helpers'; +export { fetchContents } from './helpers'; From 7a74046f1673c626066516f60cd60d900820161c Mon Sep 17 00:00:00 2001 From: Rogerio Angeliski Date: Mon, 5 Jul 2021 21:21:00 -0300 Subject: [PATCH 198/204] docs: added generated files Signed-off-by: Rogerio Angeliski --- packages/backend-common/api-report.md | 10 +++++----- packages/techdocs-common/api-report.md | 20 +++++++++---------- plugins/app-backend/api-report.md | 4 ++-- plugins/auth-backend/api-report.md | 6 +++--- .../catalog-backend-module-ldap/api-report.md | 10 +++++----- .../api-report.md | 8 ++++---- plugins/catalog-graphql/api-report.md | 4 ++-- plugins/code-coverage-backend/api-report.md | 4 ++-- plugins/graphql/api-report.md | 4 ++-- plugins/kafka-backend/api-report.md | 2 +- plugins/kubernetes-backend/api-report.md | 6 +++--- plugins/proxy-backend/api-report.md | 2 +- plugins/rollbar-backend/api-report.md | 6 +++--- plugins/search-backend-node/api-report.md | 8 ++++---- plugins/search-backend/api-report.md | 2 +- plugins/techdocs-backend/api-report.md | 2 +- plugins/todo-backend/api-report.md | 2 +- 17 files changed, 50 insertions(+), 50 deletions(-) diff --git a/packages/backend-common/api-report.md b/packages/backend-common/api-report.md index a21aaef4a6..22eac06ed2 100644 --- a/packages/backend-common/api-report.md +++ b/packages/backend-common/api-report.md @@ -19,7 +19,7 @@ import * as http from 'http'; import { isChildPath } from '@backstage/cli-common'; import { JsonValue } from '@backstage/config'; import { Knex } from 'knex'; -import { Logger } from 'winston'; +import { Logger as Logger_2 } from 'winston'; import { MergeResult } from 'isomorphic-git'; import { PushResult } from 'isomorphic-git'; import { Readable } from 'stream'; @@ -129,7 +129,7 @@ export function errorHandler(options?: ErrorHandlerOptions): ErrorRequestHandler // @public (undocumented) export type ErrorHandlerOptions = { showStackTraces?: boolean; - logger?: Logger; + logger?: Logger_2; logClientErrors?: boolean; }; @@ -185,7 +185,7 @@ export class Git { static fromAuth: ({ username, password, logger, }: { username?: string | undefined; password?: string | undefined; - logger?: Logger | undefined; + logger?: Logger_2 | undefined; }) => Git; // (undocumented) init({ dir, defaultBranch, }: { @@ -301,7 +301,7 @@ export type ReadTreeResponseFile = { }; // @public -export function requestLoggingHandler(logger?: Logger): RequestHandler; +export function requestLoggingHandler(logger?: Logger_2): RequestHandler; // @public export function resolvePackagePath(name: string, ...paths: string[]): string; @@ -337,7 +337,7 @@ export type ServiceBuilder = { loadConfig(config: ConfigReader): ServiceBuilder; setPort(port: number): ServiceBuilder; setHost(host: string): ServiceBuilder; - setLogger(logger: Logger): ServiceBuilder; + setLogger(logger: Logger_2): ServiceBuilder; enableCors(options: cors.CorsOptions): ServiceBuilder; setHttpsSettings(settings: HttpsSettings): ServiceBuilder; addRouter(root: string, router: Router | RequestHandler): ServiceBuilder; diff --git a/packages/techdocs-common/api-report.md b/packages/techdocs-common/api-report.md index 3fff030eee..d25f55bf3a 100644 --- a/packages/techdocs-common/api-report.md +++ b/packages/techdocs-common/api-report.md @@ -12,17 +12,17 @@ import { EntityName } from '@backstage/catalog-model'; import express from 'express'; import { GitHubIntegrationConfig } from '@backstage/integration'; import { GitLabIntegrationConfig } from '@backstage/integration'; -import { Logger } from 'winston'; +import { Logger as Logger_2 } from 'winston'; import { PluginEndpointDiscovery } from '@backstage/backend-common'; import { UrlReader } from '@backstage/backend-common'; import { Writable } from 'stream'; // @public (undocumented) -export const checkoutGitRepository: (repoUrl: string, config: Config, logger: Logger) => Promise; +export const checkoutGitRepository: (repoUrl: string, config: Config, logger: Logger_2) => Promise; // @public (undocumented) export class CommonGitPreparer implements PreparerBase { - constructor(config: Config, logger: Logger); + constructor(config: Config, logger: Logger_2); // (undocumented) prepare(entity: Entity, options?: { etag?: string; @@ -31,7 +31,7 @@ export class CommonGitPreparer implements PreparerBase { // @public (undocumented) export class DirectoryPreparer implements PreparerBase { - constructor(config: Config, logger: Logger, reader: UrlReader); + constructor(config: Config, logger: Logger_2, reader: UrlReader); // (undocumented) prepare(entity: Entity): Promise; } @@ -51,7 +51,7 @@ export type GeneratorBuilder = { export class Generators implements GeneratorBuilder { // (undocumented) static fromConfig(config: Config, { logger, containerRunner, }: { - logger: Logger; + logger: Logger_2; containerRunner: ContainerRunner; }): Promise; // (undocumented) @@ -69,7 +69,7 @@ export const getDefaultBranch: (repositoryUrl: string, config: Config) => Promis // @public (undocumented) export const getDocFilesFromRepository: (reader: UrlReader, entity: Entity, opts?: { etag?: string | undefined; - logger?: Logger | undefined; + logger?: Logger_2 | undefined; } | undefined) => Promise; // @public (undocumented) @@ -88,7 +88,7 @@ export const getGitRepositoryTempFolder: (repositoryUrl: string, config: Config) export function getGitRepoType(url: string): string; // @public (undocumented) -export const getLastCommitTimestamp: (repositoryLocation: string, logger: Logger) => Promise; +export const getLastCommitTimestamp: (repositoryLocation: string, logger: Logger_2) => Promise; // @public (undocumented) export const getLocationForEntity: (entity: Entity) => ParsedLocationAnnotation; @@ -108,7 +108,7 @@ export const parseReferenceAnnotation: (annotationName: string, entity: Entity) // @public (undocumented) export type PreparerBase = { prepare(entity: Entity, options?: { - logger?: Logger; + logger?: Logger_2; etag?: string; }): Promise; }; @@ -153,7 +153,7 @@ export type RemoteProtocol = 'url' | 'dir' | 'github' | 'gitlab' | 'file' | 'azu // @public (undocumented) export class TechdocsGenerator implements GeneratorBase { constructor({ logger, containerRunner, config, }: { - logger: Logger; + logger: Logger_2; containerRunner: ContainerRunner; config: Config; }); @@ -170,7 +170,7 @@ export type TechDocsMetadata = { // @public (undocumented) export class UrlPreparer implements PreparerBase { - constructor(reader: UrlReader, logger: Logger); + constructor(reader: UrlReader, logger: Logger_2); // (undocumented) prepare(entity: Entity, options?: { etag?: string; diff --git a/plugins/app-backend/api-report.md b/plugins/app-backend/api-report.md index 4f59102265..93aba5596f 100644 --- a/plugins/app-backend/api-report.md +++ b/plugins/app-backend/api-report.md @@ -6,7 +6,7 @@ import { Config } from '@backstage/config'; import express from 'express'; -import { Logger } from 'winston'; +import { Logger as Logger_2 } from 'winston'; // @public (undocumented) export function createRouter(options: RouterOptions): Promise; @@ -18,7 +18,7 @@ export interface RouterOptions { config: Config; disableConfigInjection?: boolean; // (undocumented) - logger: Logger; + logger: Logger_2; staticFallbackHandler?: express.Handler; } diff --git a/plugins/auth-backend/api-report.md b/plugins/auth-backend/api-report.md index 6ae878accf..9f9a8d18ef 100644 --- a/plugins/auth-backend/api-report.md +++ b/plugins/auth-backend/api-report.md @@ -9,7 +9,7 @@ import { Config } from '@backstage/config'; import { Entity } from '@backstage/catalog-model'; import express from 'express'; import { JSONWebKey } from 'jose'; -import { Logger } from 'winston'; +import { Logger as Logger_2 } from 'winston'; import { PluginDatabaseManager } from '@backstage/backend-common'; import { PluginEndpointDiscovery } from '@backstage/backend-common'; import { Profile } from 'passport'; @@ -23,7 +23,7 @@ export type AuthProviderFactoryOptions = { providerId: string; globalConfig: AuthProviderConfig; config: Config; - logger: Logger; + logger: Logger_2; tokenIssuer: TokenIssuer; discovery: PluginEndpointDiscovery; catalogApi: CatalogApi; @@ -206,7 +206,7 @@ export interface RouterOptions { // (undocumented) discovery: PluginEndpointDiscovery; // (undocumented) - logger: Logger; + logger: Logger_2; // (undocumented) providerFactories?: ProviderFactories; } diff --git a/plugins/catalog-backend-module-ldap/api-report.md b/plugins/catalog-backend-module-ldap/api-report.md index 55405cab41..446dc2df52 100644 --- a/plugins/catalog-backend-module-ldap/api-report.md +++ b/plugins/catalog-backend-module-ldap/api-report.md @@ -11,7 +11,7 @@ import { Config } from '@backstage/config'; import { GroupEntity } from '@backstage/catalog-model'; import { JsonValue } from '@backstage/config'; import { LocationSpec } from '@backstage/catalog-model'; -import { Logger } from 'winston'; +import { Logger as Logger_2 } from 'winston'; import { SearchEntry } from 'ldapjs'; import { SearchOptions } from 'ldapjs'; import { UserEntity } from '@backstage/catalog-model'; @@ -38,7 +38,7 @@ export const LDAP_UUID_ANNOTATION = "backstage.io/ldap-uuid"; export class LdapClient { constructor(client: Client); // (undocumented) - static create(logger: Logger, target: string, bind?: BindConfig): Promise; + static create(logger: Logger_2, target: string, bind?: BindConfig): Promise; getRootDSE(): Promise; getVendor(): Promise; search(dn: string, options: SearchOptions): Promise; @@ -48,13 +48,13 @@ export class LdapClient { export class LdapOrgReaderProcessor implements CatalogProcessor { constructor(options: { providers: LdapProviderConfig[]; - logger: Logger; + logger: Logger_2; groupTransformer?: GroupTransformer; userTransformer?: UserTransformer; }); // (undocumented) static fromConfig(config: Config, options: { - logger: Logger; + logger: Logger_2; groupTransformer?: GroupTransformer; userTransformer?: UserTransformer; }): LdapOrgReaderProcessor; @@ -80,7 +80,7 @@ export function readLdapConfig(config: Config): LdapProviderConfig[]; export function readLdapOrg(client: LdapClient, userConfig: UserConfig, groupConfig: GroupConfig, options: { groupTransformer?: GroupTransformer; userTransformer?: UserTransformer; - logger: Logger; + logger: Logger_2; }): Promise<{ users: UserEntity[]; groups: GroupEntity[]; diff --git a/plugins/catalog-backend-module-msgraph/api-report.md b/plugins/catalog-backend-module-msgraph/api-report.md index f1e7e22c35..c755514b48 100644 --- a/plugins/catalog-backend-module-msgraph/api-report.md +++ b/plugins/catalog-backend-module-msgraph/api-report.md @@ -9,7 +9,7 @@ import { CatalogProcessorEmit } from '@backstage/plugin-catalog-backend'; import { Config } from '@backstage/config'; import { GroupEntity } from '@backstage/catalog-model'; import { LocationSpec } from '@backstage/catalog-model'; -import { Logger } from 'winston'; +import { Logger as Logger_2 } from 'winston'; import * as MicrosoftGraph from '@microsoft/microsoft-graph-types'; import * as msal from '@azure/msal-node'; import { UserEntity } from '@backstage/catalog-model'; @@ -70,12 +70,12 @@ export class MicrosoftGraphClient { export class MicrosoftGraphOrgReaderProcessor implements CatalogProcessor { constructor(options: { providers: MicrosoftGraphProviderConfig[]; - logger: Logger; + logger: Logger_2; groupTransformer?: GroupTransformer; }); // (undocumented) static fromConfig(config: Config, options: { - logger: Logger; + logger: Logger_2; groupTransformer?: GroupTransformer; }): MicrosoftGraphOrgReaderProcessor; // (undocumented) @@ -107,7 +107,7 @@ export function readMicrosoftGraphOrg(client: MicrosoftGraphClient, tenantId: st userFilter?: string; groupFilter?: string; groupTransformer?: GroupTransformer; - logger: Logger; + logger: Logger_2; }): Promise<{ users: UserEntity[]; groups: GroupEntity[]; diff --git a/plugins/catalog-graphql/api-report.md b/plugins/catalog-graphql/api-report.md index cbe325f4c5..40e8a19b66 100644 --- a/plugins/catalog-graphql/api-report.md +++ b/plugins/catalog-graphql/api-report.md @@ -6,7 +6,7 @@ import { Config } from '@backstage/config'; import { GraphQLModule } from '@graphql-modules/core'; -import { Logger } from 'winston'; +import { Logger as Logger_2 } from 'winston'; // @public (undocumented) export function createModule(options: ModuleOptions): Promise; @@ -16,7 +16,7 @@ export interface ModuleOptions { // (undocumented) config: Config; // (undocumented) - logger: Logger; + logger: Logger_2; } diff --git a/plugins/code-coverage-backend/api-report.md b/plugins/code-coverage-backend/api-report.md index f8f1575d0b..186b76fb39 100644 --- a/plugins/code-coverage-backend/api-report.md +++ b/plugins/code-coverage-backend/api-report.md @@ -6,7 +6,7 @@ import { Config } from '@backstage/config'; import express from 'express'; -import { Logger } from 'winston'; +import { Logger as Logger_2 } from 'winston'; import { PluginDatabaseManager } from '@backstage/backend-common'; import { PluginEndpointDiscovery } from '@backstage/backend-common'; import { UrlReader } from '@backstage/backend-common'; @@ -32,7 +32,7 @@ export interface RouterOptions { // (undocumented) discovery: PluginEndpointDiscovery; // (undocumented) - logger: Logger; + logger: Logger_2; // (undocumented) urlReader: UrlReader; } diff --git a/plugins/graphql/api-report.md b/plugins/graphql/api-report.md index 8109c94122..ef172afbd7 100644 --- a/plugins/graphql/api-report.md +++ b/plugins/graphql/api-report.md @@ -6,7 +6,7 @@ import { Config } from '@backstage/config'; import express from 'express'; -import { Logger } from 'winston'; +import { Logger as Logger_2 } from 'winston'; // @public (undocumented) export function createRouter(options: RouterOptions): Promise; @@ -16,7 +16,7 @@ export interface RouterOptions { // (undocumented) config: Config; // (undocumented) - logger: Logger; + logger: Logger_2; } diff --git a/plugins/kafka-backend/api-report.md b/plugins/kafka-backend/api-report.md index 47754ad572..6840bd7527 100644 --- a/plugins/kafka-backend/api-report.md +++ b/plugins/kafka-backend/api-report.md @@ -6,7 +6,7 @@ import { Config } from '@backstage/config'; import express from 'express'; -import { Logger } from 'winston'; +import { Logger as Logger_2 } from 'winston'; // @public (undocumented) export function createRouter(options: RouterOptions): Promise; diff --git a/plugins/kubernetes-backend/api-report.md b/plugins/kubernetes-backend/api-report.md index fe43e8888a..a9389b7e62 100644 --- a/plugins/kubernetes-backend/api-report.md +++ b/plugins/kubernetes-backend/api-report.md @@ -9,7 +9,7 @@ import express from 'express'; import { FetchResponse } from '@backstage/plugin-kubernetes-common'; import { KubernetesFetchError } from '@backstage/plugin-kubernetes-common'; import { KubernetesRequestBody } from '@backstage/plugin-kubernetes-common'; -import { Logger } from 'winston'; +import { Logger as Logger_2 } from 'winston'; // @public (undocumented) export interface ClusterDetails { @@ -68,7 +68,7 @@ export interface KubernetesServiceLocator { } // @public (undocumented) -export const makeRouter: (logger: Logger, kubernetesFanOutHandler: KubernetesFanOutHandler, clusterDetails: ClusterDetails[]) => express.Router; +export const makeRouter: (logger: Logger_2, kubernetesFanOutHandler: KubernetesFanOutHandler, clusterDetails: ClusterDetails[]) => express.Router; // @public (undocumented) export interface ObjectFetchParams { @@ -91,7 +91,7 @@ export interface RouterOptions { // (undocumented) config: Config; // (undocumented) - logger: Logger; + logger: Logger_2; } // @public (undocumented) diff --git a/plugins/proxy-backend/api-report.md b/plugins/proxy-backend/api-report.md index 1b1eba3b00..63469a2017 100644 --- a/plugins/proxy-backend/api-report.md +++ b/plugins/proxy-backend/api-report.md @@ -6,7 +6,7 @@ import { Config } from '@backstage/config'; import express from 'express'; -import { Logger } from 'winston'; +import { Logger as Logger_2 } from 'winston'; import { PluginEndpointDiscovery } from '@backstage/backend-common'; // @public (undocumented) diff --git a/plugins/rollbar-backend/api-report.md b/plugins/rollbar-backend/api-report.md index fa8c67d4f0..9fa525cfc3 100644 --- a/plugins/rollbar-backend/api-report.md +++ b/plugins/rollbar-backend/api-report.md @@ -6,7 +6,7 @@ import { Config } from '@backstage/config'; import express from 'express'; -import { Logger } from 'winston'; +import { Logger as Logger_2 } from 'winston'; // @public (undocumented) export function createRouter(options: RouterOptions): Promise; @@ -20,7 +20,7 @@ export function getRequestHeaders(token: string): { // @public (undocumented) export class RollbarApi { - constructor(accessToken: string, logger: Logger); + constructor(accessToken: string, logger: Logger_2); // (undocumented) getActivatedCounts(projectName: string, options?: { environment: string; @@ -49,7 +49,7 @@ export interface RouterOptions { // (undocumented) config: Config; // (undocumented) - logger: Logger; + logger: Logger_2; // (undocumented) rollbarApi?: RollbarApi; } diff --git a/plugins/search-backend-node/api-report.md b/plugins/search-backend-node/api-report.md index 03585b6b99..ccb7475573 100644 --- a/plugins/search-backend-node/api-report.md +++ b/plugins/search-backend-node/api-report.md @@ -7,7 +7,7 @@ import { DocumentCollator } from '@backstage/search-common'; import { DocumentDecorator } from '@backstage/search-common'; import { IndexableDocument } from '@backstage/search-common'; -import { Logger } from 'winston'; +import { Logger as Logger_2 } from 'winston'; import { default as lunr_2 } from 'lunr'; import { SearchQuery } from '@backstage/search-common'; import { SearchResultSet } from '@backstage/search-common'; @@ -27,14 +27,14 @@ export class IndexBuilder { // @public (undocumented) export class LunrSearchEngine implements SearchEngine { constructor({ logger }: { - logger: Logger; + logger: Logger_2; }); // (undocumented) protected docStore: Record; // (undocumented) index(type: string, documents: IndexableDocument[]): void; // (undocumented) - protected logger: Logger; + protected logger: Logger_2; // (undocumented) protected lunrIndices: Record; // (undocumented) @@ -48,7 +48,7 @@ export class LunrSearchEngine implements SearchEngine { // @public export class Scheduler { constructor({ logger }: { - logger: Logger; + logger: Logger_2; }); addToSchedule(task: Function, interval: number): void; start(): void; diff --git a/plugins/search-backend/api-report.md b/plugins/search-backend/api-report.md index 9e617b73ed..7eba677439 100644 --- a/plugins/search-backend/api-report.md +++ b/plugins/search-backend/api-report.md @@ -5,7 +5,7 @@ ```ts import express from 'express'; -import { Logger } from 'winston'; +import { Logger as Logger_2 } from 'winston'; import { SearchEngine } from '@backstage/plugin-search-backend-node'; // @public (undocumented) diff --git a/plugins/techdocs-backend/api-report.md b/plugins/techdocs-backend/api-report.md index d433d428e0..947439533a 100644 --- a/plugins/techdocs-backend/api-report.md +++ b/plugins/techdocs-backend/api-report.md @@ -8,7 +8,7 @@ import { Config } from '@backstage/config'; import express from 'express'; import { GeneratorBuilder } from '@backstage/techdocs-common'; import { Knex } from 'knex'; -import { Logger } from 'winston'; +import { Logger as Logger_2 } from 'winston'; import { PluginEndpointDiscovery } from '@backstage/backend-common'; import { PreparerBuilder } from '@backstage/techdocs-common'; import { PublisherBase } from '@backstage/techdocs-common'; diff --git a/plugins/todo-backend/api-report.md b/plugins/todo-backend/api-report.md index 8bcfe30aee..d203a52b36 100644 --- a/plugins/todo-backend/api-report.md +++ b/plugins/todo-backend/api-report.md @@ -8,7 +8,7 @@ import { CatalogApi } from '@backstage/catalog-client'; import { Config } from '@backstage/config'; import { EntityName } from '@backstage/catalog-model'; import express from 'express'; -import { Logger } from 'winston'; +import { Logger as Logger_2 } from 'winston'; import { ScmIntegrations } from '@backstage/integration'; import { UrlReader } from '@backstage/backend-common'; From 02b962394b19a73c829640c86f1e6cd54841b1e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?= Date: Wed, 7 Jul 2021 13:27:39 +0200 Subject: [PATCH 199/204] Added a `context` parameter to validator functions, letting them have access to the API holder MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fredrik Adelöw --- .changeset/great-bears-work.md | 10 ++++++ plugins/scaffolder/api-report.md | 13 ++++++++ .../components/TemplatePage/TemplatePage.tsx | 33 ++++++++++++++----- .../fields/RepoUrlPicker/validation.test.ts | 3 +- .../fields/RepoUrlPicker/validation.ts | 1 + plugins/scaffolder/src/extensions/index.tsx | 4 +-- plugins/scaffolder/src/extensions/types.ts | 11 ++++++- plugins/scaffolder/src/index.ts | 6 ++-- 8 files changed, 66 insertions(+), 15 deletions(-) create mode 100644 .changeset/great-bears-work.md diff --git a/.changeset/great-bears-work.md b/.changeset/great-bears-work.md new file mode 100644 index 0000000000..572cf1538d --- /dev/null +++ b/.changeset/great-bears-work.md @@ -0,0 +1,10 @@ +--- +'@backstage/plugin-scaffolder': patch +--- + +Added a `context` parameter to validator functions, letting them have access to +the API holder. + +If you have implemented custom validators and use `createScaffolderFieldExtension`, +your `validation` function can now optionally accept a third parameter, +`context: { apiHolder: ApiHolder }`. diff --git a/plugins/scaffolder/api-report.md b/plugins/scaffolder/api-report.md index 5da1869fc2..7982ad997e 100644 --- a/plugins/scaffolder/api-report.md +++ b/plugins/scaffolder/api-report.md @@ -4,6 +4,7 @@ ```ts +import { ApiHolder } from '@backstage/core-plugin-api'; import { ApiRef } from '@backstage/core-plugin-api'; import { BackstagePlugin } from '@backstage/core-plugin-api'; import { DiscoveryApi } from '@backstage/core-plugin-api'; @@ -24,9 +25,21 @@ import { ScmIntegrationRegistry } from '@backstage/integration'; // @public (undocumented) export function createScaffolderFieldExtension(options: FieldExtensionOptions): Extension<() => null>; +// @public (undocumented) +export type CustomFieldValidator = ((data: T, field: FieldValidation) => void) | ((data: T, field: FieldValidation, context: { + apiHolder: ApiHolder; +}) => void); + // @public (undocumented) export const EntityPickerFieldExtension: () => null; +// @public (undocumented) +export type FieldExtensionOptions = { + name: string; + component: (props: FieldProps) => JSX.Element | null; + validation?: CustomFieldValidator; +}; + // @public (undocumented) export const OwnerPickerFieldExtension: () => null; diff --git a/plugins/scaffolder/src/components/TemplatePage/TemplatePage.tsx b/plugins/scaffolder/src/components/TemplatePage/TemplatePage.tsx index b6cab5b620..e72255f129 100644 --- a/plugins/scaffolder/src/components/TemplatePage/TemplatePage.tsx +++ b/plugins/scaffolder/src/components/TemplatePage/TemplatePage.tsx @@ -15,13 +15,13 @@ */ import { JsonObject, JsonValue } from '@backstage/config'; import { LinearProgress } from '@material-ui/core'; -import { FieldValidation, FormValidation, IChangeEvent } from '@rjsf/core'; +import { FormValidation, IChangeEvent } from '@rjsf/core'; import React, { useCallback, useState } from 'react'; import { generatePath, Navigate, useNavigate } from 'react-router'; import { useParams } from 'react-router-dom'; import { useAsync } from 'react-use'; import { scaffolderApiRef } from '../../api'; -import { FieldExtensionOptions } from '../../extensions'; +import { CustomFieldValidator, FieldExtensionOptions } from '../../extensions'; import { rootRouteRef } from '../../routes'; import { MultistepJsonForm } from '../MultistepJsonForm'; @@ -32,7 +32,13 @@ import { Lifecycle, Page, } from '@backstage/core-components'; -import { errorApiRef, useApi, useRouteRef } from '@backstage/core-plugin-api'; +import { + ApiHolder, + errorApiRef, + useApi, + useApiHolder, + useRouteRef, +} from '@backstage/core-plugin-api'; const useTemplateParameterSchema = (templateName: string) => { const scaffolderApi = useApi(scaffolderApiRef); @@ -54,10 +60,10 @@ function isObject(obj: unknown): obj is JsonObject { export const createValidator = ( rootSchema: JsonObject, - validators: Record< - string, - undefined | ((value: JsonValue, validation: FieldValidation) => void) - >, + validators: Record>, + context: { + apiHolder: ApiHolder; + }, ) => { function validate( schema: JsonObject, @@ -86,7 +92,11 @@ export const createValidator = ( const fieldName = isObject(propSchema) && (propSchema['ui:field'] as string); if (fieldName && typeof validators[fieldName] === 'function') { - validators[fieldName]!(propData as JsonValue, propValidation); + validators[fieldName]!( + propData as JsonValue, + propValidation, + context, + ); } } } @@ -103,6 +113,7 @@ export const TemplatePage = ({ }: { customFieldExtensions?: FieldExtensionOptions[]; }) => { + const apiHolder = useApiHolder(); const errorApi = useApi(errorApiRef); const scaffolderApi = useApi(scaffolderApiRef); const { templateName } = useParams(); @@ -171,7 +182,11 @@ export const TemplatePage = ({ steps={schema.steps.map(step => { return { ...step, - validate: createValidator(step.schema, customFieldValidators), + validate: createValidator( + step.schema, + customFieldValidators, + { apiHolder }, + ), }; })} /> diff --git a/plugins/scaffolder/src/components/fields/RepoUrlPicker/validation.test.ts b/plugins/scaffolder/src/components/fields/RepoUrlPicker/validation.test.ts index f0df198507..1ea66e7df9 100644 --- a/plugins/scaffolder/src/components/fields/RepoUrlPicker/validation.test.ts +++ b/plugins/scaffolder/src/components/fields/RepoUrlPicker/validation.test.ts @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + import { repoPickerValidation } from './validation'; import { FieldValidation } from '@rjsf/core'; @@ -22,7 +23,7 @@ describe('RepoPicker Validation', () => { addError: jest.fn(), } as unknown) as FieldValidation); - it('validaties when no repo', () => { + it('validates when no repo', () => { const mockFieldValidation = fieldValidator(); repoPickerValidation('github.com?owner=a', mockFieldValidation); diff --git a/plugins/scaffolder/src/components/fields/RepoUrlPicker/validation.ts b/plugins/scaffolder/src/components/fields/RepoUrlPicker/validation.ts index 827afa3cab..760b9f7890 100644 --- a/plugins/scaffolder/src/components/fields/RepoUrlPicker/validation.ts +++ b/plugins/scaffolder/src/components/fields/RepoUrlPicker/validation.ts @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + import { FieldValidation } from '@rjsf/core'; export const repoPickerValidation = ( diff --git a/plugins/scaffolder/src/extensions/index.tsx b/plugins/scaffolder/src/extensions/index.tsx index f53052cb67..131cd105da 100644 --- a/plugins/scaffolder/src/extensions/index.tsx +++ b/plugins/scaffolder/src/extensions/index.tsx @@ -15,7 +15,7 @@ */ import React from 'react'; -import { FieldExtensionOptions } from './types'; +import { CustomFieldValidator, FieldExtensionOptions } from './types'; import { Extension, attachComponentData } from '@backstage/core-plugin-api'; export const FIELD_EXTENSION_WRAPPER_KEY = 'scaffolder.extensions.wrapper.v1'; @@ -46,6 +46,6 @@ attachComponentData( true, ); -export type { FieldExtensionOptions }; +export type { CustomFieldValidator, FieldExtensionOptions }; export { DEFAULT_SCAFFOLDER_FIELD_EXTENSIONS } from './default'; diff --git a/plugins/scaffolder/src/extensions/types.ts b/plugins/scaffolder/src/extensions/types.ts index 8f1c155f28..644897f7f4 100644 --- a/plugins/scaffolder/src/extensions/types.ts +++ b/plugins/scaffolder/src/extensions/types.ts @@ -13,10 +13,19 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +import { ApiHolder } from '@backstage/core-plugin-api'; import { FieldValidation, FieldProps } from '@rjsf/core'; +export type CustomFieldValidator = + | ((data: T, field: FieldValidation) => void) + | (( + data: T, + field: FieldValidation, + context: { apiHolder: ApiHolder }, + ) => void); + export type FieldExtensionOptions = { name: string; component: (props: FieldProps) => JSX.Element | null; - validation?: (data: T, field: FieldValidation) => void; + validation?: CustomFieldValidator; }; diff --git a/plugins/scaffolder/src/index.ts b/plugins/scaffolder/src/index.ts index 6025abc067..a034f5f574 100644 --- a/plugins/scaffolder/src/index.ts +++ b/plugins/scaffolder/src/index.ts @@ -16,9 +16,11 @@ export { scaffolderApiRef, ScaffolderClient } from './api'; export type { ScaffolderApi } from './api'; -export { - createScaffolderFieldExtension, +export { createScaffolderFieldExtension } from './extensions'; +export type { ScaffolderFieldExtensions, + CustomFieldValidator, + FieldExtensionOptions, } from './extensions'; export { EntityPickerFieldExtension, From 32a7c5d975fb62de5426135e9189885247ec6dd7 Mon Sep 17 00:00:00 2001 From: Rogerio Angeliski Date: Wed, 7 Jul 2021 09:33:39 -0300 Subject: [PATCH 200/204] update rails plugin docs Signed-off-by: Rogerio Angeliski --- plugins/scaffolder-backend-module-rails/README.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/plugins/scaffolder-backend-module-rails/README.md b/plugins/scaffolder-backend-module-rails/README.md index 3da594dd75..4ac52be941 100644 --- a/plugins/scaffolder-backend-module-rails/README.md +++ b/plugins/scaffolder-backend-module-rails/README.md @@ -32,9 +32,7 @@ const actions = [ ]; return await createRouter({ - preparers, - templaters, - publishers, + containerRunner, logger, config, database, From 75b3d3d9815a8068862c0c0dad89f7cfcd37da92 Mon Sep 17 00:00:00 2001 From: Rogerio Angeliski Date: Wed, 7 Jul 2021 09:34:04 -0300 Subject: [PATCH 201/204] fix runCommand export Signed-off-by: Rogerio Angeliski --- .../src/scaffolder/actions/builtin/index.ts | 1 + .../src/scaffolder/stages/templater/index.ts | 20 ------------------- 2 files changed, 1 insertion(+), 20 deletions(-) delete mode 100644 plugins/scaffolder-backend/src/scaffolder/stages/templater/index.ts diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/index.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/index.ts index a5d5092327..849b056ac9 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/index.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/index.ts @@ -20,3 +20,4 @@ export * from './debug'; export * from './fetch'; export * from './filesystem'; export * from './publish'; +export { runCommand } from './helpers'; diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/templater/index.ts b/plugins/scaffolder-backend/src/scaffolder/stages/templater/index.ts deleted file mode 100644 index 4d80f86946..0000000000 --- a/plugins/scaffolder-backend/src/scaffolder/stages/templater/index.ts +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright 2020 The Backstage Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -export * from './cookiecutter'; -export * from './types'; -export * from './helpers'; -export * from './templaters'; -export * from './cra'; From 265e0851f4a79685ff06dec2b7becc7ff89dad63 Mon Sep 17 00:00:00 2001 From: Rogerio Angeliski Date: Wed, 7 Jul 2021 09:41:25 -0300 Subject: [PATCH 202/204] docs: added generated files Signed-off-by: Rogerio Angeliski --- plugins/scaffolder-backend/api-report.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/plugins/scaffolder-backend/api-report.md b/plugins/scaffolder-backend/api-report.md index e30542aca7..e8e8697291 100644 --- a/plugins/scaffolder-backend/api-report.md +++ b/plugins/scaffolder-backend/api-report.md @@ -118,6 +118,15 @@ export const createTemplateAction: | undefined; }>>(templateAction: TemplateAction) => TemplateAction; +// @public (undocumented) +export function fetchContents({ reader, integrations, baseUrl, fetchUrl, outputPath, }: { + reader: UrlReader; + integrations: ScmIntegrations; + baseUrl?: string; + fetchUrl?: JsonValue; + outputPath: string; +}): Promise; + // @public (undocumented) export interface RouterOptions { // (undocumented) @@ -138,6 +147,9 @@ export interface RouterOptions { taskWorkers?: number; } +// @public (undocumented) +export const runCommand: ({ command, args, logStream, }: RunCommandOptions) => Promise; + // @public (undocumented) export type TemplateAction = { id: string; From 1bcf50971252f63f7de8c8f80248f2cea8b95b8c Mon Sep 17 00:00:00 2001 From: Rogerio Angeliski Date: Wed, 7 Jul 2021 09:45:58 -0300 Subject: [PATCH 203/204] remove wrong dependency Signed-off-by: Rogerio Angeliski --- plugins/scaffolder-backend/package.json | 2 -- 1 file changed, 2 deletions(-) diff --git a/plugins/scaffolder-backend/package.json b/plugins/scaffolder-backend/package.json index a88413d611..7173f865c5 100644 --- a/plugins/scaffolder-backend/package.json +++ b/plugins/scaffolder-backend/package.json @@ -40,8 +40,6 @@ "@octokit/rest": "^18.5.3", "@types/express": "^4.17.6", "azure-devops-node-api": "^10.2.2", - "@types/git-url-parse": "^9.0.0", - "azure-devops-node-api": "^10.1.1", "command-exists": "^1.2.9", "compression": "^1.7.4", "cors": "^2.8.5", From 549628aac79f181c87e5cebf90b4db4848918faf Mon Sep 17 00:00:00 2001 From: Oliver Sand Date: Wed, 7 Jul 2021 19:51:22 +0200 Subject: [PATCH 204/204] Fix export type of `ScaffolderFieldExtensions` Signed-off-by: Oliver Sand --- plugins/scaffolder/src/index.ts | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/plugins/scaffolder/src/index.ts b/plugins/scaffolder/src/index.ts index a034f5f574..74091a1a85 100644 --- a/plugins/scaffolder/src/index.ts +++ b/plugins/scaffolder/src/index.ts @@ -16,12 +16,11 @@ export { scaffolderApiRef, ScaffolderClient } from './api'; export type { ScaffolderApi } from './api'; -export { createScaffolderFieldExtension } from './extensions'; -export type { +export { + createScaffolderFieldExtension, ScaffolderFieldExtensions, - CustomFieldValidator, - FieldExtensionOptions, } from './extensions'; +export type { CustomFieldValidator, FieldExtensionOptions } from './extensions'; export { EntityPickerFieldExtension, OwnerPickerFieldExtension,

    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 a0=)}i%e!6cH~K=~-tw*YH`l%nKK?)MVz__+ diff --git a/microsite/blog/assets/21-06-24/jobs-to-be-done.png b/microsite/blog/assets/21-06-24/jobs-to-be-done.png index da86befcc22bd9e8f89e8771f91c5aeda9751579..74585d0945e4877b50c006916791a91c156f9b69 100644 GIT binary patch literal 509458 zcmeEuXH-+$7H%x)v0}r90u}^8L_q|ldQcINqDWDy1(1%QAT`)4B29Wzu+c?&2`Wkl z>7CG#8hQu`$(x&O&OK~>W4ym_jFZb9a)7M8)-2!r<~J8SQB{^(vvT`N91gce{>;hq zI2>mN4!0`ouf^~c`qD$y@Xu1?6G|s=xI~Xtw972;-&|MEoL9o(9QWaHZufDx8TgXh zFC6aHAsnvX0Eav7kHc-T4$e3y0pD15MN#e~j)D9yJo}wDd}W38nTxjYh>ghq7vTbf zx5C?T@+VJRxZOC|(x>l3j$klIge~q$N@oM#Cdw-Z9vLbR-8&gM8F}nnvvplsUO~dj zyWxM`-TgFX@$Q0si|;-@aF^?^PpgH!wF&GLshOd^K9l83A9Yilbwpj>dyrXdU3$s} zW~8N&BmLo(%TLCi{lnLhFXcw___6-^dorsFx|jUjq@NW&jV z0~RhqBL>&ZuV1m_`^B>yvwOE1rGuPvUvs0ZV3FPUMh$jP6%Ug#-DV!|dNVbxv-Uxc zmrussPW1*S#j+t@`iGnN!8b9}scM=h+gu&=Zm@6Y6piAbaE<4^Yj~I1_12ufq~2A4 zta`D6RiwLjSVQ0Z1HZW$Y$c~DJ^|aITyU>|)pcle#TabYFD6;P_Yi9sRdq(?`Td@@dbl;=4HxWIASK9C*_{ z)$Igs^|-W5ZYJMYuVlsqdt!rQFN>L9)7sc$B-<(L?a}mbSd-kGZbO(bclk2<9Z#3&_i)bgnvu)ByIXYQ$DZQFC&5?nja4cdzJ^Dd1%`j+G)Y%V$32<=b~mxds{tAI3o^m zTEQypf%kH8R2=RTNWUZ9^Uj=~*2HhyI~k+PAQiQ$dEq~IaOxc!<;GKa7>cl$ua3U4v z-t(-u)9Zb;N^PSse0ZL@MjPyEUqhi`rJ2%WTFO@@yntai1MmI9|^l&(kFEK2(@5&z-Z9C)pq?T${2iiswS_my1u`3?(2xq;khE+u^4-Cj`d{p69-l1WX{mgSbcd45aj{`l#- zUb`6mFWeK^R#7`3V*y2~8ChP*1CGOAJ{9NlTkWlD$@tl99s4FZi~1!bAF}9?W2n+| z@8x0Da@9z3q5runnBrCwUkY}#sr0mtPC{X8`mP%k zpD(OAe)Mky{i0@v?2&8g7f;K|o^vv8>5K?9PO3UVexbQ<$4U=YC8Q=n0;N}9+L0Er zQGdg<5Th;rm7F|Y_bb4Sa89^DcUcahFG^yBp?!=2;e_*a|05kEkQ$fpbN3&%~Lw$W8IsWYg1Oa$e1!ON{%2DOKl z?Av`tj@n^RcNj(FnnFC^W4yRX%0(KKRuvb!U9(NE`H7l!J*jrh!#n%8g*Y4@P)_7i zk_hV0l)f4NnhF6^OjLhs$uBW>q6ZwJ#WF#lPCM7e4M2E9>V!&%+`PBo+3+8FlIhNK zUo)r)ob!h0rsQ7E=(95)4H$xzSA4${$Bl~m7^Du!s|W8a)w_?hL_3SsiwKFc-Sps^ z^TN~-)}xz}^;I%Lk_TqU1VWnA)v;)XWJ~6L5vT{<)%AKYh1TS5v|nie8;+^MWgnpENrfuP(Mrj#yzNFSJq z3;EHd;!FTz!JP+Hnga=>5Y3q%&(i9aymPhR1%#tCsy4Le%QjLf=CL@f#b|}hRS=nU z?g7s$Sr$iq>ju0XcHGm)<~Pb}CFM7As`dL4B$_RJS(j(Z8L=c^-VfL(X~}My)p~Kq z`_k#D#!;0|_LgUyZxO}_Qub3p(Z0RxoYmy)tzmZJ*oW$cqEL|_bn>fbdu!rbujO?c zOo8z^{+fNRdGQC4s!}YVGqk#a$+|baoL;%I4w%6USN{OIQbn?`$mFRZ z@Ft*f%PK8H2u^2!V|C@KC|N^k+AjO@A6-#&^J9Q501O|4--06>`ogvU{XFFJ5!OOf z%0D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 z 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