feat: use annotation to get project name

This commit is contained in:
Nikita Nek Dudnik
2020-07-23 21:05:55 +02:00
parent 9bdb010432
commit 25e41d2274
12 changed files with 95 additions and 423 deletions
@@ -23,7 +23,7 @@ import {
} from '@octokit/types';
export class GithubActionsClient implements GithubActionsApi {
reRunWorkflow({
async reRunWorkflow({
token,
owner,
repo,
+25 -203
View File
@@ -14,211 +14,33 @@
* limitations under the License.
*/
export enum BuildStatus {
Null,
Success,
Failure,
Pending,
Running,
}
export type Build = {
commitId: string;
message: string;
branch: string;
status: BuildStatus;
uri: string;
};
export type BuildDetails = {
build: Build;
author: string;
logUrl: string;
overviewUrl: string;
};
export interface Author {
export type Step = {
name: string;
email: string;
}
export interface Committer {
name: string;
email: string;
}
export interface HeadCommit {
id: string;
tree_id: string;
message: string;
timestamp: Date;
author: Author;
committer: Committer;
}
export interface Owner {
login: string;
id: number;
node_id: string;
avatar_url: string;
gravatar_id: string;
url: string;
html_url: string;
followers_url: string;
following_url: string;
gists_url: string;
starred_url: string;
subscriptions_url: string;
organizations_url: string;
repos_url: string;
events_url: string;
received_events_url: string;
type: string;
site_admin: boolean;
}
export interface Repository {
id: number;
node_id: string;
name: string;
full_name: string;
private: boolean;
owner: Owner;
html_url: string;
description?: any;
fork: boolean;
url: string;
forks_url: string;
keys_url: string;
collaborators_url: string;
teams_url: string;
hooks_url: string;
issue_events_url: string;
events_url: string;
assignees_url: string;
branches_url: string;
tags_url: string;
blobs_url: string;
git_tags_url: string;
git_refs_url: string;
trees_url: string;
statuses_url: string;
languages_url: string;
stargazers_url: string;
contributors_url: string;
subscribers_url: string;
subscription_url: string;
commits_url: string;
git_commits_url: string;
comments_url: string;
issue_comment_url: string;
contents_url: string;
compare_url: string;
merges_url: string;
archive_url: string;
downloads_url: string;
issues_url: string;
pulls_url: string;
milestones_url: string;
notifications_url: string;
labels_url: string;
releases_url: string;
deployments_url: string;
}
export interface Owner2 {
login: string;
id: number;
node_id: string;
avatar_url: string;
gravatar_id: string;
url: string;
html_url: string;
followers_url: string;
following_url: string;
gists_url: string;
starred_url: string;
subscriptions_url: string;
organizations_url: string;
repos_url: string;
events_url: string;
received_events_url: string;
type: string;
site_admin: boolean;
}
export interface HeadRepository {
id: number;
node_id: string;
name: string;
full_name: string;
private: boolean;
owner: Owner2;
html_url: string;
description?: any;
fork: boolean;
url: string;
forks_url: string;
keys_url: string;
collaborators_url: string;
teams_url: string;
hooks_url: string;
issue_events_url: string;
events_url: string;
assignees_url: string;
branches_url: string;
tags_url: string;
blobs_url: string;
git_tags_url: string;
git_refs_url: string;
trees_url: string;
statuses_url: string;
languages_url: string;
stargazers_url: string;
contributors_url: string;
subscribers_url: string;
subscription_url: string;
commits_url: string;
git_commits_url: string;
comments_url: string;
issue_comment_url: string;
contents_url: string;
compare_url: string;
merges_url: string;
archive_url: string;
downloads_url: string;
issues_url: string;
pulls_url: string;
milestones_url: string;
notifications_url: string;
labels_url: string;
releases_url: string;
deployments_url: string;
}
export interface WorkflowRun {
id: number;
node_id: string;
head_branch: string;
head_sha: string;
run_number: number;
event: string;
status: string;
conclusion: string;
workflow_id: number;
url: string;
number: number; // starts from 1
started_at: string;
completed_at: string;
};
export type Job = {
html_url: string;
pull_requests: any[];
created_at: Date;
updated_at: Date;
jobs_url: string;
logs_url: string;
check_suite_url: string;
artifacts_url: string;
cancel_url: string;
rerun_url: string;
workflow_url: string;
head_commit: HeadCommit;
repository: Repository;
head_repository: HeadRepository;
status: string;
conclusion: string;
started_at: string;
completed_at: string;
name: string;
steps: Step[];
};
export type Jobs = {
total_count: number;
jobs: Job[];
};
export enum BuildStatus {
'success',
'failure',
'pending',
'running',
}
@@ -33,14 +33,13 @@ import {
ListItemText,
CircularProgress,
Grid,
Breadcrumbs,
} from '@material-ui/core';
import moment from 'moment';
import React from 'react';
import {
Link,
useApi,
configApiRef,
Page,
Header,
HeaderLabel,
@@ -49,11 +48,12 @@ import {
SupportButton,
pageTheme,
} from '@backstage/core';
import { Job, Step, Jobs } from '../types';
import { Job, Step, Jobs } from '../../api/types';
import ExpandMoreIcon from '@material-ui/icons/ExpandMore';
import { useWorkflowRunsDetails } from './useWorkflowRunsDetails';
import { useWorkflowRunJobs } from './useWorkflowRunJobs';
import { WorkflowRunStatusIcon } from '../WorkflowRunStatusIcon/WorkflowRunStatusIcon';
import { useProjectName } from '../useProjectName';
const useStyles = makeStyles<Theme>(theme => ({
root: {
@@ -153,9 +153,12 @@ const JobListItem = ({ job, className }: { job: Job; className: string }) => {
* A component for Jobs visualization. Jobs are a property of a Workflow Run.
*/
export const WorkflowRunDetailsPage = () => {
const configApi = useApi(configApiRef);
const repo = configApi.getString('github-actions.repo');
const owner = configApi.getString('github-actions.owner');
const [owner, repo] = (
useProjectName({
kind: 'Component',
name: 'backstage-site',
}) ?? '/'
).split('/');
const details = useWorkflowRunsDetails(repo, owner);
const jobs = useWorkflowRunJobs(details.value?.jobs_url);
@@ -175,7 +178,7 @@ export const WorkflowRunDetailsPage = () => {
<Page theme={pageTheme.tool}>
<Header
title="GitHub Actions"
subtitle="See recent worflow runs and their status"
subtitle="See recent workflow runs and their status"
>
<HeaderLabel label="Owner" value="Spotify" />
<HeaderLabel label="Lifecycle" value="Alpha" />
@@ -187,16 +190,13 @@ export const WorkflowRunDetailsPage = () => {
the GitHub Actions environment.
</SupportButton>
</ContentHeader>
<Breadcrumbs aria-label="breadcrumb">
<Link to="/github-actions">Workflow runs</Link>
<Typography>Workflow run details</Typography>
</Breadcrumbs>
<Grid container spacing={3} direction="column">
<Grid item>
<div className={classes.root}>
<Typography className={classes.title} variant="h3">
<Link to="/github-actions">
<Typography component="span" variant="h3" color="primary">
&lt; Back
</Typography>
</Link>
</Typography>
<TableContainer component={Paper} className={classes.table}>
<Table>
<TableBody>
@@ -14,7 +14,7 @@
* limitations under the License.
*/
import { useAsync } from 'react-use';
import { Jobs } from '../types';
import { Jobs } from '../../api/types';
export const useWorkflowRunJobs = (jobsUrl?: string) => {
const jobs = useAsync<Jobs>(async () => {
@@ -23,13 +23,13 @@ export const useWorkflowRunsDetails = (repo: string, owner: string) => {
const auth = useApi(githubAuthApiRef);
const { id } = useParams();
const details = useAsync(async () => {
const token = await auth.getAccessToken(['repo', 'user']);
const token = await auth.getAccessToken(['repo']);
return api.getWorkflowRun({
token,
owner,
repo,
id: parseInt(id, 10),
});
}, [id]);
}, [repo, owner, id]);
return details;
};
@@ -22,8 +22,6 @@ import {
Content,
ContentHeader,
SupportButton,
useApi,
configApiRef,
} from '@backstage/core';
import { Grid } from '@material-ui/core';
import React from 'react';
@@ -31,14 +29,11 @@ import React from 'react';
import { WorkflowRunsTable } from '../WorkflowRunsTable';
export const WorkflowRunsPage = () => {
const configApi = useApi(configApiRef);
const repo = configApi.getString('github-actions.repo');
const owner = configApi.getString('github-actions.owner');
return (
<Page theme={pageTheme.tool}>
<Header
title="GitHub Actions"
subtitle="See recent worflow runs and their status"
subtitle="See recent workflow runs and their status"
>
<HeaderLabel label="Owner" value="Spotify" />
<HeaderLabel label="Lifecycle" value="Alpha" />
@@ -52,7 +47,7 @@ export const WorkflowRunsPage = () => {
</ContentHeader>
<Grid container spacing={3} direction="column">
<Grid item>
<WorkflowRunsTable repo={repo} owner={owner} />
<WorkflowRunsTable />
</Grid>
</Grid>
</Content>
@@ -14,13 +14,14 @@
* limitations under the License.
*/
import React, { FC } from 'react';
import { Link, Typography, Box, IconButton } from '@material-ui/core';
import { Link, Typography, Box, IconButton, Tooltip } from '@material-ui/core';
import RetryIcon from '@material-ui/icons/Replay';
import GitHubIcon from '@material-ui/icons/GitHub';
import { Link as RouterLink } from 'react-router-dom';
import { Table, TableColumn } from '@backstage/core';
import { useWorkflowRuns } from './useWorkflowRuns';
import { WorkflowRunStatusIcon } from '../WorkflowRunStatusIcon';
import SyncIcon from '@material-ui/icons/Sync';
export type WorkflowRun = {
id: string;
@@ -81,9 +82,11 @@ const generatedColumns: TableColumn[] = [
{
title: 'Actions',
render: (row: Partial<WorkflowRun>) => (
<IconButton onClick={row.onReRunClick}>
<RetryIcon />
</IconButton>
<Tooltip title="Rerun workflow">
<IconButton onClick={row.onReRunClick}>
<RetryIcon />
</IconButton>
</Tooltip>
),
width: '10%',
},
@@ -120,8 +123,8 @@ const WorkflowRunsTableView: FC<Props> = ({
page={page}
actions={[
{
icon: () => <RetryIcon />,
tooltip: 'Refresh Data',
icon: () => <SyncIcon />,
tooltip: 'Reload workflow runs',
isFreeAction: true,
onClick: () => retry(),
},
@@ -141,17 +144,8 @@ const WorkflowRunsTableView: FC<Props> = ({
);
};
export const WorkflowRunsTable = ({
repo,
owner,
}: {
repo: string;
owner: string;
}) => {
const [tableProps, { retry, setPage, setPageSize }] = useWorkflowRuns({
repo,
owner,
});
export const WorkflowRunsTable = () => {
const [tableProps, { retry, setPage, setPageSize }] = useWorkflowRuns();
return (
<WorkflowRunsTableView
{...tableProps}
@@ -19,16 +19,9 @@ import { WorkflowRun } from './WorkflowRunsTable';
import { githubActionsApiRef } from '../../api/GithubActionsApi';
import { useApi, githubAuthApiRef, errorApiRef } from '@backstage/core';
import { ActionsListWorkflowRunsForRepoResponseData } from '@octokit/types';
import { catalogApiRef } from '@backstage/plugin-catalog';
import { useProjectName } from '../useProjectName';
export function useWorkflowRuns({
repo,
owner,
}: {
repo: string;
owner: string;
}) {
const catalogApi = useApi(catalogApiRef);
export function useWorkflowRuns() {
const api = useApi(githubActionsApiRef);
const auth = useApi(githubAuthApiRef);
@@ -38,17 +31,15 @@ export function useWorkflowRuns({
const [page, setPage] = useState(0);
const [pageSize, setPageSize] = useState(5);
const reRunWorkflow = async () => {};
const projectName = useProjectName({
kind: 'Component',
name: 'backstage-site',
});
const { loading, value: runs, retry } = useAsyncRetry<
WorkflowRun[]
>(async () => {
const token = await auth.getAccessToken(['repo', 'user']);
const entity = await catalogApi.getEntityByName({
kind: 'Component',
name: 'backstage-site',
});
console.log(entity);
const token = await auth.getAccessToken(['repo']);
const [owner, repo] = (projectName ?? '/').split('/');
return (
api
// GitHub API pagination count starts from 1
@@ -90,23 +81,21 @@ export function useWorkflowRuns({
},
)
);
}, [page, pageSize]);
}, [page, pageSize, projectName]);
const projectName = `${owner}/${repo}`;
return [
{
page,
pageSize,
loading,
runs,
projectName,
projectName: projectName ?? '',
total,
},
{
runs,
setPage,
setPageSize,
reRunWorkflow,
retry,
},
] as const;
@@ -13,33 +13,19 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
export type Step = {
name: string;
status: string;
conclusion: string;
number: number; // starts from 1
started_at: string;
completed_at: string;
};
export type Job = {
html_url: string;
status: string;
conclusion: string;
started_at: string;
completed_at: string;
name: string;
steps: Step[];
};
import { useAsync } from 'react-use';
import { catalogApiRef, EntityCompoundName } from '@backstage/plugin-catalog';
import { useApi } from '@backstage/core';
export type Jobs = {
total_count: number;
jobs: Job[];
};
export const useProjectName = (name: EntityCompoundName) => {
const catalogApi = useApi(catalogApiRef);
export enum BuildStatus {
'success',
'failure',
'pending',
'running',
}
const { value } = useAsync<string>(async () => {
const entity = await catalogApi.getEntityByName(name);
return (
entity?.metadata.annotations?.['backstage.io/github-actions-id'] ?? ''
);
});
return value;
};