Add getSingleTag API method, start simplifying the API client

Signed-off-by: Erik Engervall <erik.engervall@gmail.com>
This commit is contained in:
Erik Engervall
2021-04-29 15:01:28 +02:00
parent 03c485f8e2
commit cfe5a53da4
12 changed files with 167 additions and 91 deletions
@@ -37,6 +37,16 @@ describe('GitReleaseApiClient', () => {
"createRelease": [Function],
"getComparison": [Function],
},
"getBranch": [Function],
"getHost": [Function],
"getLatestCommit": [Function],
"getLatestRelease": [Function],
"getOwners": [Function],
"getRecentCommits": [Function],
"getRepoPath": [Function],
"getRepositories": [Function],
"getRepository": [Function],
"getUser": [Function],
"githubAuthApi": Object {
"getAccessToken": [MockFunction],
},
@@ -58,6 +68,7 @@ describe('GitReleaseApiClient', () => {
"getAllReleases": [Function],
"getAllTags": [Function],
"getCommit": [Function],
"getSingleTag": [Function],
},
}
`);
@@ -262,18 +262,13 @@ export class GitReleaseApiClient implements GitReleaseApi {
};
},
getComparison: async ({
owner,
repo,
previousReleaseBranch,
nextReleaseBranch,
}) => {
getComparison: async ({ owner, repo, base, head }) => {
const { octokit } = await this.getOctokit();
const compareCommitsResponse = await octokit.repos.compareCommits({
owner,
repo,
base: previousReleaseBranch,
head: nextReleaseBranch,
base,
head,
});
return {
@@ -416,15 +411,15 @@ ${selectedPatchCommit.sha}`,
};
},
createTagObject: async ({ owner, repo, bumpedTag, updatedReference }) => {
createTagObject: async ({ owner, repo, tag, objectSha }) => {
const { octokit } = await this.getOctokit();
const { data: createdTagObject } = await octokit.git.createTag({
owner,
repo,
message:
'Tag generated by your friendly neighborhood Backstage Release Manager',
tag: bumpedTag,
object: updatedReference.object.sha,
tag,
object: objectSha,
type: 'commit',
});
@@ -545,6 +540,21 @@ ${selectedPatchCommit.commit.message}`,
createdAt: commit.commit.committer?.date,
};
},
getSingleTag: async ({ owner, repo, tagSha }) => {
const { octokit } = await this.getOctokit();
const singleTag = await octokit.git.getTag({
owner,
repo,
tag_sha: tagSha,
});
return {
date: singleTag.data.tagger.date,
username: singleTag.data.tagger.name,
userEmail: singleTag.data.tagger.email,
};
},
};
}
@@ -654,8 +664,8 @@ export interface GitReleaseApi {
getComparison: (
args: {
previousReleaseBranch: string;
nextReleaseBranch: string;
base: string;
head: string;
} & OwnerRepo,
) => Promise<{
htmlUrl: string;
@@ -695,13 +705,13 @@ export interface GitReleaseApi {
tempCommit: CreateTempCommitResult;
} & OwnerRepo,
) => Promise<void>;
merge: ({
base,
head,
}: {
base: string;
head: string;
} & OwnerRepo) => Promise<{
merge: (
args: {
base: string;
head: string;
} & OwnerRepo,
) => Promise<{
htmlUrl: string;
commit: {
message: string;
@@ -739,13 +749,12 @@ export interface GitReleaseApi {
};
}>;
createTagObject: ({
bumpedTag,
updatedReference,
}: {
bumpedTag: string;
updatedReference: ReplaceTempCommitResult;
} & OwnerRepo) => Promise<{
createTagObject: (
args: {
tag: string;
objectSha: string;
} & OwnerRepo,
) => Promise<{
tag: string;
sha: string;
}>;
@@ -793,6 +802,7 @@ export interface GitReleaseApi {
sha: string;
}>
>;
getAllReleases: (
args: OwnerRepo,
) => Promise<
@@ -812,6 +822,16 @@ export interface GitReleaseApi {
) => Promise<{
createdAt: string | undefined;
}>;
getSingleTag: (
args: {
tagSha: string;
} & OwnerRepo,
) => Promise<{
date: string;
username: string;
userEmail: string;
}>;
};
}
@@ -135,8 +135,8 @@ export function useCreateReleaseCandidate({
.getComparison({
owner: project.owner,
repo: project.repo,
previousReleaseBranch,
nextReleaseBranch,
base: previousReleaseBranch,
head: nextReleaseBranch,
})
.catch(asyncCatcher);
@@ -238,8 +238,8 @@ export function usePatch({
.createTagObject({
owner: project.owner,
repo: project.repo,
bumpedTag,
updatedReference: updatedRefRes.value,
tag: bumpedTag,
objectSha: updatedRefRes.value.object.sha,
})
.catch(asyncCatcher);
@@ -20,6 +20,7 @@ import { DateTime } from 'luxon';
import { useApi } from '@backstage/core';
import { getReleaseCommitPairs } from '../helpers/getReleaseCommitPairs';
import { getTagDate } from '../../helpers/getTagDate';
import { gitReleaseManagerApiRef } from '../../../../api/serviceApiRef';
import { useProjectContext } from '../../../../contexts/ProjectContext';
import { useReleaseStatsContext } from '../../contexts/ReleaseStatsContext';
@@ -80,19 +81,11 @@ export function useGetReleaseTimes() {
const { baseVersion, startCommit, endCommit } = releaseCommitPairs[index];
const [
{ createdAt: startCommitCreatedAt },
{ createdAt: endCommitCreatedAt },
{ tagDate: startCommitCreatedAt },
{ tagDate: endCommitCreatedAt },
] = await Promise.all([
pluginApiClient.stats.getCommit({
owner: project.owner,
repo: project.repo,
ref: startCommit.sha,
}),
pluginApiClient.stats.getCommit({
owner: project.owner,
repo: project.repo,
ref: endCommit.sha,
}),
getTagDate({ pluginApiClient, project, tagSha: startCommit.sha }),
getTagDate({ pluginApiClient, project, tagSha: endCommit.sha }),
]);
const releaseTime: ReleaseTime = {
@@ -38,24 +38,14 @@ describe('getMappedReleases', () => {
"releases": Object {
"1.0": Object {
"baseVersion": "1.0",
"candidates": Array [
Object {
"sha": "",
"tagName": "rc-1.0.0",
},
],
"candidates": Array [],
"createdAt": "2021-01-01T10:11:12Z",
"htmlUrl": "html_url",
"versions": Array [],
},
"1.1": Object {
"baseVersion": "1.1",
"candidates": Array [
Object {
"sha": "",
"tagName": "rc-1.1.0",
},
],
"candidates": Array [],
"createdAt": "2021-01-01T10:11:12Z",
"htmlUrl": "html_url",
"versions": Array [],
@@ -40,24 +40,18 @@ export function getMappedReleases({
return acc;
}
const prefix = match[1] as 'rc' | 'version';
const baseVersion =
project.versioningStrategy === 'semver'
? `${match[2]}.${match[3]}`
: match[2];
if (!acc.releases[baseVersion]) {
const releaseEntry = {
tagName: release.tagName,
sha: '',
};
acc.releases[baseVersion] = {
baseVersion,
createdAt: release.createdAt,
htmlUrl: release.htmlUrl,
candidates: prefix === 'rc' ? [releaseEntry] : [],
versions: prefix === 'version' ? [releaseEntry] : [],
candidates: [],
versions: [],
};
return acc;
@@ -27,24 +27,15 @@ describe('getReleaseStats', () => {
baseVersion: '1.0',
createdAt: '2021-01-01T10:11:12Z',
htmlUrl: 'html_url',
candidates: [
{
tagName: 'rc-1.0.0',
sha: '',
},
],
candidates: [],
versions: [],
},
'1.1': {
baseVersion: '1.1',
createdAt: '2021-01-01T10:11:12Z',
htmlUrl: 'html_url',
candidates: [
{
tagName: 'rc-1.1.0',
sha: '',
},
],
candidates: [],
versions: [],
},
},
@@ -96,10 +87,6 @@ describe('getReleaseStats', () => {
"1.1": Object {
"baseVersion": "1.1",
"candidates": Array [
Object {
"sha": "",
"tagName": "rc-1.1.0",
},
Object {
"sha": "sha",
"tagName": "rc-1.1.1",
@@ -55,18 +55,7 @@ export function getReleaseStats({
}
const dest = release[prefix === 'rc' ? 'candidates' : 'versions'];
const releaseToEnrich = dest.find(
({ tagName }) => tagName === tag.tagName,
);
if (releaseToEnrich) {
releaseToEnrich.sha = tag.sha;
} else {
dest.push({
tagName: tag.tagName,
sha: tag.sha,
});
}
dest.push(tag);
return acc;
},
@@ -0,0 +1,40 @@
/*
* Copyright 2021 Spotify AB
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { GitReleaseApi } from '../../../api/GitReleaseApiClient';
import { Project } from '../../../contexts/ProjectContext';
interface GetTagDate {
pluginApiClient: GitReleaseApi;
project: Project;
tagSha: string;
}
export const getTagDate = async ({
pluginApiClient,
project,
tagSha,
}: GetTagDate) => {
const commitRes = await pluginApiClient.stats.getCommit({
owner: project.owner,
repo: project.repo,
ref: tagSha,
});
return {
tagDate: commitRes.createdAt,
};
};
@@ -0,0 +1,46 @@
/*
* Copyright 2021 Spotify AB
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { useAsync } from 'react-use';
import { useApi } from '@backstage/core';
import { getTagDate } from '../helpers/getTagDate';
import { gitReleaseManagerApiRef } from '../../../api/serviceApiRef';
import { GitReleaseManagerError } from '../../../errors/GitReleaseManagerError';
import { ReleaseStats } from '../contexts/ReleaseStatsContext';
import { UnboxArray } from '../../../types/helpers';
import { useProjectContext } from '../../../contexts/ProjectContext';
export const useGetTagDate = ({
tag,
}: {
tag: UnboxArray<ReleaseStats['releases']['0']['candidates']>;
}) => {
const pluginApiClient = useApi(gitReleaseManagerApiRef);
const { project } = useProjectContext();
const tagDate = useAsync(async () => {
if (!tag) {
throw new GitReleaseManagerError('Missing tag details to get tag date');
}
return await getTagDate({ pluginApiClient, project, tagSha: tag.sha });
});
return {
tagDate,
};
};
@@ -306,5 +306,11 @@ 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',
userEmail: 'mock_userEsingle_tag_mail',
})),
},
};