@backstage/plugin-scaffolder 0.11.13 → 0.11.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +14 -0
- package/dist/esm/{Router-8b2aa17e.esm.js → Router-0282e15a.esm.js} +46 -58
- package/dist/esm/{Router-8b2aa17e.esm.js.map → Router-0282e15a.esm.js.map} +1 -1
- package/dist/esm/{index-385b3fc1.esm.js → index-306a8b5a.esm.js} +62 -47
- package/dist/esm/index-306a8b5a.esm.js.map +1 -0
- package/dist/index.esm.js +1 -1
- package/package.json +15 -14
- package/dist/esm/index-385b3fc1.esm.js.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# @backstage/plugin-scaffolder
|
|
2
2
|
|
|
3
|
+
## 0.11.14
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 6845cce533: Can specify allowedOwners to the RepoUrlPicker picker in a template definition
|
|
8
|
+
- cd450844f6: Moved React dependencies to `peerDependencies` and allow both React v16 and v17 to be used.
|
|
9
|
+
- 2edcf7738f: Fix bug with setting owner in RepoUrlPicker causing validation failure
|
|
10
|
+
- b291c3176e: Switch to using `LogViewer` component from `@backstage/core-components` to display scaffolder logs.
|
|
11
|
+
- Updated dependencies
|
|
12
|
+
- @backstage/core-components@0.8.0
|
|
13
|
+
- @backstage/core-plugin-api@0.3.0
|
|
14
|
+
- @backstage/integration-react@0.1.15
|
|
15
|
+
- @backstage/plugin-catalog-react@0.6.5
|
|
16
|
+
|
|
3
17
|
## 0.11.13
|
|
4
18
|
|
|
5
19
|
### Patch Changes
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import React, { useState, useCallback, useEffect, memo,
|
|
1
|
+
import React, { useState, useCallback, useEffect, memo, useMemo } from 'react';
|
|
2
2
|
import { useNavigate, Navigate, generatePath, useParams as useParams$1, useOutlet, Routes, Route } from 'react-router';
|
|
3
|
-
import { Page, Header, Lifecycle, Content, ContentHeader, CreateButton, SupportButton, StructuredMetadataTable, InfoCard, Link,
|
|
3
|
+
import { Page, Header, Lifecycle, Content, ContentHeader, CreateButton, SupportButton, StructuredMetadataTable, InfoCard, Link, ErrorPage, LogViewer, Progress } from '@backstage/core-components';
|
|
4
4
|
import { useRouteRef, useApi, errorApiRef, useApiHolder, useApp, useElementFilter } from '@backstage/core-plugin-api';
|
|
5
5
|
import { EntityListProvider, EntitySearchBar, EntityKindPicker, UserListPicker, EntityTagPicker, entityRouteRef } from '@backstage/plugin-catalog-react';
|
|
6
6
|
import { makeStyles, Stepper, Step, StepLabel, Typography, StepContent, Button, Paper, Box, LinearProgress, Grid, StepButton, CircularProgress, TableContainer, Table, TableHead, TableRow, TableCell, TableBody } from '@material-ui/core';
|
|
7
|
-
import { E as EntityPicker, a as EntityNamePicker, e as entityNamePickerValidation, R as RepoUrlPicker, r as repoPickerValidation, O as OwnerPicker, b as registerComponentRouteRef, T as TemplateTypePicker, c as TemplateList, s as scaffolderApiRef, d as rootRouteRef, F as FIELD_EXTENSION_WRAPPER_KEY, f as FIELD_EXTENSION_KEY } from './index-
|
|
7
|
+
import { E as EntityPicker, a as EntityNamePicker, e as entityNamePickerValidation, R as RepoUrlPicker, r as repoPickerValidation, O as OwnerPicker, b as registerComponentRouteRef, T as TemplateTypePicker, c as TemplateList, s as scaffolderApiRef, d as rootRouteRef, F as FIELD_EXTENSION_WRAPPER_KEY, f as FIELD_EXTENSION_KEY } from './index-306a8b5a.esm.js';
|
|
8
8
|
import { useParams } from 'react-router-dom';
|
|
9
9
|
import { useAsync, useInterval } from 'react-use';
|
|
10
10
|
import { withTheme } from '@rjsf/core';
|
|
@@ -128,7 +128,7 @@ function extractUiSchema(schema, uiSchema) {
|
|
|
128
128
|
if (!isObject$1(schema)) {
|
|
129
129
|
return;
|
|
130
130
|
}
|
|
131
|
-
const {properties, items, anyOf, oneOf, allOf, dependencies} = schema;
|
|
131
|
+
const { properties, items, anyOf, oneOf, allOf, dependencies } = schema;
|
|
132
132
|
for (const propName in schema) {
|
|
133
133
|
if (!schema.hasOwnProperty(propName)) {
|
|
134
134
|
continue;
|
|
@@ -197,7 +197,7 @@ function transformSchemaToProps(inputSchema) {
|
|
|
197
197
|
delete schema.title;
|
|
198
198
|
const uiSchema = {};
|
|
199
199
|
extractUiSchema(schema, uiSchema);
|
|
200
|
-
return {schema, uiSchema};
|
|
200
|
+
return { schema, uiSchema };
|
|
201
201
|
}
|
|
202
202
|
|
|
203
203
|
const Form = withTheme(Theme);
|
|
@@ -278,7 +278,7 @@ const MultistepJsonForm = ({
|
|
|
278
278
|
return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(Stepper, {
|
|
279
279
|
activeStep,
|
|
280
280
|
orientation: "vertical"
|
|
281
|
-
}, steps.map(({title, schema, ...formProps}, index) => {
|
|
281
|
+
}, steps.map(({ title, schema, ...formProps }, index) => {
|
|
282
282
|
return /* @__PURE__ */ React.createElement(Step, {
|
|
283
283
|
key: title
|
|
284
284
|
}, /* @__PURE__ */ React.createElement(StepLabel, {
|
|
@@ -337,12 +337,12 @@ const MultistepJsonForm = ({
|
|
|
337
337
|
|
|
338
338
|
const useTemplateParameterSchema = (templateName) => {
|
|
339
339
|
const scaffolderApi = useApi(scaffolderApiRef);
|
|
340
|
-
const {value, loading, error} = useAsync(() => scaffolderApi.getTemplateParameterSchema({
|
|
340
|
+
const { value, loading, error } = useAsync(() => scaffolderApi.getTemplateParameterSchema({
|
|
341
341
|
name: templateName,
|
|
342
342
|
kind: "template",
|
|
343
343
|
namespace: "default"
|
|
344
344
|
}), [scaffolderApi, templateName]);
|
|
345
|
-
return {schema: value, loading, error};
|
|
345
|
+
return { schema: value, loading, error };
|
|
346
346
|
};
|
|
347
347
|
function isObject(obj) {
|
|
348
348
|
return typeof obj === "object" && obj !== null && !Array.isArray(obj);
|
|
@@ -380,16 +380,16 @@ const TemplatePage = ({
|
|
|
380
380
|
const apiHolder = useApiHolder();
|
|
381
381
|
const errorApi = useApi(errorApiRef);
|
|
382
382
|
const scaffolderApi = useApi(scaffolderApiRef);
|
|
383
|
-
const {templateName} = useParams();
|
|
383
|
+
const { templateName } = useParams();
|
|
384
384
|
const navigate = useNavigate();
|
|
385
385
|
const rootLink = useRouteRef(rootRouteRef);
|
|
386
|
-
const {schema, loading, error} = useTemplateParameterSchema(templateName);
|
|
386
|
+
const { schema, loading, error } = useTemplateParameterSchema(templateName);
|
|
387
387
|
const [formState, setFormState] = useState({});
|
|
388
388
|
const handleFormReset = () => setFormState({});
|
|
389
389
|
const handleChange = useCallback((e) => setFormState(e.formData), [setFormState]);
|
|
390
390
|
const handleCreate = async () => {
|
|
391
391
|
const id = await scaffolderApi.scaffold(templateName, formState);
|
|
392
|
-
navigate(generatePath(`${rootLink()}/tasks/:taskId`, {taskId: id}));
|
|
392
|
+
navigate(generatePath(`${rootLink()}/tasks/:taskId`, { taskId: id }));
|
|
393
393
|
};
|
|
394
394
|
if (error) {
|
|
395
395
|
errorApi.post(new Error(`Failed to load template, ${error}`));
|
|
@@ -403,8 +403,8 @@ const TemplatePage = ({
|
|
|
403
403
|
to: rootLink()
|
|
404
404
|
});
|
|
405
405
|
}
|
|
406
|
-
const customFieldComponents = Object.fromEntries(customFieldExtensions.map(({name, component}) => [name, component]));
|
|
407
|
-
const customFieldValidators = Object.fromEntries(customFieldExtensions.map(({name, validation}) => [name, validation]));
|
|
406
|
+
const customFieldComponents = Object.fromEntries(customFieldExtensions.map(({ name, component }) => [name, component]));
|
|
407
|
+
const customFieldValidators = Object.fromEntries(customFieldExtensions.map(({ name, validation }) => [name, validation]));
|
|
408
408
|
return /* @__PURE__ */ React.createElement(Page, {
|
|
409
409
|
themeId: "home"
|
|
410
410
|
}, /* @__PURE__ */ React.createElement(Header, {
|
|
@@ -418,7 +418,7 @@ const TemplatePage = ({
|
|
|
418
418
|
}), schema && /* @__PURE__ */ React.createElement(InfoCard, {
|
|
419
419
|
title: schema.title,
|
|
420
420
|
noPadding: true,
|
|
421
|
-
titleTypographyProps: {component: "h2"}
|
|
421
|
+
titleTypographyProps: { component: "h2" }
|
|
422
422
|
}, /* @__PURE__ */ React.createElement(MultistepJsonForm, {
|
|
423
423
|
formData: formState,
|
|
424
424
|
fields: customFieldComponents,
|
|
@@ -428,7 +428,7 @@ const TemplatePage = ({
|
|
|
428
428
|
steps: schema.steps.map((step) => {
|
|
429
429
|
return {
|
|
430
430
|
...step,
|
|
431
|
-
validate: createValidator(step.schema, customFieldValidators, {apiHolder})
|
|
431
|
+
validate: createValidator(step.schema, customFieldValidators, { apiHolder })
|
|
432
432
|
};
|
|
433
433
|
})
|
|
434
434
|
}))));
|
|
@@ -439,7 +439,7 @@ function reducer(draft, action) {
|
|
|
439
439
|
switch (action.type) {
|
|
440
440
|
case "INIT": {
|
|
441
441
|
draft.steps = action.data.spec.steps.reduce((current, next) => {
|
|
442
|
-
current[next.id] = {status: "open", id: next.id};
|
|
442
|
+
current[next.id] = { status: "open", id: next.id };
|
|
443
443
|
return current;
|
|
444
444
|
}, {});
|
|
445
445
|
draft.stepLogs = action.data.spec.steps.reduce((current, next) => {
|
|
@@ -505,13 +505,13 @@ const useTaskEventStream = (taskId) => {
|
|
|
505
505
|
if (didCancel) {
|
|
506
506
|
return;
|
|
507
507
|
}
|
|
508
|
-
dispatch({type: "INIT", data: task});
|
|
509
|
-
const observable = scaffolderApi.streamLogs({taskId});
|
|
508
|
+
dispatch({ type: "INIT", data: task });
|
|
509
|
+
const observable = scaffolderApi.streamLogs({ taskId });
|
|
510
510
|
const collectedLogEvents = new Array();
|
|
511
511
|
function emitLogs() {
|
|
512
512
|
if (collectedLogEvents.length) {
|
|
513
513
|
const logs = collectedLogEvents.splice(0, collectedLogEvents.length);
|
|
514
|
-
dispatch({type: "LOGS", data: logs});
|
|
514
|
+
dispatch({ type: "LOGS", data: logs });
|
|
515
515
|
}
|
|
516
516
|
}
|
|
517
517
|
logPusher = setInterval(emitLogs, 500);
|
|
@@ -522,7 +522,7 @@ const useTaskEventStream = (taskId) => {
|
|
|
522
522
|
return collectedLogEvents.push(event);
|
|
523
523
|
case "completion":
|
|
524
524
|
emitLogs();
|
|
525
|
-
dispatch({type: "COMPLETED", data: event});
|
|
525
|
+
dispatch({ type: "COMPLETED", data: event });
|
|
526
526
|
return void 0;
|
|
527
527
|
default:
|
|
528
528
|
throw new Error(`Unhandled event type ${event.type} in observer`);
|
|
@@ -530,12 +530,12 @@ const useTaskEventStream = (taskId) => {
|
|
|
530
530
|
},
|
|
531
531
|
error: (error) => {
|
|
532
532
|
emitLogs();
|
|
533
|
-
dispatch({type: "ERROR", data: error});
|
|
533
|
+
dispatch({ type: "ERROR", data: error });
|
|
534
534
|
}
|
|
535
535
|
});
|
|
536
536
|
}, (error) => {
|
|
537
537
|
if (!didCancel) {
|
|
538
|
-
dispatch({type: "ERROR", data: error});
|
|
538
|
+
dispatch({ type: "ERROR", data: error });
|
|
539
539
|
}
|
|
540
540
|
});
|
|
541
541
|
return () => {
|
|
@@ -562,7 +562,7 @@ const useStyles$2 = makeStyles({
|
|
|
562
562
|
}
|
|
563
563
|
});
|
|
564
564
|
const IconLink = (props) => {
|
|
565
|
-
const {href, text, Icon, ...linkProps} = props;
|
|
565
|
+
const { href, text, Icon, ...linkProps } = props;
|
|
566
566
|
const classes = useStyles$2();
|
|
567
567
|
return /* @__PURE__ */ React.createElement(Grid, {
|
|
568
568
|
container: true,
|
|
@@ -581,9 +581,9 @@ const IconLink = (props) => {
|
|
|
581
581
|
}, text || href)));
|
|
582
582
|
};
|
|
583
583
|
|
|
584
|
-
const TaskPageLinks = ({output}) => {
|
|
585
|
-
const {entityRef: entityRefOutput, remoteUrl} = output;
|
|
586
|
-
let {links = []} = output;
|
|
584
|
+
const TaskPageLinks = ({ output }) => {
|
|
585
|
+
const { entityRef: entityRefOutput, remoteUrl } = output;
|
|
586
|
+
let { links = [] } = output;
|
|
587
587
|
const app = useApp();
|
|
588
588
|
const entityRoute = useRouteRef(entityRouteRef);
|
|
589
589
|
const iconResolver = (key) => {
|
|
@@ -591,7 +591,7 @@ const TaskPageLinks = ({output}) => {
|
|
|
591
591
|
return key ? (_a = app.getSystemIcon(key)) != null ? _a : LanguageIcon : LanguageIcon;
|
|
592
592
|
};
|
|
593
593
|
if (remoteUrl) {
|
|
594
|
-
links = [{url: remoteUrl, title: "Repo"}, ...links];
|
|
594
|
+
links = [{ url: remoteUrl, title: "Repo" }, ...links];
|
|
595
595
|
}
|
|
596
596
|
if (entityRefOutput) {
|
|
597
597
|
links = [
|
|
@@ -606,14 +606,14 @@ const TaskPageLinks = ({output}) => {
|
|
|
606
606
|
return /* @__PURE__ */ React.createElement(Box, {
|
|
607
607
|
px: 3,
|
|
608
608
|
pb: 3
|
|
609
|
-
}, links.filter(({url, entityRef}) => url || entityRef).map(({url, entityRef, title, icon}) => {
|
|
609
|
+
}, links.filter(({ url, entityRef }) => url || entityRef).map(({ url, entityRef, title, icon }) => {
|
|
610
610
|
if (entityRef) {
|
|
611
611
|
const entityName = parseEntityName(entityRef);
|
|
612
612
|
const target = entityRoute(entityName);
|
|
613
|
-
return {title, icon, url: target};
|
|
613
|
+
return { title, icon, url: target };
|
|
614
614
|
}
|
|
615
|
-
return {title, icon, url};
|
|
616
|
-
}).map(({url, title, icon}, i) => /* @__PURE__ */ React.createElement(IconLink, {
|
|
615
|
+
return { title, icon, url };
|
|
616
|
+
}).map(({ url, title, icon }, i) => /* @__PURE__ */ React.createElement(IconLink, {
|
|
617
617
|
key: `output-link-${i}`,
|
|
618
618
|
href: url,
|
|
619
619
|
text: title != null ? title : url,
|
|
@@ -622,7 +622,6 @@ const TaskPageLinks = ({output}) => {
|
|
|
622
622
|
})));
|
|
623
623
|
};
|
|
624
624
|
|
|
625
|
-
const LazyLog = React.lazy(() => import('react-lazylog/build/LazyLog'));
|
|
626
625
|
const humanizeDuration = require("humanize-duration");
|
|
627
626
|
const useStyles$1 = makeStyles$1((theme) => createStyles({
|
|
628
627
|
root: {
|
|
@@ -648,7 +647,7 @@ const useStyles$1 = makeStyles$1((theme) => createStyles({
|
|
|
648
647
|
width: "100%"
|
|
649
648
|
}
|
|
650
649
|
}));
|
|
651
|
-
const StepTimeTicker = ({step}) => {
|
|
650
|
+
const StepTimeTicker = ({ step }) => {
|
|
652
651
|
const [time, setTime] = useState("");
|
|
653
652
|
useInterval(() => {
|
|
654
653
|
if (!step.startedAt) {
|
|
@@ -658,7 +657,7 @@ const StepTimeTicker = ({step}) => {
|
|
|
658
657
|
const end = step.endedAt ? DateTime.fromISO(step.endedAt) : DateTime.local();
|
|
659
658
|
const startedAt = DateTime.fromISO(step.startedAt);
|
|
660
659
|
const formatted = Interval.fromDateTimes(startedAt, end).toDuration().valueOf();
|
|
661
|
-
setTime(humanizeDuration(formatted, {round: true}));
|
|
660
|
+
setTime(humanizeDuration(formatted, { round: true }));
|
|
662
661
|
}, 1e3);
|
|
663
662
|
return /* @__PURE__ */ React.createElement(Typography$1, {
|
|
664
663
|
variant: "caption"
|
|
@@ -680,7 +679,7 @@ const useStepIconStyles = makeStyles$1((theme) => createStyles({
|
|
|
680
679
|
}));
|
|
681
680
|
function TaskStepIconComponent(props) {
|
|
682
681
|
const classes = useStepIconStyles();
|
|
683
|
-
const {active, completed, error} = props;
|
|
682
|
+
const { active, completed, error } = props;
|
|
684
683
|
const getMiddle = () => {
|
|
685
684
|
if (active) {
|
|
686
685
|
return /* @__PURE__ */ React.createElement(CircularProgress, {
|
|
@@ -743,24 +742,11 @@ const TaskStatusStepper = memo(({
|
|
|
743
742
|
})))));
|
|
744
743
|
})));
|
|
745
744
|
});
|
|
746
|
-
const
|
|
747
|
-
return /* @__PURE__ */ React.createElement(Suspense, {
|
|
748
|
-
fallback: /* @__PURE__ */ React.createElement(Progress, null)
|
|
749
|
-
}, /* @__PURE__ */ React.createElement("div", {
|
|
750
|
-
style: {height: "80vh"}
|
|
751
|
-
}, /* @__PURE__ */ React.createElement(LazyLog, {
|
|
752
|
-
text: log,
|
|
753
|
-
extraLines: 1,
|
|
754
|
-
follow: true,
|
|
755
|
-
selectableLines: true,
|
|
756
|
-
enableSearch: true
|
|
757
|
-
})));
|
|
758
|
-
});
|
|
759
|
-
const hasLinks = ({entityRef, remoteUrl, links = []}) => !!(entityRef || remoteUrl || links.length > 0);
|
|
745
|
+
const hasLinks = ({ entityRef, remoteUrl, links = [] }) => !!(entityRef || remoteUrl || links.length > 0);
|
|
760
746
|
const TaskPage = () => {
|
|
761
747
|
const [userSelectedStepId, setUserSelectedStepId] = useState(void 0);
|
|
762
748
|
const [lastActiveStepId, setLastActiveStepId] = useState(void 0);
|
|
763
|
-
const {taskId} = useParams$1();
|
|
749
|
+
const { taskId } = useParams$1();
|
|
764
750
|
const taskStream = useTaskEventStream(taskId);
|
|
765
751
|
const completed = taskStream.completed;
|
|
766
752
|
const steps = useMemo(() => {
|
|
@@ -794,7 +780,7 @@ const TaskPage = () => {
|
|
|
794
780
|
return log.join("\n");
|
|
795
781
|
}, [taskStream.stepLogs, currentStepId]);
|
|
796
782
|
const taskNotFound = taskStream.completed === true && taskStream.loading === false && !taskStream.task;
|
|
797
|
-
const {output} = taskStream;
|
|
783
|
+
const { output } = taskStream;
|
|
798
784
|
return /* @__PURE__ */ React.createElement(Page, {
|
|
799
785
|
themeId: "home"
|
|
800
786
|
}, /* @__PURE__ */ React.createElement(Header, {
|
|
@@ -822,9 +808,11 @@ const TaskPage = () => {
|
|
|
822
808
|
}))), /* @__PURE__ */ React.createElement(Grid$1, {
|
|
823
809
|
item: true,
|
|
824
810
|
xs: 9
|
|
825
|
-
}, /* @__PURE__ */ React.createElement(
|
|
826
|
-
|
|
827
|
-
}
|
|
811
|
+
}, /* @__PURE__ */ React.createElement("div", {
|
|
812
|
+
style: { height: "80vh" }
|
|
813
|
+
}, /* @__PURE__ */ React.createElement(LogViewer, {
|
|
814
|
+
text: logAsString
|
|
815
|
+
})))))));
|
|
828
816
|
};
|
|
829
817
|
|
|
830
818
|
const useStyles = makeStyles((theme) => ({
|
|
@@ -851,7 +839,7 @@ const useStyles = makeStyles((theme) => ({
|
|
|
851
839
|
const ActionsPage = () => {
|
|
852
840
|
const api = useApi(scaffolderApiRef);
|
|
853
841
|
const classes = useStyles();
|
|
854
|
-
const {loading, value, error} = useAsync(async () => {
|
|
842
|
+
const { loading, value, error } = useAsync(async () => {
|
|
855
843
|
return api.listActions();
|
|
856
844
|
});
|
|
857
845
|
if (loading) {
|
|
@@ -935,7 +923,7 @@ const ActionsPage = () => {
|
|
|
935
923
|
}), /* @__PURE__ */ React.createElement(Content, null, items));
|
|
936
924
|
};
|
|
937
925
|
|
|
938
|
-
const Router = ({TemplateCardComponent, groups}) => {
|
|
926
|
+
const Router = ({ TemplateCardComponent, groups }) => {
|
|
939
927
|
const outlet = useOutlet();
|
|
940
928
|
const customFieldExtensions = useElementFilter(outlet, (elements) => elements.selectByComponentData({
|
|
941
929
|
key: FIELD_EXTENSION_WRAPPER_KEY
|
|
@@ -944,7 +932,7 @@ const Router = ({TemplateCardComponent, groups}) => {
|
|
|
944
932
|
}));
|
|
945
933
|
const fieldExtensions = [
|
|
946
934
|
...customFieldExtensions,
|
|
947
|
-
...DEFAULT_SCAFFOLDER_FIELD_EXTENSIONS.filter(({name}) => !customFieldExtensions.some((customFieldExtension) => customFieldExtension.name === name))
|
|
935
|
+
...DEFAULT_SCAFFOLDER_FIELD_EXTENSIONS.filter(({ name }) => !customFieldExtensions.some((customFieldExtension) => customFieldExtension.name === name))
|
|
948
936
|
];
|
|
949
937
|
return /* @__PURE__ */ React.createElement(Routes, null, /* @__PURE__ */ React.createElement(Route, {
|
|
950
938
|
path: "/",
|
|
@@ -967,4 +955,4 @@ const Router = ({TemplateCardComponent, groups}) => {
|
|
|
967
955
|
};
|
|
968
956
|
|
|
969
957
|
export { Router };
|
|
970
|
-
//# sourceMappingURL=Router-
|
|
958
|
+
//# sourceMappingURL=Router-0282e15a.esm.js.map
|