diff --git a/plugins/github-release-manager/src/GitHubReleaseManager.tsx b/plugins/github-release-manager/src/GitHubReleaseManager.tsx index 3876d2b3fc..a52db523d4 100644 --- a/plugins/github-release-manager/src/GitHubReleaseManager.tsx +++ b/plugins/github-release-manager/src/GitHubReleaseManager.tsx @@ -81,11 +81,7 @@ export function GitHubReleaseManager({ } return ( - +
@@ -119,7 +115,7 @@ function Cards({ ); const { versioningStrategyMatches } = useVersioningStrategyMatchesRepoTags({ - latestReleaseTagName: gitHubBatchInfo.value?.latestRelease?.tag_name, + latestReleaseTagName: gitHubBatchInfo.value?.latestRelease?.tagName, project, repositoryName: gitHubBatchInfo.value?.repository.name, }); @@ -151,7 +147,7 @@ function Cards({ return ( Versioning mismatch, expected {project.versioningStrategy} version, got{' '} - {gitHubBatchInfo.value?.latestRelease?.tag_name} + {gitHubBatchInfo.value.latestRelease?.tagName} ); } diff --git a/plugins/github-release-manager/src/api/PluginApiClient.ts b/plugins/github-release-manager/src/api/PluginApiClient.ts index 24310ef688..d348680cd1 100644 --- a/plugins/github-release-manager/src/api/PluginApiClient.ts +++ b/plugins/github-release-manager/src/api/PluginApiClient.ts @@ -19,10 +19,8 @@ import { Octokit } from '@octokit/rest'; import { readGitHubIntegrationConfigs } from '@backstage/integration'; import { - GhCompareCommitsResponse, GhCreateCommitResponse, GhCreateReferenceResponse, - GhCreateReleaseResponse, GhCreateTagObjectResponse, GhGetBranchResponse, GhGetCommitResponse, @@ -36,32 +34,72 @@ import { getRcGitHubInfo } from '../cards/createRc/getRcGitHubInfo'; import { SemverTagParts } from '../helpers/tagParts/getSemverTagParts'; import { Project } from '../contexts/ProjectContext'; -// export type UnboxPromise> = T extends Promise -// ? U -// : never; +type UnboxPromise> = T extends Promise + ? U + : never; -type Todo = any; +export type ApiMethodRetval< + T extends (...args: any) => Promise +> = UnboxPromise>; + +type Todo = any; // TODO: type PartialProject = Omit; export interface IPluginApiClient { getHost: () => string; + getRepoPath: (args: PartialProject) => string; + + getOrganizations: () => Promise<{ organizations: string[] }>; + + getRepositories: (args: { + owner: string; + }) => Promise<{ repositories: string[] }>; + + getUsername: () => Promise<{ username: string }>; + getRecentCommits: ( args: { releaseBranchName?: string } & PartialProject, - ) => Promise; - getReleases: (args: { releaseId: number } & PartialProject) => Promise; - getRelease: (args: { releaseId: number } & PartialProject) => Promise; + ) => Promise<{ + recentCommits: { + sha: string; + author: { + htmlUrl?: string; + login?: string; + }; + commit: { + message: string; + }; + }[]; + }>; + + getLatestRelease: ( + args: PartialProject, + ) => Promise<{ + latestRelease: { + targetCommitish: string; + tagName: string; + prerelease: boolean; + id: number; + htmlUrl: string; + body?: string | null; + } | null; + }>; + getRepository: ( args: PartialProject, ) => Promise<{ repository: { pushPermissions: boolean | undefined; defaultBranch: string; + name: string; }; }>; + getLatestCommit: ( args: { defaultBranch: string } & PartialProject, ) => Promise; + getBranch: (args: { branchName: string } & PartialProject) => Promise; createRc: { @@ -70,21 +108,27 @@ export interface IPluginApiClient { mostRecentSha: string; targetBranch: string; } & PartialProject, - ) => Promise; + ) => Promise<{ ref: string }>; getComparison: ( args: { previousReleaseBranch: string; nextReleaseBranch: string; } & PartialProject, - ) => Promise; + ) => Promise<{ htmlUrl: string; aheadBy: number }>; createRelease: ( args: { nextGitHubInfo: ReturnType; releaseBody: string; } & PartialProject, - ) => Promise; + ) => Promise<{ + createReleaseResponse: { + name: string | null; + htmlUrl: string; + tagName: string; + }; + }>; }; patch: { @@ -142,7 +186,9 @@ export interface IPluginApiClient { updateRelease: ( args: { bumpedTag: string; - latestRelease: GhGetReleaseResponse; + latestRelease: NonNullable< + ApiMethodRetval['latestRelease'] + >; tagParts: SemverTagParts | CalverTagParts; selectedPatchCommit: GhGetCommitResponse; } & PartialProject, @@ -157,10 +203,6 @@ export interface IPluginApiClient { } & PartialProject, ) => Promise; }; - - getOrganizations: (args: { ownerIsUser: boolean }) => Promise; - getUsername: () => Promise<{ username: string }>; - getRepositories: (args: { owner: string; username: string }) => Promise; } export class PluginApiClient implements IPluginApiClient { @@ -221,36 +263,46 @@ export class PluginApiClient implements IPluginApiClient { async getOrganizations() { const { octokit } = await this.getOctokit(); - const { data: orgs } = await octokit.orgs.listForAuthenticatedUser(); + const orgListResponse = await octokit.paginate( + octokit.orgs.listForAuthenticatedUser, + { per_page: 100 }, + ); - return { orgs }; + return { + organizations: orgListResponse.map(organization => organization.login), + }; } - async getRepositories({ - owner, - username, - }: { - owner: string; - username: string; - }) { + async getRepositories({ owner }: { owner: string }) { const { octokit } = await this.getOctokit(); - if (owner === username) { - const { data: repos } = await octokit.repos.listForUser({ username }); + const repositoryResponse = await octokit + .paginate(octokit.repos.listForOrg, { org: owner, per_page: 100 }) + .catch(async error => { + // `owner` is not an org, try listing a user's repositories instead + if (error.status === 404) { + const userRepositoryResponse = await octokit.paginate( + octokit.repos.listForUser, + { username: owner, per_page: 100 }, + ); + return userRepositoryResponse; + } - return { repos }; - } + throw error; + }); - const { data: repos } = await octokit.repos.listForOrg({ org: owner }); - - return { repos }; + return { + repositories: repositoryResponse.map(repository => repository.name), + }; } async getUsername() { const { octokit } = await this.getOctokit(); - const { data: user } = await octokit.users.getAuthenticated(); + const userResponse = await octokit.users.getAuthenticated(); - return { username: user.login }; + return { + username: userResponse.data.login, + }; } async getRecentCommits({ @@ -261,43 +313,52 @@ export class PluginApiClient implements IPluginApiClient { releaseBranchName?: string; } & PartialProject) { const { octokit } = await this.getOctokit(); - const sha = releaseBranchName ? `?sha=${releaseBranchName}` : ''; + const recentCommitsResponse = await octokit.repos.listCommits({ + owner, + repo, + ...(releaseBranchName ? { sha: releaseBranchName } : {}), + }); - const recentCommits: GhGetCommitResponse[] = ( - await octokit.request( - `/repos/${this.getRepoPath({ owner, repo })}/commits${sha}`, - ) - ).data; - - return { recentCommits }; + return { + recentCommits: recentCommitsResponse.data.map(commit => ({ + sha: commit.sha, + author: { + htmlUrl: commit.author?.html_url, + login: commit.author?.login, + }, + commit: { + message: commit.commit.message, + }, + })), + }; } - async getReleases({ owner, repo }: PartialProject) { + async getLatestRelease({ owner, repo }: PartialProject) { const { octokit } = await this.getOctokit(); + const { data: latestReleases } = await octokit.repos.listReleases({ + owner, + repo, + per_page: 1, + }); - const releases: GhGetReleaseResponse[] = ( - await octokit.request( - `/repos/${this.getRepoPath({ owner, repo })}/releases`, - ) - ).data; + if (latestReleases.length === 0) { + return { + latestRelease: null, + }; + } - return { releases }; - } + const latestRelease = latestReleases[0]; - async getRelease({ - owner, - repo, - releaseId, - }: { releaseId: number } & PartialProject) { - const { octokit } = await this.getOctokit(); - - const latestRelease: GhGetReleaseResponse = ( - await octokit.request( - `/repos/${this.getRepoPath({ owner, repo })}/releases/${releaseId}`, - ) - ).data; - - return { latestRelease }; + return { + latestRelease: { + targetCommitish: latestRelease.target_commitish, + tagName: latestRelease.tag_name, + prerelease: latestRelease.prerelease, + id: latestRelease.id, + htmlUrl: latestRelease.html_url, + body: latestRelease.body, + }, + }; } async getRepository({ owner, repo }: PartialProject) { @@ -363,21 +424,16 @@ export class PluginApiClient implements IPluginApiClient { targetBranch: string; } & PartialProject) => { const { octokit } = await this.getOctokit(); + const createRefResponse = await octokit.git.createRef({ + owner, + repo, + ref: `refs/heads/${targetBranch}`, + sha: mostRecentSha, + }); - const createdRef: GhCreateReferenceResponse = ( - await octokit.request( - `/repos/${this.getRepoPath({ owner, repo })}/git/refs`, - { - method: 'POST', - data: { - ref: `refs/heads/${targetBranch}`, - sha: mostRecentSha, - }, - }, - ) - ).data; - - return { createdRef }; + return { + ref: createRefResponse.data.ref, + }; }, getComparison: async ({ @@ -390,17 +446,17 @@ export class PluginApiClient implements IPluginApiClient { nextReleaseBranch: string; } & PartialProject) => { const { octokit } = await this.getOctokit(); + const compareCommitsResponse = await octokit.repos.compareCommits({ + owner, + repo, + base: previousReleaseBranch, + head: nextReleaseBranch, + }); - const comparison: GhCompareCommitsResponse = ( - await octokit.request( - `/repos/${this.getRepoPath({ - owner, - repo, - })}/compare/${previousReleaseBranch}...${nextReleaseBranch}`, - ) - ).data; - - return { comparison }; + return { + htmlUrl: compareCommitsResponse.data.html_url, + aheadBy: compareCommitsResponse.data.ahead_by, + }; }, createRelease: async ({ @@ -413,24 +469,23 @@ export class PluginApiClient implements IPluginApiClient { releaseBody: string; } & PartialProject) => { const { octokit } = await this.getOctokit(); + const createReleaseResponse = await octokit.repos.createRelease({ + owner, + repo, + tag_name: nextGitHubInfo.rcReleaseTag, + name: nextGitHubInfo.releaseName, + target_commitish: nextGitHubInfo.rcBranch, + body: releaseBody, + prerelease: true, + }); - const createReleaseResponse: GhCreateReleaseResponse = ( - await octokit.request( - `/repos/${this.getRepoPath({ owner, repo })}/releases`, - { - method: 'POST', - data: { - tag_name: nextGitHubInfo.rcReleaseTag, - name: nextGitHubInfo.releaseName, - target_commitish: nextGitHubInfo.rcBranch, - body: releaseBody, - prerelease: true, - }, - }, - ) - ).data; - - return { createReleaseResponse }; + return { + createReleaseResponse: { + name: createReleaseResponse.data.name, + htmlUrl: createReleaseResponse.data.html_url, + tagName: createReleaseResponse.data.tag_name, + }, + }; }, }; @@ -640,7 +695,9 @@ export class PluginApiClient implements IPluginApiClient { selectedPatchCommit, }: { bumpedTag: string; - latestRelease: GhGetReleaseResponse; + latestRelease: NonNullable< + ApiMethodRetval['latestRelease'] + >; tagParts: SemverTagParts | CalverTagParts; selectedPatchCommit: GhGetCommitResponse; } & PartialProject) => { diff --git a/plugins/github-release-manager/src/cards/createRc/CreateRc.tsx b/plugins/github-release-manager/src/cards/createRc/CreateRc.tsx index 2f2fb6963b..b36478f082 100644 --- a/plugins/github-release-manager/src/cards/createRc/CreateRc.tsx +++ b/plugins/github-release-manager/src/cards/createRc/CreateRc.tsx @@ -33,7 +33,6 @@ import { InfoCardPlus } from '../../components/InfoCardPlus'; import { ComponentConfigCreateRc, GhGetBranchResponse, - GhGetReleaseResponse, GhGetRepositoryResponse, SetRefetch, } from '../../types/types'; @@ -43,10 +42,13 @@ import { TEST_IDS } from '../../test-helpers/test-ids'; import { usePluginApiClientContext } from '../../contexts/PluginApiClientContext'; import { useProjectContext } from '../../contexts/ProjectContext'; import { useStyles } from '../../styles/styles'; +import { ApiMethodRetval, IPluginApiClient } from '../../api/PluginApiClient'; interface CreateRcProps { defaultBranch: GhGetRepositoryResponse['default_branch']; - latestRelease: GhGetReleaseResponse | null; + latestRelease: ApiMethodRetval< + IPluginApiClient['getLatestRelease'] + >['latestRelease']; releaseBranch: GhGetBranchResponse | null; setRefetch: SetRefetch; successCb?: ComponentConfigCreateRc['successCb']; @@ -97,7 +99,7 @@ export const CreateRc = ({ const tagAlreadyExists = latestRelease !== null && - latestRelease.tag_name === nextGitHubInfo.rcReleaseTag; + latestRelease.tagName === nextGitHubInfo.rcReleaseTag; const conflictingPreRelease = latestRelease !== null && latestRelease.prerelease; @@ -132,7 +134,7 @@ export const CreateRc = ({ diff --git a/plugins/github-release-manager/src/cards/createRc/getRcGitHubInfo.test.ts b/plugins/github-release-manager/src/cards/createRc/getRcGitHubInfo.test.ts index 08eeacdcc9..31f9b6a4f4 100644 --- a/plugins/github-release-manager/src/cards/createRc/getRcGitHubInfo.test.ts +++ b/plugins/github-release-manager/src/cards/createRc/getRcGitHubInfo.test.ts @@ -16,7 +16,7 @@ import { DateTime } from 'luxon'; -import { GhGetReleaseResponse } from '../../types/types'; +import { ApiMethodRetval, IPluginApiClient } from '../../api/PluginApiClient'; import { mockSemverProject, mockCalverProject, @@ -34,8 +34,8 @@ describe('getRcGitHubInfo', () => { describe('calver', () => { const latestRelease = { - tag_name: 'rc-2020.01.01_0', - } as GhGetReleaseResponse; + tagName: 'rc-2020.01.01_0', + } as ApiMethodRetval['latestRelease']; it('should return correct GitHub info', () => { expect( @@ -57,8 +57,8 @@ describe('getRcGitHubInfo', () => { describe('semver', () => { const latestRelease = { - tag_name: 'rc-1.1.1', - } as GhGetReleaseResponse; + tagName: 'rc-1.1.1', + } as ApiMethodRetval['latestRelease']; it("should return correct GitHub info when there's previous releases", () => { expect( diff --git a/plugins/github-release-manager/src/cards/createRc/getRcGitHubInfo.ts b/plugins/github-release-manager/src/cards/createRc/getRcGitHubInfo.ts index cd2140296f..de70da6f9c 100644 --- a/plugins/github-release-manager/src/cards/createRc/getRcGitHubInfo.ts +++ b/plugins/github-release-manager/src/cards/createRc/getRcGitHubInfo.ts @@ -18,9 +18,9 @@ import { DateTime } from 'luxon'; import { getBumpedSemverTagParts } from '../../helpers/getBumpedTag'; import { getSemverTagParts } from '../../helpers/tagParts/getSemverTagParts'; -import { GhGetReleaseResponse } from '../../types/types'; import { SEMVER_PARTS } from '../../constants/constants'; import { Project } from '../../contexts/ProjectContext'; +import { ApiMethodRetval, IPluginApiClient } from '../../api/PluginApiClient'; export const getRcGitHubInfo = ({ project, @@ -29,7 +29,9 @@ export const getRcGitHubInfo = ({ injectedDate = DateTime.now().toFormat('yyyy.MM.dd'), }: { project: Project; - latestRelease: GhGetReleaseResponse | null; + latestRelease: ApiMethodRetval< + IPluginApiClient['getLatestRelease'] + >['latestRelease']; semverBumpLevel: keyof typeof SEMVER_PARTS; injectedDate?: string; }) => { @@ -49,7 +51,7 @@ export const getRcGitHubInfo = ({ }; } - const tagParts = getSemverTagParts(latestRelease.tag_name); + const tagParts = getSemverTagParts(latestRelease.tagName); const { bumpedTagParts } = getBumpedSemverTagParts(tagParts, semverBumpLevel); const bumpedTag = `${bumpedTagParts.major}.${bumpedTagParts.minor}.${bumpedTagParts.patch}`; diff --git a/plugins/github-release-manager/src/cards/createRc/sideEffects/createRc.test.ts b/plugins/github-release-manager/src/cards/createRc/sideEffects/createRc.test.ts index 9f75a6c927..e9ad6aca5a 100644 --- a/plugins/github-release-manager/src/cards/createRc/sideEffects/createRc.test.ts +++ b/plugins/github-release-manager/src/cards/createRc/sideEffects/createRc.test.ts @@ -28,10 +28,10 @@ describe('createRc', () => { it('should work', async () => { const result = await createRc({ - pluginApiClient: mockApiClient, defaultBranch: mockDefaultBranch, latestRelease: mockReleaseVersion, nextGitHubInfo: mockNextGitHubInfo, + pluginApiClient: mockApiClient, project: mockCalverProject, }); diff --git a/plugins/github-release-manager/src/cards/createRc/sideEffects/createRc.ts b/plugins/github-release-manager/src/cards/createRc/sideEffects/createRc.ts index 0f659fc994..c136f33cc2 100644 --- a/plugins/github-release-manager/src/cards/createRc/sideEffects/createRc.ts +++ b/plugins/github-release-manager/src/cards/createRc/sideEffects/createRc.ts @@ -17,20 +17,23 @@ import { getRcGitHubInfo } from '../getRcGitHubInfo'; import { ComponentConfigCreateRc, - GhCreateReferenceResponse, - GhGetReleaseResponse, GhGetRepositoryResponse, ResponseStep, } from '../../../types/types'; -import { PluginApiClient } from '../../../api/PluginApiClient'; +import { + ApiMethodRetval, + IPluginApiClient, +} from '../../../api/PluginApiClient'; import { GitHubReleaseManagerError } from '../../../errors/GitHubReleaseManagerError'; import { Project } from '../../../contexts/ProjectContext'; interface CreateRC { defaultBranch: GhGetRepositoryResponse['default_branch']; - latestRelease: GhGetReleaseResponse | null; + latestRelease: ApiMethodRetval< + IPluginApiClient['getLatestRelease'] + >['latestRelease']; nextGitHubInfo: ReturnType; - pluginApiClient: PluginApiClient; + pluginApiClient: IPluginApiClient; project: Project; successCb?: ComponentConfigCreateRc['successCb']; } @@ -62,23 +65,20 @@ export async function createRc({ * 2. Create a new ref based on the default branch's most recent sha */ const mostRecentSha = latestCommit.sha; - let createdRef: GhCreateReferenceResponse; - try { - createdRef = ( - await pluginApiClient.createRc.createRef({ - ...project, - mostRecentSha, - targetBranch: nextGitHubInfo.rcBranch, - }) - ).createdRef; - } catch (error) { - if (error.body.message === 'Reference already exists') { - throw new GitHubReleaseManagerError( - `Branch "${nextGitHubInfo.rcBranch}" already exists: .../tree/${nextGitHubInfo.rcBranch}`, - ); - } - throw error; - } + const createdRef = await pluginApiClient.createRc + .createRef({ + ...project, + mostRecentSha, + targetBranch: nextGitHubInfo.rcBranch, + }) + .catch(error => { + if (error?.body?.message === 'Reference already exists') { + throw new GitHubReleaseManagerError( + `Branch "${nextGitHubInfo.rcBranch}" already exists: .../tree/${nextGitHubInfo.rcBranch}`, + ); + } + throw error; + }); responseSteps.push({ message: 'Cut Release Branch', secondaryMessage: `with ref "${createdRef.ref}"`, @@ -88,17 +88,17 @@ export async function createRc({ * 3. Compose a body for the release */ const previousReleaseBranch = latestRelease - ? latestRelease.target_commitish + ? latestRelease.targetCommitish : defaultBranch; const nextReleaseBranch = nextGitHubInfo.rcBranch; - const { comparison } = await pluginApiClient.createRc.getComparison({ + const comparison = await pluginApiClient.createRc.getComparison({ ...project, previousReleaseBranch, nextReleaseBranch, }); - const releaseBody = `**Compare** ${comparison.html_url} + const releaseBody = `**Compare** ${comparison.htmlUrl} -**Ahead by** ${comparison.ahead_by} commits +**Ahead by** ${comparison.aheadBy} commits **Release branch** ${createdRef.ref} @@ -108,7 +108,7 @@ export async function createRc({ responseSteps.push({ message: 'Fetched commit comparison', secondaryMessage: `${previousReleaseBranch}...${nextReleaseBranch}`, - link: comparison.html_url, + link: comparison.htmlUrl, }); /** @@ -124,15 +124,15 @@ export async function createRc({ responseSteps.push({ message: `Created Release Candidate "${createReleaseResponse.name}"`, secondaryMessage: `with tag "${nextGitHubInfo.rcReleaseTag}"`, - link: createReleaseResponse.html_url, + link: createReleaseResponse.htmlUrl, }); await successCb?.({ - gitHubReleaseUrl: createReleaseResponse.html_url, + gitHubReleaseUrl: createReleaseResponse.htmlUrl, gitHubReleaseName: createReleaseResponse.name, - comparisonUrl: comparison.html_url, - previousTag: latestRelease?.tag_name, - createdTag: createReleaseResponse.tag_name, + comparisonUrl: comparison.htmlUrl, + previousTag: latestRelease?.tagName, + createdTag: createReleaseResponse.tagName, }); return responseSteps; diff --git a/plugins/github-release-manager/src/cards/info/Info.tsx b/plugins/github-release-manager/src/cards/info/Info.tsx index 1f42c5b603..782ed30460 100644 --- a/plugins/github-release-manager/src/cards/info/Info.tsx +++ b/plugins/github-release-manager/src/cards/info/Info.tsx @@ -18,20 +18,24 @@ import React from 'react'; import { Link, Typography } from '@material-ui/core'; import { Differ } from '../../components/Differ'; -import { GhGetBranchResponse, GhGetReleaseResponse } from '../../types/types'; +import { GhGetBranchResponse } from '../../types/types'; import { InfoCardPlus } from '../../components/InfoCardPlus'; import { TEST_IDS } from '../../test-helpers/test-ids'; import { useProjectContext } from '../../contexts/ProjectContext'; import { useStyles } from '../../styles/styles'; import flowImage from './flow.png'; +import { ApiMethodRetval, IPluginApiClient } from '../../api/PluginApiClient'; interface InfoCardProps { releaseBranch: GhGetBranchResponse | null; - latestRelease: GhGetReleaseResponse | null; + latestRelease: ApiMethodRetval< + IPluginApiClient['getLatestRelease'] + >['latestRelease']; } export const Info = ({ releaseBranch, latestRelease }: InfoCardProps) => { const project = useProjectContext(); + const classes = useStyles(); return ( @@ -98,7 +102,7 @@ export const Info = ({ releaseBranch, latestRelease }: InfoCardProps) => { - Latest release: + Latest release:
diff --git a/plugins/github-release-manager/src/cards/patchRc/Patch.tsx b/plugins/github-release-manager/src/cards/patchRc/Patch.tsx index e0c1be7a24..e19287024c 100644 --- a/plugins/github-release-manager/src/cards/patchRc/Patch.tsx +++ b/plugins/github-release-manager/src/cards/patchRc/Patch.tsx @@ -23,15 +23,17 @@ import { NoLatestRelease } from '../../components/NoLatestRelease'; import { ComponentConfigPatch, GhGetBranchResponse, - GhGetReleaseResponse, SetRefetch, } from '../../types/types'; import { PatchBody } from './PatchBody'; import { useProjectContext } from '../../contexts/ProjectContext'; import { useStyles } from '../../styles/styles'; +import { ApiMethodRetval, IPluginApiClient } from '../../api/PluginApiClient'; interface PatchProps { - latestRelease: GhGetReleaseResponse | null; + latestRelease: ApiMethodRetval< + IPluginApiClient['getLatestRelease'] + >['latestRelease']; releaseBranch: GhGetBranchResponse | null; setRefetch: SetRefetch; successCb?: ComponentConfigPatch['successCb']; @@ -53,7 +55,7 @@ export const Patch = ({ const { bumpedTag, tagParts } = getBumpedTag({ project, - tag: latestRelease.tag_name, + tag: latestRelease.tagName, bumpLevel: 'patch', }); 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 5c208e9955..54daf2894f 100644 --- a/plugins/github-release-manager/src/cards/patchRc/PatchBody.test.tsx +++ b/plugins/github-release-manager/src/cards/patchRc/PatchBody.test.tsx @@ -41,7 +41,7 @@ describe('PatchBody', () => { beforeEach(jest.clearAllMocks); it('should render error', async () => { - mockApiClient.getBranch.mockImplementationOnce(() => { + (mockApiClient.getBranch as jest.Mock).mockImplementationOnce(() => { throw new Error('banana'); }); diff --git a/plugins/github-release-manager/src/cards/patchRc/PatchBody.tsx b/plugins/github-release-manager/src/cards/patchRc/PatchBody.tsx index 40582dbc0f..44907d30f1 100644 --- a/plugins/github-release-manager/src/cards/patchRc/PatchBody.tsx +++ b/plugins/github-release-manager/src/cards/patchRc/PatchBody.tsx @@ -38,7 +38,6 @@ import { ComponentConfigPatch, GhGetBranchResponse, GhGetCommitResponse, - GhGetReleaseResponse, SetRefetch, } from '../../types/types'; import { CalverTagParts } from '../../helpers/tagParts/getCalverTagParts'; @@ -50,10 +49,13 @@ import { TEST_IDS } from '../../test-helpers/test-ids'; import { usePluginApiClientContext } from '../../contexts/PluginApiClientContext'; import { useProjectContext } from '../../contexts/ProjectContext'; import { useStyles } from '../../styles/styles'; +import { ApiMethodRetval, IPluginApiClient } from '../../api/PluginApiClient'; interface PatchBodyProps { bumpedTag: string; - latestRelease: GhGetReleaseResponse; + latestRelease: NonNullable< + ApiMethodRetval['latestRelease'] + >; releaseBranch: GhGetBranchResponse | null; setRefetch: SetRefetch; successCb?: ComponentConfigPatch['successCb']; @@ -75,17 +77,17 @@ export const PatchBody = ({ const githubDataResponse = useAsync(async () => { const [ { branch: releaseBranchResponse }, - { recentCommits }, + { recentCommits: recentCommitsOnDefaultBranch }, ] = await Promise.all([ pluginApiClient.getBranch({ ...project, - branchName: latestRelease.target_commitish, + branchName: latestRelease.targetCommitish, }), pluginApiClient.getRecentCommits({ ...project }), ]); const { - recentCommits: recentReleaseBranchCommits, + recentCommits: recentCommitsOnReleaseBranch, } = await pluginApiClient.getRecentCommits({ ...project, releaseBranchName: releaseBranchResponse.name, @@ -93,8 +95,8 @@ export const PatchBody = ({ return { releaseBranch: releaseBranchResponse, - recentReleaseBranchCommits, - recentCommits, + recentCommitsOnReleaseBranch, + recentCommitsOnDefaultBranch, }; }); @@ -146,118 +148,118 @@ export const PatchBody = ({ )} - + ); } function CommitList() { - if (!githubDataResponse.value?.recentCommits) { + if (!githubDataResponse.value?.recentCommitsOnDefaultBranch) { return null; } return ( - {githubDataResponse.value.recentCommits.map((commit, index) => { - const commitExistsOnReleaseBranch = !!githubDataResponse.value?.recentReleaseBranchCommits.find( - ({ sha }) => { - return sha === commit.sha; - }, - ); + {githubDataResponse.value.recentCommitsOnDefaultBranch.map( + (commit, index) => { + const commitExistsOnReleaseBranch = !!githubDataResponse.value?.recentCommitsOnReleaseBranch.find( + releaseBranchCommit => releaseBranchCommit.sha === commit.sha, + ); - return ( -
- {commitExistsOnReleaseBranch && ( - - {' '} - Already exists on {releaseBranch?.name} - - )} - - 0) || - commitExistsOnReleaseBranch - } - role={undefined} - dense - button - onClick={() => { - if (index === checkedCommitIndex) { - setCheckedCommitIndex(-1); - } else { - setCheckedCommitIndex(index); - } - }} - > - - - - - - {commit.sha}{' '} - - @{commit.author.login} - - - } - /> - - - { - const repoPath = pluginApiClient.getRepoPath({ - ...project, - }); - const host = pluginApiClient.getHost(); - - const newTab = window.open( - `https://${host}/${repoPath}/compare/${releaseBranch?.name}...${commit.sha}`, - '_blank', - ); - newTab?.focus(); + return ( +
+ {commitExistsOnReleaseBranch && ( + - - - - -
- ); - })} + {' '} + Already exists on {releaseBranch?.name} + + )} + + 0) || + commitExistsOnReleaseBranch + } + role={undefined} + dense + button + onClick={() => { + if (index === checkedCommitIndex) { + setCheckedCommitIndex(-1); + } else { + setCheckedCommitIndex(index); + } + }} + > + + + + + + {commit.sha}{' '} + + @{commit.author.login} + + + } + /> + + + { + const repoPath = pluginApiClient.getRepoPath({ + ...project, + }); + const host = pluginApiClient.getHost(); + + const newTab = window.open( + `https://${host}/${repoPath}/compare/${releaseBranch?.name}...${commit.sha}`, + '_blank', + ); + newTab?.focus(); + }} + > + + + + +
+ ); + }, + )}
); } @@ -275,7 +277,11 @@ export const PatchBody = ({ ); } - if (!githubDataResponse.value?.recentCommits[checkedCommitIndex]) { + if ( + !githubDataResponse.value?.recentCommitsOnDefaultBranch[ + checkedCommitIndex + ] + ) { return (