Skip to content

Commit

Permalink
fix: use commit statuses for base image update check (#217)
Browse files Browse the repository at this point in the history
  • Loading branch information
danadajian authored Jun 15, 2023
1 parent 6fc7723 commit deb92d8
Show file tree
Hide file tree
Showing 2 changed files with 126 additions and 156 deletions.
28 changes: 10 additions & 18 deletions app/backend/src/allNonVisualChecksHavePassed.ts
Original file line number Diff line number Diff line change
@@ -1,37 +1,29 @@
import { getOctokit } from './getOctokit';
import { RestEndpointMethodTypes } from '@octokit/rest';
import { groupBy, isEqual, sortBy } from 'lodash';
import { VISUAL_REGRESSION_CONTEXT } from 'shared';

type CheckRunConclusion =
RestEndpointMethodTypes['checks']['listForRef']['response']['data']['check_runs'][number]['conclusion'];

const allowedConclusions: CheckRunConclusion[] = ['success', 'skipped'];

export const allNonVisualChecksHavePassed = async (
owner: string,
repo: string,
sha: string
): Promise<boolean> => {
const octokit = getOctokit(owner, repo);

const { data } = await octokit.rest.checks.listForRef({
const { data } = await octokit.rest.repos.listCommitStatusesForRef({
owner,
repo,
ref: sha,
});
const nonVisualChecks = data.check_runs.filter(
({ name }) => name !== VISUAL_REGRESSION_CONTEXT
const nonVisualStatuses = data.filter(
({ context }) => context !== VISUAL_REGRESSION_CONTEXT
);
const groupedChecks = groupBy(nonVisualChecks, 'name');
const mostRecentChecks = nonVisualChecks.filter(check => {
const checksSortedByDescTime = sortBy(
groupedChecks[check.name],
'completed_at'
const groupedNonVisualStatuses = groupBy(nonVisualStatuses, 'context');
const mostRecentNonVisualStatuses = nonVisualStatuses.filter(status => {
const contextsSortedByDescTime = sortBy(
groupedNonVisualStatuses[status.context],
'created_at'
).reverse();
return isEqual(check, checksSortedByDescTime[0]);
return isEqual(status, contextsSortedByDescTime.find(Boolean));
});
return mostRecentChecks.every(({ conclusion }) =>
allowedConclusions.includes(conclusion)
);
return mostRecentNonVisualStatuses.every(({ state }) => state === 'success');
};
254 changes: 116 additions & 138 deletions app/backend/test/allNonVisualChecksHavePassed.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,27 +8,25 @@ describe('allNonVisualChecksHavePassed', () => {
it('should return true when all non-visual pr checks pass', async () => {
(getOctokit as jest.Mock).mockImplementation(() => ({
rest: {
checks: {
listForRef: jest.fn().mockReturnValue({
data: {
check_runs: [
{
name: 'unit tests',
conclusion: 'success',
completed_at: '2023-05-02T19:11:02Z',
},
{
name: VISUAL_REGRESSION_CONTEXT,
conclusion: 'failure',
completed_at: '2023-05-02T19:11:02Z',
},
{
name: 'other tests',
conclusion: 'success',
completed_at: '2023-05-02T19:11:02Z',
},
],
},
repos: {
listCommitStatusesForRef: jest.fn().mockReturnValue({
data: [
{
context: 'unit tests',
state: 'success',
created_at: '2023-05-02T19:11:02Z',
},
{
context: VISUAL_REGRESSION_CONTEXT,
state: 'failure',
created_at: '2023-05-02T19:11:02Z',
},
{
context: 'other tests',
state: 'success',
created_at: '2023-05-02T19:11:02Z',
},
],
}),
},
},
Expand All @@ -44,27 +42,25 @@ describe('allNonVisualChecksHavePassed', () => {
it('should return false when at least one visual test job failed', async () => {
(getOctokit as jest.Mock).mockImplementation(() => ({
rest: {
checks: {
listForRef: jest.fn().mockReturnValue({
data: {
check_runs: [
{
name: 'unit tests',
conclusion: 'success',
completed_at: '2023-05-02T19:11:02Z',
},
{
name: VISUAL_REGRESSION_CONTEXT,
conclusion: 'failure',
completed_at: '2023-05-02T19:11:02Z',
},
{
name: 'visual tests',
conclusion: 'failure',
completed_at: '2023-05-02T19:11:02Z',
},
],
},
repos: {
listCommitStatusesForRef: jest.fn().mockReturnValue({
data: [
{
context: 'unit tests',
state: 'success',
created_at: '2023-05-02T19:11:02Z',
},
{
context: VISUAL_REGRESSION_CONTEXT,
state: 'failure',
created_at: '2023-05-02T19:11:02Z',
},
{
context: 'visual tests',
state: 'failure',
created_at: '2023-05-02T19:11:02Z',
},
],
}),
},
},
Expand All @@ -80,27 +76,25 @@ describe('allNonVisualChecksHavePassed', () => {
it('should return false when at least one non-visual check failed', async () => {
(getOctokit as jest.Mock).mockImplementation(() => ({
rest: {
checks: {
listForRef: jest.fn().mockReturnValue({
data: {
check_runs: [
{
name: 'unit tests',
conclusion: 'success',
completed_at: '2023-05-02T19:11:02Z',
},
{
name: VISUAL_REGRESSION_CONTEXT,
conclusion: 'failure',
completed_at: '2023-05-02T19:11:02Z',
},
{
name: 'other tests',
conclusion: 'failure',
completed_at: '2023-05-02T19:11:02Z',
},
],
},
repos: {
listCommitStatusesForRef: jest.fn().mockReturnValue({
data: [
{
context: 'unit tests',
state: 'success',
created_at: '2023-05-02T19:11:02Z',
},
{
context: VISUAL_REGRESSION_CONTEXT,
state: 'failure',
created_at: '2023-05-02T19:11:02Z',
},
{
context: 'other tests',
state: 'failure',
created_at: '2023-05-02T19:11:02Z',
},
],
}),
},
},
Expand All @@ -113,30 +107,28 @@ describe('allNonVisualChecksHavePassed', () => {
expect(result).toBe(false);
});

it('should return true when all non-visual pr checks pass but some are skipped', async () => {
it('should return false when all non-visual pr checks pass but some are pending', async () => {
(getOctokit as jest.Mock).mockImplementation(() => ({
rest: {
checks: {
listForRef: jest.fn().mockReturnValue({
data: {
check_runs: [
{
name: 'unit tests',
conclusion: 'success',
completed_at: '2023-05-02T19:11:02Z',
},
{
name: VISUAL_REGRESSION_CONTEXT,
conclusion: 'failure',
completed_at: '2023-05-02T19:11:02Z',
},
{
name: 'other tests',
conclusion: 'skipped',
completed_at: '2023-05-02T19:11:02Z',
},
],
},
repos: {
listCommitStatusesForRef: jest.fn().mockReturnValue({
data: [
{
context: 'unit tests',
state: 'success',
created_at: '2023-05-02T19:11:02Z',
},
{
context: VISUAL_REGRESSION_CONTEXT,
state: 'failure',
created_at: '2023-05-02T19:11:02Z',
},
{
context: 'other tests',
state: 'pending',
created_at: '2023-05-02T19:11:02Z',
},
],
}),
},
},
Expand All @@ -146,38 +138,31 @@ describe('allNonVisualChecksHavePassed', () => {
'github-repo',
'sha'
);
expect(result).toBe(true);
expect(result).toBe(false);
});

it('should return true when a non-visual check failed on an early run but passed on the latest run', async () => {
(getOctokit as jest.Mock).mockImplementation(() => ({
rest: {
checks: {
listForRef: jest.fn().mockReturnValue({
data: {
check_runs: [
{
name: 'unit tests',
conclusion: 'failure',
completed_at: '2023-05-02T19:10:02Z',
},
{
name: 'unit tests',
conclusion: 'success',
completed_at: '2023-05-02T19:11:02Z',
},
{
name: VISUAL_REGRESSION_CONTEXT,
conclusion: 'failure',
completed_at: '2023-05-02T19:11:02Z',
},
{
name: 'other tests',
conclusion: 'skipped',
completed_at: '2023-05-02T19:11:02Z',
},
],
},
repos: {
listCommitStatusesForRef: jest.fn().mockReturnValue({
data: [
{
context: 'unit tests',
state: 'failure',
created_at: '2023-05-02T19:10:02Z',
},
{
context: 'unit tests',
state: 'success',
created_at: '2023-05-02T19:11:02Z',
},
{
context: VISUAL_REGRESSION_CONTEXT,
state: 'failure',
created_at: '2023-05-02T19:11:02Z',
},
],
}),
},
},
Expand All @@ -193,32 +178,25 @@ describe('allNonVisualChecksHavePassed', () => {
it('should return false when a non-visual check fails on multiple runs and never passed', async () => {
(getOctokit as jest.Mock).mockImplementation(() => ({
rest: {
checks: {
listForRef: jest.fn().mockReturnValue({
data: {
check_runs: [
{
name: 'unit tests',
conclusion: 'failure',
completed_at: '2023-05-02T19:11:02Z',
},
{
name: 'unit tests',
conclusion: 'failure',
completed_at: '2023-05-02T19:10:02Z',
},
{
name: VISUAL_REGRESSION_CONTEXT,
conclusion: 'failure',
completed_at: '2023-05-02T19:11:02Z',
},
{
name: 'other tests',
conclusion: 'skipped',
completed_at: '2023-05-02T19:11:02Z',
},
],
},
repos: {
listCommitStatusesForRef: jest.fn().mockReturnValue({
data: [
{
context: 'unit tests',
state: 'failure',
created_at: '2023-05-02T19:11:02Z',
},
{
context: 'unit tests',
state: 'failure',
created_at: '2023-05-02T19:10:02Z',
},
{
context: VISUAL_REGRESSION_CONTEXT,
state: 'failure',
created_at: '2023-05-02T19:11:02Z',
},
],
}),
},
},
Expand Down

0 comments on commit deb92d8

Please sign in to comment.