@backstage-community/plugin-github-actions 0.6.16 → 0.6.17
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 +6 -0
- package/dist/api/GithubActionsApi.esm.js +8 -0
- package/dist/api/GithubActionsApi.esm.js.map +1 -0
- package/dist/api/GithubActionsClient.esm.js +113 -0
- package/dist/api/GithubActionsClient.esm.js.map +1 -0
- package/dist/api/types.esm.js +10 -0
- package/dist/api/types.esm.js.map +1 -0
- package/dist/components/Cards/Cards.esm.js +78 -0
- package/dist/components/Cards/Cards.esm.js.map +1 -0
- package/dist/components/Cards/RecentWorkflowRunsCard.esm.js +71 -0
- package/dist/components/Cards/RecentWorkflowRunsCard.esm.js.map +1 -0
- package/dist/components/Cards/index.esm.js +3 -0
- package/dist/components/Cards/index.esm.js.map +1 -0
- package/dist/components/Router.esm.js +28 -0
- package/dist/components/Router.esm.js.map +1 -0
- package/dist/components/WorkflowRunDetails/WorkflowRunDetails.esm.js +128 -0
- package/dist/components/WorkflowRunDetails/WorkflowRunDetails.esm.js.map +1 -0
- package/dist/components/WorkflowRunDetails/useWorkflowRunJobs.esm.js +49 -0
- package/dist/components/WorkflowRunDetails/useWorkflowRunJobs.esm.js.map +1 -0
- package/dist/components/WorkflowRunDetails/useWorkflowRunsDetails.esm.js +27 -0
- package/dist/components/WorkflowRunDetails/useWorkflowRunsDetails.esm.js.map +1 -0
- package/dist/components/WorkflowRunLogs/WorkflowRunLogs.esm.js +106 -0
- package/dist/components/WorkflowRunLogs/WorkflowRunLogs.esm.js.map +1 -0
- package/dist/components/WorkflowRunLogs/useDownloadWorkflowRunLogs.esm.js +26 -0
- package/dist/components/WorkflowRunLogs/useDownloadWorkflowRunLogs.esm.js.map +1 -0
- package/dist/components/WorkflowRunStatus/WorkflowRunStatus.esm.js +61 -0
- package/dist/components/WorkflowRunStatus/WorkflowRunStatus.esm.js.map +1 -0
- package/dist/components/WorkflowRunsCard/WorkflowRunsCard.esm.js +296 -0
- package/dist/components/WorkflowRunsCard/WorkflowRunsCard.esm.js.map +1 -0
- package/dist/components/WorkflowRunsTable/WorkflowRunsTable.esm.js +139 -0
- package/dist/components/WorkflowRunsTable/WorkflowRunsTable.esm.js.map +1 -0
- package/dist/components/getHostnameFromEntity.esm.js +10 -0
- package/dist/components/getHostnameFromEntity.esm.js.map +1 -0
- package/dist/components/getProjectNameFromEntity.esm.js +5 -0
- package/dist/components/getProjectNameFromEntity.esm.js.map +1 -0
- package/dist/components/useWorkflowRuns.esm.js +122 -0
- package/dist/components/useWorkflowRuns.esm.js.map +1 -0
- package/dist/index.esm.js +8 -1237
- package/dist/index.esm.js.map +1 -1
- package/dist/plugin.esm.js +55 -0
- package/dist/plugin.esm.js.map +1 -0
- package/dist/routes.esm.js +13 -0
- package/dist/routes.esm.js.map +1 -0
- package/package.json +16 -12
- package/dist/esm/index-CRpdBPJi.esm.js +0 -50
- package/dist/esm/index-CRpdBPJi.esm.js.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GithubActionsApi.esm.js","sources":["../../src/api/GithubActionsApi.ts"],"sourcesContent":["/*\n * Copyright 2020 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 { RestEndpointMethodTypes } from '@octokit/rest';\nimport { createApiRef } from '@backstage/core-plugin-api';\n\n/** @public */\nexport const githubActionsApiRef = createApiRef<GithubActionsApi>({\n id: 'plugin.githubactions.service',\n});\n\n/**\n * A client for fetching information about GitHub actions.\n *\n * @public\n */\nexport type GithubActionsApi = {\n listWorkflowRuns: (options: {\n hostname?: string;\n owner: string;\n repo: string;\n pageSize?: number;\n page?: number;\n branch?: string;\n }) => Promise<\n RestEndpointMethodTypes['actions']['listWorkflowRuns']['response']['data']\n >;\n\n getWorkflow: (options: {\n hostname?: string;\n owner: string;\n repo: string;\n id: number;\n }) => Promise<\n RestEndpointMethodTypes['actions']['getWorkflow']['response']['data']\n >;\n\n getWorkflowRun: (options: {\n hostname?: string;\n owner: string;\n repo: string;\n id: number;\n }) => Promise<\n RestEndpointMethodTypes['actions']['getWorkflowRun']['response']['data']\n >;\n\n reRunWorkflow: (options: {\n hostname?: string;\n owner: string;\n repo: string;\n runId: number;\n }) => Promise<any>;\n\n listJobsForWorkflowRun: (options: {\n hostname?: string;\n owner: string;\n repo: string;\n id: number;\n pageSize?: number;\n page?: number;\n }) => Promise<\n RestEndpointMethodTypes['actions']['listJobsForWorkflowRun']['response']['data']\n >;\n\n downloadJobLogsForWorkflowRun: (options: {\n hostname?: string;\n owner: string;\n repo: string;\n runId: number;\n }) => Promise<\n RestEndpointMethodTypes['actions']['downloadJobLogsForWorkflowRun']['response']['data']\n >;\n\n listBranches: (options: {\n hostname?: string;\n owner: string;\n repo: string;\n page: number;\n }) => Promise<\n RestEndpointMethodTypes['repos']['listBranches']['response']['data']\n >;\n\n getDefaultBranch: (options: {\n hostname?: string;\n owner: string;\n repo: string;\n }) => Promise<\n RestEndpointMethodTypes['repos']['get']['response']['data']['default_branch']\n >;\n};\n"],"names":[],"mappings":";;AAoBO,MAAM,sBAAsB,YAA+B,CAAA;AAAA,EAChE,EAAI,EAAA,8BAAA;AACN,CAAC;;;;"}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { readGithubIntegrationConfigs } from '@backstage/integration';
|
|
2
|
+
import { Octokit } from '@octokit/rest';
|
|
3
|
+
|
|
4
|
+
class GithubActionsClient {
|
|
5
|
+
configApi;
|
|
6
|
+
scmAuthApi;
|
|
7
|
+
constructor(options) {
|
|
8
|
+
this.configApi = options.configApi;
|
|
9
|
+
this.scmAuthApi = options.scmAuthApi;
|
|
10
|
+
}
|
|
11
|
+
async getOctokit(hostname = "github.com") {
|
|
12
|
+
const { token } = await this.scmAuthApi.getCredentials({
|
|
13
|
+
url: `https://${hostname}/`,
|
|
14
|
+
additionalScope: {
|
|
15
|
+
customScopes: {
|
|
16
|
+
github: ["repo"]
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
const configs = readGithubIntegrationConfigs(
|
|
21
|
+
this.configApi.getOptionalConfigArray("integrations.github") ?? []
|
|
22
|
+
);
|
|
23
|
+
const githubIntegrationConfig = configs.find((v) => v.host === hostname);
|
|
24
|
+
const baseUrl = githubIntegrationConfig?.apiBaseUrl;
|
|
25
|
+
return new Octokit({ auth: token, baseUrl });
|
|
26
|
+
}
|
|
27
|
+
async reRunWorkflow(options) {
|
|
28
|
+
const { hostname, owner, repo, runId } = options;
|
|
29
|
+
const octokit = await this.getOctokit(hostname);
|
|
30
|
+
return octokit.actions.reRunWorkflow({
|
|
31
|
+
owner,
|
|
32
|
+
repo,
|
|
33
|
+
run_id: runId
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
async listWorkflowRuns(options) {
|
|
37
|
+
const { hostname, owner, repo, pageSize = 100, page = 0, branch } = options;
|
|
38
|
+
const octokit = await this.getOctokit(hostname);
|
|
39
|
+
const workflowRuns = await octokit.actions.listWorkflowRunsForRepo({
|
|
40
|
+
owner,
|
|
41
|
+
repo,
|
|
42
|
+
per_page: pageSize,
|
|
43
|
+
page,
|
|
44
|
+
...branch ? { branch } : {}
|
|
45
|
+
});
|
|
46
|
+
return workflowRuns.data;
|
|
47
|
+
}
|
|
48
|
+
async getWorkflow(options) {
|
|
49
|
+
const { hostname, owner, repo, id } = options;
|
|
50
|
+
const octokit = await this.getOctokit(hostname);
|
|
51
|
+
const workflow = await octokit.actions.getWorkflow({
|
|
52
|
+
owner,
|
|
53
|
+
repo,
|
|
54
|
+
workflow_id: id
|
|
55
|
+
});
|
|
56
|
+
return workflow.data;
|
|
57
|
+
}
|
|
58
|
+
async getWorkflowRun(options) {
|
|
59
|
+
const { hostname, owner, repo, id } = options;
|
|
60
|
+
const octokit = await this.getOctokit(hostname);
|
|
61
|
+
const run = await octokit.actions.getWorkflowRun({
|
|
62
|
+
owner,
|
|
63
|
+
repo,
|
|
64
|
+
run_id: id
|
|
65
|
+
});
|
|
66
|
+
return run.data;
|
|
67
|
+
}
|
|
68
|
+
async listJobsForWorkflowRun(options) {
|
|
69
|
+
const { hostname, owner, repo, id, pageSize = 100, page = 0 } = options;
|
|
70
|
+
const octokit = await this.getOctokit(hostname);
|
|
71
|
+
const jobs = await octokit.actions.listJobsForWorkflowRun({
|
|
72
|
+
owner,
|
|
73
|
+
repo,
|
|
74
|
+
run_id: id,
|
|
75
|
+
per_page: pageSize,
|
|
76
|
+
page
|
|
77
|
+
});
|
|
78
|
+
return jobs.data;
|
|
79
|
+
}
|
|
80
|
+
async downloadJobLogsForWorkflowRun(options) {
|
|
81
|
+
const { hostname, owner, repo, runId } = options;
|
|
82
|
+
const octokit = await this.getOctokit(hostname);
|
|
83
|
+
const workflow = await octokit.actions.downloadJobLogsForWorkflowRun({
|
|
84
|
+
owner,
|
|
85
|
+
repo,
|
|
86
|
+
job_id: runId
|
|
87
|
+
});
|
|
88
|
+
return workflow.data;
|
|
89
|
+
}
|
|
90
|
+
async listBranches(options) {
|
|
91
|
+
const { hostname, owner, repo, page = 0 } = options;
|
|
92
|
+
const octokit = await this.getOctokit(hostname);
|
|
93
|
+
const response = await octokit.rest.repos.listBranches({
|
|
94
|
+
owner,
|
|
95
|
+
repo,
|
|
96
|
+
per_page: 100,
|
|
97
|
+
page
|
|
98
|
+
});
|
|
99
|
+
return response.data;
|
|
100
|
+
}
|
|
101
|
+
async getDefaultBranch(options) {
|
|
102
|
+
const { hostname, owner, repo } = options;
|
|
103
|
+
const octokit = await this.getOctokit(hostname);
|
|
104
|
+
const response = await octokit.rest.repos.get({
|
|
105
|
+
owner,
|
|
106
|
+
repo
|
|
107
|
+
});
|
|
108
|
+
return response.data.default_branch;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export { GithubActionsClient };
|
|
113
|
+
//# sourceMappingURL=GithubActionsClient.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GithubActionsClient.esm.js","sources":["../../src/api/GithubActionsClient.ts"],"sourcesContent":["/*\n * Copyright 2020 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 { readGithubIntegrationConfigs } from '@backstage/integration';\nimport { ScmAuthApi } from '@backstage/integration-react';\nimport { GithubActionsApi } from './GithubActionsApi';\nimport { Octokit, RestEndpointMethodTypes } from '@octokit/rest';\nimport { ConfigApi } from '@backstage/core-plugin-api';\n\n/**\n * A client for fetching information about GitHub actions.\n *\n * @public\n */\nexport class GithubActionsClient implements GithubActionsApi {\n private readonly configApi: ConfigApi;\n private readonly scmAuthApi: ScmAuthApi;\n\n constructor(options: { configApi: ConfigApi; scmAuthApi: ScmAuthApi }) {\n this.configApi = options.configApi;\n this.scmAuthApi = options.scmAuthApi;\n }\n\n private async getOctokit(hostname: string = 'github.com'): Promise<Octokit> {\n const { token } = await this.scmAuthApi.getCredentials({\n url: `https://${hostname}/`,\n additionalScope: {\n customScopes: {\n github: ['repo'],\n },\n },\n });\n const configs = readGithubIntegrationConfigs(\n this.configApi.getOptionalConfigArray('integrations.github') ?? [],\n );\n const githubIntegrationConfig = configs.find(v => v.host === hostname);\n const baseUrl = githubIntegrationConfig?.apiBaseUrl;\n return new Octokit({ auth: token, baseUrl });\n }\n\n async reRunWorkflow(options: {\n hostname?: string;\n owner: string;\n repo: string;\n runId: number;\n }): Promise<any> {\n const { hostname, owner, repo, runId } = options;\n\n const octokit = await this.getOctokit(hostname);\n return octokit.actions.reRunWorkflow({\n owner,\n repo,\n run_id: runId,\n });\n }\n\n async listWorkflowRuns(options: {\n hostname?: string;\n owner: string;\n repo: string;\n pageSize?: number;\n page?: number;\n branch?: string;\n }): Promise<\n RestEndpointMethodTypes['actions']['listWorkflowRuns']['response']['data']\n > {\n const { hostname, owner, repo, pageSize = 100, page = 0, branch } = options;\n\n const octokit = await this.getOctokit(hostname);\n const workflowRuns = await octokit.actions.listWorkflowRunsForRepo({\n owner,\n repo,\n per_page: pageSize,\n page,\n ...(branch ? { branch } : {}),\n });\n\n return workflowRuns.data;\n }\n\n async getWorkflow(options: {\n hostname?: string;\n owner: string;\n repo: string;\n id: number;\n }): Promise<\n RestEndpointMethodTypes['actions']['getWorkflow']['response']['data']\n > {\n const { hostname, owner, repo, id } = options;\n\n const octokit = await this.getOctokit(hostname);\n const workflow = await octokit.actions.getWorkflow({\n owner,\n repo,\n workflow_id: id,\n });\n\n return workflow.data;\n }\n\n async getWorkflowRun(options: {\n hostname?: string;\n owner: string;\n repo: string;\n id: number;\n }): Promise<\n RestEndpointMethodTypes['actions']['getWorkflowRun']['response']['data']\n > {\n const { hostname, owner, repo, id } = options;\n\n const octokit = await this.getOctokit(hostname);\n const run = await octokit.actions.getWorkflowRun({\n owner,\n repo,\n run_id: id,\n });\n\n return run.data;\n }\n\n async listJobsForWorkflowRun(options: {\n hostname?: string;\n owner: string;\n repo: string;\n id: number;\n pageSize?: number;\n page?: number;\n }): Promise<\n RestEndpointMethodTypes['actions']['listJobsForWorkflowRun']['response']['data']\n > {\n const { hostname, owner, repo, id, pageSize = 100, page = 0 } = options;\n\n const octokit = await this.getOctokit(hostname);\n const jobs = await octokit.actions.listJobsForWorkflowRun({\n owner,\n repo,\n run_id: id,\n per_page: pageSize,\n page,\n });\n\n return jobs.data;\n }\n\n async downloadJobLogsForWorkflowRun(options: {\n hostname?: string;\n owner: string;\n repo: string;\n runId: number;\n }): Promise<\n RestEndpointMethodTypes['actions']['downloadJobLogsForWorkflowRun']['response']['data']\n > {\n const { hostname, owner, repo, runId } = options;\n\n const octokit = await this.getOctokit(hostname);\n const workflow = await octokit.actions.downloadJobLogsForWorkflowRun({\n owner,\n repo,\n job_id: runId,\n });\n\n return workflow.data;\n }\n\n async listBranches(options: {\n hostname?: string;\n owner: string;\n repo: string;\n page?: number;\n }): Promise<\n RestEndpointMethodTypes['repos']['listBranches']['response']['data']\n > {\n const { hostname, owner, repo, page = 0 } = options;\n const octokit = await this.getOctokit(hostname);\n const response = await octokit.rest.repos.listBranches({\n owner,\n repo,\n per_page: 100,\n page,\n });\n\n return response.data;\n }\n\n async getDefaultBranch(options: {\n hostname?: string;\n owner: string;\n repo: string;\n }): Promise<\n RestEndpointMethodTypes['repos']['get']['response']['data']['default_branch']\n > {\n const { hostname, owner, repo } = options;\n const octokit = await this.getOctokit(hostname);\n const response = await octokit.rest.repos.get({\n owner,\n repo,\n });\n\n return response.data.default_branch;\n }\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
var BuildStatus = /* @__PURE__ */ ((BuildStatus2) => {
|
|
2
|
+
BuildStatus2[BuildStatus2["success"] = 0] = "success";
|
|
3
|
+
BuildStatus2[BuildStatus2["failure"] = 1] = "failure";
|
|
4
|
+
BuildStatus2[BuildStatus2["pending"] = 2] = "pending";
|
|
5
|
+
BuildStatus2[BuildStatus2["running"] = 3] = "running";
|
|
6
|
+
return BuildStatus2;
|
|
7
|
+
})(BuildStatus || {});
|
|
8
|
+
|
|
9
|
+
export { BuildStatus };
|
|
10
|
+
//# sourceMappingURL=types.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.esm.js","sources":["../../src/api/types.ts"],"sourcesContent":["/*\n * Copyright 2020 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\n/** @public */\nexport type Step = {\n name: string;\n status: string;\n conclusion?: string;\n number: number; // starts from 1\n started_at?: string;\n completed_at?: string;\n};\n\n/** @public */\nexport type Job = {\n html_url?: string;\n status: string;\n conclusion?: string;\n started_at: string;\n completed_at?: string;\n id: number;\n name: string;\n steps?: Step[];\n};\n\n/** @public */\nexport type Jobs = {\n total_count: number;\n jobs: Job[];\n};\n\n/** @public */\nexport enum BuildStatus {\n 'success',\n 'failure',\n 'pending',\n 'running',\n}\n\n/** @public */\nexport type Branch = {\n name: string;\n};\n\n/** @public */\nexport type Branches = {\n default_branch: string;\n branches: Branch[];\n};\n\n/** @public */\nexport interface RouterProps {\n view?: 'cards' | 'table';\n}\n"],"names":["BuildStatus"],"mappings":"AA6CY,IAAA,WAAA,qBAAAA,YAAL,KAAA;AACL,EAAAA,YAAA,CAAA,YAAA,CAAA,SAAA,CAAA,GAAA,CAAA,CAAA,GAAA,SAAA,CAAA;AACA,EAAAA,YAAA,CAAA,YAAA,CAAA,SAAA,CAAA,GAAA,CAAA,CAAA,GAAA,SAAA,CAAA;AACA,EAAAA,YAAA,CAAA,YAAA,CAAA,SAAA,CAAA,GAAA,CAAA,CAAA,GAAA,SAAA,CAAA;AACA,EAAAA,YAAA,CAAA,YAAA,CAAA,SAAA,CAAA,GAAA,CAAA,CAAA,GAAA,SAAA,CAAA;AAJU,EAAAA,OAAAA,YAAAA,CAAAA;AAAA,CAAA,EAAA,WAAA,IAAA,EAAA;;;;"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { useEntity } from '@backstage/plugin-catalog-react';
|
|
2
|
+
import LinearProgress from '@material-ui/core/LinearProgress';
|
|
3
|
+
import Typography from '@material-ui/core/Typography';
|
|
4
|
+
import { makeStyles } from '@material-ui/core/styles';
|
|
5
|
+
import ExternalLinkIcon from '@material-ui/icons/Launch';
|
|
6
|
+
import React, { useEffect } from 'react';
|
|
7
|
+
import { GITHUB_ACTIONS_ANNOTATION } from '../getProjectNameFromEntity.esm.js';
|
|
8
|
+
import { useWorkflowRuns } from '../useWorkflowRuns.esm.js';
|
|
9
|
+
import { WorkflowRunsTable } from '../WorkflowRunsTable/WorkflowRunsTable.esm.js';
|
|
10
|
+
import { WorkflowRunStatus } from '../WorkflowRunStatus/WorkflowRunStatus.esm.js';
|
|
11
|
+
import { useApi, errorApiRef } from '@backstage/core-plugin-api';
|
|
12
|
+
import { InfoCard, StructuredMetadataTable, Link } from '@backstage/core-components';
|
|
13
|
+
import { getHostnameFromEntity } from '../getHostnameFromEntity.esm.js';
|
|
14
|
+
|
|
15
|
+
const useStyles = makeStyles({
|
|
16
|
+
externalLinkIcon: {
|
|
17
|
+
fontSize: "inherit",
|
|
18
|
+
verticalAlign: "bottom"
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
const WidgetContent = (props) => {
|
|
22
|
+
const { error, loading, lastRun, branch } = props;
|
|
23
|
+
const classes = useStyles();
|
|
24
|
+
if (error) return /* @__PURE__ */ React.createElement(Typography, null, "Couldn't fetch latest ", branch, " run");
|
|
25
|
+
if (loading) return /* @__PURE__ */ React.createElement(LinearProgress, null);
|
|
26
|
+
return /* @__PURE__ */ React.createElement(
|
|
27
|
+
StructuredMetadataTable,
|
|
28
|
+
{
|
|
29
|
+
metadata: {
|
|
30
|
+
status: /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(
|
|
31
|
+
WorkflowRunStatus,
|
|
32
|
+
{
|
|
33
|
+
status: lastRun.status,
|
|
34
|
+
conclusion: lastRun.conclusion
|
|
35
|
+
}
|
|
36
|
+
)),
|
|
37
|
+
message: lastRun.message,
|
|
38
|
+
url: /* @__PURE__ */ React.createElement(Link, { to: lastRun.githubUrl ?? "" }, "See more on GitHub", " ", /* @__PURE__ */ React.createElement(ExternalLinkIcon, { className: classes.externalLinkIcon }))
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
);
|
|
42
|
+
};
|
|
43
|
+
const LatestWorkflowRunCard = (props) => {
|
|
44
|
+
const { branch = "master", variant } = props;
|
|
45
|
+
const { entity } = useEntity();
|
|
46
|
+
const errorApi = useApi(errorApiRef);
|
|
47
|
+
const hostname = getHostnameFromEntity(entity);
|
|
48
|
+
const [owner, repo] = (entity?.metadata.annotations?.[GITHUB_ACTIONS_ANNOTATION] ?? "/").split("/");
|
|
49
|
+
const [{ runs, loading, error }] = useWorkflowRuns({
|
|
50
|
+
hostname,
|
|
51
|
+
owner,
|
|
52
|
+
repo,
|
|
53
|
+
branch
|
|
54
|
+
});
|
|
55
|
+
const lastRun = runs?.[0] ?? {};
|
|
56
|
+
useEffect(() => {
|
|
57
|
+
if (error) {
|
|
58
|
+
errorApi.post(error);
|
|
59
|
+
}
|
|
60
|
+
}, [error, errorApi]);
|
|
61
|
+
return /* @__PURE__ */ React.createElement(InfoCard, { title: `Last ${branch} build`, variant }, /* @__PURE__ */ React.createElement(
|
|
62
|
+
WidgetContent,
|
|
63
|
+
{
|
|
64
|
+
error,
|
|
65
|
+
loading,
|
|
66
|
+
branch,
|
|
67
|
+
lastRun
|
|
68
|
+
}
|
|
69
|
+
));
|
|
70
|
+
};
|
|
71
|
+
const LatestWorkflowsForBranchCard = (props) => {
|
|
72
|
+
const { branch = "master", variant } = props;
|
|
73
|
+
const { entity } = useEntity();
|
|
74
|
+
return /* @__PURE__ */ React.createElement(InfoCard, { title: `Last ${branch} build`, variant }, /* @__PURE__ */ React.createElement(WorkflowRunsTable, { branch, entity }));
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
export { LatestWorkflowRunCard, LatestWorkflowsForBranchCard };
|
|
78
|
+
//# sourceMappingURL=Cards.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Cards.esm.js","sources":["../../../src/components/Cards/Cards.tsx"],"sourcesContent":["/*\n * Copyright 2020 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 { useEntity } from '@backstage/plugin-catalog-react';\nimport LinearProgress from '@material-ui/core/LinearProgress';\nimport Typography from '@material-ui/core/Typography';\nimport { makeStyles } from '@material-ui/core/styles';\nimport ExternalLinkIcon from '@material-ui/icons/Launch';\nimport React, { useEffect } from 'react';\nimport { GITHUB_ACTIONS_ANNOTATION } from '../getProjectNameFromEntity';\nimport { useWorkflowRuns, WorkflowRun } from '../useWorkflowRuns';\nimport { WorkflowRunsTable } from '../WorkflowRunsTable';\nimport { WorkflowRunStatus } from '../WorkflowRunStatus';\nimport { errorApiRef, useApi } from '@backstage/core-plugin-api';\nimport {\n InfoCard,\n InfoCardVariants,\n Link,\n StructuredMetadataTable,\n} from '@backstage/core-components';\nimport { getHostnameFromEntity } from '../getHostnameFromEntity';\n\nconst useStyles = makeStyles({\n externalLinkIcon: {\n fontSize: 'inherit',\n verticalAlign: 'bottom',\n },\n});\n\nconst WidgetContent = (props: {\n error?: Error;\n loading?: boolean;\n lastRun: WorkflowRun;\n branch: string;\n}) => {\n const { error, loading, lastRun, branch } = props;\n const classes = useStyles();\n\n if (error) return <Typography>Couldn't fetch latest {branch} run</Typography>;\n if (loading) return <LinearProgress />;\n\n return (\n <StructuredMetadataTable\n metadata={{\n status: (\n <>\n <WorkflowRunStatus\n status={lastRun.status}\n conclusion={lastRun.conclusion}\n />\n </>\n ),\n message: lastRun.message,\n url: (\n <Link to={lastRun.githubUrl ?? ''}>\n See more on GitHub{' '}\n <ExternalLinkIcon className={classes.externalLinkIcon} />\n </Link>\n ),\n }}\n />\n );\n};\n\n/** @public */\nexport const LatestWorkflowRunCard = (props: {\n branch: string;\n variant?: InfoCardVariants;\n}) => {\n const { branch = 'master', variant } = props;\n const { entity } = useEntity();\n const errorApi = useApi(errorApiRef);\n const hostname = getHostnameFromEntity(entity);\n const [owner, repo] = (\n entity?.metadata.annotations?.[GITHUB_ACTIONS_ANNOTATION] ?? '/'\n ).split('/');\n const [{ runs, loading, error }] = useWorkflowRuns({\n hostname,\n owner,\n repo,\n branch,\n });\n const lastRun = runs?.[0] ?? ({} as WorkflowRun);\n useEffect(() => {\n if (error) {\n errorApi.post(error);\n }\n }, [error, errorApi]);\n\n return (\n <InfoCard title={`Last ${branch} build`} variant={variant}>\n <WidgetContent\n error={error}\n loading={loading}\n branch={branch}\n lastRun={lastRun}\n />\n </InfoCard>\n );\n};\n\n/** @public */\nexport const LatestWorkflowsForBranchCard = (props: {\n branch: string;\n variant?: InfoCardVariants;\n}) => {\n const { branch = 'master', variant } = props;\n const { entity } = useEntity();\n\n return (\n <InfoCard title={`Last ${branch} build`} variant={variant}>\n <WorkflowRunsTable branch={branch} entity={entity} />\n </InfoCard>\n );\n};\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { useEntity } from '@backstage/plugin-catalog-react';
|
|
2
|
+
import React, { useEffect } from 'react';
|
|
3
|
+
import { Link as Link$1 } from 'react-router-dom';
|
|
4
|
+
import { GITHUB_ACTIONS_ANNOTATION } from '../getProjectNameFromEntity.esm.js';
|
|
5
|
+
import { useWorkflowRuns } from '../useWorkflowRuns.esm.js';
|
|
6
|
+
import { WorkflowRunStatus } from '../WorkflowRunStatus/WorkflowRunStatus.esm.js';
|
|
7
|
+
import Typography from '@material-ui/core/Typography';
|
|
8
|
+
import { useApi, errorApiRef, useRouteRef } from '@backstage/core-plugin-api';
|
|
9
|
+
import { ErrorPanel, InfoCard, Link, Table } from '@backstage/core-components';
|
|
10
|
+
import { buildRouteRef } from '../../routes.esm.js';
|
|
11
|
+
import { getHostnameFromEntity } from '../getHostnameFromEntity.esm.js';
|
|
12
|
+
|
|
13
|
+
const firstLine = (message) => message.split("\n")[0];
|
|
14
|
+
const RecentWorkflowRunsCard = (props) => {
|
|
15
|
+
const { branch, dense = false, limit = 5, variant } = props;
|
|
16
|
+
const { entity } = useEntity();
|
|
17
|
+
const errorApi = useApi(errorApiRef);
|
|
18
|
+
const hostname = getHostnameFromEntity(entity);
|
|
19
|
+
const [owner, repo] = (entity?.metadata.annotations?.[GITHUB_ACTIONS_ANNOTATION] ?? "/").split("/");
|
|
20
|
+
const [{ runs = [], loading, error }] = useWorkflowRuns({
|
|
21
|
+
hostname,
|
|
22
|
+
owner,
|
|
23
|
+
repo,
|
|
24
|
+
branch,
|
|
25
|
+
initialPageSize: limit
|
|
26
|
+
});
|
|
27
|
+
useEffect(() => {
|
|
28
|
+
if (error) {
|
|
29
|
+
errorApi.post(error);
|
|
30
|
+
}
|
|
31
|
+
}, [error, errorApi]);
|
|
32
|
+
const githubHost = hostname || "github.com";
|
|
33
|
+
const routeLink = useRouteRef(buildRouteRef);
|
|
34
|
+
if (error) {
|
|
35
|
+
return /* @__PURE__ */ React.createElement(ErrorPanel, { title: error.message, error });
|
|
36
|
+
}
|
|
37
|
+
return /* @__PURE__ */ React.createElement(
|
|
38
|
+
InfoCard,
|
|
39
|
+
{
|
|
40
|
+
title: "Recent Workflow Runs",
|
|
41
|
+
subheader: branch ? `Branch: ${branch}` : "All Branches",
|
|
42
|
+
noPadding: true,
|
|
43
|
+
variant
|
|
44
|
+
},
|
|
45
|
+
!runs.length ? /* @__PURE__ */ React.createElement("div", { style: { textAlign: "center" } }, /* @__PURE__ */ React.createElement(Typography, { variant: "body1" }, "This component has GitHub Actions enabled, but no workflows were found."), /* @__PURE__ */ React.createElement(Typography, { variant: "body2" }, /* @__PURE__ */ React.createElement(Link, { to: `https://${githubHost}/${owner}/${repo}/actions/new` }, "Create a new workflow"))) : /* @__PURE__ */ React.createElement(
|
|
46
|
+
Table,
|
|
47
|
+
{
|
|
48
|
+
isLoading: loading,
|
|
49
|
+
options: {
|
|
50
|
+
search: false,
|
|
51
|
+
paging: false,
|
|
52
|
+
padding: dense ? "dense" : "default",
|
|
53
|
+
toolbar: false
|
|
54
|
+
},
|
|
55
|
+
columns: [
|
|
56
|
+
{
|
|
57
|
+
title: "Commit Message",
|
|
58
|
+
field: "message",
|
|
59
|
+
render: (data) => /* @__PURE__ */ React.createElement(Link, { component: Link$1, to: routeLink({ id: data.id }) }, firstLine(data.message ?? ""))
|
|
60
|
+
},
|
|
61
|
+
{ title: "Branch", field: "source.branchName" },
|
|
62
|
+
{ title: "Status", field: "status", render: WorkflowRunStatus }
|
|
63
|
+
],
|
|
64
|
+
data: runs
|
|
65
|
+
}
|
|
66
|
+
)
|
|
67
|
+
);
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
export { RecentWorkflowRunsCard };
|
|
71
|
+
//# sourceMappingURL=RecentWorkflowRunsCard.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RecentWorkflowRunsCard.esm.js","sources":["../../../src/components/Cards/RecentWorkflowRunsCard.tsx"],"sourcesContent":["/*\n * Copyright 2020 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 */\nimport { useEntity } from '@backstage/plugin-catalog-react';\nimport React, { useEffect } from 'react';\nimport { Link as RouterLink } from 'react-router-dom';\nimport { GITHUB_ACTIONS_ANNOTATION } from '../getProjectNameFromEntity';\nimport { useWorkflowRuns, WorkflowRun } from '../useWorkflowRuns';\nimport { WorkflowRunStatus } from '../WorkflowRunStatus';\nimport Typography from '@material-ui/core/Typography';\n\nimport { errorApiRef, useApi, useRouteRef } from '@backstage/core-plugin-api';\nimport {\n ErrorPanel,\n InfoCard,\n InfoCardVariants,\n Link,\n Table,\n} from '@backstage/core-components';\nimport { buildRouteRef } from '../../routes';\nimport { getHostnameFromEntity } from '../getHostnameFromEntity';\n\nconst firstLine = (message: string): string => message.split('\\n')[0];\n\n/** @public */\nexport const RecentWorkflowRunsCard = (props: {\n branch?: string;\n dense?: boolean;\n limit?: number;\n variant?: InfoCardVariants;\n}) => {\n const { branch, dense = false, limit = 5, variant } = props;\n\n const { entity } = useEntity();\n const errorApi = useApi(errorApiRef);\n\n const hostname = getHostnameFromEntity(entity);\n\n const [owner, repo] = (\n entity?.metadata.annotations?.[GITHUB_ACTIONS_ANNOTATION] ?? '/'\n ).split('/');\n\n const [{ runs = [], loading, error }] = useWorkflowRuns({\n hostname,\n owner,\n repo,\n branch,\n initialPageSize: limit,\n });\n\n useEffect(() => {\n if (error) {\n errorApi.post(error);\n }\n }, [error, errorApi]);\n\n const githubHost = hostname || 'github.com';\n const routeLink = useRouteRef(buildRouteRef);\n\n if (error) {\n return <ErrorPanel title={error.message} error={error} />;\n }\n\n return (\n <InfoCard\n title=\"Recent Workflow Runs\"\n subheader={branch ? `Branch: ${branch}` : 'All Branches'}\n noPadding\n variant={variant}\n >\n {!runs.length ? (\n <div style={{ textAlign: 'center' }}>\n <Typography variant=\"body1\">\n This component has GitHub Actions enabled, but no workflows were\n found.\n </Typography>\n <Typography variant=\"body2\">\n <Link to={`https://${githubHost}/${owner}/${repo}/actions/new`}>\n Create a new workflow\n </Link>\n </Typography>\n </div>\n ) : (\n <Table<WorkflowRun>\n isLoading={loading}\n options={{\n search: false,\n paging: false,\n padding: dense ? 'dense' : 'default',\n toolbar: false,\n }}\n columns={[\n {\n title: 'Commit Message',\n field: 'message',\n render: data => (\n <Link component={RouterLink} to={routeLink({ id: data.id! })}>\n {firstLine(data.message ?? '')}\n </Link>\n ),\n },\n { title: 'Branch', field: 'source.branchName' },\n { title: 'Status', field: 'status', render: WorkflowRunStatus },\n ]}\n data={runs}\n />\n )}\n </InfoCard>\n );\n};\n"],"names":["RouterLink"],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.esm.js","sources":[],"sourcesContent":[],"names":[],"mappings":";"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { useEntity, MissingAnnotationEmptyState } from '@backstage/plugin-catalog-react';
|
|
3
|
+
import { Routes, Route } from 'react-router-dom';
|
|
4
|
+
import { buildRouteRef } from '../routes.esm.js';
|
|
5
|
+
import { WorkflowRunDetails } from './WorkflowRunDetails/WorkflowRunDetails.esm.js';
|
|
6
|
+
import { WorkflowRunsCard } from './WorkflowRunsCard/WorkflowRunsCard.esm.js';
|
|
7
|
+
import { WorkflowRunsTable } from './WorkflowRunsTable/WorkflowRunsTable.esm.js';
|
|
8
|
+
import { GITHUB_ACTIONS_ANNOTATION } from './getProjectNameFromEntity.esm.js';
|
|
9
|
+
|
|
10
|
+
const isGithubActionsAvailable = (entity) => Boolean(entity.metadata.annotations?.[GITHUB_ACTIONS_ANNOTATION]);
|
|
11
|
+
const Router = (props) => {
|
|
12
|
+
const { view = "table" } = props;
|
|
13
|
+
const { entity } = useEntity();
|
|
14
|
+
if (!isGithubActionsAvailable(entity)) {
|
|
15
|
+
return /* @__PURE__ */ React.createElement(MissingAnnotationEmptyState, { annotation: GITHUB_ACTIONS_ANNOTATION });
|
|
16
|
+
}
|
|
17
|
+
const workflowRunsComponent = view === "cards" ? /* @__PURE__ */ React.createElement(WorkflowRunsCard, { entity }) : /* @__PURE__ */ React.createElement(WorkflowRunsTable, { entity });
|
|
18
|
+
return /* @__PURE__ */ React.createElement(Routes, null, /* @__PURE__ */ React.createElement(Route, { path: "/", element: workflowRunsComponent }), /* @__PURE__ */ React.createElement(
|
|
19
|
+
Route,
|
|
20
|
+
{
|
|
21
|
+
path: `${buildRouteRef.path}`,
|
|
22
|
+
element: /* @__PURE__ */ React.createElement(WorkflowRunDetails, { entity })
|
|
23
|
+
}
|
|
24
|
+
));
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
export { Router, isGithubActionsAvailable };
|
|
28
|
+
//# sourceMappingURL=Router.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Router.esm.js","sources":["../../src/components/Router.tsx"],"sourcesContent":["/*\n * Copyright 2020 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 from 'react';\nimport { Entity } from '@backstage/catalog-model';\nimport {\n useEntity,\n MissingAnnotationEmptyState,\n} from '@backstage/plugin-catalog-react';\nimport { Routes, Route } from 'react-router-dom';\nimport { buildRouteRef } from '../routes';\nimport { WorkflowRunDetails } from './WorkflowRunDetails';\nimport { WorkflowRunsCard } from './WorkflowRunsCard';\nimport { WorkflowRunsTable } from './WorkflowRunsTable';\nimport { GITHUB_ACTIONS_ANNOTATION } from './getProjectNameFromEntity';\nimport { RouterProps } from '../api/types';\n\n/** @public */\nexport const isGithubActionsAvailable = (entity: Entity) =>\n Boolean(entity.metadata.annotations?.[GITHUB_ACTIONS_ANNOTATION]);\n\n/** @public */\nexport const Router = (props: RouterProps) => {\n const { view = 'table' } = props;\n const { entity } = useEntity();\n\n if (!isGithubActionsAvailable(entity)) {\n return (\n <MissingAnnotationEmptyState annotation={GITHUB_ACTIONS_ANNOTATION} />\n );\n }\n\n const workflowRunsComponent =\n view === 'cards' ? (\n <WorkflowRunsCard entity={entity} />\n ) : (\n <WorkflowRunsTable entity={entity} />\n );\n\n return (\n <Routes>\n <Route path=\"/\" element={workflowRunsComponent} />\n <Route\n path={`${buildRouteRef.path}`}\n element={<WorkflowRunDetails entity={entity} />}\n />\n </Routes>\n );\n};\n"],"names":[],"mappings":";;;;;;;;;AA+Ba,MAAA,wBAAA,GAA2B,CAAC,MACvC,KAAA,OAAA,CAAQ,OAAO,QAAS,CAAA,WAAA,GAAc,yBAAyB,CAAC,EAAA;AAGrD,MAAA,MAAA,GAAS,CAAC,KAAuB,KAAA;AAC5C,EAAM,MAAA,EAAE,IAAO,GAAA,OAAA,EAAY,GAAA,KAAA,CAAA;AAC3B,EAAM,MAAA,EAAE,MAAO,EAAA,GAAI,SAAU,EAAA,CAAA;AAE7B,EAAI,IAAA,CAAC,wBAAyB,CAAA,MAAM,CAAG,EAAA;AACrC,IACE,uBAAA,KAAA,CAAA,aAAA,CAAC,2BAA4B,EAAA,EAAA,UAAA,EAAY,yBAA2B,EAAA,CAAA,CAAA;AAAA,GAExE;AAEA,EAAM,MAAA,qBAAA,GACJ,SAAS,OACP,mBAAA,KAAA,CAAA,aAAA,CAAC,oBAAiB,MAAgB,EAAA,CAAA,mBAEjC,KAAA,CAAA,aAAA,CAAA,iBAAA,EAAA,EAAkB,MAAgB,EAAA,CAAA,CAAA;AAGvC,EACE,uBAAA,KAAA,CAAA,aAAA,CAAC,8BACE,KAAA,CAAA,aAAA,CAAA,KAAA,EAAA,EAAM,MAAK,GAAI,EAAA,OAAA,EAAS,uBAAuB,CAChD,kBAAA,KAAA,CAAA,aAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,IAAA,EAAM,CAAG,EAAA,aAAA,CAAc,IAAI,CAAA,CAAA;AAAA,MAC3B,OAAA,kBAAU,KAAA,CAAA,aAAA,CAAA,kBAAA,EAAA,EAAmB,MAAgB,EAAA,CAAA;AAAA,KAAA;AAAA,GAEjD,CAAA,CAAA;AAEJ;;;;"}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import Accordion from '@material-ui/core/Accordion';
|
|
2
|
+
import AccordionDetails from '@material-ui/core/AccordionDetails';
|
|
3
|
+
import AccordionSummary from '@material-ui/core/AccordionSummary';
|
|
4
|
+
import Box from '@material-ui/core/Box';
|
|
5
|
+
import CircularProgress from '@material-ui/core/CircularProgress';
|
|
6
|
+
import LinearProgress from '@material-ui/core/LinearProgress';
|
|
7
|
+
import ListItemText from '@material-ui/core/ListItemText';
|
|
8
|
+
import Paper from '@material-ui/core/Paper';
|
|
9
|
+
import Table from '@material-ui/core/Table';
|
|
10
|
+
import TableBody from '@material-ui/core/TableBody';
|
|
11
|
+
import TableCell from '@material-ui/core/TableCell';
|
|
12
|
+
import TableContainer from '@material-ui/core/TableContainer';
|
|
13
|
+
import TableRow from '@material-ui/core/TableRow';
|
|
14
|
+
import Typography from '@material-ui/core/Typography';
|
|
15
|
+
import { makeStyles } from '@material-ui/core/styles';
|
|
16
|
+
import ExpandMoreIcon from '@material-ui/icons/ExpandMore';
|
|
17
|
+
import ExternalLinkIcon from '@material-ui/icons/Launch';
|
|
18
|
+
import { DateTime } from 'luxon';
|
|
19
|
+
import React from 'react';
|
|
20
|
+
import { getProjectNameFromEntity } from '../getProjectNameFromEntity.esm.js';
|
|
21
|
+
import { WorkflowRunStatus } from '../WorkflowRunStatus/WorkflowRunStatus.esm.js';
|
|
22
|
+
import { useWorkflowRunJobs } from './useWorkflowRunJobs.esm.js';
|
|
23
|
+
import { useWorkflowRunsDetails } from './useWorkflowRunsDetails.esm.js';
|
|
24
|
+
import { WorkflowRunLogs } from '../WorkflowRunLogs/WorkflowRunLogs.esm.js';
|
|
25
|
+
import { Breadcrumbs, Link } from '@backstage/core-components';
|
|
26
|
+
import { getHostnameFromEntity } from '../getHostnameFromEntity.esm.js';
|
|
27
|
+
|
|
28
|
+
const useStyles = makeStyles((theme) => ({
|
|
29
|
+
root: {
|
|
30
|
+
maxWidth: 720,
|
|
31
|
+
margin: theme.spacing(2)
|
|
32
|
+
},
|
|
33
|
+
title: {
|
|
34
|
+
padding: theme.spacing(1, 0, 2, 0)
|
|
35
|
+
},
|
|
36
|
+
table: {
|
|
37
|
+
padding: theme.spacing(1)
|
|
38
|
+
},
|
|
39
|
+
accordionDetails: {
|
|
40
|
+
padding: 0
|
|
41
|
+
},
|
|
42
|
+
button: {
|
|
43
|
+
order: -1,
|
|
44
|
+
marginRight: 0,
|
|
45
|
+
marginLeft: "-20px"
|
|
46
|
+
},
|
|
47
|
+
externalLinkIcon: {
|
|
48
|
+
fontSize: "inherit",
|
|
49
|
+
verticalAlign: "bottom"
|
|
50
|
+
}
|
|
51
|
+
}));
|
|
52
|
+
const getElapsedTime = (start, end) => {
|
|
53
|
+
if (!start || !end) {
|
|
54
|
+
return "";
|
|
55
|
+
}
|
|
56
|
+
const startDate = DateTime.fromISO(start);
|
|
57
|
+
const endDate = end ? DateTime.fromISO(end) : DateTime.now();
|
|
58
|
+
const diff = endDate.diff(startDate);
|
|
59
|
+
const timeElapsed = diff.toFormat(`m 'minutes' s 'seconds'`);
|
|
60
|
+
return timeElapsed;
|
|
61
|
+
};
|
|
62
|
+
const StepView = ({ step }) => {
|
|
63
|
+
return /* @__PURE__ */ React.createElement(TableRow, null, /* @__PURE__ */ React.createElement(TableCell, null, /* @__PURE__ */ React.createElement(
|
|
64
|
+
ListItemText,
|
|
65
|
+
{
|
|
66
|
+
primary: step.name,
|
|
67
|
+
secondary: getElapsedTime(step.started_at, step.completed_at)
|
|
68
|
+
}
|
|
69
|
+
)), /* @__PURE__ */ React.createElement(TableCell, null, /* @__PURE__ */ React.createElement(
|
|
70
|
+
WorkflowRunStatus,
|
|
71
|
+
{
|
|
72
|
+
status: step.status.toLocaleUpperCase("en-US"),
|
|
73
|
+
conclusion: step.conclusion?.toLocaleUpperCase("en-US")
|
|
74
|
+
}
|
|
75
|
+
)));
|
|
76
|
+
};
|
|
77
|
+
const JobListItem = ({
|
|
78
|
+
job,
|
|
79
|
+
className,
|
|
80
|
+
entity
|
|
81
|
+
}) => {
|
|
82
|
+
const classes = useStyles();
|
|
83
|
+
return /* @__PURE__ */ React.createElement(Accordion, { TransitionProps: { unmountOnExit: true }, className }, /* @__PURE__ */ React.createElement(
|
|
84
|
+
AccordionSummary,
|
|
85
|
+
{
|
|
86
|
+
expandIcon: /* @__PURE__ */ React.createElement(ExpandMoreIcon, null),
|
|
87
|
+
IconButtonProps: {
|
|
88
|
+
className: classes.button
|
|
89
|
+
}
|
|
90
|
+
},
|
|
91
|
+
/* @__PURE__ */ React.createElement(Typography, { variant: "button" }, job.name, " (", getElapsedTime(job.started_at, job.completed_at), ")")
|
|
92
|
+
), /* @__PURE__ */ React.createElement(AccordionDetails, { className: classes.accordionDetails }, /* @__PURE__ */ React.createElement(TableContainer, null, /* @__PURE__ */ React.createElement(Table, null, job.steps?.map((step) => /* @__PURE__ */ React.createElement(StepView, { key: step.number, step }))))), job.status === "queued" || job.status === "in_progress" ? /* @__PURE__ */ React.createElement(WorkflowRunLogs, { runId: job.id, inProgress: true, entity }) : /* @__PURE__ */ React.createElement(WorkflowRunLogs, { runId: job.id, inProgress: false, entity }));
|
|
93
|
+
};
|
|
94
|
+
const JobsList = ({ jobs, entity }) => {
|
|
95
|
+
const classes = useStyles();
|
|
96
|
+
return /* @__PURE__ */ React.createElement(Box, null, jobs && jobs.total_count > 0 && jobs.jobs.map((job) => /* @__PURE__ */ React.createElement(
|
|
97
|
+
JobListItem,
|
|
98
|
+
{
|
|
99
|
+
key: job.id,
|
|
100
|
+
job,
|
|
101
|
+
className: job.status !== "success" ? classes.failed : classes.success,
|
|
102
|
+
entity
|
|
103
|
+
}
|
|
104
|
+
)));
|
|
105
|
+
};
|
|
106
|
+
const WorkflowRunDetails = ({ entity }) => {
|
|
107
|
+
const projectName = getProjectNameFromEntity(entity);
|
|
108
|
+
const hostname = getHostnameFromEntity(entity);
|
|
109
|
+
const [owner, repo] = projectName && projectName.split("/") || [];
|
|
110
|
+
const details = useWorkflowRunsDetails({ hostname, owner, repo });
|
|
111
|
+
const jobs = useWorkflowRunJobs({ hostname, owner, repo });
|
|
112
|
+
const classes = useStyles();
|
|
113
|
+
if (details.error && details.error.message) {
|
|
114
|
+
return /* @__PURE__ */ React.createElement(Typography, { variant: "h6", color: "error" }, "Failed to load build, ", details.error.message);
|
|
115
|
+
} else if (details.loading) {
|
|
116
|
+
return /* @__PURE__ */ React.createElement(LinearProgress, null);
|
|
117
|
+
}
|
|
118
|
+
return /* @__PURE__ */ React.createElement("div", { className: classes.root }, /* @__PURE__ */ React.createElement(Box, { mb: 3 }, /* @__PURE__ */ React.createElement(Breadcrumbs, { "aria-label": "breadcrumb" }, /* @__PURE__ */ React.createElement(Link, { to: ".." }, "Workflow runs"), /* @__PURE__ */ React.createElement(Typography, null, "Workflow run details"))), /* @__PURE__ */ React.createElement(TableContainer, { component: Paper, className: classes.table }, /* @__PURE__ */ React.createElement(Table, null, /* @__PURE__ */ React.createElement(TableBody, null, /* @__PURE__ */ React.createElement(TableRow, null, /* @__PURE__ */ React.createElement(TableCell, null, /* @__PURE__ */ React.createElement(Typography, { noWrap: true }, "Branch")), /* @__PURE__ */ React.createElement(TableCell, null, details.value?.head_branch)), /* @__PURE__ */ React.createElement(TableRow, null, /* @__PURE__ */ React.createElement(TableCell, null, /* @__PURE__ */ React.createElement(Typography, { noWrap: true }, "Message")), /* @__PURE__ */ React.createElement(TableCell, null, details.value?.head_commit?.message)), /* @__PURE__ */ React.createElement(TableRow, null, /* @__PURE__ */ React.createElement(TableCell, null, /* @__PURE__ */ React.createElement(Typography, { noWrap: true }, "Commit ID")), /* @__PURE__ */ React.createElement(TableCell, null, details.value?.head_commit?.id)), /* @__PURE__ */ React.createElement(TableRow, null, /* @__PURE__ */ React.createElement(TableCell, null, /* @__PURE__ */ React.createElement(Typography, { noWrap: true }, "Workflow")), /* @__PURE__ */ React.createElement(TableCell, null, details.value?.name)), /* @__PURE__ */ React.createElement(TableRow, null, /* @__PURE__ */ React.createElement(TableCell, null, /* @__PURE__ */ React.createElement(Typography, { noWrap: true }, "Status")), /* @__PURE__ */ React.createElement(TableCell, null, /* @__PURE__ */ React.createElement(
|
|
119
|
+
WorkflowRunStatus,
|
|
120
|
+
{
|
|
121
|
+
status: details.value?.status || void 0,
|
|
122
|
+
conclusion: details.value?.conclusion || void 0
|
|
123
|
+
}
|
|
124
|
+
))), /* @__PURE__ */ React.createElement(TableRow, null, /* @__PURE__ */ React.createElement(TableCell, null, /* @__PURE__ */ React.createElement(Typography, { noWrap: true }, "Author")), /* @__PURE__ */ React.createElement(TableCell, null, `${details.value?.head_commit?.author?.name} (${details.value?.head_commit?.author?.email})`)), /* @__PURE__ */ React.createElement(TableRow, null, /* @__PURE__ */ React.createElement(TableCell, null, /* @__PURE__ */ React.createElement(Typography, { noWrap: true }, "Links")), /* @__PURE__ */ React.createElement(TableCell, null, details.value?.html_url && /* @__PURE__ */ React.createElement(Link, { to: details.value.html_url }, "Workflow runs on GitHub", " ", /* @__PURE__ */ React.createElement(ExternalLinkIcon, { className: classes.externalLinkIcon })))), /* @__PURE__ */ React.createElement(TableRow, null, /* @__PURE__ */ React.createElement(TableCell, { colSpan: 2 }, /* @__PURE__ */ React.createElement(Typography, { noWrap: true }, "Jobs"), jobs.loading ? /* @__PURE__ */ React.createElement(CircularProgress, null) : /* @__PURE__ */ React.createElement(JobsList, { jobs: jobs.value, entity })))))));
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
export { WorkflowRunDetails };
|
|
128
|
+
//# sourceMappingURL=WorkflowRunDetails.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WorkflowRunDetails.esm.js","sources":["../../../src/components/WorkflowRunDetails/WorkflowRunDetails.tsx"],"sourcesContent":["/*\n * Copyright 2020 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';\nimport Accordion from '@material-ui/core/Accordion';\nimport AccordionDetails from '@material-ui/core/AccordionDetails';\nimport AccordionSummary from '@material-ui/core/AccordionSummary';\nimport Box from '@material-ui/core/Box';\nimport CircularProgress from '@material-ui/core/CircularProgress';\nimport LinearProgress from '@material-ui/core/LinearProgress';\nimport ListItemText from '@material-ui/core/ListItemText';\nimport Paper from '@material-ui/core/Paper';\nimport Table from '@material-ui/core/Table';\nimport TableBody from '@material-ui/core/TableBody';\nimport TableCell from '@material-ui/core/TableCell';\nimport TableContainer from '@material-ui/core/TableContainer';\nimport TableRow from '@material-ui/core/TableRow';\nimport Typography from '@material-ui/core/Typography';\nimport { makeStyles, Theme } from '@material-ui/core/styles';\nimport ExpandMoreIcon from '@material-ui/icons/ExpandMore';\nimport ExternalLinkIcon from '@material-ui/icons/Launch';\nimport { DateTime } from 'luxon';\nimport React from 'react';\nimport { Job, Jobs, Step } from '../../api';\nimport { getProjectNameFromEntity } from '../getProjectNameFromEntity';\nimport { WorkflowRunStatus } from '../WorkflowRunStatus';\nimport { useWorkflowRunJobs } from './useWorkflowRunJobs';\nimport { useWorkflowRunsDetails } from './useWorkflowRunsDetails';\nimport { WorkflowRunLogs } from '../WorkflowRunLogs';\nimport { Breadcrumbs, Link } from '@backstage/core-components';\nimport { getHostnameFromEntity } from '../getHostnameFromEntity';\n\nconst useStyles = makeStyles<Theme>(theme => ({\n root: {\n maxWidth: 720,\n margin: theme.spacing(2),\n },\n title: {\n padding: theme.spacing(1, 0, 2, 0),\n },\n table: {\n padding: theme.spacing(1),\n },\n accordionDetails: {\n padding: 0,\n },\n button: {\n order: -1,\n marginRight: 0,\n marginLeft: '-20px',\n },\n externalLinkIcon: {\n fontSize: 'inherit',\n verticalAlign: 'bottom',\n },\n}));\n\nconst getElapsedTime = (start: string | undefined, end: string | undefined) => {\n if (!start || !end) {\n return '';\n }\n const startDate = DateTime.fromISO(start);\n const endDate = end ? DateTime.fromISO(end) : DateTime.now();\n const diff = endDate.diff(startDate);\n const timeElapsed = diff.toFormat(`m 'minutes' s 'seconds'`);\n return timeElapsed;\n};\n\nconst StepView = ({ step }: { step: Step }) => {\n return (\n <TableRow>\n <TableCell>\n <ListItemText\n primary={step.name}\n secondary={getElapsedTime(step.started_at, step.completed_at)}\n />\n </TableCell>\n <TableCell>\n <WorkflowRunStatus\n status={step.status.toLocaleUpperCase('en-US')}\n conclusion={step.conclusion?.toLocaleUpperCase('en-US')}\n />\n </TableCell>\n </TableRow>\n );\n};\n\nconst JobListItem = ({\n job,\n className,\n entity,\n}: {\n job: Job;\n className: string;\n entity: Entity;\n}) => {\n const classes = useStyles();\n return (\n <Accordion TransitionProps={{ unmountOnExit: true }} className={className}>\n <AccordionSummary\n expandIcon={<ExpandMoreIcon />}\n IconButtonProps={{\n className: classes.button,\n }}\n >\n <Typography variant=\"button\">\n {job.name} ({getElapsedTime(job.started_at, job.completed_at)})\n </Typography>\n </AccordionSummary>\n <AccordionDetails className={classes.accordionDetails}>\n <TableContainer>\n <Table>\n {job.steps?.map(step => (\n <StepView key={step.number} step={step} />\n ))}\n </Table>\n </TableContainer>\n </AccordionDetails>\n {job.status === 'queued' || job.status === 'in_progress' ? (\n <WorkflowRunLogs runId={job.id} inProgress entity={entity} />\n ) : (\n <WorkflowRunLogs runId={job.id} inProgress={false} entity={entity} />\n )}\n </Accordion>\n );\n};\n\nconst JobsList = ({ jobs, entity }: { jobs?: Jobs; entity: Entity }) => {\n const classes = useStyles();\n return (\n <Box>\n {jobs &&\n jobs.total_count > 0 &&\n jobs.jobs.map(job => (\n <JobListItem\n key={job.id}\n job={job}\n className={\n job.status !== 'success' ? classes.failed : classes.success\n }\n entity={entity}\n />\n ))}\n </Box>\n );\n};\n\nexport const WorkflowRunDetails = ({ entity }: { entity: Entity }) => {\n const projectName = getProjectNameFromEntity(entity);\n\n const hostname = getHostnameFromEntity(entity);\n const [owner, repo] = (projectName && projectName.split('/')) || [];\n const details = useWorkflowRunsDetails({ hostname, owner, repo });\n const jobs = useWorkflowRunJobs({ hostname, owner, repo });\n\n const classes = useStyles();\n\n if (details.error && details.error.message) {\n return (\n <Typography variant=\"h6\" color=\"error\">\n Failed to load build, {details.error.message}\n </Typography>\n );\n } else if (details.loading) {\n return <LinearProgress />;\n }\n return (\n <div className={classes.root}>\n <Box mb={3}>\n <Breadcrumbs aria-label=\"breadcrumb\">\n <Link to=\"..\">Workflow runs</Link>\n <Typography>Workflow run details</Typography>\n </Breadcrumbs>\n </Box>\n <TableContainer component={Paper} className={classes.table}>\n <Table>\n <TableBody>\n <TableRow>\n <TableCell>\n <Typography noWrap>Branch</Typography>\n </TableCell>\n <TableCell>{details.value?.head_branch}</TableCell>\n </TableRow>\n <TableRow>\n <TableCell>\n <Typography noWrap>Message</Typography>\n </TableCell>\n <TableCell>{details.value?.head_commit?.message}</TableCell>\n </TableRow>\n <TableRow>\n <TableCell>\n <Typography noWrap>Commit ID</Typography>\n </TableCell>\n <TableCell>{details.value?.head_commit?.id}</TableCell>\n </TableRow>\n <TableRow>\n <TableCell>\n <Typography noWrap>Workflow</Typography>\n </TableCell>\n <TableCell>{details.value?.name}</TableCell>\n </TableRow>\n <TableRow>\n <TableCell>\n <Typography noWrap>Status</Typography>\n </TableCell>\n <TableCell>\n <WorkflowRunStatus\n status={details.value?.status || undefined}\n conclusion={details.value?.conclusion || undefined}\n />\n </TableCell>\n </TableRow>\n <TableRow>\n <TableCell>\n <Typography noWrap>Author</Typography>\n </TableCell>\n <TableCell>{`${details.value?.head_commit?.author?.name} (${details.value?.head_commit?.author?.email})`}</TableCell>\n </TableRow>\n <TableRow>\n <TableCell>\n <Typography noWrap>Links</Typography>\n </TableCell>\n <TableCell>\n {details.value?.html_url && (\n <Link to={details.value.html_url}>\n Workflow runs on GitHub{' '}\n <ExternalLinkIcon className={classes.externalLinkIcon} />\n </Link>\n )}\n </TableCell>\n </TableRow>\n <TableRow>\n <TableCell colSpan={2}>\n <Typography noWrap>Jobs</Typography>\n {jobs.loading ? (\n <CircularProgress />\n ) : (\n <JobsList jobs={jobs.value} entity={entity} />\n )}\n </TableCell>\n </TableRow>\n </TableBody>\n </Table>\n </TableContainer>\n </div>\n );\n};\n"],"names":[],"mappings":"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"}
|