@backstage/plugin-scaffolder 0.12.2-next.0 → 0.13.0
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 +109 -0
- package/dist/esm/{Router-5df57206.esm.js → Router-8ca04a51.esm.js} +44 -21
- package/dist/esm/Router-8ca04a51.esm.js.map +1 -0
- package/dist/esm/{index-71578268.esm.js → index-7ce19edf.esm.js} +89 -85
- package/dist/esm/index-7ce19edf.esm.js.map +1 -0
- package/dist/index.d.ts +111 -67
- package/dist/index.esm.js +2 -2
- package/package.json +33 -29
- package/dist/esm/Router-5df57206.esm.js.map +0 -1
- package/dist/esm/index-71578268.esm.js.map +0 -1
|
@@ -1,14 +1,14 @@
|
|
|
1
|
+
import { parseEntityRef, KubernetesValidatorFunctions, makeValidator, RELATION_OWNED_BY, stringifyEntityRef } from '@backstage/catalog-model';
|
|
1
2
|
import { createApiRef, useApi, attachComponentData, createExternalRouteRef, createRouteRef, createPlugin, createApiFactory, discoveryApiRef, fetchApiRef, createRoutableExtension, useRouteRef, alertApiRef, useApp } from '@backstage/core-plugin-api';
|
|
2
3
|
import { ResponseError } from '@backstage/errors';
|
|
3
4
|
import qs from 'qs';
|
|
4
5
|
import ObservableImpl from 'zen-observable';
|
|
5
|
-
import { catalogApiRef, formatEntityRefTitle, useOwnedEntities, useStarredEntity, getEntityRelations, getEntitySourceLocation, EntityRefLinks,
|
|
6
|
+
import { catalogApiRef, formatEntityRefTitle, useOwnedEntities, useStarredEntity, getEntityRelations, getEntitySourceLocation, EntityRefLinks, useEntityList, useEntityTypeFilter, entityRouteRef } from '@backstage/plugin-catalog-react';
|
|
6
7
|
import { TextField, FormControl as FormControl$1, withStyles, makeStyles, IconButton, Tooltip, useTheme, Card, CardMedia, CardContent, Box, Typography, Chip, CardActions, Link, FormControlLabel, Checkbox, Grid, StepButton, Paper, Button as Button$1, CircularProgress } from '@material-ui/core';
|
|
7
8
|
import FormControl from '@material-ui/core/FormControl';
|
|
8
9
|
import Autocomplete from '@material-ui/lab/Autocomplete';
|
|
9
10
|
import React, { useCallback, useEffect, useState, createContext, useContext, useMemo, memo } from 'react';
|
|
10
11
|
import useAsync from 'react-use/lib/useAsync';
|
|
11
|
-
import { KubernetesValidatorFunctions, makeValidator, RELATION_OWNED_BY, stringifyEntityRef, parseEntityName } from '@backstage/catalog-model';
|
|
12
12
|
import useEffectOnce from 'react-use/lib/useEffectOnce';
|
|
13
13
|
import { Autocomplete as Autocomplete$1 } from '@material-ui/lab';
|
|
14
14
|
import { scmIntegrationsApiRef, scmAuthApiRef, ScmIntegrationIcon } from '@backstage/integration-react';
|
|
@@ -52,15 +52,20 @@ class ScaffolderClient {
|
|
|
52
52
|
this.useLongPollingLogs = (_b = options.useLongPollingLogs) != null ? _b : false;
|
|
53
53
|
}
|
|
54
54
|
async getIntegrationsList(options) {
|
|
55
|
-
|
|
55
|
+
const integrations = [
|
|
56
56
|
...this.scmIntegrationsApi.azure.list(),
|
|
57
57
|
...this.scmIntegrationsApi.bitbucket.list(),
|
|
58
58
|
...this.scmIntegrationsApi.github.list(),
|
|
59
59
|
...this.scmIntegrationsApi.gitlab.list()
|
|
60
60
|
].map((c) => ({ type: c.type, title: c.title, host: c.config.host })).filter((c) => options.allowedHosts.includes(c.host));
|
|
61
|
+
return {
|
|
62
|
+
integrations
|
|
63
|
+
};
|
|
61
64
|
}
|
|
62
|
-
async getTemplateParameterSchema(
|
|
63
|
-
const { namespace, kind, name } =
|
|
65
|
+
async getTemplateParameterSchema(templateRef) {
|
|
66
|
+
const { namespace, kind, name } = parseEntityRef(templateRef, {
|
|
67
|
+
defaultKind: "template"
|
|
68
|
+
});
|
|
64
69
|
const baseUrl = await this.discoveryApi.getBaseUrl("scaffolder");
|
|
65
70
|
const templatePath = [namespace, kind, name].map((s) => encodeURIComponent(s)).join("/");
|
|
66
71
|
const url = `${baseUrl}/v2/templates/${templatePath}/parameter-schema`;
|
|
@@ -71,7 +76,8 @@ class ScaffolderClient {
|
|
|
71
76
|
const schema = await response.json();
|
|
72
77
|
return schema;
|
|
73
78
|
}
|
|
74
|
-
async scaffold(
|
|
79
|
+
async scaffold(options) {
|
|
80
|
+
const { templateRef, values, secrets = {} } = options;
|
|
75
81
|
const url = `${await this.discoveryApi.getBaseUrl("scaffolder")}/v2/tasks`;
|
|
76
82
|
const response = await this.fetchApi.fetch(url, {
|
|
77
83
|
method: "POST",
|
|
@@ -79,7 +85,7 @@ class ScaffolderClient {
|
|
|
79
85
|
"Content-Type": "application/json"
|
|
80
86
|
},
|
|
81
87
|
body: JSON.stringify({
|
|
82
|
-
|
|
88
|
+
templateRef,
|
|
83
89
|
values: { ...values },
|
|
84
90
|
secrets
|
|
85
91
|
})
|
|
@@ -90,7 +96,7 @@ class ScaffolderClient {
|
|
|
90
96
|
throw new Error(`Backend request failed, ${status} ${body.trim()}`);
|
|
91
97
|
}
|
|
92
98
|
const { id } = await response.json();
|
|
93
|
-
return id;
|
|
99
|
+
return { taskId: id };
|
|
94
100
|
}
|
|
95
101
|
async getTask(taskId) {
|
|
96
102
|
const baseUrl = await this.discoveryApi.getBaseUrl("scaffolder");
|
|
@@ -184,20 +190,17 @@ class ScaffolderClient {
|
|
|
184
190
|
}
|
|
185
191
|
}
|
|
186
192
|
|
|
187
|
-
const
|
|
188
|
-
var _a, _b;
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
idSchema
|
|
199
|
-
}) => {
|
|
200
|
-
var _a, _b;
|
|
193
|
+
const EntityPicker = (props) => {
|
|
194
|
+
var _a, _b, _c, _d;
|
|
195
|
+
const {
|
|
196
|
+
onChange,
|
|
197
|
+
schema: { title = "Entity", description = "An entity from the catalog" },
|
|
198
|
+
required,
|
|
199
|
+
uiSchema,
|
|
200
|
+
rawErrors,
|
|
201
|
+
formData,
|
|
202
|
+
idSchema
|
|
203
|
+
} = props;
|
|
201
204
|
const allowedKinds = (_a = uiSchema["ui:options"]) == null ? void 0 : _a.allowedKinds;
|
|
202
205
|
const defaultKind = (_b = uiSchema["ui:options"]) == null ? void 0 : _b.defaultKind;
|
|
203
206
|
const catalogApi = useApi(catalogApiRef);
|
|
@@ -223,7 +226,7 @@ const EntityPicker = ({
|
|
|
223
226
|
onChange: onSelect,
|
|
224
227
|
options: entityRefs || [],
|
|
225
228
|
autoSelect: true,
|
|
226
|
-
freeSolo:
|
|
229
|
+
freeSolo: (_d = (_c = uiSchema["ui:options"]) == null ? void 0 : _c.allowArbitraryValues) != null ? _d : true,
|
|
227
230
|
renderInput: (params) => /* @__PURE__ */ React.createElement(TextField, {
|
|
228
231
|
...params,
|
|
229
232
|
label: title,
|
|
@@ -236,35 +239,30 @@ const EntityPicker = ({
|
|
|
236
239
|
}));
|
|
237
240
|
};
|
|
238
241
|
|
|
239
|
-
const
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
...props
|
|
264
|
-
}) => /* @__PURE__ */ React.createElement(TextValuePicker, {
|
|
265
|
-
schema: { title, description },
|
|
266
|
-
...props
|
|
267
|
-
});
|
|
242
|
+
const EntityNamePicker = (props) => {
|
|
243
|
+
const {
|
|
244
|
+
onChange,
|
|
245
|
+
required,
|
|
246
|
+
schema: { title = "Name", description = "Unique name of the component" },
|
|
247
|
+
rawErrors,
|
|
248
|
+
formData,
|
|
249
|
+
uiSchema: { "ui:autofocus": autoFocus },
|
|
250
|
+
idSchema,
|
|
251
|
+
placeholder
|
|
252
|
+
} = props;
|
|
253
|
+
return /* @__PURE__ */ React.createElement(TextField, {
|
|
254
|
+
id: idSchema == null ? void 0 : idSchema.$id,
|
|
255
|
+
label: title,
|
|
256
|
+
placeholder,
|
|
257
|
+
helperText: description,
|
|
258
|
+
required,
|
|
259
|
+
value: formData != null ? formData : "",
|
|
260
|
+
onChange: ({ target: { value } }) => onChange(value),
|
|
261
|
+
margin: "normal",
|
|
262
|
+
error: (rawErrors == null ? void 0 : rawErrors.length) > 0 && !formData,
|
|
263
|
+
inputProps: { autoFocus }
|
|
264
|
+
});
|
|
265
|
+
};
|
|
268
266
|
|
|
269
267
|
const entityNamePickerValidation = (value, validation) => {
|
|
270
268
|
if (!KubernetesValidatorFunctions.isValidObjectName(value)) {
|
|
@@ -272,12 +270,9 @@ const entityNamePickerValidation = (value, validation) => {
|
|
|
272
270
|
}
|
|
273
271
|
};
|
|
274
272
|
|
|
275
|
-
const EntityTagsPicker = ({
|
|
276
|
-
formData,
|
|
277
|
-
onChange,
|
|
278
|
-
uiSchema
|
|
279
|
-
}) => {
|
|
273
|
+
const EntityTagsPicker = (props) => {
|
|
280
274
|
var _a;
|
|
275
|
+
const { formData, onChange, uiSchema } = props;
|
|
281
276
|
const catalogApi = useApi(catalogApiRef);
|
|
282
277
|
const [inputValue, setInputValue] = useState("");
|
|
283
278
|
const [inputError, setInputError] = useState(false);
|
|
@@ -334,12 +329,13 @@ const EntityTagsPicker = ({
|
|
|
334
329
|
}));
|
|
335
330
|
};
|
|
336
331
|
|
|
337
|
-
const OwnerPicker = ({
|
|
338
|
-
schema: { title = "Owner", description = "The owner of the component" },
|
|
339
|
-
uiSchema,
|
|
340
|
-
...props
|
|
341
|
-
}) => {
|
|
332
|
+
const OwnerPicker = (props) => {
|
|
342
333
|
var _a;
|
|
334
|
+
const {
|
|
335
|
+
schema: { title = "Owner", description = "The owner of the component" },
|
|
336
|
+
uiSchema,
|
|
337
|
+
...restProps
|
|
338
|
+
} = props;
|
|
343
339
|
const ownerUiSchema = {
|
|
344
340
|
...uiSchema,
|
|
345
341
|
"ui:options": {
|
|
@@ -351,7 +347,7 @@ const OwnerPicker = ({
|
|
|
351
347
|
}
|
|
352
348
|
};
|
|
353
349
|
return /* @__PURE__ */ React.createElement(EntityPicker, {
|
|
354
|
-
...
|
|
350
|
+
...restProps,
|
|
355
351
|
schema: { title, description },
|
|
356
352
|
uiSchema: ownerUiSchema
|
|
357
353
|
});
|
|
@@ -502,7 +498,7 @@ const BitbucketRepoPicker = (props) => {
|
|
|
502
498
|
const RepoUrlPickerHost = (props) => {
|
|
503
499
|
const { host, hosts, onChange, rawErrors } = props;
|
|
504
500
|
const scaffolderApi = useApi(scaffolderApiRef);
|
|
505
|
-
const { value: integrations, loading } = useAsync(async () => {
|
|
501
|
+
const { value: { integrations } = { integrations: [] }, loading } = useAsync(async () => {
|
|
506
502
|
return await scaffolderApi.getIntegrationsList({
|
|
507
503
|
allowedHosts: hosts != null ? hosts : []
|
|
508
504
|
});
|
|
@@ -700,16 +696,17 @@ const repoPickerValidation = (value, validation, context) => {
|
|
|
700
696
|
}
|
|
701
697
|
};
|
|
702
698
|
|
|
703
|
-
const OwnedEntityPicker = ({
|
|
704
|
-
onChange,
|
|
705
|
-
schema: { title = "Entity", description = "An entity from the catalog" },
|
|
706
|
-
required,
|
|
707
|
-
uiSchema,
|
|
708
|
-
rawErrors,
|
|
709
|
-
formData,
|
|
710
|
-
idSchema
|
|
711
|
-
}) => {
|
|
699
|
+
const OwnedEntityPicker = (props) => {
|
|
712
700
|
var _a, _b;
|
|
701
|
+
const {
|
|
702
|
+
onChange,
|
|
703
|
+
schema: { title = "Entity", description = "An entity from the catalog" },
|
|
704
|
+
required,
|
|
705
|
+
uiSchema,
|
|
706
|
+
rawErrors,
|
|
707
|
+
formData,
|
|
708
|
+
idSchema
|
|
709
|
+
} = props;
|
|
713
710
|
const allowedKinds = (_a = uiSchema["ui:options"]) == null ? void 0 : _a.allowedKinds;
|
|
714
711
|
const defaultKind = (_b = uiSchema["ui:options"]) == null ? void 0 : _b.defaultKind;
|
|
715
712
|
const { ownedEntities, loading } = useOwnedEntities(allowedKinds);
|
|
@@ -807,7 +804,7 @@ const OwnerPickerFieldExtension = scaffolderPlugin.provide(createScaffolderField
|
|
|
807
804
|
}));
|
|
808
805
|
const ScaffolderPage = scaffolderPlugin.provide(createRoutableExtension({
|
|
809
806
|
name: "ScaffolderPage",
|
|
810
|
-
component: () => import('./Router-
|
|
807
|
+
component: () => import('./Router-8ca04a51.esm.js').then((m) => m.Router),
|
|
811
808
|
mountPoint: rootRouteRef
|
|
812
809
|
}));
|
|
813
810
|
const OwnedEntityPickerFieldExtension = scaffolderPlugin.provide(createScaffolderFieldExtension({
|
|
@@ -906,13 +903,13 @@ const DeprecationWarning = () => {
|
|
|
906
903
|
const styles = useDeprecationStyles();
|
|
907
904
|
const Title = /* @__PURE__ */ React.createElement(Typography, {
|
|
908
905
|
style: { padding: 10, maxWidth: 300 }
|
|
909
|
-
}, "This template syntax
|
|
906
|
+
}, "This template uses a syntax that has been deprecated, and should be migrated to a newer syntax. Click for more info.");
|
|
910
907
|
return /* @__PURE__ */ React.createElement("div", {
|
|
911
908
|
className: styles.deprecationIcon
|
|
912
909
|
}, /* @__PURE__ */ React.createElement(Tooltip, {
|
|
913
910
|
title: Title
|
|
914
911
|
}, /* @__PURE__ */ React.createElement(Link, {
|
|
915
|
-
href: "https://backstage.io/docs/features/software-templates/migrating-from-
|
|
912
|
+
href: "https://backstage.io/docs/features/software-templates/migrating-from-v1beta2-to-v1beta3",
|
|
916
913
|
className: styles.link
|
|
917
914
|
}, /* @__PURE__ */ React.createElement(WarningIcon, null))));
|
|
918
915
|
};
|
|
@@ -976,7 +973,7 @@ const TemplateList = ({
|
|
|
976
973
|
TemplateCardComponent,
|
|
977
974
|
group
|
|
978
975
|
}) => {
|
|
979
|
-
const { loading, error, entities } =
|
|
976
|
+
const { loading, error, entities } = useEntityList();
|
|
980
977
|
const Card = TemplateCardComponent || TemplateCard;
|
|
981
978
|
const maybeFilteredEntities = group ? entities.filter((e) => group.filter(e)) : entities;
|
|
982
979
|
const title = group ? group.titleComponent || /* @__PURE__ */ React.createElement(ContentHeader, {
|
|
@@ -995,7 +992,8 @@ const TemplateList = ({
|
|
|
995
992
|
to: "https://backstage.io/docs/features/software-templates/adding-templates"
|
|
996
993
|
}, "adding templates"), "."), /* @__PURE__ */ React.createElement(Content, null, title, /* @__PURE__ */ React.createElement(ItemCardGrid, null, maybeFilteredEntities && (maybeFilteredEntities == null ? void 0 : maybeFilteredEntities.length) > 0 && maybeFilteredEntities.map((template) => /* @__PURE__ */ React.createElement(Card, {
|
|
997
994
|
key: stringifyEntityRef(template),
|
|
998
|
-
template
|
|
995
|
+
template,
|
|
996
|
+
deprecated: template.apiVersion === "backstage.io/v1beta2"
|
|
999
997
|
})))));
|
|
1000
998
|
};
|
|
1001
999
|
|
|
@@ -1223,7 +1221,7 @@ const TaskPageLinks = ({ output }) => {
|
|
|
1223
1221
|
pb: 3
|
|
1224
1222
|
}, links.filter(({ url, entityRef }) => url || entityRef).map(({ url, entityRef, title, icon }) => {
|
|
1225
1223
|
if (entityRef) {
|
|
1226
|
-
const entityName =
|
|
1224
|
+
const entityName = parseEntityRef(entityRef);
|
|
1227
1225
|
const target = entityRoute(entityName);
|
|
1228
1226
|
return { title, icon, url: target };
|
|
1229
1227
|
}
|
|
@@ -1357,7 +1355,11 @@ const TaskStatusStepper = memo(({
|
|
|
1357
1355
|
})))));
|
|
1358
1356
|
})));
|
|
1359
1357
|
});
|
|
1360
|
-
const hasLinks = ({
|
|
1358
|
+
const hasLinks = ({
|
|
1359
|
+
entityRef,
|
|
1360
|
+
remoteUrl,
|
|
1361
|
+
links = []
|
|
1362
|
+
}) => !!(entityRef || remoteUrl || links.length > 0);
|
|
1361
1363
|
const TaskPage = ({ loadingText }) => {
|
|
1362
1364
|
const classes = useStyles();
|
|
1363
1365
|
const navigate = useNavigate();
|
|
@@ -1400,15 +1402,17 @@ const TaskPage = ({ loadingText }) => {
|
|
|
1400
1402
|
const taskNotFound = taskStream.completed === true && taskStream.loading === false && !taskStream.task;
|
|
1401
1403
|
const { output } = taskStream;
|
|
1402
1404
|
const handleStartOver = () => {
|
|
1403
|
-
var _a, _b;
|
|
1404
|
-
if (!taskStream.task || !((_b = (_a = taskStream.task) == null ? void 0 : _a.spec.
|
|
1405
|
+
var _a, _b, _c;
|
|
1406
|
+
if (!taskStream.task || !((_b = (_a = taskStream.task) == null ? void 0 : _a.spec.templateInfo) == null ? void 0 : _b.entityRef)) {
|
|
1405
1407
|
navigate(generatePath(rootLink()));
|
|
1408
|
+
return;
|
|
1406
1409
|
}
|
|
1407
1410
|
const formData = taskStream.task.spec.apiVersion === "backstage.io/v1beta2" ? taskStream.task.spec.values : taskStream.task.spec.parameters;
|
|
1411
|
+
const { name } = parseEntityRef((_c = taskStream.task.spec.templateInfo) == null ? void 0 : _c.entityRef);
|
|
1408
1412
|
navigate(generatePath(`${rootLink()}/templates/:templateName?${qs.stringify({
|
|
1409
1413
|
formData: JSON.stringify(formData)
|
|
1410
1414
|
})}`, {
|
|
1411
|
-
templateName:
|
|
1415
|
+
templateName: name
|
|
1412
1416
|
}));
|
|
1413
1417
|
};
|
|
1414
1418
|
return /* @__PURE__ */ React.createElement(Page, {
|
|
@@ -1451,5 +1455,5 @@ const TaskPage = ({ loadingText }) => {
|
|
|
1451
1455
|
})))))));
|
|
1452
1456
|
};
|
|
1453
1457
|
|
|
1454
|
-
export { EntityPicker as E, FIELD_EXTENSION_WRAPPER_KEY as F, OwnerPicker as O, RepoUrlPicker as R, SecretsContext as S, TemplateTypePicker as T, EntityNamePicker as a, EntityTagsPicker as b, OwnedEntityPicker as c, registerComponentRouteRef as d, entityNamePickerValidation as e, TemplateList as f, rootRouteRef as g, FIELD_EXTENSION_KEY as h, SecretsContextProvider as i, TaskPage as j, ScaffolderClient as k, createScaffolderFieldExtension as l, ScaffolderFieldExtensions as m, EntityPickerFieldExtension as n, EntityNamePickerFieldExtension as o, EntityTagsPickerFieldExtension as p, OwnerPickerFieldExtension as q, repoPickerValidation as r, scaffolderApiRef as s, OwnedEntityPickerFieldExtension as t, RepoUrlPickerFieldExtension as u, ScaffolderPage as v, scaffolderPlugin as w,
|
|
1455
|
-
//# sourceMappingURL=index-
|
|
1458
|
+
export { EntityPicker as E, FIELD_EXTENSION_WRAPPER_KEY as F, OwnerPicker as O, RepoUrlPicker as R, SecretsContext as S, TemplateTypePicker as T, EntityNamePicker as a, EntityTagsPicker as b, OwnedEntityPicker as c, registerComponentRouteRef as d, entityNamePickerValidation as e, TemplateList as f, rootRouteRef as g, FIELD_EXTENSION_KEY as h, SecretsContextProvider as i, TaskPage as j, ScaffolderClient as k, createScaffolderFieldExtension as l, ScaffolderFieldExtensions as m, EntityPickerFieldExtension as n, EntityNamePickerFieldExtension as o, EntityTagsPickerFieldExtension as p, OwnerPickerFieldExtension as q, repoPickerValidation as r, scaffolderApiRef as s, OwnedEntityPickerFieldExtension as t, RepoUrlPickerFieldExtension as u, ScaffolderPage as v, scaffolderPlugin as w, FavouriteTemplate as x, useTemplateSecrets as y };
|
|
1459
|
+
//# sourceMappingURL=index-7ce19edf.esm.js.map
|