From a195fd752fdf68ab259188e51d53bf60933594a9 Mon Sep 17 00:00:00 2001 From: Johan Haals Date: Fri, 5 Mar 2021 14:54:28 +0100 Subject: [PATCH 01/27] Generate documentation for registered actions Signed-off-by: Johan Haals --- .../actions/TemplateActionRegistry.ts | 4 + .../scaffolder-backend/src/service/router.ts | 9 + plugins/scaffolder/src/api.ts | 14 +- .../components/ActionsPage/ActionsPage.tsx | 154 ++++++++++++++++++ .../src/components/ActionsPage/index.ts | 17 ++ plugins/scaffolder/src/components/Router.tsx | 2 + plugins/scaffolder/src/types.ts | 9 + 7 files changed, 208 insertions(+), 1 deletion(-) create mode 100644 plugins/scaffolder/src/components/ActionsPage/ActionsPage.tsx create mode 100644 plugins/scaffolder/src/components/ActionsPage/index.ts diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/TemplateActionRegistry.ts b/plugins/scaffolder-backend/src/scaffolder/actions/TemplateActionRegistry.ts index 2a841a564b..c9e163bfdd 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/TemplateActionRegistry.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/TemplateActionRegistry.ts @@ -38,4 +38,8 @@ export class TemplateActionRegistry { } return action; } + + list(): TemplateAction[] { + return [...this.actions.values()]; + } } diff --git a/plugins/scaffolder-backend/src/service/router.ts b/plugins/scaffolder-backend/src/service/router.ts index 3d47d5123b..b77c832ca1 100644 --- a/plugins/scaffolder-backend/src/service/router.ts +++ b/plugins/scaffolder-backend/src/service/router.ts @@ -347,6 +347,15 @@ export async function createRouter( } }, ) + .get('/v2/actions', async (_req, res) => { + const actionsList = actionRegistry.list().map(action => { + return { + id: action.id, + schema: action.schema, + }; + }); + res.json(actionsList); + }) .post('/v2/tasks', async (req, res) => { const templateName: string = req.body.templateName; const values: TemplaterValues = req.body.values; diff --git a/plugins/scaffolder/src/api.ts b/plugins/scaffolder/src/api.ts index 2be4caa81f..4e03723272 100644 --- a/plugins/scaffolder/src/api.ts +++ b/plugins/scaffolder/src/api.ts @@ -25,7 +25,7 @@ import { } from '@backstage/core'; import { ScmIntegrations } from '@backstage/integration'; import ObservableImpl from 'zen-observable'; -import { ScaffolderTask, Status } from './types'; +import { ListActionsResponse, ScaffolderTask, Status } from './types'; export const scaffolderApiRef = createApiRef({ id: 'plugin.scaffolder.service', @@ -72,6 +72,9 @@ export interface ScaffolderApi { allowedHosts: string[]; }): Promise<{ type: string; title: string; host: string }[]>; + // Returns a list of all installed actions. + listActions(): Promise; + streamLogs({ taskId, after, @@ -227,4 +230,13 @@ export class ScaffolderClient implements ScaffolderApi { ); }); } + + /** + * @Returns ListActionsResponse containg all registered actions. + */ + async listActions(): Promise { + const baseUrl = await this.discoveryApi.getBaseUrl('scaffolder'); + const response = await fetch(`${baseUrl}/v2/actions`); + return await response.json(); + } } diff --git a/plugins/scaffolder/src/components/ActionsPage/ActionsPage.tsx b/plugins/scaffolder/src/components/ActionsPage/ActionsPage.tsx new file mode 100644 index 0000000000..10bc593cf9 --- /dev/null +++ b/plugins/scaffolder/src/components/ActionsPage/ActionsPage.tsx @@ -0,0 +1,154 @@ +/* + * 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 React from 'react'; +import { useAsync } from 'react-use'; +import { + useApi, + Progress, + Content, + Header, + Page, + ErrorPage, + Button, + ItemCardGrid, + ItemCardHeader, +} from '@backstage/core'; +import { scaffolderApiRef } from '../../api'; +import { + Card, + CardMedia, + CardContent, + CardActions, + Typography, + Paper, + Table, + TableBody, + TableCell, + TableContainer, + TableHead, + TableRow, + makeStyles, +} from '@material-ui/core'; +import { JSONSchema } from '@backstage/catalog-model'; + +const useStyles = makeStyles({ + table: { + // minWidth: 650, + }, +}); + +export const ActionsPage = () => { + const api = useApi(scaffolderApiRef); + const classes = useStyles(); + const { loading, value, error } = useAsync(async () => { + return api.listActions(); + }); + + if (loading) { + return ; + } + + if (error) { + return ( + + ); + } + + const formatRows = (input: JSONSchema) => { + const properties = input.properties; + if (!properties) { + return undefined; + } + const required = input.required ? input.required : []; + + return Object.entries(properties).map(entry => { + const [key, props] = entry; + const isRequired = required.includes(key); + return ( + + + {key} + {isRequired && *} + + {props.title} + {props.description} + {props.type} + + ); + }); + }; + + const items = value?.map(action => { + if (action.id.startsWith('legacy:')) { + return undefined; + } + return ( + <> + {action.id} + {action.schema?.input && ( + <> + Input + + + + + Name + Title + Description + Type + + + {formatRows(action.schema?.input)} +
+
+ + )} + {action.schema?.output && ( + <> + Output + + + + + Name + Title + Description + Type + + + {formatRows(action.schema?.output)} +
+
+ + )} + + ); + }); + + return ( + +
+ {items} + + ); +}; diff --git a/plugins/scaffolder/src/components/ActionsPage/index.ts b/plugins/scaffolder/src/components/ActionsPage/index.ts new file mode 100644 index 0000000000..64d548e37d --- /dev/null +++ b/plugins/scaffolder/src/components/ActionsPage/index.ts @@ -0,0 +1,17 @@ +/* + * 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. + */ + +export { ActionsPage } from './ActionsPage'; diff --git a/plugins/scaffolder/src/components/Router.tsx b/plugins/scaffolder/src/components/Router.tsx index 12d4ecce82..9a525c0be4 100644 --- a/plugins/scaffolder/src/components/Router.tsx +++ b/plugins/scaffolder/src/components/Router.tsx @@ -19,11 +19,13 @@ import { Routes, Route } from 'react-router'; import { ScaffolderPage } from './ScaffolderPage'; import { TemplatePage } from './TemplatePage'; import { TaskPage } from './TaskPage'; +import { ActionsPage } from './ActionsPage'; export const Router = () => ( } /> } /> } /> + } /> ); diff --git a/plugins/scaffolder/src/types.ts b/plugins/scaffolder/src/types.ts index 0499f4aca2..886650859a 100644 --- a/plugins/scaffolder/src/types.ts +++ b/plugins/scaffolder/src/types.ts @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +import { JSONSchema } from '@backstage/catalog-model'; import { JsonValue } from '@backstage/config'; export type Status = 'open' | 'processing' | 'failed' | 'completed'; @@ -54,3 +55,11 @@ export type ScaffolderTask = { lastHeartbeatAt: string; createdAt: string; }; + +export type ListActionsResponse = Array<{ + id: string; + schema?: { + input?: JSONSchema; + output?: JSONSchema; + }; +}>; From c07407872cadbb5bb34e55f5820b767ccfd2a9b7 Mon Sep 17 00:00:00 2001 From: Johan Haals Date: Fri, 5 Mar 2021 16:24:59 +0100 Subject: [PATCH 02/27] Style content Co-authored-by: Ben Lambert Signed-off-by: Johan Haals --- .../components/ActionsPage/ActionsPage.tsx | 109 ++++++++++-------- 1 file changed, 64 insertions(+), 45 deletions(-) diff --git a/plugins/scaffolder/src/components/ActionsPage/ActionsPage.tsx b/plugins/scaffolder/src/components/ActionsPage/ActionsPage.tsx index 10bc593cf9..a9f96d8d09 100644 --- a/plugins/scaffolder/src/components/ActionsPage/ActionsPage.tsx +++ b/plugins/scaffolder/src/components/ActionsPage/ActionsPage.tsx @@ -22,20 +22,14 @@ import { Header, Page, ErrorPage, - Button, - ItemCardGrid, - ItemCardHeader, } from '@backstage/core'; import { scaffolderApiRef } from '../../api'; import { - Card, - CardMedia, - CardContent, - CardActions, Typography, Paper, Table, TableBody, + Box, TableCell, TableContainer, TableHead, @@ -44,11 +38,35 @@ import { } from '@material-ui/core'; import { JSONSchema } from '@backstage/catalog-model'; -const useStyles = makeStyles({ +const useStyles = makeStyles(theme => ({ table: { // minWidth: 650, }, -}); + + code: { + fontFamily: 'Menlo, monospaced', + padding: theme.spacing(1), + backgroundColor: + theme.palette.type === 'dark' + ? theme.palette.grey[700] + : theme.palette.grey[300], + display: 'inline-block', + borderRadius: 5, + border: `1px solid ${theme.palette.grey[500]}`, + position: 'relative', + }, + + codeRequired: { + '&::after': { + position: 'absolute', + content: '"*"', + top: 0, + right: theme.spacing(0.5), + fontWeight: 'bolder', + color: theme.palette.error.light, + }, + }, +})); export const ActionsPage = () => { const api = useApi(scaffolderApiRef); @@ -80,64 +98,65 @@ export const ActionsPage = () => { return Object.entries(properties).map(entry => { const [key, props] = entry; const isRequired = required.includes(key); + + const codeClassname = `${classes.code} ${ + isRequired ? classes.codeRequired : '' + }`; return ( - {key} - {isRequired && *} +
{key}
{props.title} {props.description} - {props.type} + + {props.type} +
); }); }; + const renderTable = (input: JSONSchema) => { + return ( + + + + + Name + Title + Description + Type + + + {formatRows(input)} +
+
+ ); + }; + const items = value?.map(action => { if (action.id.startsWith('legacy:')) { return undefined; } return ( - <> - {action.id} + + + {action.id} + {action.schema?.input && ( - <> + Input - - - - - Name - Title - Description - Type - - - {formatRows(action.schema?.input)} -
-
- + {renderTable(action.schema.input)} +
)} {action.schema?.output && ( - <> + Output - - - - - Name - Title - Description - Type - - - {formatRows(action.schema?.output)} -
-
- + {renderTable(action.schema.output)} +
)} - +
); }); From 7b66e0711613efa37828f9b8c6476e600a3f551a Mon Sep 17 00:00:00 2001 From: Johan Haals Date: Mon, 8 Mar 2021 14:07:38 +0100 Subject: [PATCH 03/27] Add description to scaffolder actions Signed-off-by: Johan Haals --- .../src/scaffolder/actions/builtin/catalog/register.ts | 1 + .../src/scaffolder/actions/builtin/fetch/cookiecutter.ts | 2 ++ .../src/scaffolder/actions/builtin/fetch/plain.ts | 2 ++ .../src/scaffolder/actions/builtin/publish/azure.ts | 2 ++ .../src/scaffolder/actions/builtin/publish/bitbucket.ts | 2 ++ .../src/scaffolder/actions/builtin/publish/github.ts | 2 ++ .../src/scaffolder/actions/builtin/publish/gitlab.ts | 2 ++ plugins/scaffolder-backend/src/scaffolder/actions/types.ts | 1 + plugins/scaffolder-backend/src/service/router.ts | 1 + plugins/scaffolder/src/types.ts | 1 + 10 files changed, 16 insertions(+) diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/catalog/register.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/catalog/register.ts index 7cf1ac2120..654b2c954d 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/catalog/register.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/catalog/register.ts @@ -31,6 +31,7 @@ export function createCatalogRegisterAction(options: { | { repoContentsUrl: string; catalogInfoPath?: string } >({ id: 'catalog:register', + description: 'Registers entity in the software catalog.', schema: { input: { oneOf: [ 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 2a04ed301d..32c374f659 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/cookiecutter.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/cookiecutter.ts @@ -38,6 +38,8 @@ export function createFetchCookiecutterAction(options: { values: JsonObject; }>({ id: 'fetch:cookiecutter', + description: + "Downloads template from 'url' and templates with cookiecutter", schema: { input: { type: 'object', 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 1eb1a6dc82..cae7364255 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/plain.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/plain.ts @@ -28,6 +28,8 @@ export function createFetchPlainAction(options: { return createTemplateAction<{ url: string; targetPath?: string }>({ id: 'fetch:plain', + description: + "Downloads content and places it in the workspacePath or optionally in a subdirectory specified by the 'targetPath' input option.", schema: { input: { type: 'object', 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 5eaba05ea0..dc66c710fc 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/azure.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/azure.ts @@ -32,6 +32,8 @@ export function createPublishAzureAction(options: { description?: string; }>({ id: 'publish:azure', + description: + 'Initializes a git repository of contents in workspacePath and publishes to Azure.', schema: { input: { type: 'object', 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 4c3cf30ecd..842dee0df9 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/bitbucket.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/bitbucket.ts @@ -167,6 +167,8 @@ export function createPublishBitbucketAction(options: { repoVisibility: 'private' | 'public'; }>({ id: 'publish:bitbucket', + description: + 'Initializes a git repository of contents in workspacePath and publishes to Bitbucket.', schema: { input: { type: 'object', 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 be0820d0b1..258f0625ca 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/github.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/github.ts @@ -43,6 +43,8 @@ export function createPublishGithubAction(options: { repoVisibility: 'private' | 'internal' | 'public'; }>({ id: 'publish:github', + description: + 'Initializes a git repository of contents in workspacePath and publishes to GitHub.', schema: { input: { type: 'object', 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 9122c828a0..10113b324a 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.ts @@ -31,6 +31,8 @@ export function createPublishGitlabAction(options: { repoVisibility: 'private' | 'internal' | 'public'; }>({ id: 'publish:gitlab', + description: + 'Initializes a git repository of contents in workspacePath and publishes to GitLab.', schema: { input: { type: 'object', diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/types.ts b/plugins/scaffolder-backend/src/scaffolder/actions/types.ts index 20b7696d70..955cb72de9 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/types.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/types.ts @@ -44,6 +44,7 @@ export type ActionContext = { export type TemplateAction = { id: string; + description?: string; schema?: { input?: Schema; output?: Schema; diff --git a/plugins/scaffolder-backend/src/service/router.ts b/plugins/scaffolder-backend/src/service/router.ts index b77c832ca1..81be03730b 100644 --- a/plugins/scaffolder-backend/src/service/router.ts +++ b/plugins/scaffolder-backend/src/service/router.ts @@ -351,6 +351,7 @@ export async function createRouter( const actionsList = actionRegistry.list().map(action => { return { id: action.id, + description: action.description, schema: action.schema, }; }); diff --git a/plugins/scaffolder/src/types.ts b/plugins/scaffolder/src/types.ts index 886650859a..6a2c2eede4 100644 --- a/plugins/scaffolder/src/types.ts +++ b/plugins/scaffolder/src/types.ts @@ -58,6 +58,7 @@ export type ScaffolderTask = { export type ListActionsResponse = Array<{ id: string; + description?: string; schema?: { input?: JSONSchema; output?: JSONSchema; From 584f1a04f5a1cf739e7aa8330c8229e62ce04324 Mon Sep 17 00:00:00 2001 From: Johan Haals Date: Mon, 8 Mar 2021 14:08:17 +0100 Subject: [PATCH 04/27] Render description and oneOf fields Signed-off-by: Johan Haals --- plugins/scaffolder/package.json | 1 + .../components/ActionsPage/ActionsPage.tsx | 38 ++++++++++++++----- 2 files changed, 30 insertions(+), 9 deletions(-) diff --git a/plugins/scaffolder/package.json b/plugins/scaffolder/package.json index 53716fd1dc..d0dc0d70d7 100644 --- a/plugins/scaffolder/package.json +++ b/plugins/scaffolder/package.json @@ -43,6 +43,7 @@ "@rjsf/core": "^2.4.0", "@rjsf/material-ui": "^2.4.0", "classnames": "^2.2.6", + "json-schema": "^0.3.0", "git-url-parse": "^11.4.4", "humanize-duration": "^3.25.1", "luxon": "^1.25.0", diff --git a/plugins/scaffolder/src/components/ActionsPage/ActionsPage.tsx b/plugins/scaffolder/src/components/ActionsPage/ActionsPage.tsx index a9f96d8d09..07d1bd2ec4 100644 --- a/plugins/scaffolder/src/components/ActionsPage/ActionsPage.tsx +++ b/plugins/scaffolder/src/components/ActionsPage/ActionsPage.tsx @@ -37,12 +37,9 @@ import { makeStyles, } from '@material-ui/core'; import { JSONSchema } from '@backstage/catalog-model'; +import { JSONSchema7Definition } from 'json-schema'; const useStyles = makeStyles(theme => ({ - table: { - // minWidth: 650, - }, - code: { fontFamily: 'Menlo, monospaced', padding: theme.spacing(1), @@ -96,7 +93,8 @@ export const ActionsPage = () => { const required = input.required ? input.required : []; return Object.entries(properties).map(entry => { - const [key, props] = entry; + const [key] = entry; + const props = (entry[0] as unknown) as JSONSchema; const isRequired = required.includes(key); const codeClassname = `${classes.code} ${ @@ -118,9 +116,12 @@ export const ActionsPage = () => { }; const renderTable = (input: JSONSchema) => { + if (!input.properties) { + return undefined; + } return ( - +
Name @@ -135,24 +136,43 @@ export const ActionsPage = () => { ); }; + const renderTables = (name: string, input?: JSONSchema7Definition[]) => { + if (!input) { + return undefined; + } + + return ( + <> + {name} + {input.map((i, index) => ( +
{renderTable((i as unknown) as JSONSchema)}
+ ))} + + ); + }; + const items = value?.map(action => { if (action.id.startsWith('legacy:')) { return undefined; } + + const oneOf = renderTables('oneOf', action.schema?.input?.oneOf); return ( - + {action.id} + {action.description} {action.schema?.input && ( - Input + Input {renderTable(action.schema.input)} + {oneOf} )} {action.schema?.output && ( - Output + Output {renderTable(action.schema.output)} )} From b6dfc7dcd9338ba4f9d81a3282d4aa45d70081c4 Mon Sep 17 00:00:00 2001 From: Johan Haals Date: Mon, 8 Mar 2021 14:12:32 +0100 Subject: [PATCH 05/27] use correct field from array Signed-off-by: Johan Haals --- plugins/scaffolder/src/components/ActionsPage/ActionsPage.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/scaffolder/src/components/ActionsPage/ActionsPage.tsx b/plugins/scaffolder/src/components/ActionsPage/ActionsPage.tsx index 07d1bd2ec4..09c3e0f131 100644 --- a/plugins/scaffolder/src/components/ActionsPage/ActionsPage.tsx +++ b/plugins/scaffolder/src/components/ActionsPage/ActionsPage.tsx @@ -94,7 +94,7 @@ export const ActionsPage = () => { return Object.entries(properties).map(entry => { const [key] = entry; - const props = (entry[0] as unknown) as JSONSchema; + const props = (entry[1] as unknown) as JSONSchema; const isRequired = required.includes(key); const codeClassname = `${classes.code} ${ From d36c6975387c48a0706e5357cefe1ca07f081912 Mon Sep 17 00:00:00 2001 From: Johan Haals Date: Mon, 8 Mar 2021 14:49:29 +0100 Subject: [PATCH 06/27] fix tests Signed-off-by: Johan Haals --- plugins/scaffolder-backend/src/service/router.test.ts | 9 +++++++++ .../src/components/TemplatePage/TemplatePage.test.tsx | 1 + 2 files changed, 10 insertions(+) diff --git a/plugins/scaffolder-backend/src/service/router.test.ts b/plugins/scaffolder-backend/src/service/router.test.ts index b7c2582c81..f01b4f8c95 100644 --- a/plugins/scaffolder-backend/src/service/router.test.ts +++ b/plugins/scaffolder-backend/src/service/router.test.ts @@ -261,6 +261,15 @@ describe('createRouter', () => { }); }); + describe('GET /v2/actions', () => { + it('lists available actions', async () => { + const response = await request(app).get('/v2/actions').send(); + expect(response.status).toEqual(200); + expect(response.body[0].id).toBeDefined(); + expect(response.body.length).toBeGreaterThan(8); + }); + }); + describe('POST /v2/tasks', () => { it('rejects template values which do not match the template schema definition', async () => { const response = await request(app) diff --git a/plugins/scaffolder/src/components/TemplatePage/TemplatePage.test.tsx b/plugins/scaffolder/src/components/TemplatePage/TemplatePage.test.tsx index 1b11b704ae..3cdf6c9738 100644 --- a/plugins/scaffolder/src/components/TemplatePage/TemplatePage.test.tsx +++ b/plugins/scaffolder/src/components/TemplatePage/TemplatePage.test.tsx @@ -39,6 +39,7 @@ const scaffolderApiMock: jest.Mocked = { getIntegrationsList: jest.fn(), getTask: jest.fn(), streamLogs: jest.fn(), + listActions: jest.fn(), }; const errorApiMock = { post: jest.fn(), error$: jest.fn() }; From 3126fe1d05a05d1285e4e40079e28ded9dd4c317 Mon Sep 17 00:00:00 2001 From: Johan Haals Date: Tue, 9 Mar 2021 09:02:26 +0100 Subject: [PATCH 07/27] Update plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/plain.ts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Johan Haals Co-authored-by: Fredrik Adelöw --- .../src/scaffolder/actions/builtin/fetch/plain.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 cae7364255..00c63535ca 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/plain.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/plain.ts @@ -29,7 +29,7 @@ export function createFetchPlainAction(options: { return createTemplateAction<{ url: string; targetPath?: string }>({ id: 'fetch:plain', description: - "Downloads content and places it in the workspacePath or optionally in a subdirectory specified by the 'targetPath' input option.", + "Downloads content and places it in the workspace, or optionally in a subdirectory specified by the 'targetPath' input option.", schema: { input: { type: 'object', From 955ae4556b1b36c7db40a06fa6f28aa57824995c Mon Sep 17 00:00:00 2001 From: Johan Haals Date: Tue, 9 Mar 2021 09:02:37 +0100 Subject: [PATCH 08/27] Update plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.ts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Johan Haals Co-authored-by: Fredrik Adelöw --- .../src/scaffolder/actions/builtin/publish/gitlab.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 10113b324a..4aad8589b8 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.ts @@ -32,7 +32,7 @@ export function createPublishGitlabAction(options: { }>({ id: 'publish:gitlab', description: - 'Initializes a git repository of contents in workspacePath and publishes to GitLab.', + 'Initializes a git repository of the content in the workspace, and publishes to GitLab.', schema: { input: { type: 'object', From 2156c26f935b54ce670b220ee9c59a77fefa14ba Mon Sep 17 00:00:00 2001 From: Johan Haals Date: Tue, 9 Mar 2021 09:02:53 +0100 Subject: [PATCH 09/27] Update plugins/scaffolder/src/api.ts Signed-off-by: Johan Haals Co-authored-by: Adam Harvey --- plugins/scaffolder/src/api.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/scaffolder/src/api.ts b/plugins/scaffolder/src/api.ts index 4e03723272..758cd555e3 100644 --- a/plugins/scaffolder/src/api.ts +++ b/plugins/scaffolder/src/api.ts @@ -232,7 +232,7 @@ export class ScaffolderClient implements ScaffolderApi { } /** - * @Returns ListActionsResponse containg all registered actions. + * @returns ListActionsResponse containing all registered actions. */ async listActions(): Promise { const baseUrl = await this.discoveryApi.getBaseUrl('scaffolder'); From 4c43faa51aba90d7afbd87e43ee4964e307d79a7 Mon Sep 17 00:00:00 2001 From: Johan Haals Date: Tue, 9 Mar 2021 09:03:57 +0100 Subject: [PATCH 10/27] Update plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/cookiecutter.ts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Johan Haals Co-authored-by: Fredrik Adelöw --- .../src/scaffolder/actions/builtin/fetch/cookiecutter.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 32c374f659..5de22d5467 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/cookiecutter.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/cookiecutter.ts @@ -39,7 +39,7 @@ export function createFetchCookiecutterAction(options: { }>({ id: 'fetch:cookiecutter', description: - "Downloads template from 'url' and templates with cookiecutter", + "Downloads a template from the given URL into the workspace, and runs cookiecutter on it.", schema: { input: { type: 'object', From f6ce3d50f1af1d8ef040f6ad69829f92b91b7a35 Mon Sep 17 00:00:00 2001 From: Johan Haals Date: Tue, 9 Mar 2021 09:05:18 +0100 Subject: [PATCH 11/27] Update plugins/scaffolder/src/components/ActionsPage/ActionsPage.tsx MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Johan Haals Co-authored-by: Fredrik Adelöw --- plugins/scaffolder/src/components/ActionsPage/ActionsPage.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/scaffolder/src/components/ActionsPage/ActionsPage.tsx b/plugins/scaffolder/src/components/ActionsPage/ActionsPage.tsx index 09c3e0f131..d91221f1f9 100644 --- a/plugins/scaffolder/src/components/ActionsPage/ActionsPage.tsx +++ b/plugins/scaffolder/src/components/ActionsPage/ActionsPage.tsx @@ -41,7 +41,7 @@ import { JSONSchema7Definition } from 'json-schema'; const useStyles = makeStyles(theme => ({ code: { - fontFamily: 'Menlo, monospaced', + fontFamily: 'Menlo, monospace', padding: theme.spacing(1), backgroundColor: theme.palette.type === 'dark' From 88f2b69850d54e0c7244281acea4fe9ed375b995 Mon Sep 17 00:00:00 2001 From: Johan Haals Date: Tue, 9 Mar 2021 09:23:11 +0100 Subject: [PATCH 12/27] use classNames Signed-off-by: Johan Haals --- .../src/components/ActionsPage/ActionsPage.tsx | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/plugins/scaffolder/src/components/ActionsPage/ActionsPage.tsx b/plugins/scaffolder/src/components/ActionsPage/ActionsPage.tsx index d91221f1f9..a06ca50736 100644 --- a/plugins/scaffolder/src/components/ActionsPage/ActionsPage.tsx +++ b/plugins/scaffolder/src/components/ActionsPage/ActionsPage.tsx @@ -38,6 +38,7 @@ import { } from '@material-ui/core'; import { JSONSchema } from '@backstage/catalog-model'; import { JSONSchema7Definition } from 'json-schema'; +import classNames from 'classnames'; const useStyles = makeStyles(theme => ({ code: { @@ -90,16 +91,14 @@ export const ActionsPage = () => { if (!properties) { return undefined; } - const required = input.required ? input.required : []; return Object.entries(properties).map(entry => { const [key] = entry; const props = (entry[1] as unknown) as JSONSchema; - const isRequired = required.includes(key); + const codeClassname = classNames(classes.code, { + [classes.codeRequired]: input.required?.includes(key), + }); - const codeClassname = `${classes.code} ${ - isRequired ? classes.codeRequired : '' - }`; return ( From 26e40330709cc46f7bf32c7157eedc545666ea74 Mon Sep 17 00:00:00 2001 From: Johan Haals Date: Tue, 9 Mar 2021 09:24:05 +0100 Subject: [PATCH 13/27] format Signed-off-by: Johan Haals --- .../src/scaffolder/actions/builtin/fetch/cookiecutter.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 5de22d5467..070aaa9679 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/cookiecutter.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/cookiecutter.ts @@ -39,7 +39,7 @@ export function createFetchCookiecutterAction(options: { }>({ id: 'fetch:cookiecutter', description: - "Downloads a template from the given URL into the workspace, and runs cookiecutter on it.", + 'Downloads a template from the given URL into the workspace, and runs cookiecutter on it.', schema: { input: { type: 'object', From f98f212e40807e9c6c5125dd882aa4d8b90ab93c Mon Sep 17 00:00:00 2001 From: Johan Haals Date: Tue, 9 Mar 2021 09:36:58 +0100 Subject: [PATCH 14/27] Add changeset Signed-off-by: Johan Haals --- .changeset/red-readers-mix.md | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 .changeset/red-readers-mix.md diff --git a/.changeset/red-readers-mix.md b/.changeset/red-readers-mix.md new file mode 100644 index 0000000000..1f1828cb4b --- /dev/null +++ b/.changeset/red-readers-mix.md @@ -0,0 +1,10 @@ +--- +'@backstage/plugin-scaffolder': patch +'@backstage/plugin-scaffolder-backend': patch +--- + +Introduce scaffolder actions page which lists all available actions along with documentation about their input/output. + +Allow for actions to be extended with a description. + +The list actions page is by default available at `/create/actions`. From 269dba9ff7b258d5bdd6ea60e98c7b078a635f19 Mon Sep 17 00:00:00 2001 From: Johan Haals Date: Tue, 9 Mar 2021 11:20:53 +0100 Subject: [PATCH 15/27] Update plugins/scaffolder-backend/src/scaffolder/actions/builtin/catalog/register.ts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Johan Haals Co-authored-by: Fredrik Adelöw --- .../src/scaffolder/actions/builtin/catalog/register.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/catalog/register.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/catalog/register.ts index 654b2c954d..64c2e9f721 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/catalog/register.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/catalog/register.ts @@ -31,7 +31,7 @@ export function createCatalogRegisterAction(options: { | { repoContentsUrl: string; catalogInfoPath?: string } >({ id: 'catalog:register', - description: 'Registers entity in the software catalog.', + description: 'Registers entities from a catalog descriptor file in the workspace into the software catalog.', schema: { input: { oneOf: [ From 83ab18b4a48248091c99e734095a02622c6c7066 Mon Sep 17 00:00:00 2001 From: Johan Haals Date: Tue, 9 Mar 2021 11:21:11 +0100 Subject: [PATCH 16/27] Update plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/bitbucket.ts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Johan Haals Co-authored-by: Fredrik Adelöw --- .../src/scaffolder/actions/builtin/publish/bitbucket.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 842dee0df9..63a0516712 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/bitbucket.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/bitbucket.ts @@ -168,7 +168,7 @@ export function createPublishBitbucketAction(options: { }>({ id: 'publish:bitbucket', description: - 'Initializes a git repository of contents in workspacePath and publishes to Bitbucket.', + 'Initializes a git repository of the content in the workspace, and publishes to Bitbucket.', schema: { input: { type: 'object', From eaa4fc82ad0ae16a174bc869b62b3bc11044e19f Mon Sep 17 00:00:00 2001 From: Johan Haals Date: Tue, 9 Mar 2021 11:21:40 +0100 Subject: [PATCH 17/27] Update plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/azure.ts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Johan Haals Co-authored-by: Fredrik Adelöw --- .../src/scaffolder/actions/builtin/publish/azure.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 dc66c710fc..db38960086 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/azure.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/azure.ts @@ -33,7 +33,7 @@ export function createPublishAzureAction(options: { }>({ id: 'publish:azure', description: - 'Initializes a git repository of contents in workspacePath and publishes to Azure.', + 'Initializes a git repository of the content in the workspace, and publishes it to Azure.', schema: { input: { type: 'object', From cc8072158bcd56ccf5d119c946efeae5dedbd569 Mon Sep 17 00:00:00 2001 From: Johan Haals Date: Tue, 9 Mar 2021 12:45:51 +0100 Subject: [PATCH 18/27] format Signed-off-by: Johan Haals --- .../src/scaffolder/actions/builtin/catalog/register.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/catalog/register.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/catalog/register.ts index 64c2e9f721..b034b480e2 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/catalog/register.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/catalog/register.ts @@ -31,7 +31,8 @@ export function createCatalogRegisterAction(options: { | { repoContentsUrl: string; catalogInfoPath?: string } >({ id: 'catalog:register', - description: 'Registers entities from a catalog descriptor file in the workspace into the software catalog.', + description: + 'Registers entities from a catalog descriptor file in the workspace into the software catalog.', schema: { input: { oneOf: [ From 53a111d238c4fc1abc9f03a17fb34f7348fdf99f Mon Sep 17 00:00:00 2001 From: Johan Haals Date: Tue, 9 Mar 2021 12:46:04 +0100 Subject: [PATCH 19/27] Add rendering tests Signed-off-by: Johan Haals --- .../ActionsPage/ActionsPage.test.tsx | 167 ++++++++++++++++++ 1 file changed, 167 insertions(+) create mode 100644 plugins/scaffolder/src/components/ActionsPage/ActionsPage.test.tsx diff --git a/plugins/scaffolder/src/components/ActionsPage/ActionsPage.test.tsx b/plugins/scaffolder/src/components/ActionsPage/ActionsPage.test.tsx new file mode 100644 index 0000000000..708d08359a --- /dev/null +++ b/plugins/scaffolder/src/components/ActionsPage/ActionsPage.test.tsx @@ -0,0 +1,167 @@ +/* + * 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 { ApiRegistry, ApiProvider } from '@backstage/core'; +import React from 'react'; +import { ScaffolderApi, scaffolderApiRef } from '../../api'; +import { ActionsPage } from './ActionsPage'; +import { rootRouteRef } from '../../routes'; +import { renderInTestApp } from '@backstage/test-utils'; + +const scaffolderApiMock: jest.Mocked = { + scaffold: jest.fn(), + getTemplateParameterSchema: jest.fn(), + getIntegrationsList: jest.fn(), + getTask: jest.fn(), + streamLogs: jest.fn(), + listActions: jest.fn(), +}; + +const apis = ApiRegistry.from([[scaffolderApiRef, scaffolderApiMock]]); + +describe('TemplatePage', () => { + beforeEach(() => jest.resetAllMocks()); + + it('renders action with input', async () => { + scaffolderApiMock.listActions.mockResolvedValue([ + { + id: 'test', + description: 'example description', + schema: { + input: { + type: 'object', + required: ['foobar'], + properties: { + foobar: { + title: 'Test title', + type: 'string', + }, + }, + }, + }, + }, + ]); + const rendered = await renderInTestApp( + + + , + { + mountedRoutes: { + '/create/actions': rootRouteRef, + }, + }, + ); + expect(rendered.queryByText('Test title')).toBeInTheDocument(); + expect(rendered.queryByText('example description')).toBeInTheDocument(); + expect(rendered.queryByText('foobar')).toBeInTheDocument(); + expect(rendered.queryByText('output')).not.toBeInTheDocument(); + }); + + it('renders action with input and output', async () => { + scaffolderApiMock.listActions.mockResolvedValue([ + { + id: 'test', + description: 'example description', + schema: { + input: { + type: 'object', + required: ['foobar'], + properties: { + foobar: { + title: 'Test title', + type: 'string', + }, + }, + }, + output: { + type: 'object', + properties: { + buzz: { + title: 'Test output', + type: 'string', + }, + }, + }, + }, + }, + ]); + const rendered = await renderInTestApp( + + + , + { + mountedRoutes: { + '/create/actions': rootRouteRef, + }, + }, + ); + expect(rendered.queryByText('Test title')).toBeInTheDocument(); + expect(rendered.queryByText('example description')).toBeInTheDocument(); + expect(rendered.queryByText('foobar')).toBeInTheDocument(); + expect(rendered.queryByText('Test output')).toBeInTheDocument(); + }); + + it('renders action with oneOf input', async () => { + scaffolderApiMock.listActions.mockResolvedValue([ + { + id: 'test', + description: 'example description', + schema: { + input: { + oneOf: [ + { + type: 'object', + required: ['foo'], + properties: { + foo: { + title: 'Foo title', + description: 'Foo description', + type: 'string', + }, + }, + }, + { + type: 'object', + required: ['bar'], + properties: { + bar: { + title: 'Bar title', + description: 'Bar description', + type: 'string', + }, + }, + }, + ], + }, + }, + }, + ]); + const rendered = await renderInTestApp( + + + , + { + mountedRoutes: { + '/create/actions': rootRouteRef, + }, + }, + ); + expect(rendered.queryByText('oneOf')).toBeInTheDocument(); + expect(rendered.queryByText('Foo title')).toBeInTheDocument(); + expect(rendered.queryByText('Foo description')).toBeInTheDocument(); + expect(rendered.queryByText('Bar title')).toBeInTheDocument(); + expect(rendered.queryByText('Bar description')).toBeInTheDocument(); + }); +}); From f9aeab88a00c236f0cdb822915c34632a2705a11 Mon Sep 17 00:00:00 2001 From: Johan Haals Date: Tue, 9 Mar 2021 13:43:19 +0100 Subject: [PATCH 20/27] Move built-in actions docs to the scaffolder itself Signed-off-by: Johan Haals --- .../software-templates/builtin-actions.md | 113 ++---------------- 1 file changed, 8 insertions(+), 105 deletions(-) diff --git a/docs/features/software-templates/builtin-actions.md b/docs/features/software-templates/builtin-actions.md index e6886b1f04..fc89e9fca6 100644 --- a/docs/features/software-templates/builtin-actions.md +++ b/docs/features/software-templates/builtin-actions.md @@ -6,110 +6,13 @@ description: Documentation describing the built-in template actions. # Built-in Actions -This is the list of built-in template actions +The scaffolder comes with several built-in actions for fetching content, +registering in the catalog and of course actions for creating and publishing a +git repository. -## `fetch:plain` +There are several repository providers supported out of the box such as GitHub, +Azure, GitLab and Bitbucket. -Downloads content and places it in the workspacePath or optionally in a -subdirectory specified by the `targetPath` input option. - -input: - -- `url` (required) Relative path or absolute URL pointing to the directory tree - to fetch. -- `targetPath` Target path within the working directory to download the contents - to. - -output: nothing - -## `fetch:cookiecutter` - -Downloads template from `url` and templates with cookiecutter - -input: - -- `url` (required) Relative path or absolute URL pointing to the directory tree - to fetch. -- `targetPath` Target path within the working directory to download the contents - to. -- `values` Values to pass on to cookiecutter for templating. - -output: nothing - -## `catalog:register` - -Registers entity in the software catalog. - -input: - -- `catalogInfoUrl` (required) An absolute URL pointing to the catalog info file - location. - -output: - -- `repoContentsUrl` An absolute URL pointing to the root of a repository - directory tree. -- `catalogInfoPath` A relative path from the repo root pointing to the catalog - info file, defaults to /catalog-info.yaml - -## `publish:github` - -Initializes a git repository of contents in workspacePath and publishes to -GitHub. - -input: - -- `repoUrl` (required) Repository location -- `repoVisibility` (optional, default: 'private') Possible values: 'private', - 'public' or 'internal'. - -output: - -- `remoteUrl` A URL to the repository with the provider -- `repoContentsUrl` A URL to the root of the repository - -## `publish:gitlab` - -Initializes a git repository of contents in workspacePath and publishes to -GitLab. - -input: - -- `repoUrl` (required) Repository location -- `repoVisibility` (optional, default: 'private') Possible values: 'private', - 'public' or 'internal'. - -output: - -- `remoteUrl` A URL to the repository with the provider -- `repoContentsUrl` A URL to the root of the repository - -## `publish:bitbucket` - -Initializes a git repository of contents in workspacePath and publishes to -Bitbucket. - -input: - -- `repoUrl` (required) Repository location -- `repoVisibility` (optional, default: 'private') Possible values: 'private', - 'public'. - -output: - -- `remoteUrl` A URL to the repository with the provider -- `repoContentsUrl` A URL to the root of the repository - -## `publish:azure` - -Initializes a git repository of contents in workspacePath and publishes to -Azure. - -input: - -- `repoUrl` (required) Repository location - -output: - -- `remoteUrl` A URL to the repository with the provider -- `repoContentsUrl` A URL to the root of the repository +A list of all registered actions can be found under `/create/actions`. For local +development you should be able to reach them at +`http://localhost:3000/create/actions`. From 4d4e0bdfb537a8c24513a99f349a76a850706b69 Mon Sep 17 00:00:00 2001 From: Johan Haals Date: Tue, 9 Mar 2021 13:54:41 +0100 Subject: [PATCH 21/27] Remove redundant header Signed-off-by: Johan Haals --- docs/features/software-templates/builtin-actions.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/docs/features/software-templates/builtin-actions.md b/docs/features/software-templates/builtin-actions.md index fc89e9fca6..14dc7ef861 100644 --- a/docs/features/software-templates/builtin-actions.md +++ b/docs/features/software-templates/builtin-actions.md @@ -4,8 +4,6 @@ title: Builtin actions description: Documentation describing the built-in template actions. --- -# Built-in Actions - The scaffolder comes with several built-in actions for fetching content, registering in the catalog and of course actions for creating and publishing a git repository. From 2e57922dead255a7f6d90d6d47c5fb642ad836d1 Mon Sep 17 00:00:00 2001 From: Johan Haals Date: Tue, 9 Mar 2021 14:58:14 +0100 Subject: [PATCH 22/27] scaffolder: Improve GitHub publishers permission update error message Signed-off-by: Johan Haals --- .changeset/wet-hounds-vanish.md | 5 +++ .../src/scaffolder/stages/publish/github.ts | 40 ++++++++++--------- 2 files changed, 27 insertions(+), 18 deletions(-) create mode 100644 .changeset/wet-hounds-vanish.md diff --git a/.changeset/wet-hounds-vanish.md b/.changeset/wet-hounds-vanish.md new file mode 100644 index 0000000000..1a74bfb08d --- /dev/null +++ b/.changeset/wet-hounds-vanish.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-scaffolder-backend': patch +--- + +Update GitHub publisher to display a more helpful error message when repository access update fails. diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/publish/github.ts b/plugins/scaffolder-backend/src/scaffolder/stages/publish/github.ts index a449eddd5d..22233ee5dc 100644 --- a/plugins/scaffolder-backend/src/scaffolder/stages/publish/github.ts +++ b/plugins/scaffolder-backend/src/scaffolder/stages/publish/github.ts @@ -131,25 +131,29 @@ export class GithubPublisher implements PublisherBase { const { data } = await repoCreationPromise; - 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 own's the personal account - } else if (access && access !== owner) { - await client.repos.addCollaborator({ - owner, - repo: name, - username: access, - permission: 'admin', - }); + 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 own's the personal account + } else if (access && access !== owner) { + await client.repos.addCollaborator({ + owner, + repo: name, + username: access, + permission: 'admin', + }); + } + } catch (e) { + e.message = `Failed to add access to '${access}': ${e.message}`; + throw e; } - return data?.clone_url; } } From 12cdd556e7648b59c2b6fa444a171cf67b110a75 Mon Sep 17 00:00:00 2001 From: Johan Haals Date: Tue, 9 Mar 2021 15:40:01 +0100 Subject: [PATCH 23/27] Update plugins/scaffolder-backend/src/scaffolder/stages/publish/github.ts Signed-off-by: Johan Haals johan.haals@gmail.com Co-authored-by: Adam Harvey Signed-off-by: Johan Haals --- .../scaffolder-backend/src/scaffolder/stages/publish/github.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/publish/github.ts b/plugins/scaffolder-backend/src/scaffolder/stages/publish/github.ts index 22233ee5dc..bc2537a766 100644 --- a/plugins/scaffolder-backend/src/scaffolder/stages/publish/github.ts +++ b/plugins/scaffolder-backend/src/scaffolder/stages/publish/github.ts @@ -141,7 +141,7 @@ export class GithubPublisher implements PublisherBase { repo: name, permission: 'admin', }); - // no need to add access if it's the person who own's the personal account + // 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, From 8e4999f6103af6a2863090b15b6a2aeb581841c9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 10 Mar 2021 10:18:59 +0000 Subject: [PATCH 24/27] chore(deps): bump elliptic from 6.5.3 to 6.5.4 Bumps [elliptic](https://github.com/indutny/elliptic) from 6.5.3 to 6.5.4. - [Release notes](https://github.com/indutny/elliptic/releases) - [Commits](https://github.com/indutny/elliptic/compare/v6.5.3...v6.5.4) Signed-off-by: dependabot[bot] --- yarn.lock | 49 ++++++++++++++++++++++--------------------------- 1 file changed, 22 insertions(+), 27 deletions(-) diff --git a/yarn.lock b/yarn.lock index 76af8b892b..306aae2542 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6505,11 +6505,6 @@ resolved "https://registry.npmjs.org/@types/node/-/node-14.14.32.tgz#90c5c4a8d72bbbfe53033f122341343249183448" integrity sha512-/Ctrftx/zp4m8JOujM5ZhwzlWLx22nbQJiVqz8/zE15gOeEW+uly3FSX4fGFpcfEvFzXcMCJwq9lGVWgyARXhg== -"@types/node@^14.14.32": - version "14.14.32" - resolved "https://registry.npmjs.org/@types/node/-/node-14.14.32.tgz#90c5c4a8d72bbbfe53033f122341343249183448" - integrity sha512-/Ctrftx/zp4m8JOujM5ZhwzlWLx22nbQJiVqz8/zE15gOeEW+uly3FSX4fGFpcfEvFzXcMCJwq9lGVWgyARXhg== - "@types/normalize-package-data@^2.4.0": version "2.4.0" resolved "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.0.tgz#e486d0d97396d79beedd0a6e33f4534ff6b4973e" @@ -8889,10 +8884,10 @@ bluebird@~3.4.1: resolved "https://registry.npmjs.org/bluebird/-/bluebird-3.4.7.tgz#f72d760be09b7f76d08ed8fae98b289a8d05fab3" integrity sha1-9y12C+Cbf3bQjtj66Ysomo0F+rM= -bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.1.1, bn.js@^4.4.0: - version "4.11.8" - resolved "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz#2cde09eb5ee341f484746bb0309b3253b1b1442f" - integrity sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA== +bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.1.1, bn.js@^4.11.9: + version "4.12.0" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.0.tgz#775b3f278efbb9718eec7361f483fb36fbbfea88" + integrity sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA== body-parser@1.19.0, body-parser@^1.18.3: version "1.19.0" @@ -8997,9 +8992,9 @@ breakword@^1.0.5: dependencies: wcwidth "^1.0.1" -brorand@^1.0.1: +brorand@^1.0.1, brorand@^1.1.0: version "1.1.0" - resolved "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" + resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" integrity sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8= browser-process-hrtime@^1.0.0: @@ -12067,17 +12062,17 @@ element-resize-detector@^1.2.1: batch-processor "1.0.0" elliptic@^6.0.0: - version "6.5.3" - resolved "https://registry.npmjs.org/elliptic/-/elliptic-6.5.3.tgz#cb59eb2efdaf73a0bd78ccd7015a62ad6e0f93d6" - integrity sha512-IMqzv5wNQf+E6aHeIqATs0tOLeOTwj1QKbRcS3jBbYkl5oLAserA8yJTT7/VyHUYG91PRmPyeQDObKLPpeS4dw== + version "6.5.4" + resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.4.tgz#da37cebd31e79a1367e941b592ed1fbebd58abbb" + integrity sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ== dependencies: - bn.js "^4.4.0" - brorand "^1.0.1" + bn.js "^4.11.9" + brorand "^1.1.0" hash.js "^1.0.0" - hmac-drbg "^1.0.0" - inherits "^2.0.1" - minimalistic-assert "^1.0.0" - minimalistic-crypto-utils "^1.0.0" + hmac-drbg "^1.0.1" + inherits "^2.0.4" + minimalistic-assert "^1.0.1" + minimalistic-crypto-utils "^1.0.1" emitter-component@^1.1.1: version "1.1.1" @@ -14678,7 +14673,7 @@ hash-stream-validation@^0.2.1, hash-stream-validation@^0.2.2: hash.js@^1.0.0, hash.js@^1.0.3: version "1.1.7" - resolved "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz#0babca538e8d4ee4a0f8988d68866537a003cf42" + resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.7.tgz#0babca538e8d4ee4a0f8988d68866537a003cf42" integrity sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA== dependencies: inherits "^2.0.3" @@ -14755,9 +14750,9 @@ history@^5.0.0: dependencies: "@babel/runtime" "^7.7.6" -hmac-drbg@^1.0.0: +hmac-drbg@^1.0.1: version "1.0.1" - resolved "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" + resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" integrity sha1-0nRXAQJabHdabFRXk+1QL8DGSaE= dependencies: hash.js "^1.0.3" @@ -15303,7 +15298,7 @@ inflight@^1.0.4: inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.0, inherits@~2.0.1, inherits@~2.0.3: version "2.0.4" - resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== inherits@2.0.1: @@ -18508,12 +18503,12 @@ mini-css-extract-plugin@^0.9.0: minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: version "1.0.1" - resolved "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" + resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== -minimalistic-crypto-utils@^1.0.0, minimalistic-crypto-utils@^1.0.1: +minimalistic-crypto-utils@^1.0.1: version "1.0.1" - resolved "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" + resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" integrity sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo= minimatch@0.3: From 3848bc1cfad06b7a97134a1ebb57d1e618895df2 Mon Sep 17 00:00:00 2001 From: Johan Haals Date: Wed, 10 Mar 2021 14:17:27 +0100 Subject: [PATCH 25/27] Throw error with status included Signed-off-by: Johan Haals --- .../src/scaffolder/stages/publish/github.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/plugins/scaffolder-backend/src/scaffolder/stages/publish/github.ts b/plugins/scaffolder-backend/src/scaffolder/stages/publish/github.ts index bc2537a766..d0bfc89529 100644 --- a/plugins/scaffolder-backend/src/scaffolder/stages/publish/github.ts +++ b/plugins/scaffolder-backend/src/scaffolder/stages/publish/github.ts @@ -151,8 +151,9 @@ export class GithubPublisher implements PublisherBase { }); } } catch (e) { - e.message = `Failed to add access to '${access}': ${e.message}`; - throw e; + throw new Error( + `Failed to add access to '${access}'. Status ${e.status} ${e.message}`, + ); } return data?.clone_url; } From 843078a5d69f06a5c82e093071f652cf2ab2e944 Mon Sep 17 00:00:00 2001 From: Johan Haals Date: Wed, 10 Mar 2021 14:29:17 +0100 Subject: [PATCH 26/27] Update description to be consistent Signed-off-by: Johan Haals --- .../src/scaffolder/actions/builtin/publish/bitbucket.ts | 2 +- .../src/scaffolder/actions/builtin/publish/github.ts | 2 +- .../src/scaffolder/actions/builtin/publish/gitlab.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) 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 63a0516712..03881af35d 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/bitbucket.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/bitbucket.ts @@ -168,7 +168,7 @@ export function createPublishBitbucketAction(options: { }>({ id: 'publish:bitbucket', description: - 'Initializes a git repository of the content in the workspace, and publishes to Bitbucket.', + 'Initializes a git repository of the content in the workspace, and publishes it to Bitbucket.', schema: { input: { type: 'object', 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 258f0625ca..cb11e3d08a 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/github.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/github.ts @@ -44,7 +44,7 @@ export function createPublishGithubAction(options: { }>({ id: 'publish:github', description: - 'Initializes a git repository of contents in workspacePath and publishes to GitHub.', + 'Initializes a git repository of contents in workspace and publishes it to GitHub.', schema: { input: { type: 'object', 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 4aad8589b8..eefdcdf11b 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/publish/gitlab.ts @@ -32,7 +32,7 @@ export function createPublishGitlabAction(options: { }>({ id: 'publish:gitlab', description: - 'Initializes a git repository of the content in the workspace, and publishes to GitLab.', + 'Initializes a git repository of the content in the workspace, and publishes it to GitLab.', schema: { input: { type: 'object', From be140d3b1d450be79f06d55919c285c0f6554159 Mon Sep 17 00:00:00 2001 From: Johan Haals Date: Wed, 10 Mar 2021 14:30:05 +0100 Subject: [PATCH 27/27] Use the same json-schema version as other plugins Signed-off-by: Johan Haals --- plugins/scaffolder/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/scaffolder/package.json b/plugins/scaffolder/package.json index d0dc0d70d7..48a4a2b5fb 100644 --- a/plugins/scaffolder/package.json +++ b/plugins/scaffolder/package.json @@ -43,7 +43,7 @@ "@rjsf/core": "^2.4.0", "@rjsf/material-ui": "^2.4.0", "classnames": "^2.2.6", - "json-schema": "^0.3.0", + "json-schema": "^0.2.5", "git-url-parse": "^11.4.4", "humanize-duration": "^3.25.1", "luxon": "^1.25.0",