Create annotated tags for promotions as well. Remove duplicate api.getCommit method

Signed-off-by: Erik Engervall <erik.engervall@gmail.com>
This commit is contained in:
Erik Engervall
2021-04-29 15:43:41 +02:00
parent c7ba03393c
commit 46d8949703
8 changed files with 129 additions and 52 deletions
@@ -39,8 +39,8 @@ describe('GitReleaseApiClient', () => {
"createRef": [Function],
"createTagObject": [Function],
"getBranch": [Function],
"getCommit": [Function],
"getHost": [Function],
"getLatestCommit": [Function],
"getLatestRelease": [Function],
"getOwners": [Function],
"getRecentCommits": [Function],
@@ -66,7 +66,6 @@ describe('GitReleaseApiClient', () => {
"stats": Object {
"getAllReleases": [Function],
"getAllTags": [Function],
"getCommit": [Function],
"getSingleTag": [Function],
},
}
@@ -195,16 +195,12 @@ export class GitReleaseApiClient implements GitReleaseApi {
};
};
getLatestCommit: GitReleaseApi['getLatestCommit'] = async ({
owner,
repo,
defaultBranch,
}) => {
getCommit: GitReleaseApi['getCommit'] = async ({ owner, repo, ref }) => {
const { octokit } = await this.getOctokit();
const { data: latestCommit } = await octokit.repos.getCommit({
owner,
repo,
ref: defaultBranch,
ref,
...DISABLE_CACHE,
});
@@ -214,6 +210,7 @@ export class GitReleaseApiClient implements GitReleaseApi {
commit: {
message: latestCommit.commit.message,
},
createdAt: latestCommit.commit.committer?.date,
};
};
@@ -527,20 +524,6 @@ ${selectedPatchCommit.commit.message}`,
}));
},
getCommit: async ({ owner, repo, ref }) => {
const { octokit } = await this.getOctokit();
const { data: commit } = await octokit.repos.getCommit({
owner,
repo,
ref,
});
return {
createdAt: commit.commit.committer?.date,
};
},
getSingleTag: async ({ owner, repo, tagSha }) => {
const { octokit } = await this.getOctokit();
const singleTag = await octokit.git.getTag({
@@ -621,9 +604,9 @@ export interface GitReleaseApi {
name: string;
}>;
getLatestCommit: (
getCommit: (
args: {
defaultBranch: string;
ref: string;
} & OwnerRepo,
) => Promise<{
sha: string;
@@ -631,6 +614,7 @@ export interface GitReleaseApi {
commit: {
message: string;
};
createdAt?: string;
}>;
getBranch: (
@@ -812,14 +796,6 @@ export interface GitReleaseApi {
}>
>;
getCommit: (
args: {
ref: string;
} & OwnerRepo,
) => Promise<{
createdAt: string | undefined;
}>;
getSingleTag: (
args: {
tagSha: string;
@@ -848,7 +824,7 @@ export type GetRepositoryResult = UnboxReturnedPromise<
GitReleaseApi['getRepository']
>;
export type GetLatestCommitResult = UnboxReturnedPromise<
GitReleaseApi['getLatestCommit']
GitReleaseApi['getCommit']
>;
export type GetBranchResult = UnboxReturnedPromise<GitReleaseApi['getBranch']>;
export type CreateRefResult = UnboxReturnedPromise<GitReleaseApi['createRef']>;
@@ -883,9 +859,6 @@ export type PromoteReleaseResult = UnboxReturnedPromise<
export type GetAllTagsResult = UnboxReturnedPromise<
GitReleaseApi['stats']['getAllTags']
>;
export type GetCommitResult = UnboxReturnedPromise<
GitReleaseApi['stats']['getCommit']
>;
export type GetAllReleasesResult = UnboxReturnedPromise<
GitReleaseApi['stats']['getAllReleases']
>;
@@ -71,10 +71,10 @@ export function useCreateReleaseCandidate({
*/
const [latestCommitRes, run] = useAsyncFn(async () => {
const latestCommit = await pluginApiClient
.getLatestCommit({
.getCommit({
owner: project.owner,
repo: project.repo,
defaultBranch,
ref: defaultBranch,
})
.catch(asyncCatcher);
@@ -21,6 +21,7 @@ import {
mockApiClient,
mockCalverProject,
mockReleaseCandidateCalver,
mockUser,
} from '../../../test-helpers/test-helpers';
import { usePromoteRc } from './usePromoteRc';
@@ -33,6 +34,9 @@ jest.mock('../../../contexts/ProjectContext', () => ({
project: mockCalverProject,
}),
}));
jest.mock('../../../contexts/UserContext', () => ({
useUserContext: () => ({ user: mockUser }),
}));
describe('usePromoteRc', () => {
beforeEach(jest.clearAllMocks);
@@ -50,7 +54,7 @@ describe('usePromoteRc', () => {
});
expect(result.error).toEqual(undefined);
expect(result.current.responseSteps).toHaveLength(1);
expect(result.current.responseSteps).toHaveLength(4);
});
it('should return the expected responseSteps and progress (with successCb)', async () => {
@@ -66,11 +70,23 @@ describe('usePromoteRc', () => {
await waitFor(() => result.current.run());
});
expect(result.current.responseSteps).toHaveLength(2);
expect(result.current.responseSteps).toHaveLength(5);
expect(result.current).toMatchInlineSnapshot(`
Object {
"progress": 100,
"responseSteps": Array [
Object {
"message": "Fetched most recent commit from release branch",
"secondaryMessage": "with sha \\"latestCommit.sha\\"",
},
Object {
"message": "Created Tag Object",
"secondaryMessage": "with sha \\"mock_tag_object_sha\\"",
},
Object {
"message": "Create Tag Reference",
"secondaryMessage": "with ref \\"mock_createRef_ref\\"",
},
Object {
"link": "mock_release_html_url",
"message": "Promoted \\"mock_release_name\\"",
@@ -23,6 +23,9 @@ import { GetLatestReleaseResult } from '../../../api/GitReleaseApiClient';
import { gitReleaseManagerApiRef } from '../../../api/serviceApiRef';
import { useProjectContext } from '../../../contexts/ProjectContext';
import { useResponseSteps } from '../../../hooks/useResponseSteps';
import { useUserContext } from '../../../contexts/UserContext';
import { TAG_OBJECT_MESSAGE } from '../../../constants/constants';
import { GitReleaseManagerError } from '../../../errors/GitReleaseManagerError';
interface PromoteRc {
rcRelease: NonNullable<GetLatestReleaseResult>;
@@ -36,6 +39,7 @@ export function usePromoteRc({
successCb,
}: PromoteRc): CardHook<void> {
const pluginApiClient = useApi(gitReleaseManagerApiRef);
const { user } = useUserContext();
const { project } = useProjectContext();
const {
responseSteps,
@@ -45,9 +49,97 @@ export function usePromoteRc({
} = useResponseSteps();
/**
* (1) Promote Release Candidate to Release Version
* (1) Fetch most recent release branch commit
*/
const [promotedReleaseRes, run] = useAsyncFn(async () => {
const [latestReleaseBranchCommitSha, run] = useAsyncFn(async () => {
const latestCommit = await pluginApiClient
.getCommit({
owner: project.owner,
repo: project.repo,
ref: rcRelease.targetCommitish,
})
.catch(asyncCatcher);
addStepToResponseSteps({
message: 'Fetched most recent commit from release branch',
secondaryMessage: `with sha "${latestCommit.sha}"`,
});
return {
...latestCommit,
};
});
/**
* (2) Create tag object for our soon-to-be-created annotated tag
*/
const tagObjectRes = useAsync(async () => {
abortIfError(latestReleaseBranchCommitSha.error);
if (!latestReleaseBranchCommitSha.value) return undefined;
const createdTagObject = await pluginApiClient
.createTagObject({
owner: project.owner,
repo: project.repo,
tag: releaseVersion,
objectSha: latestReleaseBranchCommitSha.value.sha,
taggerName: user.username,
taggerEmail: user.email,
message: TAG_OBJECT_MESSAGE,
})
.catch(asyncCatcher);
addStepToResponseSteps({
message: 'Created Tag Object',
secondaryMessage: `with sha "${createdTagObject.tagSha}"`,
});
return {
...createdTagObject,
};
}, [latestReleaseBranchCommitSha.value, latestReleaseBranchCommitSha.error]);
/**
* (3) Create reference for tag object
*/
const createRcRes = useAsync(async () => {
abortIfError(tagObjectRes.error);
if (!tagObjectRes.value) return undefined;
const createdRef = await pluginApiClient
.createRef({
owner: project.owner,
repo: project.repo,
ref: `refs/tags/${releaseVersion}`,
sha: tagObjectRes.value.tagSha,
})
.catch(error => {
if (error?.body?.message === 'Reference already exists') {
throw new GitReleaseManagerError(
`Tag reference "${releaseVersion}" already exists`,
);
}
throw error;
})
.catch(asyncCatcher);
addStepToResponseSteps({
message: 'Create Tag Reference',
secondaryMessage: `with ref "${createdRef.ref}"`,
});
return {
...createdRef,
};
}, [tagObjectRes.value, tagObjectRes.error]);
/**
* (4) Promote Release Candidate to Release Version
*/
const promotedReleaseRes = useAsync(async () => {
abortIfError(createRcRes.error);
if (!createRcRes.value) return undefined;
const promotedRelease = await pluginApiClient.promoteRc
.promoteRelease({
owner: project.owner,
@@ -66,10 +158,10 @@ export function usePromoteRc({
return {
...promotedRelease,
};
});
}, [createRcRes.value, createRcRes.error]);
/**
* (2) Run successCb if defined
* (5) Run successCb if defined
*/
useAsync(async () => {
if (successCb && !!promotedReleaseRes.value) {
@@ -95,7 +187,7 @@ export function usePromoteRc({
}
}, [promotedReleaseRes.value]);
const TOTAL_STEPS = 1 + (!!successCb ? 1 : 0);
const TOTAL_STEPS = 4 + (!!successCb ? 1 : 0);
const [progress, setProgress] = useState(0);
useEffect(() => {
setProgress((responseSteps.length / TOTAL_STEPS) * 100);
@@ -28,7 +28,7 @@ export const getTagDate = async ({
project,
tagSha,
}: GetTagDate) => {
const commitRes = await pluginApiClient.stats.getCommit({
const commitRes = await pluginApiClient.getCommit({
owner: project.owner,
repo: project.repo,
ref: tagSha,
@@ -30,7 +30,7 @@ export const useGetCommit = ({ ref }: { ref?: string }) => {
throw new GitReleaseManagerError('Missing ref to get commit');
}
return pluginApiClient.stats.getCommit({
return pluginApiClient.getCommit({
owner: project.owner,
repo: project.repo,
ref,
@@ -209,12 +209,13 @@ export const mockApiClient: GitReleaseApi = {
name: mockRepo,
})),
getLatestCommit: jest.fn(async () => ({
getCommit: jest.fn(async () => ({
sha: 'latestCommit.sha',
htmlUrl: 'latestCommit.html_url',
commit: {
message: 'latestCommit.commit.message',
},
createdAt: '2021-01-01T10:11:12Z',
})),
getBranch: jest.fn(async () => createMockBranch()),
@@ -305,10 +306,6 @@ export const mockApiClient: GitReleaseApi = {
},
]),
getCommit: jest.fn(async () => ({
createdAt: '2021-01-01T10:11:12Z',
})),
getSingleTag: jest.fn(async () => ({
date: '2021-04-29T12:48:30.120Z',
username: 'mock_usersingle_tag_name',