From 25e41d227436cabec1f0786158a10de53b41f9c6 Mon Sep 17 00:00:00 2001 From: Nikita Nek Dudnik Date: Thu, 23 Jul 2020 21:05:55 +0200 Subject: [PATCH] feat: use annotation to get project name --- .../examples/shuffle-api-component.yaml | 2 + .../src/api/GithubActionsClient.ts | 2 +- plugins/github-actions/src/api/types.ts | 228 ++---------------- .../WorkflowRunDetailsPage.tsx | 28 +-- .../useWorkflowRunJobs.ts | 2 +- .../useWorkflowRunsDetails.ts | 4 +- .../WorkflowRunsPage/WorkflowRunsPage.tsx | 9 +- .../WorkflowRunsTable/WorkflowRunsTable.tsx | 28 +-- .../WorkflowRunsTable/useWorkflowRuns.ts | 31 +-- .../{types.ts => useProjectName.ts} | 40 +-- .../react-ssr-template/template.yaml | 17 +- yarn.lock | 127 ---------- 12 files changed, 95 insertions(+), 423 deletions(-) rename plugins/github-actions/src/components/{types.ts => useProjectName.ts} (54%) diff --git a/packages/catalog-model/examples/shuffle-api-component.yaml b/packages/catalog-model/examples/shuffle-api-component.yaml index 275c48d6ba..1726f7aec7 100644 --- a/packages/catalog-model/examples/shuffle-api-component.yaml +++ b/packages/catalog-model/examples/shuffle-api-component.yaml @@ -3,6 +3,8 @@ kind: Component metadata: name: shuffle-api description: Shuffle API + annotations: + backstage.io/github-actions-id: 'spotify/backstage' spec: type: service lifecycle: production diff --git a/plugins/github-actions/src/api/GithubActionsClient.ts b/plugins/github-actions/src/api/GithubActionsClient.ts index 6e6f1cb1e2..a96f5341fd 100644 --- a/plugins/github-actions/src/api/GithubActionsClient.ts +++ b/plugins/github-actions/src/api/GithubActionsClient.ts @@ -23,7 +23,7 @@ import { } from '@octokit/types'; export class GithubActionsClient implements GithubActionsApi { - reRunWorkflow({ + async reRunWorkflow({ token, owner, repo, diff --git a/plugins/github-actions/src/api/types.ts b/plugins/github-actions/src/api/types.ts index 8a7b2ca548..cd74a20cda 100644 --- a/plugins/github-actions/src/api/types.ts +++ b/plugins/github-actions/src/api/types.ts @@ -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', } diff --git a/plugins/github-actions/src/components/WorkflowRunDetailsPage/WorkflowRunDetailsPage.tsx b/plugins/github-actions/src/components/WorkflowRunDetailsPage/WorkflowRunDetailsPage.tsx index 6bda0f50b8..a8ddcfef12 100644 --- a/plugins/github-actions/src/components/WorkflowRunDetailsPage/WorkflowRunDetailsPage.tsx +++ b/plugins/github-actions/src/components/WorkflowRunDetailsPage/WorkflowRunDetailsPage.tsx @@ -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 => ({ 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 = () => {
@@ -187,16 +190,13 @@ export const WorkflowRunDetailsPage = () => { the GitHub Actions environment. + + Workflow runs + Workflow run details +
- - - - < Back - - - diff --git a/plugins/github-actions/src/components/WorkflowRunDetailsPage/useWorkflowRunJobs.ts b/plugins/github-actions/src/components/WorkflowRunDetailsPage/useWorkflowRunJobs.ts index c941ed6389..d4c09abf7d 100644 --- a/plugins/github-actions/src/components/WorkflowRunDetailsPage/useWorkflowRunJobs.ts +++ b/plugins/github-actions/src/components/WorkflowRunDetailsPage/useWorkflowRunJobs.ts @@ -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(async () => { diff --git a/plugins/github-actions/src/components/WorkflowRunDetailsPage/useWorkflowRunsDetails.ts b/plugins/github-actions/src/components/WorkflowRunDetailsPage/useWorkflowRunsDetails.ts index 088c286d94..623f55eea6 100644 --- a/plugins/github-actions/src/components/WorkflowRunDetailsPage/useWorkflowRunsDetails.ts +++ b/plugins/github-actions/src/components/WorkflowRunDetailsPage/useWorkflowRunsDetails.ts @@ -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; }; diff --git a/plugins/github-actions/src/components/WorkflowRunsPage/WorkflowRunsPage.tsx b/plugins/github-actions/src/components/WorkflowRunsPage/WorkflowRunsPage.tsx index a4cb576468..b75a70f326 100644 --- a/plugins/github-actions/src/components/WorkflowRunsPage/WorkflowRunsPage.tsx +++ b/plugins/github-actions/src/components/WorkflowRunsPage/WorkflowRunsPage.tsx @@ -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 (
@@ -52,7 +47,7 @@ export const WorkflowRunsPage = () => { - + diff --git a/plugins/github-actions/src/components/WorkflowRunsTable/WorkflowRunsTable.tsx b/plugins/github-actions/src/components/WorkflowRunsTable/WorkflowRunsTable.tsx index 4c54d12121..313a51e28a 100644 --- a/plugins/github-actions/src/components/WorkflowRunsTable/WorkflowRunsTable.tsx +++ b/plugins/github-actions/src/components/WorkflowRunsTable/WorkflowRunsTable.tsx @@ -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) => ( - - - + + + + + ), width: '10%', }, @@ -120,8 +123,8 @@ const WorkflowRunsTableView: FC = ({ page={page} actions={[ { - icon: () => , - tooltip: 'Refresh Data', + icon: () => , + tooltip: 'Reload workflow runs', isFreeAction: true, onClick: () => retry(), }, @@ -141,17 +144,8 @@ const WorkflowRunsTableView: FC = ({ ); }; -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 ( {}; - + 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; diff --git a/plugins/github-actions/src/components/types.ts b/plugins/github-actions/src/components/useProjectName.ts similarity index 54% rename from plugins/github-actions/src/components/types.ts rename to plugins/github-actions/src/components/useProjectName.ts index 3174cd23c0..d6fe9bd35d 100644 --- a/plugins/github-actions/src/components/types.ts +++ b/plugins/github-actions/src/components/useProjectName.ts @@ -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(async () => { + const entity = await catalogApi.getEntityByName(name); + return ( + entity?.metadata.annotations?.['backstage.io/github-actions-id'] ?? '' + ); + }); + return value; +}; diff --git a/plugins/scaffolder-backend/sample-templates/react-ssr-template/template.yaml b/plugins/scaffolder-backend/sample-templates/react-ssr-template/template.yaml index 71f75c7695..dc9fb22aa8 100644 --- a/plugins/scaffolder-backend/sample-templates/react-ssr-template/template.yaml +++ b/plugins/scaffolder-backend/sample-templates/react-ssr-template/template.yaml @@ -13,7 +13,7 @@ spec: type: website path: '.' schema: - required: + required: - component_id - description properties: @@ -22,7 +22,18 @@ spec: type: string description: Unique name of the component description: - title: Description + title: Description type: string description: Description of the component - +--- +apiVersion: backstage.io/v1alpha1 +kind: Component +metadata: + name: backstage-site + description: backstage.io + annotations: + backstage.io/github-actions-id: 'spotify/backstage' +spec: + type: website + lifecycle: production + owner: guest diff --git a/yarn.lock b/yarn.lock index c662364db6..8b2af1f211 100644 --- a/yarn.lock +++ b/yarn.lock @@ -939,133 +939,6 @@ lodash "^4.17.13" to-fast-properties "^2.0.0" -"@backstage/catalog-model@^0.1.1-alpha.15": - version "0.1.1-alpha.15" - resolved "https://registry.npmjs.org/@backstage/catalog-model/-/catalog-model-0.1.1-alpha.15.tgz#d1bb2eb53ff12af6868f49a24693fb2c0c209c78" - integrity sha512-nHfdeVpeyUpSyL4sjXRgCZ53ODP66o9Koc7oAXM2Gih07Z+thefIXDpY2bjWRcz+VLkVJJyVxRj/5VhrN2bukg== - dependencies: - "@backstage/config" "^0.1.1-alpha.13" - "@types/json-schema" "^7.0.5" - "@types/yup" "^0.28.2" - json-schema "^0.2.5" - lodash "^4.17.15" - uuid "^8.0.0" - yup "^0.29.1" - -"@backstage/core-api@^0.1.1-alpha.15": - version "0.1.1-alpha.15" - resolved "https://registry.npmjs.org/@backstage/core-api/-/core-api-0.1.1-alpha.15.tgz#c5d70339ee1b0646841c95f69665be9094b54331" - integrity sha512-U4MWV2MZS+0tEUod0HaugYEbsBB2VLG2t41UXm2kYYhLc3JfCr99DRR2KXJSyl2To6fc9//l7IMg4efpfhpWYw== - dependencies: - "@backstage/config" "^0.1.1-alpha.13" - "@backstage/theme" "^0.1.1-alpha.15" - "@material-ui/core" "^4.9.1" - "@material-ui/icons" "^4.9.1" - "@types/react" "^16.9" - prop-types "^15.7.2" - react "^16.12.0" - react-router-dom "6.0.0-beta.0" - react-use "^14.2.0" - zen-observable "^0.8.15" - -"@backstage/core@^0.1.1-alpha.15": - version "0.1.1-alpha.15" - resolved "https://registry.npmjs.org/@backstage/core/-/core-0.1.1-alpha.15.tgz#bb998f84643d6e6c88dfe6e8c3b1855cc35d7ed9" - integrity sha512-DaKwwj+mS5fa1Wq4R9+jbWMJdPj0JXv+Rzyy1iFKq9Ng9z1Rwum8h3R+q/DlPwSdSNlWaTdikZyw1C43Z+3FYw== - dependencies: - "@backstage/config" "^0.1.1-alpha.13" - "@backstage/core-api" "^0.1.1-alpha.15" - "@backstage/theme" "^0.1.1-alpha.15" - "@material-ui/core" "^4.9.1" - "@material-ui/icons" "^4.9.1" - "@material-ui/lab" "4.0.0-alpha.45" - "@types/react" "^16.9" - "@types/react-sparklines" "^1.7.0" - classnames "^2.2.6" - clsx "^1.1.0" - lodash "^4.17.15" - material-table "1.62.x" - prop-types "^15.7.2" - rc-progress "^3.0.0" - react "^16.12.0" - react-dom "^16.12.0" - react-helmet "6.1.0" - react-hook-form "^5.7.2" - react-router "6.0.0-beta.0" - react-router-dom "6.0.0-beta.0" - react-sparklines "^1.7.0" - react-syntax-highlighter "^12.2.1" - react-use "^14.2.0" - -"@backstage/plugin-catalog@^0.1.1-alpha.15": - version "0.1.1-alpha.15" - resolved "https://registry.npmjs.org/@backstage/plugin-catalog/-/plugin-catalog-0.1.1-alpha.15.tgz#438b2bf035ea2acf21cddda9c33363ffc6629b55" - integrity sha512-4wGs4AROaF+nq7DsQzpgdtifwjQnTfWRO541zSNh117qJe7yIHXzY+XVAzQ5ct421hYXn7ofxwKUsGI4hYgVRg== - dependencies: - "@backstage/catalog-model" "^0.1.1-alpha.15" - "@backstage/core" "^0.1.1-alpha.15" - "@backstage/plugin-scaffolder" "^0.1.1-alpha.15" - "@backstage/plugin-sentry" "^0.1.1-alpha.15" - "@backstage/theme" "^0.1.1-alpha.15" - "@material-ui/core" "^4.9.1" - "@material-ui/icons" "^4.9.1" - "@material-ui/lab" "4.0.0-alpha.45" - moment "^2.26.0" - react "^16.13.1" - react-dom "^16.13.1" - react-router "6.0.0-beta.0" - react-router-dom "6.0.0-beta.0" - react-use "^14.2.0" - swr "^0.2.2" - -"@backstage/plugin-scaffolder@^0.1.1-alpha.15": - version "0.1.1-alpha.15" - resolved "https://registry.npmjs.org/@backstage/plugin-scaffolder/-/plugin-scaffolder-0.1.1-alpha.15.tgz#935d21a5c815c530bd4fed89b9c1d4cb983a57bb" - integrity sha512-+HZ/aPlMcacuT7JYN2hYlZqWA8jYoAEoh7laBripm1nIxhxCLi4BuPX4X0W73a3cpCv+MYefvUq0g7yYDJvQJw== - dependencies: - "@backstage/catalog-model" "^0.1.1-alpha.15" - "@backstage/core" "^0.1.1-alpha.15" - "@backstage/plugin-catalog" "^0.1.1-alpha.15" - "@backstage/theme" "^0.1.1-alpha.15" - "@material-ui/core" "^4.9.1" - "@material-ui/icons" "^4.9.1" - "@material-ui/lab" "4.0.0-alpha.45" - "@rjsf/core" "^2.1.0" - "@rjsf/material-ui" "^2.1.0" - classnames "^2.2.6" - moment "^2.26.0" - react "^16.13.1" - react-dom "^16.13.1" - react-lazylog "^4.5.2" - react-router "6.0.0-beta.0" - react-router-dom "6.0.0-beta.0" - react-use "^14.2.0" - swr "^0.2.2" - -"@backstage/plugin-sentry@^0.1.1-alpha.15": - version "0.1.1-alpha.15" - resolved "https://registry.npmjs.org/@backstage/plugin-sentry/-/plugin-sentry-0.1.1-alpha.15.tgz#8a507f7143766582dc5bed7a9ee09ea256cbdd0d" - integrity sha512-wBOSqOvF6qedZ9gAYR3aQ8rqbgCUQz5WA5Mw7KZVa0FeWdjLIKYsDl0oI6EE3EQZV9iZef6kzY7W/8gjJV3fHQ== - dependencies: - "@backstage/core" "^0.1.1-alpha.15" - "@backstage/theme" "^0.1.1-alpha.15" - "@material-ui/core" "^4.9.1" - "@material-ui/icons" "^4.9.1" - "@material-ui/lab" "4.0.0-alpha.45" - "@types/react" "^16.9" - react "^16.13.1" - react-dom "^16.13.1" - react-sparklines "^1.7.0" - react-use "^14.2.0" - timeago.js "^4.0.2" - -"@backstage/theme@^0.1.1-alpha.15": - version "0.1.1-alpha.15" - resolved "https://registry.npmjs.org/@backstage/theme/-/theme-0.1.1-alpha.15.tgz#b30ec50ef0aba672f3b6f6ed3fb0209ec2990008" - integrity sha512-cyE3jj3Oynd8NHYSVm7H1Dhz573oe7V6vOAetdoqt7fX7I28onoSrUzv8x9eVM8uX4FiMck8PISPVKPGddCDZQ== - dependencies: - "@material-ui/core" "^4.9.1" - "@bcoe/v8-coverage@^0.2.3": version "0.2.3" resolved "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39"