@backstage/plugin-scaffolder 1.4.0 → 1.5.0-next.2
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 +35 -0
- package/alpha/package.json +1 -1
- package/dist/esm/{Router-e14e5f4e.esm.js → Router-fa1fcf0c.esm.js} +289 -175
- package/dist/esm/{Router-e14e5f4e.esm.js.map → Router-fa1fcf0c.esm.js.map} +1 -1
- package/dist/esm/{default-ffab2851.esm.js → default-2a48fcb0.esm.js} +2 -2
- package/dist/esm/{default-ffab2851.esm.js.map → default-2a48fcb0.esm.js.map} +1 -1
- package/dist/esm/{index-a298f509.esm.js → index-3b171258.esm.js} +388 -265
- package/dist/esm/index-3b171258.esm.js.map +1 -0
- package/dist/esm/{index-8dd91f94.esm.js → index-bdece754.esm.js} +290 -51
- package/dist/esm/index-bdece754.esm.js.map +1 -0
- package/dist/index.alpha.d.ts +3 -1
- package/dist/index.beta.d.ts +3 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.esm.js +1 -1
- package/package.json +14 -14
- package/dist/esm/index-8dd91f94.esm.js.map +0 -1
- package/dist/esm/index-a298f509.esm.js.map +0 -1
|
@@ -51,11 +51,15 @@ class ScaffolderClient {
|
|
|
51
51
|
}
|
|
52
52
|
async listTasks(options) {
|
|
53
53
|
if (!this.identityApi) {
|
|
54
|
-
throw new Error(
|
|
54
|
+
throw new Error(
|
|
55
|
+
"IdentityApi is not available in the ScaffolderClient, please pass through the IdentityApi to the ScaffolderClient constructor in order to use the listTasks method"
|
|
56
|
+
);
|
|
55
57
|
}
|
|
56
58
|
const baseUrl = await this.discoveryApi.getBaseUrl("scaffolder");
|
|
57
59
|
const { userEntityRef } = await this.identityApi.getBackstageIdentity();
|
|
58
|
-
const query = qs.stringify(
|
|
60
|
+
const query = qs.stringify(
|
|
61
|
+
options.filterByOwnership === "owned" ? { createdBy: userEntityRef } : {}
|
|
62
|
+
);
|
|
59
63
|
const response = await this.fetchApi.fetch(`${baseUrl}/v2/tasks?${query}`);
|
|
60
64
|
if (!response.ok) {
|
|
61
65
|
throw await ResponseError.fromResponse(response);
|
|
@@ -65,7 +69,9 @@ class ScaffolderClient {
|
|
|
65
69
|
async getIntegrationsList(options) {
|
|
66
70
|
const integrations = [
|
|
67
71
|
...this.scmIntegrationsApi.azure.list(),
|
|
68
|
-
...this.scmIntegrationsApi.bitbucket.list().filter(
|
|
72
|
+
...this.scmIntegrationsApi.bitbucket.list().filter(
|
|
73
|
+
(item) => !this.scmIntegrationsApi.bitbucketCloud.byHost(item.config.host) && !this.scmIntegrationsApi.bitbucketServer.byHost(item.config.host)
|
|
74
|
+
),
|
|
69
75
|
...this.scmIntegrationsApi.bitbucketCloud.list(),
|
|
70
76
|
...this.scmIntegrationsApi.bitbucketServer.list(),
|
|
71
77
|
...this.scmIntegrationsApi.gerrit.list(),
|
|
@@ -155,35 +161,40 @@ class ScaffolderClient {
|
|
|
155
161
|
if (after !== void 0) {
|
|
156
162
|
params.set("after", String(Number(after)));
|
|
157
163
|
}
|
|
158
|
-
this.discoveryApi.getBaseUrl("scaffolder").then(
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
164
|
+
this.discoveryApi.getBaseUrl("scaffolder").then(
|
|
165
|
+
(baseUrl) => {
|
|
166
|
+
const url = `${baseUrl}/v2/tasks/${encodeURIComponent(
|
|
167
|
+
taskId
|
|
168
|
+
)}/eventstream`;
|
|
169
|
+
const eventSource = new EventSource(url, { withCredentials: true });
|
|
170
|
+
eventSource.addEventListener("log", (event) => {
|
|
171
|
+
if (event.data) {
|
|
172
|
+
try {
|
|
173
|
+
subscriber.next(JSON.parse(event.data));
|
|
174
|
+
} catch (ex) {
|
|
175
|
+
subscriber.error(ex);
|
|
176
|
+
}
|
|
167
177
|
}
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
178
|
+
});
|
|
179
|
+
eventSource.addEventListener("completion", (event) => {
|
|
180
|
+
if (event.data) {
|
|
181
|
+
try {
|
|
182
|
+
subscriber.next(JSON.parse(event.data));
|
|
183
|
+
} catch (ex) {
|
|
184
|
+
subscriber.error(ex);
|
|
185
|
+
}
|
|
176
186
|
}
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
+
eventSource.close();
|
|
188
|
+
subscriber.complete();
|
|
189
|
+
});
|
|
190
|
+
eventSource.addEventListener("error", (event) => {
|
|
191
|
+
subscriber.error(event);
|
|
192
|
+
});
|
|
193
|
+
},
|
|
194
|
+
(error) => {
|
|
195
|
+
subscriber.error(error);
|
|
196
|
+
}
|
|
197
|
+
);
|
|
187
198
|
});
|
|
188
199
|
}
|
|
189
200
|
streamLogsPolling({
|
|
@@ -194,7 +205,9 @@ class ScaffolderClient {
|
|
|
194
205
|
return new ObservableImpl((subscriber) => {
|
|
195
206
|
this.discoveryApi.getBaseUrl("scaffolder").then(async (baseUrl) => {
|
|
196
207
|
while (!subscriber.closed) {
|
|
197
|
-
const url = `${baseUrl}/v2/tasks/${encodeURIComponent(
|
|
208
|
+
const url = `${baseUrl}/v2/tasks/${encodeURIComponent(
|
|
209
|
+
taskId
|
|
210
|
+
)}/events?${qs.stringify({ after })}`;
|
|
198
211
|
const response = await this.fetchApi.fetch(url);
|
|
199
212
|
if (!response.ok) {
|
|
200
213
|
await new Promise((resolve) => setTimeout(resolve, 1e3));
|
|
@@ -237,11 +250,20 @@ const EntityPicker = (props) => {
|
|
|
237
250
|
const allowedKinds = (_a = uiSchema["ui:options"]) == null ? void 0 : _a.allowedKinds;
|
|
238
251
|
const defaultKind = (_b = uiSchema["ui:options"]) == null ? void 0 : _b.defaultKind;
|
|
239
252
|
const catalogApi = useApi(catalogApiRef);
|
|
240
|
-
const { value: entities, loading } = useAsync(
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
253
|
+
const { value: entities, loading } = useAsync(
|
|
254
|
+
() => catalogApi.getEntities(
|
|
255
|
+
allowedKinds ? { filter: { kind: allowedKinds } } : void 0
|
|
256
|
+
)
|
|
257
|
+
);
|
|
258
|
+
const entityRefs = entities == null ? void 0 : entities.items.map(
|
|
259
|
+
(e) => humanizeEntityRef(e, { defaultKind })
|
|
260
|
+
);
|
|
261
|
+
const onSelect = useCallback(
|
|
262
|
+
(_, value) => {
|
|
263
|
+
onChange(value || "");
|
|
264
|
+
},
|
|
265
|
+
[onChange]
|
|
266
|
+
);
|
|
245
267
|
useEffect(() => {
|
|
246
268
|
if ((entityRefs == null ? void 0 : entityRefs.length) === 1) {
|
|
247
269
|
onChange(entityRefs[0]);
|
|
@@ -263,8 +285,9 @@ const EntityPicker = (props) => {
|
|
|
263
285
|
renderInput: (params) => /* @__PURE__ */ React.createElement(TextField, {
|
|
264
286
|
...params,
|
|
265
287
|
label: title,
|
|
266
|
-
margin: "
|
|
288
|
+
margin: "dense",
|
|
267
289
|
helperText: description,
|
|
290
|
+
FormHelperTextProps: { margin: "dense", style: { marginLeft: 0 } },
|
|
268
291
|
variant: "outlined",
|
|
269
292
|
required,
|
|
270
293
|
InputProps: params.InputProps
|
|
@@ -299,7 +322,9 @@ const EntityNamePicker = (props) => {
|
|
|
299
322
|
|
|
300
323
|
const entityNamePickerValidation = (value, validation) => {
|
|
301
324
|
if (!KubernetesValidatorFunctions.isValidObjectName(value)) {
|
|
302
|
-
validation.addError(
|
|
325
|
+
validation.addError(
|
|
326
|
+
"must start and end with an alphanumeric character, and contain only alphanumeric characters, hyphens, underscores, and periods. Maximum length is 63 characters."
|
|
327
|
+
);
|
|
303
328
|
}
|
|
304
329
|
};
|
|
305
330
|
|
|
@@ -318,10 +343,12 @@ const EntityTagsPicker = (props) => {
|
|
|
318
343
|
}
|
|
319
344
|
const entities = await catalogApi.getEntities(tagsRequest);
|
|
320
345
|
return [
|
|
321
|
-
...new Set(
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
346
|
+
...new Set(
|
|
347
|
+
entities.items.flatMap((e) => {
|
|
348
|
+
var _a2;
|
|
349
|
+
return (_a2 = e.metadata) == null ? void 0 : _a2.tags;
|
|
350
|
+
}).filter(Boolean)
|
|
351
|
+
)
|
|
325
352
|
].sort();
|
|
326
353
|
});
|
|
327
354
|
const setTags = (_, values) => {
|
|
@@ -525,11 +552,13 @@ const GerritRepoPicker = (props) => {
|
|
|
525
552
|
const RepoUrlPickerHost = (props) => {
|
|
526
553
|
const { host, hosts, onChange, rawErrors } = props;
|
|
527
554
|
const scaffolderApi = useApi(scaffolderApiRef);
|
|
528
|
-
const { value: { integrations } = { integrations: [] }, loading } = useAsync(
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
555
|
+
const { value: { integrations } = { integrations: [] }, loading } = useAsync(
|
|
556
|
+
async () => {
|
|
557
|
+
return await scaffolderApi.getIntegrationsList({
|
|
558
|
+
allowedHosts: hosts != null ? hosts : []
|
|
559
|
+
});
|
|
560
|
+
}
|
|
561
|
+
);
|
|
533
562
|
useEffect(() => {
|
|
534
563
|
if (!host) {
|
|
535
564
|
if (hosts == null ? void 0 : hosts.length) {
|
|
@@ -632,7 +661,9 @@ function parseRepoPickerUrl(url) {
|
|
|
632
661
|
return { host, owner, repoName, organization, workspace, project };
|
|
633
662
|
}
|
|
634
663
|
|
|
635
|
-
const SecretsContext = createContext(
|
|
664
|
+
const SecretsContext = createContext(
|
|
665
|
+
void 0
|
|
666
|
+
);
|
|
636
667
|
const SecretsContextProvider = ({ children }) => {
|
|
637
668
|
const [secrets, setSecrets] = useState({});
|
|
638
669
|
return /* @__PURE__ */ React.createElement(SecretsContext.Provider, {
|
|
@@ -642,34 +673,50 @@ const SecretsContextProvider = ({ children }) => {
|
|
|
642
673
|
const useTemplateSecrets = () => {
|
|
643
674
|
const value = useContext(SecretsContext);
|
|
644
675
|
if (!value) {
|
|
645
|
-
throw new Error(
|
|
676
|
+
throw new Error(
|
|
677
|
+
"useTemplateSecrets must be used within a SecretsContextProvider"
|
|
678
|
+
);
|
|
646
679
|
}
|
|
647
680
|
const { setSecrets: updateSecrets } = value;
|
|
648
|
-
const setSecrets = useCallback(
|
|
649
|
-
|
|
650
|
-
|
|
681
|
+
const setSecrets = useCallback(
|
|
682
|
+
(input) => {
|
|
683
|
+
updateSecrets((currentSecrets) => ({ ...currentSecrets, ...input }));
|
|
684
|
+
},
|
|
685
|
+
[updateSecrets]
|
|
686
|
+
);
|
|
651
687
|
return { setSecrets };
|
|
652
688
|
};
|
|
653
689
|
|
|
654
690
|
const RepoUrlPicker = (props) => {
|
|
655
691
|
var _a, _b;
|
|
656
692
|
const { uiSchema, onChange, rawErrors, formData } = props;
|
|
657
|
-
const [state, setState] = useState(
|
|
693
|
+
const [state, setState] = useState(
|
|
694
|
+
parseRepoPickerUrl(formData)
|
|
695
|
+
);
|
|
658
696
|
const integrationApi = useApi(scmIntegrationsApiRef);
|
|
659
697
|
const scmAuthApi = useApi(scmAuthApiRef);
|
|
660
698
|
const { setSecrets } = useTemplateSecrets();
|
|
661
|
-
const allowedHosts = useMemo(
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
699
|
+
const allowedHosts = useMemo(
|
|
700
|
+
() => {
|
|
701
|
+
var _a2, _b2;
|
|
702
|
+
return (_b2 = (_a2 = uiSchema == null ? void 0 : uiSchema["ui:options"]) == null ? void 0 : _a2.allowedHosts) != null ? _b2 : [];
|
|
703
|
+
},
|
|
704
|
+
[uiSchema]
|
|
705
|
+
);
|
|
706
|
+
const allowedOwners = useMemo(
|
|
707
|
+
() => {
|
|
708
|
+
var _a2, _b2;
|
|
709
|
+
return (_b2 = (_a2 = uiSchema == null ? void 0 : uiSchema["ui:options"]) == null ? void 0 : _a2.allowedOwners) != null ? _b2 : [];
|
|
710
|
+
},
|
|
711
|
+
[uiSchema]
|
|
712
|
+
);
|
|
713
|
+
const allowedRepos = useMemo(
|
|
714
|
+
() => {
|
|
715
|
+
var _a2, _b2;
|
|
716
|
+
return (_b2 = (_a2 = uiSchema == null ? void 0 : uiSchema["ui:options"]) == null ? void 0 : _a2.allowedRepos) != null ? _b2 : [];
|
|
717
|
+
},
|
|
718
|
+
[uiSchema]
|
|
719
|
+
);
|
|
673
720
|
useEffect(() => {
|
|
674
721
|
onChange(serializeRepoPickerUrl(state));
|
|
675
722
|
}, [state, onChange]);
|
|
@@ -683,29 +730,36 @@ const RepoUrlPicker = (props) => {
|
|
|
683
730
|
setState((prevState) => ({ ...prevState, repoName: allowedRepos[0] }));
|
|
684
731
|
}
|
|
685
732
|
}, [setState, allowedRepos]);
|
|
686
|
-
const updateLocalState = useCallback(
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
state.host
|
|
697
|
-
|
|
698
|
-
state.repoName
|
|
699
|
-
].map(encodeURIComponent);
|
|
700
|
-
const { token } = await scmAuthApi.getCredentials({
|
|
701
|
-
url: `https://${host}/${owner}/${repoName}`,
|
|
702
|
-
additionalScope: {
|
|
703
|
-
repoWrite: true,
|
|
704
|
-
customScopes: requestUserCredentials.additionalScopes
|
|
733
|
+
const updateLocalState = useCallback(
|
|
734
|
+
(newState) => {
|
|
735
|
+
setState((prevState) => ({ ...prevState, ...newState }));
|
|
736
|
+
},
|
|
737
|
+
[setState]
|
|
738
|
+
);
|
|
739
|
+
useDebounce(
|
|
740
|
+
async () => {
|
|
741
|
+
var _a2;
|
|
742
|
+
const { requestUserCredentials } = (_a2 = uiSchema == null ? void 0 : uiSchema["ui:options"]) != null ? _a2 : {};
|
|
743
|
+
if (!requestUserCredentials || !(state.host && state.owner && state.repoName)) {
|
|
744
|
+
return;
|
|
705
745
|
}
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
746
|
+
const [host, owner, repoName] = [
|
|
747
|
+
state.host,
|
|
748
|
+
state.owner,
|
|
749
|
+
state.repoName
|
|
750
|
+
].map(encodeURIComponent);
|
|
751
|
+
const { token } = await scmAuthApi.getCredentials({
|
|
752
|
+
url: `https://${host}/${owner}/${repoName}`,
|
|
753
|
+
additionalScope: {
|
|
754
|
+
repoWrite: true,
|
|
755
|
+
customScopes: requestUserCredentials.additionalScopes
|
|
756
|
+
}
|
|
757
|
+
});
|
|
758
|
+
setSecrets({ [requestUserCredentials.secretsKey]: token });
|
|
759
|
+
},
|
|
760
|
+
500,
|
|
761
|
+
[state, uiSchema]
|
|
762
|
+
);
|
|
709
763
|
const hostType = (_b = state.host && ((_a = integrationApi.byHost(state.host)) == null ? void 0 : _a.type)) != null ? _b : null;
|
|
710
764
|
return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(RepoUrlPickerHost, {
|
|
711
765
|
host: state.host,
|
|
@@ -749,22 +803,32 @@ const repoPickerValidation = (value, validation, context) => {
|
|
|
749
803
|
const { host, searchParams } = new URL(`https://${value}`);
|
|
750
804
|
const integrationApi = context.apiHolder.get(scmIntegrationsApiRef);
|
|
751
805
|
if (!host) {
|
|
752
|
-
validation.addError(
|
|
806
|
+
validation.addError(
|
|
807
|
+
"Incomplete repository location provided, host not provided"
|
|
808
|
+
);
|
|
753
809
|
} else {
|
|
754
810
|
if (((_a = integrationApi == null ? void 0 : integrationApi.byHost(host)) == null ? void 0 : _a.type) === "bitbucket") {
|
|
755
811
|
if (host === "bitbucket.org" && !searchParams.get("workspace")) {
|
|
756
|
-
validation.addError(
|
|
812
|
+
validation.addError(
|
|
813
|
+
"Incomplete repository location provided, workspace not provided"
|
|
814
|
+
);
|
|
757
815
|
}
|
|
758
816
|
if (!searchParams.get("project")) {
|
|
759
|
-
validation.addError(
|
|
817
|
+
validation.addError(
|
|
818
|
+
"Incomplete repository location provided, project not provided"
|
|
819
|
+
);
|
|
760
820
|
}
|
|
761
821
|
} else if (((_b = integrationApi == null ? void 0 : integrationApi.byHost(host)) == null ? void 0 : _b.type) !== "gerrit") {
|
|
762
822
|
if (!searchParams.get("owner")) {
|
|
763
|
-
validation.addError(
|
|
823
|
+
validation.addError(
|
|
824
|
+
"Incomplete repository location provided, owner not provided"
|
|
825
|
+
);
|
|
764
826
|
}
|
|
765
827
|
}
|
|
766
828
|
if (!searchParams.get("repo")) {
|
|
767
|
-
validation.addError(
|
|
829
|
+
validation.addError(
|
|
830
|
+
"Incomplete repository location provided, repo not provided"
|
|
831
|
+
);
|
|
768
832
|
}
|
|
769
833
|
}
|
|
770
834
|
} catch {
|
|
@@ -820,16 +884,18 @@ function useOwnedEntities(allowedKinds) {
|
|
|
820
884
|
const { loading, value: refs } = useAsync(async () => {
|
|
821
885
|
const identity = await identityApi.getBackstageIdentity();
|
|
822
886
|
const identityRefs = identity.ownershipEntityRefs;
|
|
823
|
-
const catalogs = await catalogApi.getEntities(
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
887
|
+
const catalogs = await catalogApi.getEntities(
|
|
888
|
+
allowedKinds ? {
|
|
889
|
+
filter: {
|
|
890
|
+
kind: allowedKinds,
|
|
891
|
+
[`relations.${RELATION_OWNED_BY}`]: identityRefs || []
|
|
892
|
+
}
|
|
893
|
+
} : {
|
|
894
|
+
filter: {
|
|
895
|
+
[`relations.${RELATION_OWNED_BY}`]: identityRefs || []
|
|
896
|
+
}
|
|
831
897
|
}
|
|
832
|
-
|
|
898
|
+
);
|
|
833
899
|
return catalogs;
|
|
834
900
|
}, []);
|
|
835
901
|
const ownedEntities = useMemo(() => {
|
|
@@ -844,13 +910,21 @@ function createScaffolderFieldExtension(options) {
|
|
|
844
910
|
return {
|
|
845
911
|
expose() {
|
|
846
912
|
const FieldExtensionDataHolder = () => null;
|
|
847
|
-
attachComponentData(
|
|
913
|
+
attachComponentData(
|
|
914
|
+
FieldExtensionDataHolder,
|
|
915
|
+
FIELD_EXTENSION_KEY,
|
|
916
|
+
options
|
|
917
|
+
);
|
|
848
918
|
return FieldExtensionDataHolder;
|
|
849
919
|
}
|
|
850
920
|
};
|
|
851
921
|
}
|
|
852
922
|
const ScaffolderFieldExtensions = () => null;
|
|
853
|
-
attachComponentData(
|
|
923
|
+
attachComponentData(
|
|
924
|
+
ScaffolderFieldExtensions,
|
|
925
|
+
FIELD_EXTENSION_WRAPPER_KEY,
|
|
926
|
+
true
|
|
927
|
+
);
|
|
854
928
|
|
|
855
929
|
const registerComponentRouteRef = createExternalRouteRef({
|
|
856
930
|
id: "register-component",
|
|
@@ -864,11 +938,19 @@ const legacySelectedTemplateRouteRef = createSubRouteRef({
|
|
|
864
938
|
parent: rootRouteRef,
|
|
865
939
|
path: "/templates/:templateName"
|
|
866
940
|
});
|
|
941
|
+
const nextRouteRef = createRouteRef({
|
|
942
|
+
id: "scaffolder/next"
|
|
943
|
+
});
|
|
867
944
|
const selectedTemplateRouteRef = createSubRouteRef({
|
|
868
945
|
id: "scaffolder/selected-template",
|
|
869
946
|
parent: rootRouteRef,
|
|
870
947
|
path: "/templates/:namespace/:templateName"
|
|
871
948
|
});
|
|
949
|
+
const nextSelectedTemplateRouteRef = createSubRouteRef({
|
|
950
|
+
id: "scaffolder/next/selected-template",
|
|
951
|
+
parent: nextRouteRef,
|
|
952
|
+
path: "/templates/:namespace/:templateName"
|
|
953
|
+
});
|
|
872
954
|
const scaffolderTaskRouteRef = createSubRouteRef({
|
|
873
955
|
id: "scaffolder/task",
|
|
874
956
|
parent: rootRouteRef,
|
|
@@ -916,42 +998,58 @@ const scaffolderPlugin = createPlugin({
|
|
|
916
998
|
registerComponent: registerComponentRouteRef
|
|
917
999
|
}
|
|
918
1000
|
});
|
|
919
|
-
const EntityPickerFieldExtension = scaffolderPlugin.provide(
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
1001
|
+
const EntityPickerFieldExtension = scaffolderPlugin.provide(
|
|
1002
|
+
createScaffolderFieldExtension({
|
|
1003
|
+
component: EntityPicker,
|
|
1004
|
+
name: "EntityPicker"
|
|
1005
|
+
})
|
|
1006
|
+
);
|
|
1007
|
+
const EntityNamePickerFieldExtension = scaffolderPlugin.provide(
|
|
1008
|
+
createScaffolderFieldExtension({
|
|
1009
|
+
component: EntityNamePicker,
|
|
1010
|
+
name: "EntityNamePicker",
|
|
1011
|
+
validation: entityNamePickerValidation
|
|
1012
|
+
})
|
|
1013
|
+
);
|
|
1014
|
+
const RepoUrlPickerFieldExtension = scaffolderPlugin.provide(
|
|
1015
|
+
createScaffolderFieldExtension({
|
|
1016
|
+
component: RepoUrlPicker,
|
|
1017
|
+
name: "RepoUrlPicker",
|
|
1018
|
+
validation: repoPickerValidation
|
|
1019
|
+
})
|
|
1020
|
+
);
|
|
1021
|
+
const OwnerPickerFieldExtension = scaffolderPlugin.provide(
|
|
1022
|
+
createScaffolderFieldExtension({
|
|
1023
|
+
component: OwnerPicker,
|
|
1024
|
+
name: "OwnerPicker"
|
|
1025
|
+
})
|
|
1026
|
+
);
|
|
1027
|
+
const ScaffolderPage = scaffolderPlugin.provide(
|
|
1028
|
+
createRoutableExtension({
|
|
1029
|
+
name: "ScaffolderPage",
|
|
1030
|
+
component: () => import('./Router-fa1fcf0c.esm.js').then((m) => m.Router),
|
|
1031
|
+
mountPoint: rootRouteRef
|
|
1032
|
+
})
|
|
1033
|
+
);
|
|
1034
|
+
const OwnedEntityPickerFieldExtension = scaffolderPlugin.provide(
|
|
1035
|
+
createScaffolderFieldExtension({
|
|
1036
|
+
component: OwnedEntityPicker,
|
|
1037
|
+
name: "OwnedEntityPicker"
|
|
1038
|
+
})
|
|
1039
|
+
);
|
|
1040
|
+
const EntityTagsPickerFieldExtension = scaffolderPlugin.provide(
|
|
1041
|
+
createScaffolderFieldExtension({
|
|
1042
|
+
component: EntityTagsPicker,
|
|
1043
|
+
name: "EntityTagsPicker"
|
|
1044
|
+
})
|
|
1045
|
+
);
|
|
1046
|
+
const NextScaffolderPage = scaffolderPlugin.provide(
|
|
1047
|
+
createRoutableExtension({
|
|
1048
|
+
name: "NextScaffolderPage",
|
|
1049
|
+
component: () => import('./index-bdece754.esm.js').then((m) => m.Router),
|
|
1050
|
+
mountPoint: nextRouteRef
|
|
1051
|
+
})
|
|
1052
|
+
);
|
|
955
1053
|
|
|
956
1054
|
const icon = /* @__PURE__ */ React.createElement(CheckBoxOutlineBlankIcon, {
|
|
957
1055
|
fontSize: "small"
|
|
@@ -1070,43 +1168,51 @@ const useTaskEventStream = (taskId) => {
|
|
|
1070
1168
|
let didCancel = false;
|
|
1071
1169
|
let subscription;
|
|
1072
1170
|
let logPusher;
|
|
1073
|
-
scaffolderApi.getTask(taskId).then(
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
dispatch({ type: "INIT", data: task });
|
|
1078
|
-
const observable = scaffolderApi.streamLogs({ taskId });
|
|
1079
|
-
const collectedLogEvents = new Array();
|
|
1080
|
-
function emitLogs() {
|
|
1081
|
-
if (collectedLogEvents.length) {
|
|
1082
|
-
const logs = collectedLogEvents.splice(0, collectedLogEvents.length);
|
|
1083
|
-
dispatch({ type: "LOGS", data: logs });
|
|
1171
|
+
scaffolderApi.getTask(taskId).then(
|
|
1172
|
+
(task) => {
|
|
1173
|
+
if (didCancel) {
|
|
1174
|
+
return;
|
|
1084
1175
|
}
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
return void 0;
|
|
1096
|
-
default:
|
|
1097
|
-
throw new Error(`Unhandled event type ${event.type} in observer`);
|
|
1176
|
+
dispatch({ type: "INIT", data: task });
|
|
1177
|
+
const observable = scaffolderApi.streamLogs({ taskId });
|
|
1178
|
+
const collectedLogEvents = new Array();
|
|
1179
|
+
function emitLogs() {
|
|
1180
|
+
if (collectedLogEvents.length) {
|
|
1181
|
+
const logs = collectedLogEvents.splice(
|
|
1182
|
+
0,
|
|
1183
|
+
collectedLogEvents.length
|
|
1184
|
+
);
|
|
1185
|
+
dispatch({ type: "LOGS", data: logs });
|
|
1098
1186
|
}
|
|
1099
|
-
}
|
|
1100
|
-
|
|
1101
|
-
|
|
1187
|
+
}
|
|
1188
|
+
logPusher = setInterval(emitLogs, 500);
|
|
1189
|
+
subscription = observable.subscribe({
|
|
1190
|
+
next: (event) => {
|
|
1191
|
+
switch (event.type) {
|
|
1192
|
+
case "log":
|
|
1193
|
+
return collectedLogEvents.push(event);
|
|
1194
|
+
case "completion":
|
|
1195
|
+
emitLogs();
|
|
1196
|
+
dispatch({ type: "COMPLETED", data: event });
|
|
1197
|
+
return void 0;
|
|
1198
|
+
default:
|
|
1199
|
+
throw new Error(
|
|
1200
|
+
`Unhandled event type ${event.type} in observer`
|
|
1201
|
+
);
|
|
1202
|
+
}
|
|
1203
|
+
},
|
|
1204
|
+
error: (error) => {
|
|
1205
|
+
emitLogs();
|
|
1206
|
+
dispatch({ type: "ERROR", data: error });
|
|
1207
|
+
}
|
|
1208
|
+
});
|
|
1209
|
+
},
|
|
1210
|
+
(error) => {
|
|
1211
|
+
if (!didCancel) {
|
|
1102
1212
|
dispatch({ type: "ERROR", data: error });
|
|
1103
1213
|
}
|
|
1104
|
-
});
|
|
1105
|
-
}, (error) => {
|
|
1106
|
-
if (!didCancel) {
|
|
1107
|
-
dispatch({ type: "ERROR", data: error });
|
|
1108
1214
|
}
|
|
1109
|
-
|
|
1215
|
+
);
|
|
1110
1216
|
return () => {
|
|
1111
1217
|
didCancel = true;
|
|
1112
1218
|
if (subscription) {
|
|
@@ -1181,30 +1287,32 @@ const TaskPageLinks = ({ output }) => {
|
|
|
1181
1287
|
};
|
|
1182
1288
|
|
|
1183
1289
|
const humanizeDuration = require("humanize-duration");
|
|
1184
|
-
const useStyles = makeStyles$1(
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
}
|
|
1290
|
+
const useStyles = makeStyles$1(
|
|
1291
|
+
(theme) => createStyles({
|
|
1292
|
+
root: {
|
|
1293
|
+
width: "100%"
|
|
1294
|
+
},
|
|
1295
|
+
button: {
|
|
1296
|
+
marginBottom: theme.spacing(2),
|
|
1297
|
+
marginLeft: theme.spacing(2)
|
|
1298
|
+
},
|
|
1299
|
+
actionsContainer: {
|
|
1300
|
+
marginBottom: theme.spacing(2)
|
|
1301
|
+
},
|
|
1302
|
+
resetContainer: {
|
|
1303
|
+
padding: theme.spacing(3)
|
|
1304
|
+
},
|
|
1305
|
+
labelWrapper: {
|
|
1306
|
+
display: "flex",
|
|
1307
|
+
flex: 1,
|
|
1308
|
+
flexDirection: "row",
|
|
1309
|
+
justifyContent: "space-between"
|
|
1310
|
+
},
|
|
1311
|
+
stepWrapper: {
|
|
1312
|
+
width: "100%"
|
|
1313
|
+
}
|
|
1314
|
+
})
|
|
1315
|
+
);
|
|
1208
1316
|
const StepTimeTicker = ({ step }) => {
|
|
1209
1317
|
const [time, setTime] = useState("");
|
|
1210
1318
|
useInterval(() => {
|
|
@@ -1221,20 +1329,22 @@ const StepTimeTicker = ({ step }) => {
|
|
|
1221
1329
|
variant: "caption"
|
|
1222
1330
|
}, time);
|
|
1223
1331
|
};
|
|
1224
|
-
const useStepIconStyles = makeStyles$1(
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
}
|
|
1332
|
+
const useStepIconStyles = makeStyles$1(
|
|
1333
|
+
(theme) => createStyles({
|
|
1334
|
+
root: {
|
|
1335
|
+
color: theme.palette.text.disabled,
|
|
1336
|
+
display: "flex",
|
|
1337
|
+
height: 22,
|
|
1338
|
+
alignItems: "center"
|
|
1339
|
+
},
|
|
1340
|
+
completed: {
|
|
1341
|
+
color: theme.palette.status.ok
|
|
1342
|
+
},
|
|
1343
|
+
error: {
|
|
1344
|
+
color: theme.palette.status.error
|
|
1345
|
+
}
|
|
1346
|
+
})
|
|
1347
|
+
);
|
|
1238
1348
|
function TaskStepIconComponent(props) {
|
|
1239
1349
|
const classes = useStepIconStyles();
|
|
1240
1350
|
const { active, completed, error } = props;
|
|
@@ -1259,44 +1369,46 @@ function TaskStepIconComponent(props) {
|
|
|
1259
1369
|
})
|
|
1260
1370
|
}, getMiddle());
|
|
1261
1371
|
}
|
|
1262
|
-
const TaskStatusStepper = memo(
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
});
|
|
1372
|
+
const TaskStatusStepper = memo(
|
|
1373
|
+
(props) => {
|
|
1374
|
+
const { steps, currentStepId, onUserStepChange } = props;
|
|
1375
|
+
const classes = useStyles(props);
|
|
1376
|
+
return /* @__PURE__ */ React.createElement("div", {
|
|
1377
|
+
className: classes.root
|
|
1378
|
+
}, /* @__PURE__ */ React.createElement(Stepper, {
|
|
1379
|
+
activeStep: steps.findIndex((s) => s.id === currentStepId),
|
|
1380
|
+
orientation: "vertical",
|
|
1381
|
+
nonLinear: true
|
|
1382
|
+
}, steps.map((step, index) => {
|
|
1383
|
+
const isCompleted = step.status === "completed";
|
|
1384
|
+
const isFailed = step.status === "failed";
|
|
1385
|
+
const isActive = step.status === "processing";
|
|
1386
|
+
const isSkipped = step.status === "skipped";
|
|
1387
|
+
return /* @__PURE__ */ React.createElement(Step, {
|
|
1388
|
+
key: String(index),
|
|
1389
|
+
expanded: true
|
|
1390
|
+
}, /* @__PURE__ */ React.createElement(StepButton, {
|
|
1391
|
+
onClick: () => onUserStepChange(step.id)
|
|
1392
|
+
}, /* @__PURE__ */ React.createElement(StepLabel, {
|
|
1393
|
+
StepIconProps: {
|
|
1394
|
+
completed: isCompleted,
|
|
1395
|
+
error: isFailed,
|
|
1396
|
+
active: isActive
|
|
1397
|
+
},
|
|
1398
|
+
StepIconComponent: TaskStepIconComponent,
|
|
1399
|
+
className: classes.stepWrapper
|
|
1400
|
+
}, /* @__PURE__ */ React.createElement("div", {
|
|
1401
|
+
className: classes.labelWrapper
|
|
1402
|
+
}, /* @__PURE__ */ React.createElement(Typography$1, {
|
|
1403
|
+
variant: "subtitle2"
|
|
1404
|
+
}, step.name), isSkipped ? /* @__PURE__ */ React.createElement(Typography$1, {
|
|
1405
|
+
variant: "caption"
|
|
1406
|
+
}, "Skipped") : /* @__PURE__ */ React.createElement(StepTimeTicker, {
|
|
1407
|
+
step
|
|
1408
|
+
})))));
|
|
1409
|
+
})));
|
|
1410
|
+
}
|
|
1411
|
+
);
|
|
1300
1412
|
const hasLinks = ({ links = [] }) => links.length > 0;
|
|
1301
1413
|
const TaskPage = ({ loadingText }) => {
|
|
1302
1414
|
const classes = useStyles();
|
|
@@ -1304,23 +1416,30 @@ const TaskPage = ({ loadingText }) => {
|
|
|
1304
1416
|
const rootPath = useRouteRef(rootRouteRef);
|
|
1305
1417
|
const templateRoute = useRouteRef(selectedTemplateRouteRef);
|
|
1306
1418
|
const [userSelectedStepId, setUserSelectedStepId] = useState(void 0);
|
|
1307
|
-
const [lastActiveStepId, setLastActiveStepId] = useState(
|
|
1419
|
+
const [lastActiveStepId, setLastActiveStepId] = useState(
|
|
1420
|
+
void 0
|
|
1421
|
+
);
|
|
1308
1422
|
const { taskId } = useParams();
|
|
1309
1423
|
const taskStream = useTaskEventStream(taskId);
|
|
1310
1424
|
const completed = taskStream.completed;
|
|
1311
|
-
const steps = useMemo(
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1425
|
+
const steps = useMemo(
|
|
1426
|
+
() => {
|
|
1427
|
+
var _a, _b;
|
|
1428
|
+
return (_b = (_a = taskStream.task) == null ? void 0 : _a.spec.steps.map((step) => {
|
|
1429
|
+
var _a2;
|
|
1430
|
+
return {
|
|
1431
|
+
...step,
|
|
1432
|
+
...(_a2 = taskStream == null ? void 0 : taskStream.steps) == null ? void 0 : _a2[step.id]
|
|
1433
|
+
};
|
|
1434
|
+
})) != null ? _b : [];
|
|
1435
|
+
},
|
|
1436
|
+
[taskStream]
|
|
1437
|
+
);
|
|
1321
1438
|
useEffect(() => {
|
|
1322
1439
|
var _a;
|
|
1323
|
-
const mostRecentFailedOrActiveStep = steps.find(
|
|
1440
|
+
const mostRecentFailedOrActiveStep = steps.find(
|
|
1441
|
+
(step) => ["failed", "processing"].includes(step.status)
|
|
1442
|
+
);
|
|
1324
1443
|
if (completed && !mostRecentFailedOrActiveStep) {
|
|
1325
1444
|
setLastActiveStepId((_a = steps[steps.length - 1]) == null ? void 0 : _a.id);
|
|
1326
1445
|
return;
|
|
@@ -1347,10 +1466,14 @@ const TaskPage = ({ loadingText }) => {
|
|
|
1347
1466
|
return;
|
|
1348
1467
|
}
|
|
1349
1468
|
const formData = taskStream.task.spec.parameters;
|
|
1350
|
-
const { name, namespace } = parseEntityRef(
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1469
|
+
const { name, namespace } = parseEntityRef(
|
|
1470
|
+
(_c = taskStream.task.spec.templateInfo) == null ? void 0 : _c.entityRef
|
|
1471
|
+
);
|
|
1472
|
+
navigate(
|
|
1473
|
+
`${templateRoute({ templateName: name, namespace })}?${qs.stringify({
|
|
1474
|
+
formData: JSON.stringify(formData)
|
|
1475
|
+
})}`
|
|
1476
|
+
);
|
|
1354
1477
|
};
|
|
1355
1478
|
return /* @__PURE__ */ React.createElement(Page, {
|
|
1356
1479
|
themeId: "home"
|
|
@@ -1389,5 +1512,5 @@ const TaskPage = ({ loadingText }) => {
|
|
|
1389
1512
|
})))))));
|
|
1390
1513
|
};
|
|
1391
1514
|
|
|
1392
|
-
export {
|
|
1393
|
-
//# sourceMappingURL=index-
|
|
1515
|
+
export { EntityTagsPickerFieldExtension as A, OwnerPickerFieldExtension as B, OwnedEntityPickerFieldExtension as C, RepoUrlPickerFieldExtension as D, EntityPicker as E, FIELD_EXTENSION_WRAPPER_KEY as F, ScaffolderPage as G, scaffolderPlugin as H, useTemplateSecrets as I, NextScaffolderPage as N, OwnerPicker as O, RepoUrlPicker as R, SecretsContext as S, TemplateTypePicker as T, actionsRouteRef as a, scaffolderListTaskRouteRef as b, scaffolderApiRef as c, scaffolderTaskRouteRef as d, editRouteRef as e, rootRouteRef as f, TaskStatusStepper as g, TaskPageLinks as h, FIELD_EXTENSION_KEY as i, SecretsContextProvider as j, TaskPage as k, legacySelectedTemplateRouteRef as l, EntityNamePicker as m, entityNamePickerValidation as n, EntityTagsPicker as o, repoPickerValidation as p, OwnedEntityPicker as q, registerComponentRouteRef as r, selectedTemplateRouteRef as s, nextSelectedTemplateRouteRef as t, nextRouteRef as u, ScaffolderClient as v, createScaffolderFieldExtension as w, ScaffolderFieldExtensions as x, EntityPickerFieldExtension as y, EntityNamePickerFieldExtension as z };
|
|
1516
|
+
//# sourceMappingURL=index-3b171258.esm.js.map
|