diff --git a/plugins/github-release-manager/dev/index.tsx b/plugins/github-release-manager/dev/index.tsx index 5518d633e2..1b5236b920 100644 --- a/plugins/github-release-manager/dev/index.tsx +++ b/plugins/github-release-manager/dev/index.tsx @@ -22,14 +22,27 @@ import { GitHubReleaseManagerPage, } from '../src/plugin'; +function DevWrapper({ children }: { children: React.ReactNode }) { + return
{children}
; +} + createDevApp() .registerPlugin(gitHubReleaseManagerPlugin) .addPage({ title: 'Page 1', - element: , + element: ( + + + + ), }) .addPage({ title: 'Page 2', - element: , + element: ( + + {' '} + + + ), }) .render(); diff --git a/plugins/github-release-manager/package.json b/plugins/github-release-manager/package.json index 5462595e0b..0a21a8e018 100644 --- a/plugins/github-release-manager/package.json +++ b/plugins/github-release-manager/package.json @@ -28,8 +28,8 @@ "@material-ui/lab": "4.0.0-alpha.45", "@octokit/rest": "^18.0.12", "luxon": "^1.26.0", + "qs": "^6.10.1", "react-dom": "^16.13.1", - "react-hook-form": "^6.6.0", "react-router": "6.0.0-beta.0", "react-use": "^15.3.3", "react": "^16.13.1" diff --git a/plugins/github-release-manager/src/GitHubReleaseManager.tsx b/plugins/github-release-manager/src/GitHubReleaseManager.tsx index a52db523d4..692b43baa1 100644 --- a/plugins/github-release-manager/src/GitHubReleaseManager.tsx +++ b/plugins/github-release-manager/src/GitHubReleaseManager.tsx @@ -16,7 +16,6 @@ import React, { useState } from 'react'; import { useAsync } from 'react-use'; -import { useForm } from 'react-hook-form'; import { Alert } from '@material-ui/lab'; import { makeStyles } from '@material-ui/core'; import { useApi, ContentHeader, ErrorBoundary } from '@backstage/core'; @@ -42,6 +41,9 @@ import { InfoCardPlus } from './components/InfoCardPlus'; import { RepoDetailsForm } from './cards/projectForm/RepoDetailsForm'; import { CenteredCircularProgress } from './components/CenteredCircularProgress'; import { useVersioningStrategyMatchesRepoTags } from './helpers/useVersioningStrategyMatchesRepoTags'; +import { useQuery } from './helpers/useQuery'; +import { getParsedQuery } from './helpers/getNewQueryParams'; +import { RefetchContext } from './contexts/RefetchContext'; interface GitHubReleaseManagerProps { components?: { @@ -65,8 +67,14 @@ export function GitHubReleaseManager({ const pluginApiClient = useApi(githubReleaseManagerApiRef); const classes = useStyles(); const usernameResponse = useAsync(() => pluginApiClient.getUsername()); - const { control, watch } = useForm(); - const project: Project = watch('repo-details-form'); + const query = useQuery(); + + const parsedQuery = getParsedQuery({ query }); + const project: Project = { + owner: parsedQuery.owner ?? '', + repo: parsedQuery.repo ?? '', + versioningStrategy: parsedQuery.versioningStrategy ?? 'semver', + }; if (usernameResponse.error) { return {usernameResponse.error.message}; @@ -87,8 +95,8 @@ export function GitHubReleaseManager({ @@ -108,10 +116,10 @@ function Cards({ project: Project; }) { const pluginApiClient = usePluginApiClientContext(); - const [refetch, setRefetch] = useState(0); + const [refetchTrigger, setRefetchTrigger] = useState(0); const gitHubBatchInfo = useAsync( getGitHubBatchInfo({ project, pluginApiClient }), - [project, refetch], + [project, refetchTrigger], ); const { versioningStrategyMatches } = useVersioningStrategyMatchesRepoTags({ @@ -121,7 +129,12 @@ function Cards({ }); if (gitHubBatchInfo.error) { - return {gitHubBatchInfo.error.message}; + return ( + + Error occured while fetching information for "{project.owner}/ + {project.repo}" ({gitHubBatchInfo.error.message}) + + ); } if (gitHubBatchInfo.loading) { @@ -154,39 +167,38 @@ function Cards({ return ( - - - - {components?.default?.createRc?.omit !== true && ( - + + - )} - {components?.default?.promoteRc?.omit !== true && ( - - )} + {components?.default?.createRc?.omit !== true && ( + + )} - {components?.default?.patch?.omit !== true && ( - - )} - + {components?.default?.promoteRc?.omit !== true && ( + + )} + + {components?.default?.patch?.omit !== true && ( + + )} + + ); } diff --git a/plugins/github-release-manager/src/api/PluginApiClient.ts b/plugins/github-release-manager/src/api/PluginApiClient.ts index 42b3210823..3b7e0da80f 100644 --- a/plugins/github-release-manager/src/api/PluginApiClient.ts +++ b/plugins/github-release-manager/src/api/PluginApiClient.ts @@ -40,7 +40,7 @@ export interface IPluginApiClient { getRepoPath: (args: PartialProject) => string; - getOrganizations: () => Promise<{ organizations: string[] }>; + getOwners: () => Promise<{ owners: string[] }>; getRepositories: (args: { owner: string; @@ -50,8 +50,8 @@ export interface IPluginApiClient { getRecentCommits: ( args: { releaseBranchName?: string } & PartialProject, - ) => Promise<{ - recentCommits: { + ) => Promise< + { htmlUrl: string; sha: string; author: { @@ -62,8 +62,8 @@ export interface IPluginApiClient { message: string; }; firstParentSha?: string; - }[]; - }>; + }[] + >; getLatestRelease: ( args: PartialProject, @@ -154,7 +154,7 @@ export interface IPluginApiClient { tagParts: SemverTagParts | CalverTagParts; releaseBranchTree: string; selectedPatchCommit: UnboxArray< - ApiMethodRetval['recentCommits'] + ApiMethodRetval >; } & PartialProject, ) => Promise<{ @@ -191,7 +191,7 @@ export interface IPluginApiClient { args: { bumpedTag: string; selectedPatchCommit: UnboxArray< - ApiMethodRetval['recentCommits'] + ApiMethodRetval >; mergeTree: string; releaseBranchSha: string; @@ -247,7 +247,7 @@ export interface IPluginApiClient { >; tagParts: SemverTagParts | CalverTagParts; selectedPatchCommit: UnboxArray< - ApiMethodRetval['recentCommits'] + ApiMethodRetval >; } & PartialProject, ) => Promise<{ @@ -273,6 +273,12 @@ export interface IPluginApiClient { }; } +const DISABLE_CACHE = { + headers: { + 'If-None-Match': '', + }, +}; + export class PluginApiClient implements IPluginApiClient { private readonly githubAuthApi: OAuthApi; private readonly baseUrl: string; @@ -329,7 +335,7 @@ export class PluginApiClient implements IPluginApiClient { return `${owner}/${repo}`; } - async getOrganizations() { + async getOwners() { const { octokit } = await this.getOctokit(); const orgListResponse = await octokit.paginate( octokit.orgs.listForAuthenticatedUser, @@ -337,7 +343,7 @@ export class PluginApiClient implements IPluginApiClient { ); return { - organizations: orgListResponse.map(organization => organization.login), + owners: orgListResponse.map(organization => organization.login), }; } @@ -385,22 +391,21 @@ export class PluginApiClient implements IPluginApiClient { owner, repo, ...(releaseBranchName ? { sha: releaseBranchName } : {}), + ...DISABLE_CACHE, }); - return { - recentCommits: recentCommitsResponse.data.map(commit => ({ - htmlUrl: commit.html_url, - sha: commit.sha, - author: { - htmlUrl: commit.author?.html_url, - login: commit.author?.login, - }, - commit: { - message: commit.commit.message, - }, - firstParentSha: commit.parents?.[0].sha, - })), - }; + return recentCommitsResponse.data.map(commit => ({ + htmlUrl: commit.html_url, + sha: commit.sha, + author: { + htmlUrl: commit.author?.html_url, + login: commit.author?.login, + }, + commit: { + message: commit.commit.message, + }, + firstParentSha: commit.parents?.[0]?.sha, + })); } async getLatestRelease({ owner, repo }: PartialProject) { @@ -409,6 +414,7 @@ export class PluginApiClient implements IPluginApiClient { owner, repo, per_page: 1, + ...DISABLE_CACHE, }); if (latestReleases.length === 0) { @@ -433,10 +439,10 @@ export class PluginApiClient implements IPluginApiClient { async getRepository({ owner, repo }: PartialProject) { const { octokit } = await this.getOctokit(); - const { data: repository } = await octokit.repos.get({ owner, repo, + ...DISABLE_CACHE, }); return { @@ -458,6 +464,7 @@ export class PluginApiClient implements IPluginApiClient { owner, repo, ref: defaultBranch, + ...DISABLE_CACHE, }); return { @@ -480,6 +487,7 @@ export class PluginApiClient implements IPluginApiClient { owner, repo, branch: branchName, + ...DISABLE_CACHE, }); return { @@ -585,7 +593,7 @@ export class PluginApiClient implements IPluginApiClient { tagParts: SemverTagParts | CalverTagParts; releaseBranchTree: string; selectedPatchCommit: UnboxArray< - ApiMethodRetval['recentCommits'] + ApiMethodRetval >; } & PartialProject) => { const { octokit } = await this.getOctokit(); @@ -659,7 +667,7 @@ export class PluginApiClient implements IPluginApiClient { }: { bumpedTag: string; selectedPatchCommit: UnboxArray< - ApiMethodRetval['recentCommits'] + ApiMethodRetval >; mergeTree: string; releaseBranchSha: string; @@ -773,7 +781,7 @@ export class PluginApiClient implements IPluginApiClient { >; tagParts: SemverTagParts | CalverTagParts; selectedPatchCommit: UnboxArray< - ApiMethodRetval['recentCommits'] + ApiMethodRetval >; } & PartialProject) => { const { octokit } = await this.getOctokit(); diff --git a/plugins/github-release-manager/src/cards/createRc/CreateRc.test.tsx b/plugins/github-release-manager/src/cards/createRc/CreateRc.test.tsx index 4bc22398b2..f200a29fc5 100644 --- a/plugins/github-release-manager/src/cards/createRc/CreateRc.test.tsx +++ b/plugins/github-release-manager/src/cards/createRc/CreateRc.test.tsx @@ -47,7 +47,6 @@ describe('CreateRc', () => { , ); @@ -62,7 +61,6 @@ describe('CreateRc', () => { , ); diff --git a/plugins/github-release-manager/src/cards/createRc/CreateRc.tsx b/plugins/github-release-manager/src/cards/createRc/CreateRc.tsx index d629e9beeb..ba3733e88f 100644 --- a/plugins/github-release-manager/src/cards/createRc/CreateRc.tsx +++ b/plugins/github-release-manager/src/cards/createRc/CreateRc.tsx @@ -30,7 +30,7 @@ import { createRc } from './sideEffects/createRc'; import { Differ } from '../../components/Differ'; import { getRcGitHubInfo } from './getRcGitHubInfo'; import { InfoCardPlus } from '../../components/InfoCardPlus'; -import { ComponentConfigCreateRc, SetRefetch } from '../../types/types'; +import { ComponentConfigCreateRc } from '../../types/types'; import { ResponseStepList } from '../../components/ResponseStepList/ResponseStepList'; import { SEMVER_PARTS } from '../../constants/constants'; import { TEST_IDS } from '../../test-helpers/test-ids'; @@ -47,7 +47,6 @@ interface CreateRcProps { IPluginApiClient['getLatestRelease'] >['latestRelease']; releaseBranch: ApiMethodRetval | null; - setRefetch: SetRefetch; successCb?: ComponentConfigCreateRc['successCb']; } @@ -55,7 +54,6 @@ export const CreateRc = ({ defaultBranch, latestRelease, releaseBranch, - setRefetch, successCb, }: CreateRcProps) => { const pluginApiClient = usePluginApiClientContext(); @@ -149,7 +147,6 @@ export const CreateRc = ({ responseSteps={createGitHubReleaseResponse.value} loading={createGitHubReleaseResponse.loading} title="Create RC result" - setRefetch={setRefetch} /> ); } diff --git a/plugins/github-release-manager/src/cards/patchRc/Patch.test.tsx b/plugins/github-release-manager/src/cards/patchRc/Patch.test.tsx index 3f83a0d9ea..a9ac2d31a5 100644 --- a/plugins/github-release-manager/src/cards/patchRc/Patch.test.tsx +++ b/plugins/github-release-manager/src/cards/patchRc/Patch.test.tsx @@ -32,11 +32,7 @@ import { Patch } from './Patch'; describe('Patch', () => { it('should return early if no latestRelease exists', () => { const { getByTestId } = render( - , + , ); expect( diff --git a/plugins/github-release-manager/src/cards/patchRc/Patch.tsx b/plugins/github-release-manager/src/cards/patchRc/Patch.tsx index fc18be1d1d..822c1b09ea 100644 --- a/plugins/github-release-manager/src/cards/patchRc/Patch.tsx +++ b/plugins/github-release-manager/src/cards/patchRc/Patch.tsx @@ -18,7 +18,7 @@ import React from 'react'; import { Typography } from '@material-ui/core'; import { ApiMethodRetval, IPluginApiClient } from '../../api/PluginApiClient'; -import { ComponentConfigPatch, SetRefetch } from '../../types/types'; +import { ComponentConfigPatch } from '../../types/types'; import { getBumpedTag } from '../../helpers/getBumpedTag'; import { InfoCardPlus } from '../../components/InfoCardPlus'; import { NoLatestRelease } from '../../components/NoLatestRelease'; @@ -31,14 +31,12 @@ interface PatchProps { IPluginApiClient['getLatestRelease'] >['latestRelease']; releaseBranch: ApiMethodRetval | null; - setRefetch: SetRefetch; successCb?: ComponentConfigPatch['successCb']; } export const Patch = ({ latestRelease, releaseBranch, - setRefetch, successCb, }: PatchProps) => { const project = useProjectContext(); @@ -64,7 +62,6 @@ export const Patch = ({ bumpedTag={bumpedTag} latestRelease={latestRelease} releaseBranch={releaseBranch} - setRefetch={setRefetch} successCb={successCb} tagParts={tagParts} /> diff --git a/plugins/github-release-manager/src/cards/patchRc/PatchBody.test.tsx b/plugins/github-release-manager/src/cards/patchRc/PatchBody.test.tsx index 9b6d971056..2e0642402d 100644 --- a/plugins/github-release-manager/src/cards/patchRc/PatchBody.test.tsx +++ b/plugins/github-release-manager/src/cards/patchRc/PatchBody.test.tsx @@ -50,7 +50,6 @@ describe('PatchBody', () => { bumpedTag={mockBumpedTag} latestRelease={mockRcRelease} releaseBranch={mockReleaseBranch} - setRefetch={jest.fn()} tagParts={mockTagParts} />, ); @@ -66,7 +65,6 @@ describe('PatchBody', () => { const { getByTestId } = render( ['latestRelease'] >; releaseBranch: ApiMethodRetval; - setRefetch: SetRefetch; successCb?: ComponentConfigPatch['successCb']; tagParts: NonNullable; } @@ -65,7 +65,6 @@ export const PatchBody = ({ bumpedTag, latestRelease, releaseBranch, - setRefetch, successCb, tagParts, }: PatchBodyProps) => { @@ -75,15 +74,19 @@ export const PatchBody = ({ const githubDataResponse = useAsync(async () => { const [ - { recentCommits: recentCommitsOnDefaultBranch }, - ] = await Promise.all([pluginApiClient.getRecentCommits({ ...project })]); - - const { - recentCommits: recentCommitsOnReleaseBranch, - } = await pluginApiClient.getRecentCommits({ - ...project, - releaseBranchName: releaseBranch.name, - }); + recentCommitsOnDefaultBranch, + recentCommitsOnReleaseBranch, + ] = await Promise.all([ + pluginApiClient.getRecentCommits({ + owner: project.owner, + repo: project.repo, + }), + pluginApiClient.getRecentCommits({ + owner: project.owner, + repo: project.repo, + releaseBranchName: releaseBranch.name, + }), + ]); return { recentCommitsOnReleaseBranch, @@ -93,7 +96,7 @@ export const PatchBody = ({ const [patchReleaseResponse, patchReleaseFn] = useAsyncFn(async (...args) => { const selectedPatchCommit: UnboxArray< - ApiMethodRetval['recentCommits'] + ApiMethodRetval > = args[0]; const patchResponseSteps = await patch({ project, @@ -111,13 +114,15 @@ export const PatchBody = ({ if (githubDataResponse.error) { return ( - {githubDataResponse.error.message} + Unexpected error: {githubDataResponse.error.message} ); } + if (patchReleaseResponse.error) { return {patchReleaseResponse.error.message}; } + if (githubDataResponse.loading) { return ; } @@ -156,9 +161,11 @@ export const PatchBody = ({ {githubDataResponse.value.recentCommitsOnDefaultBranch.map( (commit, index) => { + // FIXME: Performance improvement opportunity: Convert to object lookup const commitExistsOnReleaseBranch = !!githubDataResponse.value?.recentCommitsOnReleaseBranch.find( releaseBranchCommit => releaseBranchCommit.sha === commit.sha, ); + const hasNoParent = !commit.firstParentSha; return (
@@ -190,7 +197,8 @@ export const PatchBody = ({ patchReleaseResponse.loading || (patchReleaseResponse.value && patchReleaseResponse.value.length > 0) || - commitExistsOnReleaseBranch + commitExistsOnReleaseBranch || + hasNoParent } role={undefined} dense @@ -264,36 +272,28 @@ export const PatchBody = ({ responseSteps={patchReleaseResponse.value} loading={patchReleaseResponse.loading} title="Patch result" - setRefetch={setRefetch} closeable /> ); } - if ( - !githubDataResponse.value?.recentCommitsOnDefaultBranch[ + const selectedPatchCommit = + githubDataResponse.value?.recentCommitsOnDefaultBranch[ checkedCommitIndex - ] - ) { - return ( - - ); - } - + ]; return ( )}