Skip to content

Commit

Permalink
feat(github): implement requiredStatusChecks
Browse files Browse the repository at this point in the history
  • Loading branch information
sarunint committed Oct 7, 2019
1 parent 3791f61 commit e9e1e0a
Show file tree
Hide file tree
Showing 2 changed files with 233 additions and 43 deletions.
55 changes: 39 additions & 16 deletions lib/platform/github/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -561,23 +561,26 @@ export async function getBranchPr(branchName: string) {
// Returns the combined status for a branch.
export async function getBranchStatus(
branchName: string,
requiredStatusChecks: any
requiredStatusChecks: string[] | null
) {
logger.debug(`getBranchStatus(${branchName})`);
if (!requiredStatusChecks) {
// null means disable status checks, so it always succeeds
logger.debug('Status checks disabled = returning "success"');
return 'success';
}
if (requiredStatusChecks.length) {
// This is Unsupported
logger.warn({ requiredStatusChecks }, `Unsupported requiredStatusChecks`);
return 'failed';
}
const commitStatusUrl = `repos/${config.repository}/commits/${branchName}/status`;
let commitStatus;
const commitStatusUrl = `repos/${config.repository}/commits/${branchName}/statuses`;
let commitStatuses: {
context: string;
state: string;
}[];
try {
commitStatus = (await api.get(commitStatusUrl)).body;
commitStatuses = (await api.get<
{
context: string;
state: string;
}[]
>(commitStatusUrl)).body;
} catch (err) /* istanbul ignore next */ {
if (err.statusCode === 404) {
logger.info(
Expand All @@ -588,10 +591,7 @@ export async function getBranchStatus(
logger.info('Unknown error when checking branch status');
throw err;
}
logger.debug(
{ state: commitStatus.state, statuses: commitStatus.statuses },
'branch status check result'
);
logger.debug({ statuses: commitStatuses }, 'branch status check result');
let checkRuns: { name: string; status: string; conclusion: string }[] = [];
if (!config.isGhe) {
try {
Expand Down Expand Up @@ -629,17 +629,40 @@ export async function getBranchStatus(
}
}
}

const filteredStatuses = commitStatuses.filter(
status =>
requiredStatusChecks.includes(status.context) ||
requiredStatusChecks.length === 0
);
const contexts = filteredStatuses.map(s => s.context);
const states = filteredStatuses.map(s => s.state);
const allStatusesExists = requiredStatusChecks.every(s =>
contexts.includes(s)
);

let filteredStatusesCombined: string;
if (states.includes('failure') || states.includes('error')) {
filteredStatusesCombined = 'failed';
} else if (states.includes('pending') || !allStatusesExists) {
filteredStatusesCombined = 'pending';
} else {
filteredStatusesCombined = 'success';
}

if (checkRuns.length === 0) {
return commitStatus.state;
return filteredStatusesCombined;
}

if (
commitStatus.state === 'failed' ||
filteredStatusesCombined === 'failed' ||
checkRuns.some(run => run.conclusion === 'failed')
) {
return 'failed';
}

if (
(commitStatus.state === 'success' || commitStatus.statuses.length === 0) &&
(filteredStatusesCombined === 'success' || filteredStatuses.length === 0) &&
checkRuns.every(run => ['neutral', 'success'].includes(run.conclusion))
) {
return 'success';
Expand Down
221 changes: 194 additions & 27 deletions test/platform/github/index.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -576,38 +576,66 @@ describe('platform/github', () => {
const res = await github.getBranchStatus('somebranch', null);
expect(res).toEqual('success');
});
it('return failed if unsupported requiredStatusChecks', async () => {
await initRepo({
repository: 'some/repo',
});
const res = await github.getBranchStatus('somebranch', ['foo']);
expect(res).toEqual('failed');
});
it('should pass through success', async () => {
// it('return failed if unsupported requiredStatusChecks', async () => {
// await initRepo({
// repository: 'some/repo',
// });
// const res = await github.getBranchStatus('somebranch', ['foo']);
// expect(res).toEqual('failed');
// });
it('should pass through success (with empty array)', async () => {
await initRepo({
repository: 'some/repo',
});
api.get.mockImplementationOnce(
() =>
({
body: {
state: 'success',
},
body: [
{
state: 'success',
},
{
state: 'success',
},
{
state: 'success',
},
{
state: 'success',
},
{
state: 'success',
},
],
} as any)
);
const res = await github.getBranchStatus('somebranch', []);
expect(res).toEqual('success');
});
it('should pass through failed', async () => {
it('should pass through failed (with empty array)', async () => {
await initRepo({
repository: 'some/repo',
});
api.get.mockImplementationOnce(
() =>
({
body: {
state: 'failed',
},
body: [
{
state: 'failed',
},
{
state: 'success',
},
{
state: 'success',
},
{
state: 'success',
},
{
state: 'success',
},
],
} as any)
);
const res = await github.getBranchStatus('somebranch', []);
Expand All @@ -620,10 +648,7 @@ describe('platform/github', () => {
api.get.mockImplementationOnce(
() =>
({
body: {
state: 'pending',
statuses: [],
},
body: [],
} as any)
);
api.get.mockImplementationOnce(
Expand Down Expand Up @@ -658,10 +683,7 @@ describe('platform/github', () => {
api.get.mockImplementationOnce(
() =>
({
body: {
state: 'pending',
statuses: [],
},
body: [],
} as any)
);
api.get.mockImplementationOnce(
Expand Down Expand Up @@ -696,10 +718,7 @@ describe('platform/github', () => {
api.get.mockImplementationOnce(
() =>
({
body: {
state: 'pending',
statuses: [],
},
body: [],
} as any)
);
api.get.mockImplementationOnce(
Expand All @@ -726,6 +745,154 @@ describe('platform/github', () => {
const res = await github.getBranchStatus('somebranch', []);
expect(res).toEqual('pending');
});
it('should pass through success (with non-empty array)', async () => {
await initRepo({
repository: 'some/repo',
});
api.get.mockImplementationOnce(
() =>
({
body: [
{
state: 'failed',
context: 'context1',
},
{
state: 'success',
context: 'context2',
},
{
state: 'success',
context: 'context3',
},
{
state: 'failed',
context: 'context4',
},
{
state: 'success',
context: 'context5',
},
],
} as any)
);
const res = await github.getBranchStatus('somebranch', [
'context2',
'context3',
'context5',
]);
expect(res).toEqual('success');
});
it('should pass through failed (with non-empty array)', async () => {
await initRepo({
repository: 'some/repo',
});
api.get.mockImplementationOnce(
() =>
({
body: [
{
state: 'failed',
context: 'context1',
},
{
state: 'success',
context: 'context2',
},
{
state: 'success',
context: 'context3',
},
{
state: 'failed',
context: 'context4',
},
{
state: 'success',
context: 'context5',
},
],
} as any)
);
const res = await github.getBranchStatus('somebranch', [
'context1',
'context3',
'context5',
]);
expect(res).toEqual('failed');
});
it('should pass through pending (with non-empty array)', async () => {
await initRepo({
repository: 'some/repo',
});
api.get.mockImplementationOnce(
() =>
({
body: [
{
state: 'pending',
context: 'context1',
},
{
state: 'success',
context: 'context2',
},
{
state: 'success',
context: 'context3',
},
{
state: 'failed',
context: 'context4',
},
{
state: 'success',
context: 'context5',
},
],
} as any)
);
const res = await github.getBranchStatus('somebranch', [
'context1',
'context3',
'context5',
]);
expect(res).toEqual('pending');
});
it('should pass through pending when not all required statuses exists (with non-empty array)', async () => {
await initRepo({
repository: 'some/repo',
});
api.get.mockImplementationOnce(
() =>
({
body: [
{
state: 'success',
context: 'context1',
},
{
state: 'success',
context: 'context2',
},
{
state: 'success',
context: 'context3',
},
{
state: 'failed',
context: 'context4',
},
],
} as any)
);
const res = await github.getBranchStatus('somebranch', [
'context1',
'context3',
'context5',
]);
expect(res).toEqual('pending');
});
});
describe('getBranchStatusCheck', () => {
it('returns state if found', async () => {
Expand Down

0 comments on commit e9e1e0a

Please sign in to comment.