@backstage-community/plugin-cicd-statistics 0.1.37 → 0.1.38

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.
Files changed (58) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/dist/apis/cicd-statistics.esm.js +8 -0
  3. package/dist/apis/cicd-statistics.esm.js.map +1 -0
  4. package/dist/apis/types.esm.js +22 -0
  5. package/dist/apis/types.esm.js.map +1 -0
  6. package/dist/charts/colors.esm.js +28 -0
  7. package/dist/charts/colors.esm.js.map +1 -0
  8. package/dist/charts/logic/analysis.esm.js +37 -0
  9. package/dist/charts/logic/analysis.esm.js.map +1 -0
  10. package/dist/charts/logic/conversions.esm.js +66 -0
  11. package/dist/charts/logic/conversions.esm.js.map +1 -0
  12. package/dist/charts/logic/count-builds-per-day.esm.js +24 -0
  13. package/dist/charts/logic/count-builds-per-day.esm.js.map +1 -0
  14. package/dist/charts/logic/daily-summary.esm.js +72 -0
  15. package/dist/charts/logic/daily-summary.esm.js.map +1 -0
  16. package/dist/charts/logic/finalize-stage.esm.js +45 -0
  17. package/dist/charts/logic/finalize-stage.esm.js.map +1 -0
  18. package/dist/charts/logic/utils.esm.js +59 -0
  19. package/dist/charts/logic/utils.esm.js.map +1 -0
  20. package/dist/charts/stage-chart.esm.js +168 -0
  21. package/dist/charts/stage-chart.esm.js.map +1 -0
  22. package/dist/charts/status-chart.esm.js +142 -0
  23. package/dist/charts/status-chart.esm.js.map +1 -0
  24. package/dist/charts/zoom.esm.js +142 -0
  25. package/dist/charts/zoom.esm.js.map +1 -0
  26. package/dist/components/button-switch.esm.js +86 -0
  27. package/dist/components/button-switch.esm.js.map +1 -0
  28. package/dist/components/chart-filters.esm.js +379 -0
  29. package/dist/components/chart-filters.esm.js.map +1 -0
  30. package/dist/components/duration-slider.esm.js +85 -0
  31. package/dist/components/duration-slider.esm.js.map +1 -0
  32. package/dist/components/label.esm.js +22 -0
  33. package/dist/components/label.esm.js.map +1 -0
  34. package/dist/components/progress.esm.js +78 -0
  35. package/dist/components/progress.esm.js.map +1 -0
  36. package/dist/components/toggle.esm.js +23 -0
  37. package/dist/components/toggle.esm.js.map +1 -0
  38. package/dist/components/utils.esm.js +92 -0
  39. package/dist/components/utils.esm.js.map +1 -0
  40. package/dist/entity-page.esm.js +140 -0
  41. package/dist/entity-page.esm.js.map +1 -0
  42. package/dist/hooks/use-cicd-configuration.esm.js +40 -0
  43. package/dist/hooks/use-cicd-configuration.esm.js.map +1 -0
  44. package/dist/hooks/use-cicd-statistics-api.esm.js +13 -0
  45. package/dist/hooks/use-cicd-statistics-api.esm.js.map +1 -0
  46. package/dist/hooks/use-cicd-statistics.esm.js +100 -0
  47. package/dist/hooks/use-cicd-statistics.esm.js.map +1 -0
  48. package/dist/index.esm.js +3 -44
  49. package/dist/index.esm.js.map +1 -1
  50. package/dist/plugin.esm.js +21 -0
  51. package/dist/plugin.esm.js.map +1 -0
  52. package/dist/utils/api.esm.js +16 -0
  53. package/dist/utils/api.esm.js.map +1 -0
  54. package/dist/utils/stage-names.esm.js +36 -0
  55. package/dist/utils/stage-names.esm.js.map +1 -0
  56. package/package.json +10 -6
  57. package/dist/esm/entity-page-CNIrdNBp.esm.js +0 -1797
  58. package/dist/esm/entity-page-CNIrdNBp.esm.js.map +0 -1
@@ -0,0 +1,23 @@
1
+ import React, { useCallback } from 'react';
2
+ import FormControlLabel from '@material-ui/core/FormControlLabel';
3
+ import Switch from '@material-ui/core/Switch';
4
+
5
+ function Toggle({
6
+ checked,
7
+ setChecked,
8
+ children
9
+ }) {
10
+ const toggler = useCallback(() => {
11
+ setChecked(!checked);
12
+ }, [checked, setChecked]);
13
+ return /* @__PURE__ */ React.createElement(
14
+ FormControlLabel,
15
+ {
16
+ control: /* @__PURE__ */ React.createElement(Switch, { checked, onChange: toggler }),
17
+ label: children
18
+ }
19
+ );
20
+ }
21
+
22
+ export { Toggle };
23
+ //# sourceMappingURL=toggle.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toggle.esm.js","sources":["../../src/components/toggle.tsx"],"sourcesContent":["/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport React, { useCallback, PropsWithChildren } from 'react';\nimport FormControlLabel from '@material-ui/core/FormControlLabel';\nimport Switch from '@material-ui/core/Switch';\n\nexport interface ToggleProps {\n checked: boolean;\n setChecked: (checked: boolean) => void;\n}\n\nexport function Toggle({\n checked,\n setChecked,\n children,\n}: PropsWithChildren<ToggleProps>) {\n const toggler = useCallback(() => {\n setChecked(!checked);\n }, [checked, setChecked]);\n\n return (\n <FormControlLabel\n control={<Switch checked={checked} onChange={toggler} />}\n label={children}\n />\n );\n}\n"],"names":[],"mappings":";;;;AAyBO,SAAS,MAAO,CAAA;AAAA,EACrB,OAAA;AAAA,EACA,UAAA;AAAA,EACA,QAAA;AACF,CAAmC,EAAA;AACjC,EAAM,MAAA,OAAA,GAAU,YAAY,MAAM;AAChC,IAAA,UAAA,CAAW,CAAC,OAAO,CAAA,CAAA;AAAA,GAClB,EAAA,CAAC,OAAS,EAAA,UAAU,CAAC,CAAA,CAAA;AAExB,EACE,uBAAA,KAAA,CAAA,aAAA;AAAA,IAAC,gBAAA;AAAA,IAAA;AAAA,MACC,OAAS,kBAAA,KAAA,CAAA,aAAA,CAAC,MAAO,EAAA,EAAA,OAAA,EAAkB,UAAU,OAAS,EAAA,CAAA;AAAA,MACtD,KAAO,EAAA,QAAA;AAAA,KAAA;AAAA,GACT,CAAA;AAEJ;;;;"}
@@ -0,0 +1,92 @@
1
+ import React from 'react';
2
+ import { Duration, DateTime } from 'luxon';
3
+ import humanizeDuration from 'humanize-duration';
4
+ import { capitalize } from 'lodash';
5
+ import Typography from '@material-ui/core/Typography';
6
+
7
+ const infoText = { color: "InfoText" };
8
+ function pickElements(arr, num) {
9
+ if (arr.length <= num) {
10
+ return [...arr];
11
+ }
12
+ if (num < 2) {
13
+ return [arr[arr.length / 2]];
14
+ }
15
+ const step = arr.length / (num - 1);
16
+ return [
17
+ ...Array.from(Array(num - 1)).map(
18
+ (_, index) => arr[Math.round(index * step)]
19
+ ),
20
+ arr[arr.length - 1]
21
+ ];
22
+ }
23
+ function formatDateShort(milliseconds) {
24
+ if (milliseconds === "auto") {
25
+ return "";
26
+ }
27
+ return DateTime.fromMillis(milliseconds).toLocaleString(DateTime.DATE_SHORT);
28
+ }
29
+ function formatDateTimeShort(milliseconds) {
30
+ if (milliseconds === "auto") {
31
+ return "";
32
+ }
33
+ return DateTime.fromMillis(milliseconds).toLocaleString(
34
+ DateTime.DATETIME_SHORT
35
+ );
36
+ }
37
+ function labelFormatter(epoch) {
38
+ return /* @__PURE__ */ React.createElement(Typography, { component: "span", style: infoText }, formatDateTimeShort(epoch));
39
+ }
40
+ function labelFormatterWithoutTime(epoch) {
41
+ return /* @__PURE__ */ React.createElement(Typography, { component: "span", style: infoText }, formatDateShort(epoch));
42
+ }
43
+ function tickFormatterX(epoch) {
44
+ return formatDateShort(epoch);
45
+ }
46
+ function tickFormatterY(duration) {
47
+ if (duration === 0) {
48
+ return "0";
49
+ } else if (duration < 500) {
50
+ return `${duration} ms`;
51
+ }
52
+ return formatDuration(duration).replace(/second.*/, "sec").replace(/minute.*/, "min").replace(/hour.*/, "h").replace(/day.*/, "d").replace(/month.*/, "m").replace(/year.*/, "y");
53
+ }
54
+ function tooltipValueFormatter(durationOrCount, name) {
55
+ return [
56
+ // TODO(Rugvip): Types don't allow returning elements, but it was here before so presumably works
57
+ /* @__PURE__ */ React.createElement(Typography, { component: "span", style: infoText }, capitalize(name), ":", " ", name.endsWith(" count") ? durationOrCount : formatDuration(durationOrCount)),
58
+ null
59
+ ];
60
+ }
61
+ function formatDuration(millis) {
62
+ let rest = Math.round(millis);
63
+ const days = Math.floor(rest / (1e3 * 60 * 60 * 24));
64
+ rest -= days * (1e3 * 60 * 60 * 24);
65
+ const hours = Math.floor(rest / (1e3 * 60 * 60));
66
+ rest -= hours * (1e3 * 60 * 60);
67
+ const minutes = Math.floor(rest / (1e3 * 60));
68
+ rest -= minutes * (1e3 * 60);
69
+ const seconds = Math.floor(rest / 1e3);
70
+ rest -= seconds * 1e3;
71
+ const milliseconds = rest;
72
+ if (!days && !hours && !minutes) {
73
+ if (seconds < 1) {
74
+ return `${milliseconds}ms`;
75
+ } else if (seconds < 2) {
76
+ return `${((milliseconds + seconds * 1e3) / 1e3).toFixed(1)}s`;
77
+ }
78
+ }
79
+ const dur = Duration.fromObject({
80
+ ...days && { days },
81
+ ...hours && { hours },
82
+ ...minutes && !days && { minutes },
83
+ ...seconds && !days && !hours && { seconds }
84
+ });
85
+ return humanizeDuration(dur.toMillis(), { round: true });
86
+ }
87
+ function formatDurationFromSeconds(seconds) {
88
+ return formatDuration(seconds * 1e3);
89
+ }
90
+
91
+ export { formatDuration, formatDurationFromSeconds, labelFormatter, labelFormatterWithoutTime, pickElements, tickFormatterX, tickFormatterY, tooltipValueFormatter };
92
+ //# sourceMappingURL=utils.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.esm.js","sources":["../../src/components/utils.tsx"],"sourcesContent":["/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport React, { CSSProperties } from 'react';\nimport { DateTime, Duration } from 'luxon';\nimport humanizeDuration from 'humanize-duration';\nimport { capitalize } from 'lodash';\nimport Typography from '@material-ui/core/Typography';\n\nconst infoText: CSSProperties = { color: 'InfoText' };\n\n/**\n * Picks {num} elements from {arr} evenly, from the first to the last\n */\nexport function pickElements<T>(arr: ReadonlyArray<T>, num: number): Array<T> {\n if (arr.length <= num) {\n return [...arr];\n }\n\n if (num < 2) {\n return [arr[arr.length / 2]];\n }\n\n const step = arr.length / (num - 1);\n return [\n ...Array.from(Array(num - 1)).map(\n (_, index) => arr[Math.round(index * step)],\n ),\n arr[arr.length - 1],\n ];\n}\n\nfunction formatDateShort(milliseconds: number) {\n if ((milliseconds as any) === 'auto') {\n // When recharts gets confused (empty data)\n return '';\n }\n return DateTime.fromMillis(milliseconds).toLocaleString(DateTime.DATE_SHORT);\n}\nfunction formatDateTimeShort(milliseconds: number) {\n if ((milliseconds as any) === 'auto') {\n // When recharts gets confused (empty data)\n return '';\n }\n return DateTime.fromMillis(milliseconds).toLocaleString(\n DateTime.DATETIME_SHORT,\n );\n}\n\nexport function labelFormatter(epoch: number) {\n return (\n <Typography component=\"span\" style={infoText}>\n {formatDateTimeShort(epoch)}\n </Typography>\n );\n}\n\nexport function labelFormatterWithoutTime(epoch: number) {\n return (\n <Typography component=\"span\" style={infoText}>\n {formatDateShort(epoch)}\n </Typography>\n );\n}\n\nexport function tickFormatterX(epoch: number) {\n return formatDateShort(epoch);\n}\n\nexport function tickFormatterY(duration: number) {\n if (duration === 0) {\n return '0';\n } else if (duration < 500) {\n return `${duration} ms`;\n }\n return formatDuration(duration)\n .replace(/second.*/, 'sec')\n .replace(/minute.*/, 'min')\n .replace(/hour.*/, 'h')\n .replace(/day.*/, 'd')\n .replace(/month.*/, 'm')\n .replace(/year.*/, 'y');\n}\n\nexport function tooltipValueFormatter(\n durationOrCount: number,\n name: string,\n): [any, any] {\n return [\n // TODO(Rugvip): Types don't allow returning elements, but it was here before so presumably works\n <Typography component=\"span\" style={infoText}>\n {capitalize(name)}:{' '}\n {name.endsWith(' count')\n ? durationOrCount\n : formatDuration(durationOrCount)}\n </Typography>,\n null,\n ];\n}\n\nexport function formatDuration(millis: number) {\n let rest = Math.round(millis);\n const days = Math.floor(rest / (1000 * 60 * 60 * 24));\n rest -= days * (1000 * 60 * 60 * 24);\n const hours = Math.floor(rest / (1000 * 60 * 60));\n rest -= hours * (1000 * 60 * 60);\n const minutes = Math.floor(rest / (1000 * 60));\n rest -= minutes * (1000 * 60);\n const seconds = Math.floor(rest / 1000);\n rest -= seconds * 1000;\n const milliseconds = rest;\n\n if (!days && !hours && !minutes) {\n if (seconds < 1) {\n return `${milliseconds}ms`;\n } else if (seconds < 2) {\n return `${((milliseconds + seconds * 1000) / 1000).toFixed(1)}s`;\n }\n }\n\n const dur = Duration.fromObject({\n ...(days && { days }),\n ...(hours && { hours }),\n ...(minutes && !days && { minutes }),\n ...(seconds && !days && !hours && { seconds }),\n });\n\n return humanizeDuration(dur.toMillis(), { round: true });\n}\n\nexport function formatDurationFromSeconds(seconds: number) {\n return formatDuration(seconds * 1000);\n}\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,140 @@
1
+ import React, { useState, useMemo, useCallback, useEffect } from 'react';
2
+ import Grid from '@material-ui/core/Grid';
3
+ import { makeStyles } from '@material-ui/core/styles';
4
+ import Alert from '@material-ui/lab/Alert';
5
+ import { useEntity } from '@backstage/plugin-catalog-react';
6
+ import { useApi, errorApiRef } from '@backstage/core-plugin-api';
7
+ import { DateTime } from 'luxon';
8
+ import { useCicdStatistics } from './hooks/use-cicd-statistics.esm.js';
9
+ import { useCicdConfiguration } from './hooks/use-cicd-configuration.esm.js';
10
+ import { buildsToChartableStages } from './charts/logic/conversions.esm.js';
11
+ import { ZoomProvider, useZoom } from './charts/zoom.esm.js';
12
+ import { StageChart } from './charts/stage-chart.esm.js';
13
+ import { StatusChart } from './charts/status-chart.esm.js';
14
+ import { getDefaultChartFilter, getDefaultViewOptions, ChartFilters } from './components/chart-filters.esm.js';
15
+ import { cleanupBuildTree } from './utils/stage-names.esm.js';
16
+ import { renderFallbacks, useAsyncChain } from './components/progress.esm.js';
17
+ import { sortFilterStatusType } from './utils/api.esm.js';
18
+
19
+ function EntityPageCicdCharts() {
20
+ const state = useCicdConfiguration();
21
+ return renderFallbacks(state, (value) => /* @__PURE__ */ React.createElement(ZoomProvider, null, /* @__PURE__ */ React.createElement(CicdCharts, { cicdConfiguration: value })));
22
+ }
23
+ const useStyles = makeStyles(
24
+ (theme) => ({
25
+ pane: {
26
+ padding: theme.spacing(1, 1, 1, 1)
27
+ }
28
+ }),
29
+ {
30
+ name: "CicdStatisticsView"
31
+ }
32
+ );
33
+ function startOfDay(date) {
34
+ return DateTime.fromJSDate(date).startOf("day").toJSDate();
35
+ }
36
+ function endOfDay(date) {
37
+ return DateTime.fromJSDate(date).endOf("day").toJSDate();
38
+ }
39
+ function cleanChartFilter(filter) {
40
+ return {
41
+ ...filter,
42
+ status: sortFilterStatusType(filter.status)
43
+ };
44
+ }
45
+ function CicdCharts(props) {
46
+ const { cicdConfiguration } = props;
47
+ const errorApi = useApi(errorApiRef);
48
+ const { entity } = useEntity();
49
+ const classes = useStyles();
50
+ const { resetZoom } = useZoom();
51
+ const [chartFilter, setChartFilter] = useState(
52
+ getDefaultChartFilter(cicdConfiguration)
53
+ );
54
+ const [fetchedChartData, setFetchedChartData] = useState({
55
+ abortController: null,
56
+ chartFilter
57
+ });
58
+ const [viewOptions, setViewOptions] = useState(
59
+ getDefaultViewOptions(cicdConfiguration)
60
+ );
61
+ const fetchStatisticsOptions = useMemo(() => {
62
+ const abortController = new AbortController();
63
+ fetchedChartData.abortController = abortController;
64
+ return {
65
+ abortController,
66
+ entity,
67
+ timeFrom: startOfDay(fetchedChartData.chartFilter.fromDate),
68
+ timeTo: endOfDay(fetchedChartData.chartFilter.toDate),
69
+ filterStatus: fetchedChartData.chartFilter.status,
70
+ filterType: fetchedChartData.chartFilter.branch
71
+ };
72
+ }, [entity, fetchedChartData]);
73
+ const statisticsState = useCicdStatistics(fetchStatisticsOptions);
74
+ const updateFilter = useCallback(() => {
75
+ fetchedChartData.abortController?.abort();
76
+ setFetchedChartData({ abortController: null, chartFilter });
77
+ }, [fetchedChartData, setFetchedChartData, chartFilter]);
78
+ const chartableStagesState = useAsyncChain(
79
+ statisticsState,
80
+ async (value) => buildsToChartableStages(
81
+ await cleanupBuildTree(value.builds, {
82
+ formatStageName: cicdConfiguration.formatStageName,
83
+ lowerCase: viewOptions.lowercaseNames
84
+ }),
85
+ { normalizeTimeRange: viewOptions.normalizeTimeRange }
86
+ ),
87
+ [statisticsState, cicdConfiguration, viewOptions]
88
+ );
89
+ useEffect(() => {
90
+ resetZoom();
91
+ }, [resetZoom, statisticsState.value]);
92
+ const onFilterChange = useCallback((filter) => {
93
+ setChartFilter(cleanChartFilter(filter));
94
+ }, []);
95
+ const onViewOptionsChange = useCallback(
96
+ (options) => {
97
+ setViewOptions(options);
98
+ },
99
+ [setViewOptions]
100
+ );
101
+ useEffect(() => {
102
+ if (!chartableStagesState.error || chartableStagesState.error?.name === "AbortError") {
103
+ return;
104
+ }
105
+ errorApi.post(chartableStagesState.error);
106
+ }, [errorApi, chartableStagesState.error]);
107
+ return /* @__PURE__ */ React.createElement(Grid, { container: true }, /* @__PURE__ */ React.createElement(Grid, { item: true, lg: 2, className: classes.pane }, /* @__PURE__ */ React.createElement(
108
+ ChartFilters,
109
+ {
110
+ analysis: chartableStagesState.value,
111
+ cicdConfiguration,
112
+ initialFetchFilter: chartFilter,
113
+ currentFetchFilter: fetchedChartData.chartFilter,
114
+ onChangeFetchFilter: onFilterChange,
115
+ updateFetchFilter: updateFilter,
116
+ initialViewOptions: viewOptions,
117
+ onChangeViewOptions: onViewOptionsChange
118
+ }
119
+ )), /* @__PURE__ */ React.createElement(Grid, { item: true, xs: 12, lg: 10, className: classes.pane }, renderFallbacks(chartableStagesState, (chartableStages) => /* @__PURE__ */ React.createElement(React.Fragment, null, chartableStages.stages.size > 0 ? null : /* @__PURE__ */ React.createElement(Alert, { severity: "info" }, "No data"), !statisticsState.value?.builds?.length || !chartableStagesState.value?.daily?.values?.length ? null : /* @__PURE__ */ React.createElement(StatusChart, { analysis: chartableStagesState.value }), /* @__PURE__ */ React.createElement(
120
+ StageChart,
121
+ {
122
+ stage: chartableStages.total,
123
+ defaultCollapsed: 0,
124
+ defaultHidden: viewOptions.hideLimit,
125
+ chartTypes: viewOptions.chartTypes
126
+ }
127
+ ), [...chartableStages.stages.entries()].map(([name, stage]) => /* @__PURE__ */ React.createElement(
128
+ StageChart,
129
+ {
130
+ key: name,
131
+ stage,
132
+ defaultCollapsed: viewOptions.collapsedLimit,
133
+ defaultHidden: viewOptions.hideLimit,
134
+ chartTypes: viewOptions.chartTypes
135
+ }
136
+ ))))));
137
+ }
138
+
139
+ export { EntityPageCicdCharts };
140
+ //# sourceMappingURL=entity-page.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"entity-page.esm.js","sources":["../src/entity-page.tsx"],"sourcesContent":["/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport React, { useCallback, useState, useMemo, useEffect } from 'react';\nimport Grid from '@material-ui/core/Grid';\nimport { makeStyles } from '@material-ui/core/styles';\nimport Alert from '@material-ui/lab/Alert';\nimport { useEntity } from '@backstage/plugin-catalog-react';\nimport { useApi, errorApiRef } from '@backstage/core-plugin-api';\nimport { DateTime } from 'luxon';\n\nimport {\n useCicdStatistics,\n UseCicdStatisticsOptions,\n} from './hooks/use-cicd-statistics';\nimport { useCicdConfiguration } from './hooks/use-cicd-configuration';\nimport { buildsToChartableStages } from './charts/logic/conversions';\nimport { ZoomProvider, useZoom } from './charts/zoom';\nimport { StageChart } from './charts/stage-chart';\nimport { StatusChart } from './charts/status-chart';\nimport {\n ChartFilter,\n ChartFilters,\n getDefaultChartFilter,\n getDefaultViewOptions,\n ViewOptions,\n} from './components/chart-filters';\nimport {\n CicdConfiguration,\n FilterStatusType,\n FilterBranchType,\n} from './apis/types';\nimport { cleanupBuildTree } from './utils/stage-names';\nimport { renderFallbacks, useAsyncChain } from './components/progress';\nimport { sortFilterStatusType } from './utils/api';\n\n/** @public */\nexport function EntityPageCicdCharts() {\n const state = useCicdConfiguration();\n\n return renderFallbacks(state, value => (\n <ZoomProvider>\n <CicdCharts cicdConfiguration={value} />\n </ZoomProvider>\n ));\n}\n\nconst useStyles = makeStyles(\n theme => ({\n pane: {\n padding: theme.spacing(1, 1, 1, 1),\n },\n }),\n {\n name: 'CicdStatisticsView',\n },\n);\n\nfunction startOfDay(date: Date) {\n return DateTime.fromJSDate(date).startOf('day').toJSDate();\n}\nfunction endOfDay(date: Date) {\n return DateTime.fromJSDate(date).endOf('day').toJSDate();\n}\nfunction cleanChartFilter(filter: ChartFilter): ChartFilter {\n return {\n ...filter,\n status: sortFilterStatusType(filter.status as FilterStatusType[]),\n };\n}\n\ninterface CicdChartsProps {\n cicdConfiguration: CicdConfiguration;\n}\n\nfunction CicdCharts(props: CicdChartsProps) {\n const { cicdConfiguration } = props;\n\n const errorApi = useApi(errorApiRef);\n const { entity } = useEntity();\n\n const classes = useStyles();\n\n const { resetZoom } = useZoom();\n\n const [chartFilter, setChartFilter] = useState(\n getDefaultChartFilter(cicdConfiguration),\n );\n const [fetchedChartData, setFetchedChartData] = useState({\n abortController: null as null | AbortController,\n chartFilter,\n });\n\n const [viewOptions, setViewOptions] = useState(\n getDefaultViewOptions(cicdConfiguration),\n );\n\n const fetchStatisticsOptions = useMemo((): UseCicdStatisticsOptions => {\n const abortController = new AbortController();\n fetchedChartData.abortController = abortController;\n return {\n abortController,\n entity,\n timeFrom: startOfDay(fetchedChartData.chartFilter.fromDate),\n timeTo: endOfDay(fetchedChartData.chartFilter.toDate),\n filterStatus: fetchedChartData.chartFilter.status as FilterStatusType[],\n filterType: fetchedChartData.chartFilter.branch as FilterBranchType,\n };\n }, [entity, fetchedChartData]);\n\n const statisticsState = useCicdStatistics(fetchStatisticsOptions);\n\n const updateFilter = useCallback(() => {\n // Abort previous fetch\n fetchedChartData.abortController?.abort();\n\n setFetchedChartData({ abortController: null, chartFilter });\n }, [fetchedChartData, setFetchedChartData, chartFilter]);\n\n const chartableStagesState = useAsyncChain(\n statisticsState,\n async value =>\n buildsToChartableStages(\n await cleanupBuildTree(value.builds, {\n formatStageName: cicdConfiguration.formatStageName,\n lowerCase: viewOptions.lowercaseNames,\n }),\n { normalizeTimeRange: viewOptions.normalizeTimeRange },\n ),\n [statisticsState, cicdConfiguration, viewOptions],\n );\n\n useEffect(() => {\n resetZoom();\n }, [resetZoom, statisticsState.value]);\n\n const onFilterChange = useCallback((filter: ChartFilter) => {\n setChartFilter(cleanChartFilter(filter));\n }, []);\n\n const onViewOptionsChange = useCallback(\n (options: ViewOptions) => {\n setViewOptions(options);\n },\n [setViewOptions],\n );\n\n useEffect(() => {\n if (\n !chartableStagesState.error ||\n chartableStagesState.error?.name === 'AbortError'\n ) {\n return;\n }\n errorApi.post(chartableStagesState.error);\n }, [errorApi, chartableStagesState.error]);\n\n return (\n <Grid container>\n <Grid item lg={2} className={classes.pane}>\n <ChartFilters\n analysis={chartableStagesState.value}\n cicdConfiguration={cicdConfiguration}\n initialFetchFilter={chartFilter}\n currentFetchFilter={fetchedChartData.chartFilter}\n onChangeFetchFilter={onFilterChange}\n updateFetchFilter={updateFilter}\n initialViewOptions={viewOptions}\n onChangeViewOptions={onViewOptionsChange}\n />\n </Grid>\n <Grid item xs={12} lg={10} className={classes.pane}>\n {renderFallbacks(chartableStagesState, chartableStages => (\n <>\n {chartableStages.stages.size > 0 ? null : (\n <Alert severity=\"info\">No data</Alert>\n )}\n {!statisticsState.value?.builds?.length ||\n !chartableStagesState.value?.daily?.values?.length ? null : (\n <StatusChart analysis={chartableStagesState.value} />\n )}\n <StageChart\n stage={chartableStages.total}\n defaultCollapsed={0}\n defaultHidden={viewOptions.hideLimit}\n chartTypes={viewOptions.chartTypes}\n />\n {[...chartableStages.stages.entries()].map(([name, stage]) => (\n <StageChart\n key={name}\n stage={stage}\n defaultCollapsed={viewOptions.collapsedLimit}\n defaultHidden={viewOptions.hideLimit}\n chartTypes={viewOptions.chartTypes}\n />\n ))}\n </>\n ))}\n </Grid>\n </Grid>\n );\n}\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,40 @@
1
+ import { useState, useEffect } from 'react';
2
+ import { useEntity } from '@backstage/plugin-catalog-react';
3
+ import { statusTypes } from '../apis/types.esm.js';
4
+ import '../apis/cicd-statistics.esm.js';
5
+ import { defaultFormatStageName } from '../utils/stage-names.esm.js';
6
+ import { useCicdStatisticsApi } from './use-cicd-statistics-api.esm.js';
7
+
8
+ function useCicdConfiguration() {
9
+ const cicdStatisticsApi = useCicdStatisticsApi();
10
+ const { entity } = useEntity();
11
+ const [state, setState] = useState({
12
+ loading: true
13
+ });
14
+ useEffect(() => {
15
+ if (!cicdStatisticsApi) {
16
+ setState({ error: new Error("No CI/CD Statistics API installed") });
17
+ return;
18
+ }
19
+ cicdStatisticsApi.getConfiguration({ entity }).then((configuration) => {
20
+ const {
21
+ availableStatuses = statusTypes,
22
+ formatStageName = defaultFormatStageName,
23
+ defaults = {}
24
+ } = configuration;
25
+ setState({
26
+ value: {
27
+ availableStatuses,
28
+ formatStageName,
29
+ defaults
30
+ }
31
+ });
32
+ }).catch((error) => {
33
+ setState({ error });
34
+ });
35
+ }, [cicdStatisticsApi, entity]);
36
+ return state;
37
+ }
38
+
39
+ export { useCicdConfiguration };
40
+ //# sourceMappingURL=use-cicd-configuration.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-cicd-configuration.esm.js","sources":["../../src/hooks/use-cicd-configuration.ts"],"sourcesContent":["/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { useState, useEffect } from 'react';\nimport { useEntity } from '@backstage/plugin-catalog-react';\n\nimport { CicdConfiguration, statusTypes } from '../apis';\nimport { ProgressType } from '../components/progress';\nimport { defaultFormatStageName } from '../utils/stage-names';\nimport { useCicdStatisticsApi } from './use-cicd-statistics-api';\n\nexport function useCicdConfiguration(): ProgressType<CicdConfiguration> {\n const cicdStatisticsApi = useCicdStatisticsApi();\n const { entity } = useEntity();\n\n const [state, setState] = useState<ProgressType<CicdConfiguration>>({\n loading: true,\n });\n\n useEffect(() => {\n if (!cicdStatisticsApi) {\n setState({ error: new Error('No CI/CD Statistics API installed') });\n return;\n }\n\n cicdStatisticsApi\n .getConfiguration({ entity })\n .then(configuration => {\n const {\n availableStatuses = statusTypes,\n formatStageName = defaultFormatStageName,\n defaults = {},\n } = configuration;\n setState({\n value: {\n availableStatuses,\n formatStageName,\n defaults,\n },\n });\n })\n .catch(error => {\n setState({ error });\n });\n }, [cicdStatisticsApi, entity]);\n\n return state;\n}\n"],"names":[],"mappings":";;;;;;;AAwBO,SAAS,oBAAwD,GAAA;AACtE,EAAA,MAAM,oBAAoB,oBAAqB,EAAA,CAAA;AAC/C,EAAM,MAAA,EAAE,MAAO,EAAA,GAAI,SAAU,EAAA,CAAA;AAE7B,EAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,CAAA,GAAI,QAA0C,CAAA;AAAA,IAClE,OAAS,EAAA,IAAA;AAAA,GACV,CAAA,CAAA;AAED,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,IAAI,CAAC,iBAAmB,EAAA;AACtB,MAAA,QAAA,CAAS,EAAE,KAAO,EAAA,IAAI,KAAM,CAAA,mCAAmC,GAAG,CAAA,CAAA;AAClE,MAAA,OAAA;AAAA,KACF;AAEA,IAAA,iBAAA,CACG,iBAAiB,EAAE,MAAA,EAAQ,CAAA,CAC3B,KAAK,CAAiB,aAAA,KAAA;AACrB,MAAM,MAAA;AAAA,QACJ,iBAAoB,GAAA,WAAA;AAAA,QACpB,eAAkB,GAAA,sBAAA;AAAA,QAClB,WAAW,EAAC;AAAA,OACV,GAAA,aAAA,CAAA;AACJ,MAAS,QAAA,CAAA;AAAA,QACP,KAAO,EAAA;AAAA,UACL,iBAAA;AAAA,UACA,eAAA;AAAA,UACA,QAAA;AAAA,SACF;AAAA,OACD,CAAA,CAAA;AAAA,KACF,CACA,CAAA,KAAA,CAAM,CAAS,KAAA,KAAA;AACd,MAAS,QAAA,CAAA,EAAE,OAAO,CAAA,CAAA;AAAA,KACnB,CAAA,CAAA;AAAA,GACF,EAAA,CAAC,iBAAmB,EAAA,MAAM,CAAC,CAAA,CAAA;AAE9B,EAAO,OAAA,KAAA,CAAA;AACT;;;;"}
@@ -0,0 +1,13 @@
1
+ import { useApi } from '@backstage/core-plugin-api';
2
+ import { cicdStatisticsApiRef } from '../apis/cicd-statistics.esm.js';
3
+
4
+ function useCicdStatisticsApi() {
5
+ try {
6
+ return useApi(cicdStatisticsApiRef);
7
+ } catch (err) {
8
+ return void 0;
9
+ }
10
+ }
11
+
12
+ export { useCicdStatisticsApi };
13
+ //# sourceMappingURL=use-cicd-statistics-api.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-cicd-statistics-api.esm.js","sources":["../../src/hooks/use-cicd-statistics-api.ts"],"sourcesContent":["/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { useApi } from '@backstage/core-plugin-api';\n\nimport { cicdStatisticsApiRef } from '../apis';\n\nexport function useCicdStatisticsApi() {\n try {\n return useApi(cicdStatisticsApiRef);\n } catch (err) {\n return undefined;\n }\n}\n"],"names":[],"mappings":";;;AAoBO,SAAS,oBAAuB,GAAA;AACrC,EAAI,IAAA;AACF,IAAA,OAAO,OAAO,oBAAoB,CAAA,CAAA;AAAA,WAC3B,GAAK,EAAA;AACZ,IAAO,OAAA,KAAA,CAAA,CAAA;AAAA,GACT;AACF;;;;"}
@@ -0,0 +1,100 @@
1
+ import { useState, useEffect } from 'react';
2
+ import { throttle } from 'lodash';
3
+ import { AbortError } from '../apis/types.esm.js';
4
+ import '../apis/cicd-statistics.esm.js';
5
+ import { useCicdStatisticsApi } from './use-cicd-statistics-api.esm.js';
6
+
7
+ function useCicdStatistics(options) {
8
+ const {
9
+ entity,
10
+ abortController,
11
+ timeFrom,
12
+ timeTo,
13
+ filterStatus,
14
+ filterType
15
+ } = options;
16
+ const [state, setState] = useState({
17
+ loading: true
18
+ });
19
+ const cicdStatisticsApi = useCicdStatisticsApi();
20
+ useEffect(() => {
21
+ if (!cicdStatisticsApi) {
22
+ setState({ error: new Error("No CI/CD Statistics API installed") });
23
+ return () => {
24
+ };
25
+ }
26
+ let mounted = true;
27
+ let completed = false;
28
+ const updateProgressImpl = (_count, _total, _started) => {
29
+ if (!mounted || completed) {
30
+ return;
31
+ }
32
+ if (Array.isArray(_count)) {
33
+ setState({
34
+ loading: true,
35
+ steps: _count.map((step) => ({
36
+ title: step.title,
37
+ progress: !step.total ? 0 : step.completed / step.total,
38
+ progressBuffer: !step.total ? 0 : (step.started ?? 0) / step.total
39
+ }))
40
+ });
41
+ } else {
42
+ const count = _count;
43
+ const total = _total;
44
+ const started = _started ?? 0;
45
+ setState({
46
+ loading: true,
47
+ progress: !total ? 0 : count / total,
48
+ progressBuffer: !total ? 0 : started / total
49
+ });
50
+ }
51
+ };
52
+ const updateProgress = throttle(
53
+ updateProgressImpl,
54
+ 200
55
+ // throttle doesn't handle types of multi-signature functions
56
+ );
57
+ const fetchOptions = {
58
+ entity,
59
+ updateProgress,
60
+ abortSignal: abortController.signal,
61
+ timeFrom,
62
+ timeTo,
63
+ filterStatus,
64
+ filterType
65
+ };
66
+ (async () => {
67
+ return cicdStatisticsApi.fetchBuilds(fetchOptions);
68
+ })().then((builds) => {
69
+ completed = true;
70
+ if (mounted) {
71
+ setState({
72
+ value: builds
73
+ });
74
+ }
75
+ }).catch((err) => {
76
+ completed = true;
77
+ if (mounted) {
78
+ setState({
79
+ error: abortController.signal.aborted ? new AbortError() : err
80
+ });
81
+ }
82
+ });
83
+ return () => {
84
+ mounted = false;
85
+ abortController.abort();
86
+ };
87
+ }, [
88
+ abortController,
89
+ entity,
90
+ timeFrom,
91
+ timeTo,
92
+ filterStatus,
93
+ filterType,
94
+ cicdStatisticsApi
95
+ ]);
96
+ return state;
97
+ }
98
+
99
+ export { useCicdStatistics };
100
+ //# sourceMappingURL=use-cicd-statistics.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-cicd-statistics.esm.js","sources":["../../src/hooks/use-cicd-statistics.ts"],"sourcesContent":["/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { useState, useEffect } from 'react';\nimport { throttle } from 'lodash';\nimport { Entity } from '@backstage/catalog-model';\n\nimport {\n CicdState,\n FetchBuildsOptions,\n AbortError,\n FilterStatusType,\n FilterBranchType,\n UpdateProgress,\n} from '../apis';\nimport { ProgressType } from '../components/progress';\nimport { useCicdStatisticsApi } from './use-cicd-statistics-api';\n\nexport interface UseCicdStatisticsOptions {\n entity: Entity;\n abortController: AbortController;\n timeFrom: Date;\n timeTo: Date;\n filterStatus: Array<FilterStatusType | 'all'>;\n filterType: FilterBranchType | 'all';\n}\n\nexport function useCicdStatistics(\n options: UseCicdStatisticsOptions,\n): ProgressType<CicdState> {\n const {\n entity,\n abortController,\n timeFrom,\n timeTo,\n filterStatus,\n filterType,\n } = options;\n\n const [state, setState] = useState<ProgressType<CicdState>>({\n loading: true,\n });\n\n const cicdStatisticsApi = useCicdStatisticsApi();\n\n useEffect(() => {\n if (!cicdStatisticsApi) {\n setState({ error: new Error('No CI/CD Statistics API installed') });\n return () => {};\n }\n\n let mounted = true;\n let completed = false; // successfully or failed\n\n const updateProgressImpl: UpdateProgress = (_count, _total?, _started?) => {\n if (!mounted || completed) {\n return;\n }\n\n if (Array.isArray(_count)) {\n // Multi-progress\n setState({\n loading: true,\n steps: _count.map(step => ({\n title: step.title,\n progress: !step.total ? 0 : step.completed / step.total,\n progressBuffer: !step.total ? 0 : (step.started ?? 0) / step.total,\n })),\n });\n } else {\n // Single-progress\n const count = _count;\n const total = _total as number;\n const started = (_started as number) ?? 0;\n setState({\n loading: true,\n progress: !total ? 0 : count / total,\n progressBuffer: !total ? 0 : started / total,\n });\n }\n };\n\n const updateProgress = throttle(\n updateProgressImpl,\n 200,\n // throttle doesn't handle types of multi-signature functions\n ) as any as UpdateProgress;\n\n const fetchOptions: FetchBuildsOptions = {\n entity,\n updateProgress,\n abortSignal: abortController.signal,\n timeFrom,\n timeTo,\n filterStatus,\n filterType,\n };\n\n (async () => {\n return cicdStatisticsApi.fetchBuilds(fetchOptions);\n })()\n .then(builds => {\n completed = true;\n if (mounted) {\n setState({\n value: builds,\n });\n }\n })\n .catch(err => {\n completed = true;\n if (mounted) {\n setState({\n error: abortController.signal.aborted ? new AbortError() : err,\n });\n }\n });\n\n return () => {\n mounted = false;\n abortController.abort();\n };\n }, [\n abortController,\n entity,\n timeFrom,\n timeTo,\n filterStatus,\n filterType,\n cicdStatisticsApi,\n ]);\n\n return state;\n}\n"],"names":[],"mappings":"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"}
package/dist/index.esm.js CHANGED
@@ -1,45 +1,4 @@
1
- import { createRouteRef, createPlugin, createRoutableExtension, createApiRef } from '@backstage/core-plugin-api';
2
-
3
- const rootCatalogCicdStatsRouteRef = createRouteRef({
4
- id: "cicd-statistics"
5
- });
6
- const cicdStatisticsPlugin = createPlugin({
7
- id: "cicd-statistics",
8
- routes: {
9
- entityContent: rootCatalogCicdStatsRouteRef
10
- }
11
- });
12
- const EntityCicdStatisticsContent = cicdStatisticsPlugin.provide(
13
- createRoutableExtension({
14
- component: () => import('./esm/entity-page-CNIrdNBp.esm.js').then((m) => m.EntityPageCicdCharts),
15
- mountPoint: rootCatalogCicdStatsRouteRef,
16
- name: "EntityCicdStatisticsContent"
17
- })
18
- );
19
-
20
- const statusTypes = [
21
- "succeeded",
22
- "failed",
23
- "enqueued",
24
- "scheduled",
25
- "running",
26
- "aborted",
27
- "stalled",
28
- "expired",
29
- "unknown"
30
- ];
31
- const triggerReasons = [
32
- "scm",
33
- "manual",
34
- "internal",
35
- "other"
36
- ];
37
- class AbortError extends Error {
38
- }
39
-
40
- const cicdStatisticsApiRef = createApiRef({
41
- id: "cicd-statistics-api"
42
- });
43
-
44
- export { AbortError, EntityCicdStatisticsContent, cicdStatisticsApiRef, cicdStatisticsPlugin, statusTypes, triggerReasons };
1
+ export { EntityCicdStatisticsContent, cicdStatisticsPlugin } from './plugin.esm.js';
2
+ export { AbortError, statusTypes, triggerReasons } from './apis/types.esm.js';
3
+ export { cicdStatisticsApiRef } from './apis/cicd-statistics.esm.js';
45
4
  //# sourceMappingURL=index.esm.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.esm.js","sources":["../src/plugin.ts","../src/apis/types.ts","../src/apis/cicd-statistics.ts"],"sourcesContent":["/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n createPlugin,\n createRoutableExtension,\n createRouteRef,\n} from '@backstage/core-plugin-api';\n\nexport type { EntityPageCicdCharts } from './entity-page';\n\nconst rootCatalogCicdStatsRouteRef = createRouteRef({\n id: 'cicd-statistics',\n});\n\n/** @public */\nexport const cicdStatisticsPlugin = createPlugin({\n id: 'cicd-statistics',\n routes: {\n entityContent: rootCatalogCicdStatsRouteRef,\n },\n});\n\n/** @public */\nexport const EntityCicdStatisticsContent = cicdStatisticsPlugin.provide(\n createRoutableExtension({\n component: () => import('./entity-page').then(m => m.EntityPageCicdCharts),\n mountPoint: rootCatalogCicdStatsRouteRef,\n name: 'EntityCicdStatisticsContent',\n }),\n);\n","/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Entity } from '@backstage/catalog-model';\n\n/**\n * This is a generic enum of build statuses.\n *\n * If all of these aren't applicable to the underlying CI/CD, these can be\n * configured to be hidden, using the `availableStatuses` in `CicdConfiguration`.\n *\n * @public\n */\nexport type FilterStatusType =\n | 'unknown'\n | 'enqueued'\n | 'scheduled'\n | 'running'\n | 'aborted'\n | 'succeeded'\n | 'failed'\n | 'stalled'\n | 'expired';\n\n/**\n * @public\n */\nexport const statusTypes: Array<FilterStatusType> = [\n 'succeeded',\n 'failed',\n 'enqueued',\n 'scheduled',\n 'running',\n 'aborted',\n 'stalled',\n 'expired',\n 'unknown',\n];\n\n/**\n * The branch enum of either 'master' or 'branch' (or possibly the meta 'all').\n *\n * The concept of what constitutes a master branch is generic. It might be called\n * something like 'release' or 'main' or 'trunk' in the underlying CI/CD system,\n * which is then up to the Api to map accordingly.\n *\n * @public\n */\nexport type FilterBranchType = 'master' | 'branch';\n\n/**\n * @public\n */\nexport type TriggerReason =\n /** Triggered by source code management, e.g. a Github hook */\n | 'scm'\n /** Triggered manually */\n | 'manual'\n /** Triggered internally (non-scm, or perhaps after being delayed/enqueued) */\n | 'internal'\n /** Triggered for some other reason */\n | 'other';\n\n/**\n * @public\n */\nexport const triggerReasons: Array<TriggerReason> = [\n 'scm',\n 'manual',\n 'internal',\n 'other',\n];\n\n/**\n * A Stage is a part of either a Build or a parent Stage.\n *\n * This may be called things like Stage or Step or Task in CI/CD systems, but is\n * generic here. There's also no concept of parallelism which might exist within\n * some stages.\n *\n * @public\n */\nexport interface Stage {\n name: string;\n\n /** The status of the stage */\n status: FilterStatusType;\n\n /** Stage duration in milliseconds */\n duration: number;\n\n /** Sub stages within this stage */\n stages?: Array<Stage>;\n}\n\n/**\n * Generic Build type.\n *\n * A build has e.g. a build type (master/branch), a status and (possibly) sub stages.\n *\n * @public\n */\nexport interface Build {\n raw?: unknown;\n\n /** Build id */\n id: string;\n\n /** The reason this build was started */\n triggeredBy?: TriggerReason;\n\n /** The status of the build */\n status: FilterStatusType;\n\n /** Branch type */\n branchType: FilterBranchType;\n\n /** Time when the build started */\n requestedAt: Date;\n\n /** The overall duration of the build */\n duration: number;\n\n /** Top-level build stages */\n stages: Array<Stage>;\n}\n\n/**\n * Helper type which is a Build with a certain typed 'raw' field.\n *\n * This can be useful in an Api to use while mapping internal data structures\n * (raw) into generic builds.\n *\n * @public\n */\nexport type BuildWithRaw<T = any> = Build & {\n raw: T;\n};\n\n/**\n * Chart type.\n *\n * Values are:\n * * `duration`: shows an area chart of the duration over time\n * * `count`: shows a bar chart of the number of build per day\n *\n * @public\n */\nexport type ChartType = 'duration' | 'count';\n\n/**\n * Chart types.\n *\n * @public\n */\nexport type ChartTypes = Array<ChartType>;\n\n/**\n * Default settings for the fetching options and view options.\n *\n * These are all optional, but can be overridden from the Api to whatever makes\n * most sense for that implementation.\n *\n * @public\n */\nexport interface CicdDefaults {\n timeFrom: Date;\n timeTo: Date;\n filterStatus: Array<FilterStatusType>;\n filterType: FilterBranchType | 'all';\n\n /** Lower-case all stage names (to potentially merge stages with different cases) */\n lowercaseNames: boolean;\n /** Normalize the from-to date range in all charts */\n normalizeTimeRange: boolean;\n /** Default collapse the stages with a max-duration below this value */\n collapsedLimit: number;\n /** Default hide stages with a max-duration below this value */\n hideLimit: number;\n /** Chart types per status */\n chartTypes: Record<FilterStatusType, ChartTypes>;\n}\n\n/**\n * A configuration interface which the Api must implement.\n *\n * When the UI for the CI/CD Statistics is loaded, it begins with fetching the\n * configuration before anything else.\n *\n * All of these fields are optional though, and will fallback to hard-coded defaults.\n *\n * @public\n */\nexport interface CicdConfiguration {\n /**\n * This field can be used to override what statuses are available\n */\n availableStatuses: ReadonlyArray<FilterStatusType>;\n\n /**\n * When transposing the list of builds into a tree of stages, the stage names\n * will be transformed through this function.\n *\n * Override this for a custom implementation. The default will try to remove\n * parent names off of child names, if they are prepended by them.\n *\n * For example; if a stage has the name 'Install' and a child stage has the\n * name 'Install - Fetch dependencies', the child name will be replaced with\n * 'Fetch dependencies'.\n */\n formatStageName: (parentNames: Array<string>, stageName: string) => string;\n\n /**\n * Default options for the UI\n */\n defaults: Partial<CicdDefaults>;\n}\n\n/**\n * If the Api implements support for aborting the fetching of builds, throw an\n * AbortError of this type (or any other error with name === 'AbortError').\n *\n * @public\n */\nexport class AbortError extends Error {}\n\n/**\n * The result type for `fetchBuilds`.\n *\n * @public\n */\nexport interface CicdState {\n builds: Array<Build>;\n}\n\n/**\n * When fetching, if applicable, the Api can feedback progress back to the UI.\n *\n * Use the `updateProgress(completed, total, started?)` to signal that\n * `completed` builds out of a `total` has finished. Optionally use the\n * `started` to signal how many builds have been started in total (i.e. at least\n * the amount of `completed`).\n *\n * This can be called at any rate. Rate limiting (debouncing) is implemented in\n * the UI.\n *\n * Optionally this can signal multiple progresses in several steps\n *\n * @public\n */\nexport interface UpdateProgress {\n (completed: number, total: number, started?: number): void;\n (\n steps: Array<{\n title: string;\n completed: number;\n total: number;\n started?: number;\n }>,\n ): void;\n}\n\n/**\n * When reading configuration, the Api can return a custom settings depending on\n * the entity being viewed.\n *\n * @public\n */\nexport interface GetConfigurationOptions {\n entity: Entity;\n}\n\n/**\n * When fetching, the Api should fetch build information about the `entity` and\n * respect the `timeFrom`, `timeTo`, `filterStatus` and `filterType`.\n *\n * Optionally implement support for `updateProgress` and `abortSignal` if\n * preferred.\n *\n * When the UI re-fetches, it will abort any previous fetching, so polling\n * `abortSignal.aborted`, and possibly throwing an `AbortError`, can be useful.\n *\n * @public\n */\nexport interface FetchBuildsOptions {\n entity: Entity;\n updateProgress: UpdateProgress;\n abortSignal: AbortSignal;\n timeFrom: Date;\n timeTo: Date;\n filterStatus: Array<FilterStatusType | 'all'>;\n filterType: FilterBranchType | 'all';\n}\n\n/**\n * The interface which is mapped to the `cicdStatisticsApiRef` which is used by\n * the UI.\n *\n * @public\n */\nexport interface CicdStatisticsApi {\n getConfiguration(\n options: GetConfigurationOptions,\n ): Promise<Partial<CicdConfiguration>>;\n fetchBuilds(options: FetchBuildsOptions): Promise<CicdState>;\n}\n","/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { createApiRef } from '@backstage/core-plugin-api';\nimport { CicdStatisticsApi } from './types';\n\n/** @public */\nexport const cicdStatisticsApiRef = createApiRef<CicdStatisticsApi>({\n id: 'cicd-statistics-api',\n});\n"],"names":[],"mappings":";;AAwBA,MAAM,+BAA+B,cAAe,CAAA;AAAA,EAClD,EAAI,EAAA,iBAAA;AACN,CAAC,CAAA,CAAA;AAGM,MAAM,uBAAuB,YAAa,CAAA;AAAA,EAC/C,EAAI,EAAA,iBAAA;AAAA,EACJ,MAAQ,EAAA;AAAA,IACN,aAAe,EAAA,4BAAA;AAAA,GACjB;AACF,CAAC,EAAA;AAGM,MAAM,8BAA8B,oBAAqB,CAAA,OAAA;AAAA,EAC9D,uBAAwB,CAAA;AAAA,IACtB,SAAA,EAAW,MAAM,OAAO,mCAAe,EAAE,IAAK,CAAA,CAAA,CAAA,KAAK,EAAE,oBAAoB,CAAA;AAAA,IACzE,UAAY,EAAA,4BAAA;AAAA,IACZ,IAAM,EAAA,6BAAA;AAAA,GACP,CAAA;AACH;;ACHO,MAAM,WAAuC,GAAA;AAAA,EAClD,WAAA;AAAA,EACA,QAAA;AAAA,EACA,UAAA;AAAA,EACA,WAAA;AAAA,EACA,SAAA;AAAA,EACA,SAAA;AAAA,EACA,SAAA;AAAA,EACA,SAAA;AAAA,EACA,SAAA;AACF,EAAA;AA6BO,MAAM,cAAuC,GAAA;AAAA,EAClD,KAAA;AAAA,EACA,QAAA;AAAA,EACA,UAAA;AAAA,EACA,OAAA;AACF,EAAA;AAyJO,MAAM,mBAAmB,KAAM,CAAA;AAAC;;ACzNhC,MAAM,uBAAuB,YAAgC,CAAA;AAAA,EAClE,EAAI,EAAA,qBAAA;AACN,CAAC;;;;"}
1
+ {"version":3,"file":"index.esm.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;"}
@@ -0,0 +1,21 @@
1
+ import { createRouteRef, createPlugin, createRoutableExtension } from '@backstage/core-plugin-api';
2
+
3
+ const rootCatalogCicdStatsRouteRef = createRouteRef({
4
+ id: "cicd-statistics"
5
+ });
6
+ const cicdStatisticsPlugin = createPlugin({
7
+ id: "cicd-statistics",
8
+ routes: {
9
+ entityContent: rootCatalogCicdStatsRouteRef
10
+ }
11
+ });
12
+ const EntityCicdStatisticsContent = cicdStatisticsPlugin.provide(
13
+ createRoutableExtension({
14
+ component: () => import('./entity-page.esm.js').then((m) => m.EntityPageCicdCharts),
15
+ mountPoint: rootCatalogCicdStatsRouteRef,
16
+ name: "EntityCicdStatisticsContent"
17
+ })
18
+ );
19
+
20
+ export { EntityCicdStatisticsContent, cicdStatisticsPlugin };
21
+ //# sourceMappingURL=plugin.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin.esm.js","sources":["../src/plugin.ts"],"sourcesContent":["/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n createPlugin,\n createRoutableExtension,\n createRouteRef,\n} from '@backstage/core-plugin-api';\n\nexport type { EntityPageCicdCharts } from './entity-page';\n\nconst rootCatalogCicdStatsRouteRef = createRouteRef({\n id: 'cicd-statistics',\n});\n\n/** @public */\nexport const cicdStatisticsPlugin = createPlugin({\n id: 'cicd-statistics',\n routes: {\n entityContent: rootCatalogCicdStatsRouteRef,\n },\n});\n\n/** @public */\nexport const EntityCicdStatisticsContent = cicdStatisticsPlugin.provide(\n createRoutableExtension({\n component: () => import('./entity-page').then(m => m.EntityPageCicdCharts),\n mountPoint: rootCatalogCicdStatsRouteRef,\n name: 'EntityCicdStatisticsContent',\n }),\n);\n"],"names":[],"mappings":";;AAwBA,MAAM,+BAA+B,cAAe,CAAA;AAAA,EAClD,EAAI,EAAA,iBAAA;AACN,CAAC,CAAA,CAAA;AAGM,MAAM,uBAAuB,YAAa,CAAA;AAAA,EAC/C,EAAI,EAAA,iBAAA;AAAA,EACJ,MAAQ,EAAA;AAAA,IACN,aAAe,EAAA,4BAAA;AAAA,GACjB;AACF,CAAC,EAAA;AAGM,MAAM,8BAA8B,oBAAqB,CAAA,OAAA;AAAA,EAC9D,uBAAwB,CAAA;AAAA,IACtB,SAAA,EAAW,MAAM,OAAO,sBAAe,EAAE,IAAK,CAAA,CAAA,CAAA,KAAK,EAAE,oBAAoB,CAAA;AAAA,IACzE,UAAY,EAAA,4BAAA;AAAA,IACZ,IAAM,EAAA,6BAAA;AAAA,GACP,CAAA;AACH;;;;"}
@@ -0,0 +1,16 @@
1
+ import { statusTypes } from '../apis/types.esm.js';
2
+
3
+ function sortFilterStatusType(statuses) {
4
+ const statusSet = new Set(statuses);
5
+ const sorted = ["all", ...statusTypes].filter((status) => {
6
+ if (statusSet.has(status)) {
7
+ statusSet.delete(status);
8
+ return true;
9
+ }
10
+ return false;
11
+ });
12
+ return [...sorted, ...statusSet];
13
+ }
14
+
15
+ export { sortFilterStatusType };
16
+ //# sourceMappingURL=api.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api.esm.js","sources":["../../src/utils/api.ts"],"sourcesContent":["/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { FilterStatusType, statusTypes } from '../apis/types';\n\nexport function sortFilterStatusType<T extends FilterStatusType>(\n statuses: ReadonlyArray<T>,\n): Array<T> {\n const statusSet = new Set<T>(statuses);\n\n const sorted = (['all', ...statusTypes] as Array<T>).filter((status: T) => {\n if (statusSet.has(status)) {\n statusSet.delete(status);\n return true;\n }\n return false;\n });\n\n return [...sorted, ...statusSet];\n}\n"],"names":[],"mappings":";;AAkBO,SAAS,qBACd,QACU,EAAA;AACV,EAAM,MAAA,SAAA,GAAY,IAAI,GAAA,CAAO,QAAQ,CAAA,CAAA;AAErC,EAAM,MAAA,MAAA,GAAU,CAAC,KAAO,EAAA,GAAG,WAAW,CAAe,CAAA,MAAA,CAAO,CAAC,MAAc,KAAA;AACzE,IAAI,IAAA,SAAA,CAAU,GAAI,CAAA,MAAM,CAAG,EAAA;AACzB,MAAA,SAAA,CAAU,OAAO,MAAM,CAAA,CAAA;AACvB,MAAO,OAAA,IAAA,CAAA;AAAA,KACT;AACA,IAAO,OAAA,KAAA,CAAA;AAAA,GACR,CAAA,CAAA;AAED,EAAA,OAAO,CAAC,GAAG,MAAQ,EAAA,GAAG,SAAS,CAAA,CAAA;AACjC;;;;"}