@backstage/plugin-scaffolder 1.3.0-next.2 → 1.4.0-next.1

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 CHANGED
@@ -1,5 +1,89 @@
1
1
  # @backstage/plugin-scaffolder
2
2
 
3
+ ## 1.4.0-next.1
4
+
5
+ ### Patch Changes
6
+
7
+ - Updated dependencies
8
+ - @backstage/core-components@0.9.6-next.1
9
+ - @backstage/catalog-model@1.1.0-next.1
10
+ - @backstage/errors@1.1.0-next.0
11
+ - @backstage/theme@0.2.16-next.0
12
+ - @backstage/catalog-client@1.0.4-next.1
13
+ - @backstage/integration@1.2.2-next.1
14
+ - @backstage/integration-react@1.1.2-next.1
15
+ - @backstage/plugin-catalog-common@1.0.4-next.0
16
+ - @backstage/plugin-catalog-react@1.1.2-next.1
17
+ - @backstage/plugin-permission-react@0.4.3-next.0
18
+
19
+ ## 1.4.0-next.0
20
+
21
+ ### Minor Changes
22
+
23
+ - 3500c13a33: A new template editor has been added which is accessible via the context menu on the top right hand corner of the Create page. It allows you to load a template from a local directory, edit it with a preview, execute it in dry-run mode, and view the results. Note that the [File System Access API](https://developer.mozilla.org/en-US/docs/Web/API/File_System_Access_API) must be supported by your browser for this to be available.
24
+
25
+ To support the new template editor the `ScaffolderApi` now has an optional `dryRun` method, which is implemented by the default `ScaffolderClient`.
26
+
27
+ ### Patch Changes
28
+
29
+ - 37539e29d8: The template editor now shows the cause of request errors that happen during a dry-run.
30
+ - 842282ecf9: Bumped `codemirror` dependencies to `v6.0.0`.
31
+ - 464bb0e6c8: The max content size for dry-run files has been reduced from 256k to 64k.
32
+ - a7c0b34d70: Swap usage of `MaterialTable` with `Table` from `core-components`
33
+ - Updated dependencies
34
+ - @backstage/catalog-model@1.1.0-next.0
35
+ - @backstage/core-components@0.9.6-next.0
36
+ - @backstage/integration@1.2.2-next.0
37
+ - @backstage/catalog-client@1.0.4-next.0
38
+ - @backstage/plugin-catalog-react@1.1.2-next.0
39
+ - @backstage/plugin-scaffolder-common@1.1.2-next.0
40
+ - @backstage/integration-react@1.1.2-next.0
41
+
42
+ ## 1.3.0
43
+
44
+ ### Minor Changes
45
+
46
+ - dc39366bdb: - Added a new page under `/create/tasks` to show tasks that have been run by the Scaffolder.
47
+ - Ability to filter these tasks by the signed in user, and all tasks.
48
+ - Added optional method to the `ScaffolderApi` interface called `listTasks` to get tasks with an required `filterByOwnership` parameter.
49
+ - 86a4a0f72d: Get data of other fields in Form from a custom field in template Scaffolder.
50
+ following:
51
+
52
+ ```tsx
53
+ const CustomFieldExtensionComponent = (props: FieldExtensionComponentProps<string[]>) => {
54
+ const { formData } = props.formContext;
55
+ ...
56
+ };
57
+
58
+ const CustomFieldExtension = scaffolderPlugin.provide(
59
+ createScaffolderFieldExtension({
60
+ name: ...,
61
+ component: CustomFieldExtensionComponent,
62
+ validation: ...
63
+ })
64
+ );
65
+ ```
66
+
67
+ - 72dfcbc8bf: Gerrit Integration: Implemented a `RepoUrlPicker` for Gerrit.
68
+ - f93af969cd: Added the ability to support running of templates that are not in the `default` namespace
69
+
70
+ ### Patch Changes
71
+
72
+ - ac0c7e45ee: Fixes review mask in `MultistepJsonForm` to work as documented. `show: true` no longer needed when mask is set.
73
+ - 8f7b1835df: Updated dependency `msw` to `^0.41.0`.
74
+ - fd505f40c0: Handle binary files and files that are too large during dry-run content upload.
75
+ - Updated dependencies
76
+ - @backstage/plugin-catalog-react@1.1.1
77
+ - @backstage/plugin-catalog-common@1.0.3
78
+ - @backstage/core-components@0.9.5
79
+ - @backstage/integration@1.2.1
80
+ - @backstage/catalog-client@1.0.3
81
+ - @backstage/core-plugin-api@1.0.3
82
+ - @backstage/integration-react@1.1.1
83
+ - @backstage/catalog-model@1.0.3
84
+ - @backstage/plugin-permission-react@0.4.2
85
+ - @backstage/plugin-scaffolder-common@1.1.1
86
+
3
87
  ## 1.3.0-next.2
4
88
 
5
89
  ### Minor Changes
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@backstage/plugin-scaffolder",
3
- "version": "1.3.0-next.2",
3
+ "version": "1.4.0-next.1",
4
4
  "main": "../dist/index.esm.js",
5
5
  "types": "../dist/index.alpha.d.ts"
6
6
  }
@@ -1,10 +1,10 @@
1
1
  import React, { useState, useContext, useCallback, createContext, useEffect, useRef, useMemo, Children, Component, Fragment } from 'react';
2
- import { useNavigate, Navigate, useOutlet, Routes, Route } from 'react-router';
3
- import { ItemCardHeader, MarkdownContent, Button, ContentHeader, Progress, WarningPanel, Link as Link$1, Content, ItemCardGrid, Page, Header, CreateButton, SupportButton, StructuredMetadataTable, InfoCard, ErrorPage, ErrorPanel, LogViewer, StatusError, StatusOK, StatusPending, Lifecycle, EmptyState } from '@backstage/core-components';
2
+ import { useNavigate, Navigate, useOutlet, Routes, Route, useParams as useParams$1 } from 'react-router';
3
+ import { ItemCardHeader, MarkdownContent, Button, ContentHeader, Progress, WarningPanel, Link as Link$1, Content, ItemCardGrid, Page, Header, CreateButton, SupportButton, StructuredMetadataTable, InfoCard, ErrorPage, ErrorPanel, LogViewer, StatusError, StatusOK, StatusPending, Lifecycle, EmptyState, Table as Table$1 } from '@backstage/core-components';
4
4
  import { useRouteRef, useApi, errorApiRef, featureFlagsApiRef, useApiHolder, alertApiRef, useElementFilter } from '@backstage/core-plugin-api';
5
5
  import { getEntityRelations, getEntitySourceLocation, FavoriteEntity, EntityRefLinks, useEntityList, EntityListProvider, CatalogFilterLayout, EntitySearchBar, EntityKindPicker, UserListPicker, EntityTagPicker, catalogApiRef, humanizeEntityRef, EntityRefLink } from '@backstage/plugin-catalog-react';
6
- import { s as selectedTemplateRouteRef, e as editRouteRef, a as actionsRouteRef, b as scaffolderListTaskRouteRef, r as registerComponentRouteRef, T as TemplateTypePicker, S as SecretsContext, c as scaffolderApiRef, d as scaffolderTaskRouteRef, f as rootRouteRef, g as TaskStatusStepper, h as TaskPageLinks, F as FIELD_EXTENSION_WRAPPER_KEY, i as FIELD_EXTENSION_KEY, j as SecretsContextProvider, k as TaskPage } from './index-b64713a1.esm.js';
7
- import { RELATION_OWNED_BY, stringifyEntityRef, parseEntityRef } from '@backstage/catalog-model';
6
+ import { s as selectedTemplateRouteRef, e as editRouteRef, a as actionsRouteRef, b as scaffolderListTaskRouteRef, r as registerComponentRouteRef, T as TemplateTypePicker, S as SecretsContext, c as scaffolderApiRef, d as scaffolderTaskRouteRef, f as rootRouteRef, g as TaskStatusStepper, h as TaskPageLinks, F as FIELD_EXTENSION_WRAPPER_KEY, i as FIELD_EXTENSION_KEY, l as legacySelectedTemplateRouteRef, j as SecretsContextProvider, k as TaskPage } from './index-470abc37.esm.js';
7
+ import { RELATION_OWNED_BY, parseEntityRef, stringifyEntityRef } from '@backstage/catalog-model';
8
8
  import { makeStyles, useTheme, Card, CardMedia, CardContent, Box, Typography, Chip, CardActions, IconButton, Tooltip, Link, Stepper, Step, StepLabel, StepContent, Button as Button$1, Paper, LinearProgress, TableContainer, Table, TableHead, TableRow, TableCell, TableBody, Divider as Divider$1, FormControl, InputLabel, Select, MenuItem as MenuItem$1, List as List$2, ListItemIcon as ListItemIcon$1, ListItemText as ListItemText$1 } from '@material-ui/core';
9
9
  import { scmIntegrationsApiRef, ScmIntegrationIcon } from '@backstage/integration-react';
10
10
  import WarningIcon from '@material-ui/icons/Warning';
@@ -62,12 +62,11 @@ import RefreshIcon from '@material-ui/icons/Refresh';
62
62
  import SaveIcon from '@material-ui/icons/Save';
63
63
  import useDebounce from 'react-use/lib/useDebounce';
64
64
  import { showPanel } from '@codemirror/view';
65
- import MaterialTable from '@material-table/core';
66
65
  import SettingsIcon from '@material-ui/icons/Settings';
67
66
  import AllIcon from '@material-ui/icons/FontDownload';
68
67
  import { DateTime, Interval } from 'luxon';
69
68
  import humanizeDuration from 'humanize-duration';
70
- import { D as DEFAULT_SCAFFOLDER_FIELD_EXTENSIONS } from './default-554cb9ad.esm.js';
69
+ import { D as DEFAULT_SCAFFOLDER_FIELD_EXTENSIONS } from './default-a3df1f11.esm.js';
71
70
  import '@backstage/errors';
72
71
  import 'zen-observable';
73
72
  import '@material-ui/core/FormControl';
@@ -169,7 +168,8 @@ const TemplateCard = ({ template, deprecated }) => {
169
168
  const themeId = backstageTheme.getPageTheme({ themeId: templateProps.type }) ? templateProps.type : "other";
170
169
  const theme = backstageTheme.getPageTheme({ themeId });
171
170
  const classes = useStyles$e({ backgroundImage: theme.backgroundImage });
172
- const href = templateRoute({ templateName: templateProps.name });
171
+ const { name, namespace } = parseEntityRef(stringifyEntityRef(template));
172
+ const href = templateRoute({ templateName: name, namespace });
173
173
  const scmIntegrationsApi = useApi(scmIntegrationsApiRef);
174
174
  const sourceLocation = getEntitySourceLocation(template, scmIntegrationsApi);
175
175
  return /* @__PURE__ */ React.createElement(Card, null, /* @__PURE__ */ React.createElement(CardMedia, {
@@ -671,11 +671,16 @@ const TemplatePage = ({
671
671
  const secretsContext = useContext(SecretsContext);
672
672
  const errorApi = useApi(errorApiRef);
673
673
  const scaffolderApi = useApi(scaffolderApiRef);
674
- const { templateName } = useParams();
674
+ const { templateName, namespace } = useParams();
675
+ const templateRef = stringifyEntityRef({
676
+ name: templateName,
677
+ kind: "template",
678
+ namespace
679
+ });
675
680
  const navigate = useNavigate();
676
681
  const scaffolderTaskRoute = useRouteRef(scaffolderTaskRouteRef);
677
682
  const rootRoute = useRouteRef(rootRouteRef);
678
- const { schema, loading, error } = useTemplateParameterSchema(templateName);
683
+ const { schema, loading, error } = useTemplateParameterSchema(templateRef);
679
684
  const [formState, setFormState] = useState(() => {
680
685
  var _a;
681
686
  const query = qs.parse(window.location.search, {
@@ -692,11 +697,7 @@ const TemplatePage = ({
692
697
  const handleCreate = async () => {
693
698
  var _a;
694
699
  const { taskId } = await scaffolderApi.scaffold({
695
- templateRef: stringifyEntityRef({
696
- name: templateName,
697
- kind: "template",
698
- namespace: "default"
699
- }),
700
+ templateRef,
700
701
  values: formState,
701
702
  secrets: secretsContext == null ? void 0 : secretsContext.secrets
702
703
  });
@@ -1147,8 +1148,8 @@ function DirectoryEditorProvider(props) {
1147
1148
  }, props.children);
1148
1149
  }
1149
1150
 
1150
- const MAX_CONTENT_SIZE = 256 * 1024;
1151
- const CHUNK_SIZE = 32768;
1151
+ const MAX_CONTENT_SIZE = 64 * 1024;
1152
+ const CHUNK_SIZE = 32 * 1024;
1152
1153
  const DryRunContext = createContext(void 0);
1153
1154
  function base64EncodeContent(content) {
1154
1155
  if (content.length > MAX_CONTENT_SIZE) {
@@ -1774,11 +1775,17 @@ function TemplateEditorFormDirectoryEditorDryRun(props) {
1774
1775
  if (!selectedFile) {
1775
1776
  return;
1776
1777
  }
1777
- await dryRun.execute({
1778
- templateContent: selectedFile.content,
1779
- values: data,
1780
- files: directoryEditor.files
1781
- });
1778
+ try {
1779
+ await dryRun.execute({
1780
+ templateContent: selectedFile.content,
1781
+ values: data,
1782
+ files: directoryEditor.files
1783
+ });
1784
+ setErrorText();
1785
+ } catch (e) {
1786
+ setErrorText(String(e.cause || e));
1787
+ throw e;
1788
+ }
1782
1789
  };
1783
1790
  const content = selectedFile && selectedFile.path.match(/\.ya?ml$/) ? selectedFile.content : void 0;
1784
1791
  return /* @__PURE__ */ React.createElement(TemplateEditorForm, {
@@ -2266,7 +2273,7 @@ const ListTaskPageContent = (props) => {
2266
2273
  return /* @__PURE__ */ React.createElement(CatalogFilterLayout, null, /* @__PURE__ */ React.createElement(CatalogFilterLayout.Filters, null, /* @__PURE__ */ React.createElement(OwnerListPicker, {
2267
2274
  filter: ownerFilter,
2268
2275
  onSelectOwner: (id) => setOwnerFilter(id)
2269
- })), /* @__PURE__ */ React.createElement(CatalogFilterLayout.Content, null, /* @__PURE__ */ React.createElement(MaterialTable, {
2276
+ })), /* @__PURE__ */ React.createElement(CatalogFilterLayout.Content, null, /* @__PURE__ */ React.createElement(Table$1, {
2270
2277
  data: (_a = value == null ? void 0 : value.tasks) != null ? _a : [],
2271
2278
  title: "Tasks",
2272
2279
  columns: [
@@ -2342,6 +2349,14 @@ const Router = (props) => {
2342
2349
  ...customFieldExtensions,
2343
2350
  ...DEFAULT_SCAFFOLDER_FIELD_EXTENSIONS.filter(({ name }) => !customFieldExtensions.some((customFieldExtension) => customFieldExtension.name === name))
2344
2351
  ];
2352
+ const RedirectingComponent = () => {
2353
+ const { templateName } = useParams$1();
2354
+ const newLink = useRouteRef(selectedTemplateRouteRef);
2355
+ useEffect(() => console.warn("The route /template/:templateName is deprecated, please use the new /template/:namespace/:templateName route instead"), []);
2356
+ return /* @__PURE__ */ React.createElement(Navigate, {
2357
+ to: newLink({ namespace: "default", templateName })
2358
+ });
2359
+ };
2345
2360
  return /* @__PURE__ */ React.createElement(Routes, null, /* @__PURE__ */ React.createElement(Route, {
2346
2361
  element: /* @__PURE__ */ React.createElement(ScaffolderPage, {
2347
2362
  groups,
@@ -2349,6 +2364,8 @@ const Router = (props) => {
2349
2364
  contextMenu: props.contextMenu
2350
2365
  })
2351
2366
  }), /* @__PURE__ */ React.createElement(Route, {
2367
+ path: legacySelectedTemplateRouteRef.path
2368
+ }, /* @__PURE__ */ React.createElement(RedirectingComponent, null)), /* @__PURE__ */ React.createElement(Route, {
2352
2369
  path: selectedTemplateRouteRef.path,
2353
2370
  element: /* @__PURE__ */ React.createElement(SecretsContextProvider, null, /* @__PURE__ */ React.createElement(TemplatePage, {
2354
2371
  customFieldExtensions: fieldExtensions
@@ -2377,4 +2394,4 @@ const Router = (props) => {
2377
2394
  };
2378
2395
 
2379
2396
  export { Router };
2380
- //# sourceMappingURL=Router-09b6a7c3.esm.js.map
2397
+ //# sourceMappingURL=Router-a85c58bd.esm.js.map