feat: branch status unification (#5658)

This commit is contained in:
Rhys Arkins 2020-03-08 15:03:19 +01:00 committed by GitHub
parent 51a89a3107
commit 588616f669
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
30 changed files with 358 additions and 382 deletions

View file

@ -1,8 +0,0 @@
// Branch Status
export const BRANCH_STATUS_SUCCESS = 'success';
export const BRANCH_STATUS_FAILURE = 'failure';
export const BRANCH_STATUS_ERROR = 'error';
export const BRANCH_STATUS_PENDING = 'pending';
export const BRANCH_STATUS_CREATED = 'created';
export const BRANCH_STATUS_RUNNING = 'running';
export const BRANCH_STATUS_FAILED = 'failed';

View file

@ -2,11 +2,7 @@ import is from '@sindresorhus/is';
import * as _hostRules from '../../util/host-rules'; import * as _hostRules from '../../util/host-rules';
import { RepoParams, Platform } from '../common'; import { RepoParams, Platform } from '../common';
import { REPOSITORY_DISABLED } from '../../constants/error-messages'; import { REPOSITORY_DISABLED } from '../../constants/error-messages';
import { import { BranchStatus } from '../../types';
BRANCH_STATUS_FAILED,
BRANCH_STATUS_PENDING,
BRANCH_STATUS_SUCCESS,
} from '../../constants/branch-constants';
describe('platform/azure', () => { describe('platform/azure', () => {
let hostRules: jest.Mocked<typeof _hostRules>; let hostRules: jest.Mocked<typeof _hostRules>;
@ -416,12 +412,12 @@ describe('platform/azure', () => {
it('return success if requiredStatusChecks null', async () => { it('return success if requiredStatusChecks null', async () => {
await initRepo('some-repo'); await initRepo('some-repo');
const res = await azure.getBranchStatus('somebranch', null); const res = await azure.getBranchStatus('somebranch', null);
expect(res).toEqual(BRANCH_STATUS_SUCCESS); expect(res).toEqual(BranchStatus.green);
}); });
it('return failed if unsupported requiredStatusChecks', async () => { it('return failed if unsupported requiredStatusChecks', async () => {
await initRepo('some-repo'); await initRepo('some-repo');
const res = await azure.getBranchStatus('somebranch', ['foo']); const res = await azure.getBranchStatus('somebranch', ['foo']);
expect(res).toEqual(BRANCH_STATUS_FAILED); expect(res).toEqual(BranchStatus.red);
}); });
it('should pass through success', async () => { it('should pass through success', async () => {
await initRepo({ repository: 'some/repo' }); await initRepo({ repository: 'some/repo' });
@ -432,7 +428,7 @@ describe('platform/azure', () => {
} as any) } as any)
); );
const res = await azure.getBranchStatus('somebranch', []); const res = await azure.getBranchStatus('somebranch', []);
expect(res).toEqual(BRANCH_STATUS_SUCCESS); expect(res).toEqual(BranchStatus.green);
}); });
it('should pass through failed', async () => { it('should pass through failed', async () => {
await initRepo({ repository: 'some/repo' }); await initRepo({ repository: 'some/repo' });
@ -443,7 +439,7 @@ describe('platform/azure', () => {
} as any) } as any)
); );
const res = await azure.getBranchStatus('somebranch', []); const res = await azure.getBranchStatus('somebranch', []);
expect(res).toEqual(BRANCH_STATUS_PENDING); expect(res).toEqual(BranchStatus.yellow);
}); });
}); });
@ -856,7 +852,7 @@ describe('platform/azure', () => {
branchName: 'test', branchName: 'test',
context: 'test', context: 'test',
description: 'test', description: 'test',
state: 'test', state: BranchStatus.yellow,
url: 'test', url: 'test',
}); });
expect(res).toBeUndefined(); expect(res).toBeUndefined();

View file

@ -20,7 +20,6 @@ import {
FindPRConfig, FindPRConfig,
EnsureCommentConfig, EnsureCommentConfig,
EnsureIssueResult, EnsureIssueResult,
BranchStatus,
} from '../common'; } from '../common';
import { sanitize } from '../../util/sanitize'; import { sanitize } from '../../util/sanitize';
import { smartTruncate } from '../utils/pr-body'; import { smartTruncate } from '../utils/pr-body';
@ -31,11 +30,7 @@ import {
PR_STATE_NOT_OPEN, PR_STATE_NOT_OPEN,
PR_STATE_OPEN, PR_STATE_OPEN,
} from '../../constants/pull-requests'; } from '../../constants/pull-requests';
import { import { BranchStatus } from '../../types';
BRANCH_STATUS_FAILED,
BRANCH_STATUS_PENDING,
BRANCH_STATUS_SUCCESS,
} from '../../constants/branch-constants';
import { RenovateConfig } from '../../config'; import { RenovateConfig } from '../../config';
interface Config { interface Config {
@ -393,7 +388,7 @@ export /* istanbul ignore next */ function getCommitMessages(): Promise<
export async function getBranchStatusCheck( export async function getBranchStatusCheck(
branchName: string, branchName: string,
context?: string context: string
): Promise<BranchStatus> { ): Promise<BranchStatus> {
logger.trace(`getBranchStatusCheck(${branchName}, ${context})`); logger.trace(`getBranchStatusCheck(${branchName}, ${context})`);
const azureApiGit = await azureApi.gitApi(); const azureApiGit = await azureApi.gitApi();
@ -402,9 +397,9 @@ export async function getBranchStatusCheck(
azureHelper.getBranchNameWithoutRefsheadsPrefix(branchName)! azureHelper.getBranchNameWithoutRefsheadsPrefix(branchName)!
); );
if (branch.aheadCount === 0) { if (branch.aheadCount === 0) {
return BRANCH_STATUS_SUCCESS; return BranchStatus.green;
} }
return BRANCH_STATUS_PENDING; return BranchStatus.yellow;
} }
export async function getBranchStatus( export async function getBranchStatus(
@ -414,14 +409,14 @@ export async function getBranchStatus(
logger.debug(`getBranchStatus(${branchName})`); logger.debug(`getBranchStatus(${branchName})`);
if (!requiredStatusChecks) { if (!requiredStatusChecks) {
// null means disable status checks, so it always succeeds // null means disable status checks, so it always succeeds
return BRANCH_STATUS_SUCCESS; return BranchStatus.green;
} }
if (requiredStatusChecks.length) { if (requiredStatusChecks.length) {
// This is Unsupported // This is Unsupported
logger.warn({ requiredStatusChecks }, `Unsupported requiredStatusChecks`); logger.warn({ requiredStatusChecks }, `Unsupported requiredStatusChecks`);
return BRANCH_STATUS_FAILED; return BranchStatus.red;
} }
const branchStatusCheck = await getBranchStatusCheck(branchName); const branchStatusCheck = await getBranchStatusCheck(branchName, null);
return branchStatusCheck; return branchStatusCheck;
} }

View file

@ -7,12 +7,7 @@ import {
REPOSITORY_NOT_FOUND, REPOSITORY_NOT_FOUND,
} from '../../constants/error-messages'; } from '../../constants/error-messages';
import { PR_STATE_CLOSED, PR_STATE_OPEN } from '../../constants/pull-requests'; import { PR_STATE_CLOSED, PR_STATE_OPEN } from '../../constants/pull-requests';
import { import { BranchStatus } from '../../types';
BRANCH_STATUS_FAILED,
BRANCH_STATUS_FAILURE,
BRANCH_STATUS_PENDING,
BRANCH_STATUS_SUCCESS,
} from '../../constants/branch-constants';
describe('platform/bitbucket-server', () => { describe('platform/bitbucket-server', () => {
Object.entries(responses).forEach(([scenarioName, mockResponses]) => { Object.entries(responses).forEach(([scenarioName, mockResponses]) => {
@ -787,11 +782,11 @@ Followed by some information.
await expect( await expect(
bitbucket.getBranchStatus('somebranch', []) bitbucket.getBranchStatus('somebranch', [])
).resolves.toEqual(BRANCH_STATUS_SUCCESS); ).resolves.toEqual(BranchStatus.green);
await expect( await expect(
bitbucket.getBranchStatus('somebranch') bitbucket.getBranchStatus('somebranch')
).resolves.toEqual(BRANCH_STATUS_SUCCESS); ).resolves.toEqual(BranchStatus.green);
expect(api.get.mock.calls).toMatchSnapshot(); expect(api.get.mock.calls).toMatchSnapshot();
}); });
@ -809,7 +804,7 @@ Followed by some information.
await expect( await expect(
bitbucket.getBranchStatus('somebranch', []) bitbucket.getBranchStatus('somebranch', [])
).resolves.toEqual(BRANCH_STATUS_PENDING); ).resolves.toEqual(BranchStatus.yellow);
api.get.mockReturnValueOnce({ api.get.mockReturnValueOnce({
body: { body: {
@ -821,7 +816,7 @@ Followed by some information.
await expect( await expect(
bitbucket.getBranchStatus('somebranch', []) bitbucket.getBranchStatus('somebranch', [])
).resolves.toEqual(BRANCH_STATUS_PENDING); ).resolves.toEqual(BranchStatus.yellow);
expect(api.get.mock.calls).toMatchSnapshot(); expect(api.get.mock.calls).toMatchSnapshot();
}); });
@ -840,7 +835,7 @@ Followed by some information.
await expect( await expect(
bitbucket.getBranchStatus('somebranch', []) bitbucket.getBranchStatus('somebranch', [])
).resolves.toEqual(BRANCH_STATUS_FAILED); ).resolves.toEqual(BranchStatus.red);
api.get.mockImplementationOnce(() => { api.get.mockImplementationOnce(() => {
throw new Error('requst-failed'); throw new Error('requst-failed');
@ -848,7 +843,7 @@ Followed by some information.
await expect( await expect(
bitbucket.getBranchStatus('somebranch', []) bitbucket.getBranchStatus('somebranch', [])
).resolves.toEqual(BRANCH_STATUS_FAILED); ).resolves.toEqual(BranchStatus.red);
expect(api.get.mock.calls).toMatchSnapshot(); expect(api.get.mock.calls).toMatchSnapshot();
}); });
@ -889,7 +884,7 @@ Followed by some information.
await expect( await expect(
bitbucket.getBranchStatusCheck('somebranch', 'context-2') bitbucket.getBranchStatusCheck('somebranch', 'context-2')
).resolves.toEqual(BRANCH_STATUS_SUCCESS); ).resolves.toEqual(BranchStatus.green);
expect(api.get.mock.calls).toMatchSnapshot(); expect(api.get.mock.calls).toMatchSnapshot();
}); });
@ -912,7 +907,7 @@ Followed by some information.
await expect( await expect(
bitbucket.getBranchStatusCheck('somebranch', 'context-2') bitbucket.getBranchStatusCheck('somebranch', 'context-2')
).resolves.toEqual(BRANCH_STATUS_PENDING); ).resolves.toEqual(BranchStatus.yellow);
expect(api.get.mock.calls).toMatchSnapshot(); expect(api.get.mock.calls).toMatchSnapshot();
}); });
@ -935,7 +930,7 @@ Followed by some information.
await expect( await expect(
bitbucket.getBranchStatusCheck('somebranch', 'context-2') bitbucket.getBranchStatusCheck('somebranch', 'context-2')
).resolves.toEqual(BRANCH_STATUS_FAILURE); ).resolves.toEqual(BranchStatus.red);
expect(api.get.mock.calls).toMatchSnapshot(); expect(api.get.mock.calls).toMatchSnapshot();
}); });
@ -976,28 +971,28 @@ Followed by some information.
branchName: 'somebranch', branchName: 'somebranch',
context: 'context-2', context: 'context-2',
description: null as any, description: null as any,
state: BRANCH_STATUS_SUCCESS, state: BranchStatus.green,
}); });
await bitbucket.setBranchStatus({ await bitbucket.setBranchStatus({
branchName: 'somebranch', branchName: 'somebranch',
context: 'context-2', context: 'context-2',
description: null as any, description: null as any,
state: BRANCH_STATUS_FAILED, state: BranchStatus.red,
}); });
await bitbucket.setBranchStatus({ await bitbucket.setBranchStatus({
branchName: 'somebranch', branchName: 'somebranch',
context: 'context-2', context: 'context-2',
description: null as any, description: null as any,
state: BRANCH_STATUS_FAILURE, state: BranchStatus.red,
}); });
await bitbucket.setBranchStatus({ await bitbucket.setBranchStatus({
branchName: 'somebranch', branchName: 'somebranch',
context: 'context-2', context: 'context-2',
description: null as any, description: null as any,
state: BRANCH_STATUS_PENDING, state: BranchStatus.yellow,
}); });
api.post.mockImplementationOnce(() => { api.post.mockImplementationOnce(() => {
@ -1008,14 +1003,14 @@ Followed by some information.
branchName: 'somebranch', branchName: 'somebranch',
context: 'context-2', context: 'context-2',
description: null as any, description: null as any,
state: BRANCH_STATUS_SUCCESS, state: BranchStatus.green,
}); });
await bitbucket.setBranchStatus({ await bitbucket.setBranchStatus({
branchName: 'somebranch', branchName: 'somebranch',
context: 'context-1', context: 'context-1',
description: null as any, description: null as any,
state: BRANCH_STATUS_SUCCESS, state: BranchStatus.green,
}); });
expect(api.get.mock.calls).toMatchSnapshot(); expect(api.get.mock.calls).toMatchSnapshot();

View file

@ -20,7 +20,6 @@ import {
EnsureCommentConfig, EnsureCommentConfig,
EnsureIssueResult, EnsureIssueResult,
EnsureIssueConfig, EnsureIssueConfig,
BranchStatus,
} from '../common'; } from '../common';
import { sanitize } from '../../util/sanitize'; import { sanitize } from '../../util/sanitize';
import { smartTruncate } from '../utils/pr-body'; import { smartTruncate } from '../utils/pr-body';
@ -31,12 +30,7 @@ import {
REPOSITORY_NOT_FOUND, REPOSITORY_NOT_FOUND,
} from '../../constants/error-messages'; } from '../../constants/error-messages';
import { PR_STATE_ALL, PR_STATE_OPEN } from '../../constants/pull-requests'; import { PR_STATE_ALL, PR_STATE_OPEN } from '../../constants/pull-requests';
import { import { BranchStatus } from '../../types';
BRANCH_STATUS_FAILED,
BRANCH_STATUS_FAILURE,
BRANCH_STATUS_PENDING,
BRANCH_STATUS_SUCCESS,
} from '../../constants/branch-constants';
import { RenovateConfig } from '../../config'; import { RenovateConfig } from '../../config';
/* /*
* Version: 5.3 (EOL Date: 15 Aug 2019) * Version: 5.3 (EOL Date: 15 Aug 2019)
@ -536,7 +530,7 @@ export async function getBranchStatus(
if (!requiredStatusChecks) { if (!requiredStatusChecks) {
// null means disable status checks, so it always succeeds // null means disable status checks, so it always succeeds
logger.debug('Status checks disabled = returning "success"'); logger.debug('Status checks disabled = returning "success"');
return BRANCH_STATUS_SUCCESS; return BranchStatus.green;
} }
if (!(await branchExists(branchName))) { if (!(await branchExists(branchName))) {
@ -548,14 +542,14 @@ export async function getBranchStatus(
logger.debug({ commitStatus }, 'branch status check result'); logger.debug({ commitStatus }, 'branch status check result');
if (commitStatus.failed > 0) return BRANCH_STATUS_FAILED; if (commitStatus.failed > 0) return BranchStatus.red;
if (commitStatus.inProgress > 0) return BRANCH_STATUS_PENDING; if (commitStatus.inProgress > 0) return BranchStatus.yellow;
return commitStatus.successful > 0 return commitStatus.successful > 0
? BRANCH_STATUS_SUCCESS ? BranchStatus.green
: BRANCH_STATUS_PENDING; : BranchStatus.yellow;
} catch (err) { } catch (err) {
logger.warn({ err }, `Failed to get branch status`); logger.warn({ err }, `Failed to get branch status`);
return BRANCH_STATUS_FAILED; return BranchStatus.red;
} }
} }
@ -576,7 +570,7 @@ async function getStatusCheck(
export async function getBranchStatusCheck( export async function getBranchStatusCheck(
branchName: string, branchName: string,
context: string context: string
): Promise<string | null> { ): Promise<BranchStatus | null> {
logger.debug(`getBranchStatusCheck(${branchName}, context=${context})`); logger.debug(`getBranchStatusCheck(${branchName}, context=${context})`);
try { try {
@ -586,12 +580,12 @@ export async function getBranchStatusCheck(
if (state.key === context) { if (state.key === context) {
switch (state.state) { switch (state.state) {
case 'SUCCESSFUL': case 'SUCCESSFUL':
return BRANCH_STATUS_SUCCESS; return BranchStatus.green;
case 'INPROGRESS': case 'INPROGRESS':
return BRANCH_STATUS_PENDING; return BranchStatus.yellow;
case 'FAILED': case 'FAILED':
default: default:
return BRANCH_STATUS_FAILURE; return BranchStatus.red;
} }
} }
} }
@ -626,13 +620,13 @@ export async function setBranchStatus({
}; };
switch (state) { switch (state) {
case BRANCH_STATUS_SUCCESS: case BranchStatus.green:
body.state = 'SUCCESSFUL'; body.state = 'SUCCESSFUL';
break; break;
case BRANCH_STATUS_PENDING: case BranchStatus.yellow:
body.state = 'INPROGRESS'; body.state = 'INPROGRESS';
break; break;
case BRANCH_STATUS_FAILURE: case BranchStatus.red:
default: default:
body.state = 'FAILED'; body.state = 'FAILED';
break; break;

View file

@ -2,11 +2,7 @@ import URL from 'url';
import responses from './__fixtures__/responses'; import responses from './__fixtures__/responses';
import { GotApi, RepoParams, Platform } from '../common'; import { GotApi, RepoParams, Platform } from '../common';
import { REPOSITORY_DISABLED } from '../../constants/error-messages'; import { REPOSITORY_DISABLED } from '../../constants/error-messages';
import { import { BranchStatus } from '../../types';
BRANCH_STATUS_FAILED,
BRANCH_STATUS_PENDING,
BRANCH_STATUS_SUCCESS,
} from '../../constants/branch-constants';
describe('platform/bitbucket', () => { describe('platform/bitbucket', () => {
let bitbucket: Platform; let bitbucket: Platform;
@ -197,17 +193,15 @@ describe('platform/bitbucket', () => {
const getBranchStatus = wrap('getBranchStatus'); const getBranchStatus = wrap('getBranchStatus');
it('works', async () => { it('works', async () => {
await initRepo(); await initRepo();
expect(await getBranchStatus('master', null)).toBe(BRANCH_STATUS_SUCCESS); expect(await getBranchStatus('master', null)).toBe(BranchStatus.green);
expect(await getBranchStatus('master', ['foo'])).toBe( expect(await getBranchStatus('master', ['foo'])).toBe(BranchStatus.red);
BRANCH_STATUS_FAILED expect(await getBranchStatus('master', true)).toBe(BranchStatus.red);
); expect(await getBranchStatus('branch', true)).toBe(BranchStatus.green);
expect(await getBranchStatus('master', true)).toBe(BRANCH_STATUS_FAILED);
expect(await getBranchStatus('branch', true)).toBe(BRANCH_STATUS_SUCCESS);
expect(await getBranchStatus('pending/branch', true)).toBe( expect(await getBranchStatus('pending/branch', true)).toBe(
BRANCH_STATUS_PENDING BranchStatus.yellow
); );
expect(await getBranchStatus('branch-with-empty-status', true)).toBe( expect(await getBranchStatus('branch-with-empty-status', true)).toBe(
BRANCH_STATUS_PENDING BranchStatus.yellow
); );
}); });
}); });
@ -217,7 +211,9 @@ describe('platform/bitbucket', () => {
it('works', async () => { it('works', async () => {
await initRepo(); await initRepo();
expect(await getBranchStatusCheck('master', null)).toBeNull(); expect(await getBranchStatusCheck('master', null)).toBeNull();
expect(await getBranchStatusCheck('master', 'foo')).toBe('failed'); expect(await getBranchStatusCheck('master', 'foo')).toBe(
BranchStatus.red
);
expect(await getBranchStatusCheck('master', 'bar')).toBeNull(); expect(await getBranchStatusCheck('master', 'bar')).toBeNull();
}); });
}); });
@ -230,7 +226,7 @@ describe('platform/bitbucket', () => {
branchName: 'branch', branchName: 'branch',
context: 'context', context: 'context',
description: 'description', description: 'description',
state: BRANCH_STATUS_FAILED, state: BranchStatus.red,
url: 'targetUrl', url: 'targetUrl',
}); });
expect(api.post.mock.calls).toMatchSnapshot(); expect(api.post.mock.calls).toMatchSnapshot();

View file

@ -20,7 +20,6 @@ import {
FindPRConfig, FindPRConfig,
EnsureCommentConfig, EnsureCommentConfig,
EnsureIssueResult, EnsureIssueResult,
BranchStatus,
} from '../common'; } from '../common';
import { sanitize } from '../../util/sanitize'; import { sanitize } from '../../util/sanitize';
import { smartTruncate } from '../utils/pr-body'; import { smartTruncate } from '../utils/pr-body';
@ -30,11 +29,7 @@ import {
} from '../../constants/error-messages'; } from '../../constants/error-messages';
import { PR_STATE_ALL, PR_STATE_OPEN } from '../../constants/pull-requests'; import { PR_STATE_ALL, PR_STATE_OPEN } from '../../constants/pull-requests';
import { PLATFORM_TYPE_BITBUCKET } from '../../constants/platforms'; import { PLATFORM_TYPE_BITBUCKET } from '../../constants/platforms';
import { import { BranchStatus } from '../../types';
BRANCH_STATUS_FAILED,
BRANCH_STATUS_PENDING,
BRANCH_STATUS_SUCCESS,
} from '../../constants/branch-constants';
import { RenovateConfig } from '../../config'; import { RenovateConfig } from '../../config';
let config: utils.Config = {} as any; let config: utils.Config = {} as any;
@ -415,46 +410,47 @@ export async function getBranchStatus(
if (!requiredStatusChecks) { if (!requiredStatusChecks) {
// null means disable status checks, so it always succeeds // null means disable status checks, so it always succeeds
logger.debug('Status checks disabled = returning "success"'); logger.debug('Status checks disabled = returning "success"');
return BRANCH_STATUS_SUCCESS; return BranchStatus.green;
} }
if (requiredStatusChecks.length) { if (requiredStatusChecks.length) {
// This is Unsupported // This is Unsupported
logger.warn({ requiredStatusChecks }, `Unsupported requiredStatusChecks`); logger.warn({ requiredStatusChecks }, `Unsupported requiredStatusChecks`);
return BRANCH_STATUS_FAILED; return BranchStatus.red;
} }
const statuses = await getStatus(branchName); const statuses = await getStatus(branchName);
logger.debug({ branch: branchName, statuses }, 'branch status check result'); logger.debug({ branch: branchName, statuses }, 'branch status check result');
if (!statuses.length) { if (!statuses.length) {
logger.debug('empty branch status check result = returning "pending"'); logger.debug('empty branch status check result = returning "pending"');
return BRANCH_STATUS_PENDING; return BranchStatus.yellow;
} }
const noOfFailures = statuses.filter( const noOfFailures = statuses.filter(
(status: { state: string }) => status.state === 'FAILED' (status: { state: string }) => status.state === 'FAILED'
).length; ).length;
if (noOfFailures) { if (noOfFailures) {
return BRANCH_STATUS_FAILED; return BranchStatus.red;
} }
const noOfPending = statuses.filter( const noOfPending = statuses.filter(
(status: { state: string }) => status.state === 'INPROGRESS' (status: { state: string }) => status.state === 'INPROGRESS'
).length; ).length;
if (noOfPending) { if (noOfPending) {
return BRANCH_STATUS_PENDING; return BranchStatus.yellow;
} }
return BRANCH_STATUS_SUCCESS; return BranchStatus.green;
} }
const bbToRenovateStatusMapping: Record<string, BranchStatus> = {
SUCCESSFUL: BranchStatus.green,
INPROGRESS: BranchStatus.yellow,
FAILED: BranchStatus.red,
};
export async function getBranchStatusCheck( export async function getBranchStatusCheck(
branchName: string, branchName: string,
context: string context: string
): Promise<string | null> { ): Promise<BranchStatus | null> {
const statuses = await getStatus(branchName); const statuses = await getStatus(branchName);
const bbState = (statuses.find(status => status.key === context) || {}).state; const bbState = (statuses.find(status => status.key === context) || {}).state;
return bbToRenovateStatusMapping[bbState] || null;
return (
Object.keys(utils.buildStates).find(
stateKey => utils.buildStates[stateKey] === bbState
) || null
);
} }
export async function setBranchStatus({ export async function setBranchStatus({

View file

@ -3,6 +3,7 @@ import { api } from './bb-got-wrapper';
import { Storage } from '../git/storage'; import { Storage } from '../git/storage';
import { GotResponse, Pr } from '../common'; import { GotResponse, Pr } from '../common';
import { PR_STATE_CLOSED } from '../../constants/pull-requests'; import { PR_STATE_CLOSED } from '../../constants/pull-requests';
import { BranchStatus } from '../../types';
export interface Config { export interface Config {
baseBranch: string; baseBranch: string;
@ -59,15 +60,10 @@ export const prStates = {
all: ['OPEN', 'MERGED', 'DECLINED', 'SUPERSEDED'], all: ['OPEN', 'MERGED', 'DECLINED', 'SUPERSEDED'],
}; };
export const buildStates: { export const buildStates: Record<BranchStatus, BitbucketBranchState> = {
[key: string]: BitbucketBranchState; green: 'SUCCESSFUL',
success: BitbucketBranchState; red: 'FAILED',
failed: BitbucketBranchState; yellow: 'INPROGRESS',
pending: BitbucketBranchState;
} = {
success: 'SUCCESSFUL',
failed: 'FAILED',
pending: 'INPROGRESS',
}; };
const addMaxLength = (inputUrl: string, pagelen = 100): string => { const addMaxLength = (inputUrl: string, pagelen = 100): string => {

View file

@ -2,6 +2,7 @@ import got from 'got';
import Git from 'simple-git/promise'; import Git from 'simple-git/promise';
import { RenovateConfig } from '../config/common'; import { RenovateConfig } from '../config/common';
import { CommitFilesConfig } from './git/storage'; import { CommitFilesConfig } from './git/storage';
import { BranchStatus } from '../types';
export interface FileData { export interface FileData {
name: string; name: string;
@ -95,14 +96,6 @@ export interface Issue {
state?: string; state?: string;
title?: string; title?: string;
} }
export type BranchStatus =
| 'pending'
| 'success'
| 'failed'
| 'running'
| 'failure';
export type PlatformPrOptions = { export type PlatformPrOptions = {
azureAutoComplete?: boolean; azureAutoComplete?: boolean;
statusCheckVerify?: boolean; statusCheckVerify?: boolean;
@ -126,7 +119,7 @@ export interface BranchStatusConfig {
branchName: string; branchName: string;
context: string; context: string;
description: string; description: string;
state: string | null; state: BranchStatus;
url?: string; url?: string;
} }
export interface FindPRConfig { export interface FindPRConfig {
@ -175,7 +168,10 @@ export interface Platform {
getRepoForceRebase(): Promise<boolean>; getRepoForceRebase(): Promise<boolean>;
deleteLabel(number: number, label: string): Promise<void>; deleteLabel(number: number, label: string): Promise<void>;
setBranchStatus(branchStatusConfig: BranchStatusConfig): Promise<void>; setBranchStatus(branchStatusConfig: BranchStatusConfig): Promise<void>;
getBranchStatusCheck(branchName: string, context: string): Promise<string>; getBranchStatusCheck(
branchName: string,
context: string
): Promise<BranchStatus | null>;
ensureCommentRemoval(number: number, subject: string): Promise<void>; ensureCommentRemoval(number: number, subject: string): Promise<void>;
deleteBranch(branchName: string, closePr?: boolean): Promise<void>; deleteBranch(branchName: string, closePr?: boolean): Promise<void>;
ensureComment(ensureComment: EnsureCommentConfig): Promise<boolean>; ensureComment(ensureComment: EnsureCommentConfig): Promise<boolean>;

View file

@ -2,6 +2,7 @@ import { URLSearchParams } from 'url';
import { api, GiteaGotOptions } from './gitea-got-wrapper'; import { api, GiteaGotOptions } from './gitea-got-wrapper';
import { GotResponse } from '../common'; import { GotResponse } from '../common';
import { PR_STATE_CLOSED } from '../../constants/pull-requests'; import { PR_STATE_CLOSED } from '../../constants/pull-requests';
import { BranchStatus } from '../../types';
export type PRState = 'open' | 'closed' | 'all'; export type PRState = 'open' | 'closed' | 'all';
export type IssueState = 'open' | 'closed' | 'all'; export type IssueState = 'open' | 'closed' | 'all';
@ -474,6 +475,27 @@ export async function createCommitStatus(
return res.body; return res.body;
} }
export const giteaToRenovateStatusMapping: Record<
CommitStatusType,
BranchStatus | null
> = {
unknown: BranchStatus.yellow,
success: BranchStatus.green,
pending: BranchStatus.yellow,
warning: BranchStatus.red,
failure: BranchStatus.red,
error: BranchStatus.red,
};
export const renovateToGiteaStatusMapping: Record<
BranchStatus,
CommitStatusType
> = {
green: 'success',
yellow: 'pending',
red: 'failure',
};
export async function getCombinedCommitStatus( export async function getCombinedCommitStatus(
repoPath: string, repoPath: string,
branchName: string, branchName: string,

View file

@ -10,7 +10,6 @@ import {
REPOSITORY_MIRRORED, REPOSITORY_MIRRORED,
} from '../../constants/error-messages'; } from '../../constants/error-messages';
import { import {
BranchStatus,
BranchStatusConfig, BranchStatusConfig,
GotResponse, GotResponse,
RepoConfig, RepoConfig,
@ -18,11 +17,7 @@ import {
Platform, Platform,
} from '..'; } from '..';
import { logger as _logger } from '../../logger'; import { logger as _logger } from '../../logger';
import { import { BranchStatus } from '../../types';
BRANCH_STATUS_FAILED,
BRANCH_STATUS_PENDING,
BRANCH_STATUS_SUCCESS,
} from '../../constants/branch-constants';
import { GiteaGotApi } from './gitea-got-wrapper'; import { GiteaGotApi } from './gitea-got-wrapper';
import { CommitFilesConfig, File } from '../git/storage'; import { CommitFilesConfig, File } from '../git/storage';
@ -371,7 +366,7 @@ describe('platform/gitea', () => {
await initFakeRepo(); await initFakeRepo();
await gitea.setBranchStatus({ await gitea.setBranchStatus({
branchName: 'some-branch', branchName: 'some-branch',
state: 'some-state', state: BranchStatus.green,
context: 'some-context', context: 'some-context',
description: 'some-description', description: 'some-description',
...bsc, ...bsc,
@ -386,7 +381,7 @@ describe('platform/gitea', () => {
mockRepo.full_name, mockRepo.full_name,
mockCommitHash, mockCommitHash,
{ {
state: 'some-state', state: 'success',
context: 'some-context', context: 'some-context',
description: 'some-description', description: 'some-description',
} }
@ -416,7 +411,7 @@ describe('platform/gitea', () => {
mockRepo.full_name, mockRepo.full_name,
mockCommitHash, mockCommitHash,
{ {
state: 'some-state', state: 'success',
context: 'some-context', context: 'some-context',
description: 'some-description', description: 'some-description',
target_url: 'some-url', target_url: 'some-url',
@ -446,30 +441,30 @@ describe('platform/gitea', () => {
it('should return success if requiredStatusChecks null', async () => { it('should return success if requiredStatusChecks null', async () => {
expect(await gitea.getBranchStatus('some-branch', null)).toEqual( expect(await gitea.getBranchStatus('some-branch', null)).toEqual(
BRANCH_STATUS_SUCCESS BranchStatus.green
); );
}); });
it('should return failed if unsupported requiredStatusChecks', async () => { it('should return failed if unsupported requiredStatusChecks', async () => {
expect(await gitea.getBranchStatus('some-branch', ['foo'])).toEqual( expect(await gitea.getBranchStatus('some-branch', ['foo'])).toEqual(
BRANCH_STATUS_FAILED BranchStatus.red
); );
}); });
it('should return pending state for unknown result', async () => { it('should return yellow for unknown result', async () => {
expect(await getBranchStatus('unknown')).toEqual(BRANCH_STATUS_PENDING); expect(await getBranchStatus('unknown')).toEqual(BranchStatus.yellow);
}); });
it('should return pending state for pending result', async () => { it('should return pending state for pending result', async () => {
expect(await getBranchStatus('pending')).toEqual(BRANCH_STATUS_PENDING); expect(await getBranchStatus('pending')).toEqual(BranchStatus.yellow);
}); });
it('should return success state for success result', async () => { it('should return success state for success result', async () => {
expect(await getBranchStatus('success')).toEqual(BRANCH_STATUS_SUCCESS); expect(await getBranchStatus('success')).toEqual(BranchStatus.green);
}); });
it('should return failed state for all other results', async () => { it('should return null for all other results', async () => {
expect(await getBranchStatus('invalid')).toEqual(BRANCH_STATUS_FAILED); expect(await getBranchStatus('invalid')).toEqual(BranchStatus.yellow);
}); });
it('should abort when branch status returns 404', async () => { it('should abort when branch status returns 404', async () => {
@ -515,8 +510,23 @@ describe('platform/gitea', () => {
await gitea.getBranchStatusCheck('some-branch', 'some-context') await gitea.getBranchStatusCheck('some-branch', 'some-context')
).toBeNull(); ).toBeNull();
}); });
it('should return yellow with unknown status', async () => {
helper.getCombinedCommitStatus.mockResolvedValueOnce(
partial<ght.CombinedCommitStatus>({
statuses: [
partial<ght.CommitStatus>({
context: 'some-context',
}),
],
})
);
it('should return status of matching result', async () => { expect(
await gitea.getBranchStatusCheck('some-branch', 'some-context')
).toEqual(BranchStatus.yellow);
});
it('should return green of matching result', async () => {
helper.getCombinedCommitStatus.mockResolvedValueOnce( helper.getCombinedCommitStatus.mockResolvedValueOnce(
partial<ght.CombinedCommitStatus>({ partial<ght.CombinedCommitStatus>({
statuses: [ statuses: [
@ -530,7 +540,7 @@ describe('platform/gitea', () => {
expect( expect(
await gitea.getBranchStatusCheck('some-branch', 'some-context') await gitea.getBranchStatusCheck('some-branch', 'some-context')
).toEqual('success'); ).toEqual(BranchStatus.green);
}); });
}); });

View file

@ -2,7 +2,6 @@ import URL from 'url';
import GitStorage, { CommitFilesConfig, StatusResult } from '../git/storage'; import GitStorage, { CommitFilesConfig, StatusResult } from '../git/storage';
import * as hostRules from '../../util/host-rules'; import * as hostRules from '../../util/host-rules';
import { import {
BranchStatus,
BranchStatusConfig, BranchStatusConfig,
CreatePRConfig, CreatePRConfig,
EnsureCommentConfig, EnsureCommentConfig,
@ -32,11 +31,7 @@ import { RenovateConfig } from '../../config';
import { configFileNames } from '../../config/app-strings'; import { configFileNames } from '../../config/app-strings';
import { smartTruncate } from '../utils/pr-body'; import { smartTruncate } from '../utils/pr-body';
import { sanitize } from '../../util/sanitize'; import { sanitize } from '../../util/sanitize';
import { import { BranchStatus } from '../../types';
BRANCH_STATUS_FAILED,
BRANCH_STATUS_PENDING,
BRANCH_STATUS_SUCCESS,
} from '../../constants/branch-constants';
import * as helper from './gitea-helper'; import * as helper from './gitea-helper';
import { PR_STATE_ALL, PR_STATE_OPEN } from '../../constants/pull-requests'; import { PR_STATE_ALL, PR_STATE_OPEN } from '../../constants/pull-requests';
@ -360,7 +355,7 @@ const platform: Platform = {
// Create new status for branch commit // Create new status for branch commit
const branchCommit = await config.storage.getBranchCommit(branchName); const branchCommit = await config.storage.getBranchCommit(branchName);
await helper.createCommitStatus(config.repository, branchCommit, { await helper.createCommitStatus(config.repository, branchCommit, {
state: state ? (state as helper.CommitStatusType) : 'pending', state: helper.renovateToGiteaStatusMapping[state] || 'pending',
context, context,
description, description,
...(target_url && { target_url }), ...(target_url && { target_url }),
@ -380,12 +375,12 @@ const platform: Platform = {
requiredStatusChecks?: string[] | null requiredStatusChecks?: string[] | null
): Promise<BranchStatus> { ): Promise<BranchStatus> {
if (!requiredStatusChecks) { if (!requiredStatusChecks) {
return BRANCH_STATUS_SUCCESS; return BranchStatus.green;
} }
if (Array.isArray(requiredStatusChecks) && requiredStatusChecks.length) { if (Array.isArray(requiredStatusChecks) && requiredStatusChecks.length) {
logger.warn({ requiredStatusChecks }, 'Unsupported requiredStatusChecks'); logger.warn({ requiredStatusChecks }, 'Unsupported requiredStatusChecks');
return BRANCH_STATUS_FAILED; return BranchStatus.red;
} }
let ccs: helper.CombinedCommitStatus; let ccs: helper.CombinedCommitStatus;
@ -404,28 +399,29 @@ const platform: Platform = {
} }
logger.debug({ ccs }, 'Branch status check result'); logger.debug({ ccs }, 'Branch status check result');
switch (ccs.worstStatus) { return (
case 'unknown': helper.giteaToRenovateStatusMapping[ccs.worstStatus] ||
case 'pending': BranchStatus.yellow
return BRANCH_STATUS_PENDING; );
case 'success':
return BRANCH_STATUS_SUCCESS;
default:
return BRANCH_STATUS_FAILED;
}
}, },
async getBranchStatusCheck( async getBranchStatusCheck(
branchName: string, branchName: string,
context: string context: string
): Promise<string> { ): Promise<BranchStatus | null> {
const ccs = await helper.getCombinedCommitStatus( const ccs = await helper.getCombinedCommitStatus(
config.repository, config.repository,
branchName branchName
); );
const cs = ccs.statuses.find(s => s.context === context); const cs = ccs.statuses.find(s => s.context === context);
if (!cs) return null; // no status check exists
return cs ? cs.status : null; const status = helper.giteaToRenovateStatusMapping[cs.status];
if (status) return status;
logger.warn(
{ check: cs },
'Could not map Gitea status value to Renovate status'
);
return BranchStatus.yellow;
}, },
async setBaseBranch( async setBaseBranch(

View file

@ -72,7 +72,7 @@ Array [
"body": Object { "body": Object {
"context": "renovate/verify", "context": "renovate/verify",
"description": "Renovate verified pull request", "description": "Renovate verified pull request",
"state": "success", "state": "green",
"target_url": "https://github.com/renovatebot/renovate", "target_url": "https://github.com/renovatebot/renovate",
}, },
}, },

View file

@ -5,11 +5,7 @@ import {
REPOSITORY_NOT_FOUND, REPOSITORY_NOT_FOUND,
REPOSITORY_RENAMED, REPOSITORY_RENAMED,
} from '../../constants/error-messages'; } from '../../constants/error-messages';
import { import { BranchStatus } from '../../types';
BRANCH_STATUS_FAILED,
BRANCH_STATUS_PENDING,
BRANCH_STATUS_SUCCESS,
} from '../../constants/branch-constants';
import { mocked } from '../../../test/util'; import { mocked } from '../../../test/util';
describe('platform/github', () => { describe('platform/github', () => {
@ -612,14 +608,14 @@ describe('platform/github', () => {
repository: 'some/repo', repository: 'some/repo',
}); });
const res = await github.getBranchStatus('somebranch', null); const res = await github.getBranchStatus('somebranch', null);
expect(res).toEqual(BRANCH_STATUS_SUCCESS); expect(res).toEqual(BranchStatus.green);
}); });
it('return failed if unsupported requiredStatusChecks', async () => { it('return failed if unsupported requiredStatusChecks', async () => {
await initRepo({ await initRepo({
repository: 'some/repo', repository: 'some/repo',
}); });
const res = await github.getBranchStatus('somebranch', ['foo']); const res = await github.getBranchStatus('somebranch', ['foo']);
expect(res).toEqual(BRANCH_STATUS_FAILED); expect(res).toEqual(BranchStatus.red);
}); });
it('should pass through success', async () => { it('should pass through success', async () => {
await initRepo({ await initRepo({
@ -634,7 +630,7 @@ describe('platform/github', () => {
} as any) } as any)
); );
const res = await github.getBranchStatus('somebranch', []); const res = await github.getBranchStatus('somebranch', []);
expect(res).toEqual(BRANCH_STATUS_SUCCESS); expect(res).toEqual(BranchStatus.green);
}); });
it('should pass through failed', async () => { it('should pass through failed', async () => {
await initRepo({ await initRepo({
@ -649,7 +645,22 @@ describe('platform/github', () => {
} as any) } as any)
); );
const res = await github.getBranchStatus('somebranch', []); const res = await github.getBranchStatus('somebranch', []);
expect(res).toEqual(BRANCH_STATUS_FAILED); expect(res).toEqual(BranchStatus.red);
});
it('defaults to pending', async () => {
await initRepo({
repository: 'some/repo',
});
api.get.mockImplementationOnce(
() =>
({
body: {
state: 'unknown',
},
} as any)
);
const res = await github.getBranchStatus('somebranch', []);
expect(res).toEqual(BranchStatus.yellow);
}); });
it('should fail if a check run has failed', async () => { it('should fail if a check run has failed', async () => {
await initRepo({ await initRepo({
@ -687,7 +698,7 @@ describe('platform/github', () => {
} as any) } as any)
); );
const res = await github.getBranchStatus('somebranch', []); const res = await github.getBranchStatus('somebranch', []);
expect(res).toEqual(BRANCH_STATUS_FAILED); expect(res).toEqual(BranchStatus.red);
}); });
it('should suceed if no status and all passed check runs', async () => { it('should suceed if no status and all passed check runs', async () => {
await initRepo({ await initRepo({
@ -725,7 +736,7 @@ describe('platform/github', () => {
} as any) } as any)
); );
const res = await github.getBranchStatus('somebranch', []); const res = await github.getBranchStatus('somebranch', []);
expect(res).toEqual(BRANCH_STATUS_SUCCESS); expect(res).toEqual(BranchStatus.green);
}); });
it('should fail if a check run has failed', async () => { it('should fail if a check run has failed', async () => {
await initRepo({ await initRepo({
@ -762,7 +773,7 @@ describe('platform/github', () => {
} as any) } as any)
); );
const res = await github.getBranchStatus('somebranch', []); const res = await github.getBranchStatus('somebranch', []);
expect(res).toEqual(BRANCH_STATUS_PENDING); expect(res).toEqual(BranchStatus.yellow);
}); });
}); });
describe('getBranchStatusCheck', () => { describe('getBranchStatusCheck', () => {
@ -777,15 +788,15 @@ describe('platform/github', () => {
body: [ body: [
{ {
context: 'context-1', context: 'context-1',
state: 'state-1', state: 'success',
}, },
{ {
context: 'context-2', context: 'context-2',
state: 'state-2', state: 'pending',
}, },
{ {
context: 'context-3', context: 'context-3',
state: 'state-3', state: 'failed',
}, },
], ],
} as any) } as any)
@ -794,7 +805,7 @@ describe('platform/github', () => {
'renovate/future_branch', 'renovate/future_branch',
'context-2' 'context-2'
); );
expect(res).toEqual('state-2'); expect(res).toEqual(BranchStatus.yellow);
}); });
it('returns null', async () => { it('returns null', async () => {
await initRepo({ await initRepo({
@ -806,15 +817,15 @@ describe('platform/github', () => {
body: [ body: [
{ {
context: 'context-1', context: 'context-1',
state: 'state-1', state: 'success',
}, },
{ {
context: 'context-2', context: 'context-2',
state: 'state-2', state: 'pending',
}, },
{ {
context: 'context-3', context: 'context-3',
state: 'state-3', state: 'failed',
}, },
], ],
} as any) } as any)
@ -834,7 +845,7 @@ describe('platform/github', () => {
body: [ body: [
{ {
context: 'some-context', context: 'some-context',
state: 'some-state', state: 'pending',
}, },
], ],
} as any) } as any)
@ -843,7 +854,7 @@ describe('platform/github', () => {
branchName: 'some-branch', branchName: 'some-branch',
context: 'some-context', context: 'some-context',
description: 'some-description', description: 'some-description',
state: 'some-state', state: BranchStatus.yellow,
url: 'some-url', url: 'some-url',
}); });
expect(api.post).toHaveBeenCalledTimes(0); expect(api.post).toHaveBeenCalledTimes(0);
@ -892,7 +903,7 @@ describe('platform/github', () => {
branchName: 'some-branch', branchName: 'some-branch',
context: 'some-context', context: 'some-context',
description: 'some-description', description: 'some-description',
state: 'some-state', state: BranchStatus.green,
url: 'some-url', url: 'some-url',
}); });
expect(api.post).toHaveBeenCalledTimes(1); expect(api.post).toHaveBeenCalledTimes(1);

View file

@ -19,7 +19,6 @@ import {
FindPRConfig, FindPRConfig,
EnsureCommentConfig, EnsureCommentConfig,
EnsureIssueResult, EnsureIssueResult,
BranchStatus,
} from '../common'; } from '../common';
import { configFileNames } from '../../config/app-strings'; import { configFileNames } from '../../config/app-strings';
@ -41,11 +40,7 @@ import {
REPOSITORY_RENAMED, REPOSITORY_RENAMED,
} from '../../constants/error-messages'; } from '../../constants/error-messages';
import { PLATFORM_TYPE_GITHUB } from '../../constants/platforms'; import { PLATFORM_TYPE_GITHUB } from '../../constants/platforms';
import { import { BranchStatus } from '../../types';
BRANCH_STATUS_FAILED,
BRANCH_STATUS_PENDING,
BRANCH_STATUS_SUCCESS,
} from '../../constants/branch-constants';
import { import {
PR_STATE_ALL, PR_STATE_ALL,
PR_STATE_CLOSED, PR_STATE_CLOSED,
@ -1095,12 +1090,12 @@ export async function getBranchStatus(
if (!requiredStatusChecks) { if (!requiredStatusChecks) {
// null means disable status checks, so it always succeeds // null means disable status checks, so it always succeeds
logger.debug('Status checks disabled = returning "success"'); logger.debug('Status checks disabled = returning "success"');
return BRANCH_STATUS_SUCCESS; return BranchStatus.green;
} }
if (requiredStatusChecks.length) { if (requiredStatusChecks.length) {
// This is Unsupported // This is Unsupported
logger.warn({ requiredStatusChecks }, `Unsupported requiredStatusChecks`); logger.warn({ requiredStatusChecks }, `Unsupported requiredStatusChecks`);
return BRANCH_STATUS_FAILED; return BranchStatus.red;
} }
let commitStatus; let commitStatus;
try { try {
@ -1159,21 +1154,27 @@ export async function getBranchStatus(
} }
} }
if (checkRuns.length === 0) { if (checkRuns.length === 0) {
return commitStatus.state; if (commitStatus.state === 'success') {
return BranchStatus.green;
}
if (commitStatus.state === 'failed') {
return BranchStatus.red;
}
return BranchStatus.yellow;
} }
if ( if (
commitStatus.state === 'failed' || commitStatus.state === 'failed' ||
checkRuns.some(run => run.conclusion === 'failed') checkRuns.some(run => run.conclusion === 'failed')
) { ) {
return BRANCH_STATUS_FAILED; return BranchStatus.red;
} }
if ( if (
(commitStatus.state === 'success' || commitStatus.statuses.length === 0) && (commitStatus.state === 'success' || commitStatus.statuses.length === 0) &&
checkRuns.every(run => ['neutral', 'success'].includes(run.conclusion)) checkRuns.every(run => ['neutral', 'success'].includes(run.conclusion))
) { ) {
return BRANCH_STATUS_SUCCESS; return BranchStatus.green;
} }
return BRANCH_STATUS_PENDING; return BranchStatus.yellow;
} }
async function getStatusCheck( async function getStatusCheck(
@ -1187,15 +1188,23 @@ async function getStatusCheck(
return (await api.get(url, { useCache })).body; return (await api.get(url, { useCache })).body;
} }
const githubToRenovateStatusMapping = {
success: BranchStatus.green,
failed: BranchStatus.red,
pending: BranchStatus.yellow,
};
export async function getBranchStatusCheck( export async function getBranchStatusCheck(
branchName: string, branchName: string,
context: string context: string
): Promise<string> { ): Promise<BranchStatus | null> {
try { try {
const res = await getStatusCheck(branchName); const res = await getStatusCheck(branchName);
for (const check of res) { for (const check of res) {
if (check.context === context) { if (check.context === context) {
return check.state; return (
githubToRenovateStatusMapping[check.state] || BranchStatus.yellow
);
} }
} }
return null; return null;
@ -1696,7 +1705,7 @@ export async function createPr({
branchName, branchName,
context: `renovate/verify`, context: `renovate/verify`,
description: `Renovate verified pull request`, description: `Renovate verified pull request`,
state: BRANCH_STATUS_SUCCESS, state: BranchStatus.green,
url: 'https://github.com/renovatebot/renovate', url: 'https://github.com/renovatebot/renovate',
}); });
} }

View file

@ -10,12 +10,7 @@ import {
PR_STATE_NOT_OPEN, PR_STATE_NOT_OPEN,
PR_STATE_OPEN, PR_STATE_OPEN,
} from '../../constants/pull-requests'; } from '../../constants/pull-requests';
import { import { BranchStatus } from '../../types';
BRANCH_STATUS_FAILED,
BRANCH_STATUS_FAILURE,
BRANCH_STATUS_PENDING,
BRANCH_STATUS_SUCCESS,
} from '../../constants/branch-constants';
import { GotResponse, Platform } from '..'; import { GotResponse, Platform } from '..';
import { partial } from '../../../test/util'; import { partial } from '../../../test/util';
@ -438,11 +433,11 @@ describe('platform/gitlab', () => {
describe('getBranchStatus(branchName, requiredStatusChecks)', () => { describe('getBranchStatus(branchName, requiredStatusChecks)', () => {
it('returns success if requiredStatusChecks null', async () => { it('returns success if requiredStatusChecks null', async () => {
const res = await gitlab.getBranchStatus('somebranch', null); const res = await gitlab.getBranchStatus('somebranch', null);
expect(res).toEqual(BRANCH_STATUS_SUCCESS); expect(res).toEqual(BranchStatus.green);
}); });
it('return failed if unsupported requiredStatusChecks', async () => { it('return failed if unsupported requiredStatusChecks', async () => {
const res = await gitlab.getBranchStatus('somebranch', ['foo']); const res = await gitlab.getBranchStatus('somebranch', ['foo']);
expect(res).toEqual(BRANCH_STATUS_FAILED); expect(res).toEqual(BranchStatus.red);
}); });
it('returns pending if no results', async () => { it('returns pending if no results', async () => {
await initRepo(); await initRepo();
@ -452,7 +447,7 @@ describe('platform/gitlab', () => {
}) })
); );
const res = await gitlab.getBranchStatus('somebranch', []); const res = await gitlab.getBranchStatus('somebranch', []);
expect(res).toEqual(BRANCH_STATUS_PENDING); expect(res).toEqual(BranchStatus.yellow);
}); });
it('returns success if all are success', async () => { it('returns success if all are success', async () => {
await initRepo(); await initRepo();
@ -462,7 +457,7 @@ describe('platform/gitlab', () => {
}) })
); );
const res = await gitlab.getBranchStatus('somebranch', []); const res = await gitlab.getBranchStatus('somebranch', []);
expect(res).toEqual(BRANCH_STATUS_SUCCESS); expect(res).toEqual(BranchStatus.green);
}); });
it('returns success if optional jobs fail', async () => { it('returns success if optional jobs fail', async () => {
await initRepo(); await initRepo();
@ -475,7 +470,17 @@ describe('platform/gitlab', () => {
}) })
); );
const res = await gitlab.getBranchStatus('somebranch', []); const res = await gitlab.getBranchStatus('somebranch', []);
expect(res).toEqual(BRANCH_STATUS_SUCCESS); expect(res).toEqual(BranchStatus.green);
});
it('returns success if all are optional', async () => {
await initRepo();
api.get.mockResolvedValueOnce(
partial<GotResponse>({
body: [{ status: 'failed', allow_failure: true }],
})
);
const res = await gitlab.getBranchStatus('somebranch', []);
expect(res).toEqual(BranchStatus.green);
}); });
it('returns failure if any mandatory jobs fails', async () => { it('returns failure if any mandatory jobs fails', async () => {
await initRepo(); await initRepo();
@ -489,9 +494,9 @@ describe('platform/gitlab', () => {
}) })
); );
const res = await gitlab.getBranchStatus('somebranch', []); const res = await gitlab.getBranchStatus('somebranch', []);
expect(res).toEqual(BRANCH_STATUS_FAILURE); expect(res).toEqual(BranchStatus.red);
}); });
it('returns custom statuses', async () => { it('maps custom statuses to yellow', async () => {
await initRepo(); await initRepo();
api.get.mockResolvedValueOnce( api.get.mockResolvedValueOnce(
partial<GotResponse>({ partial<GotResponse>({
@ -499,7 +504,7 @@ describe('platform/gitlab', () => {
}) })
); );
const res = await gitlab.getBranchStatus('somebranch', []); const res = await gitlab.getBranchStatus('somebranch', []);
expect(res).toEqual('foo'); expect(res).toEqual(BranchStatus.yellow);
}); });
it('throws repository-changed', async () => { it('throws repository-changed', async () => {
expect.assertions(1); expect.assertions(1);
@ -554,21 +559,24 @@ describe('platform/gitlab', () => {
'somebranch', 'somebranch',
'some-context' 'some-context'
); );
expect(res).toEqual(BRANCH_STATUS_SUCCESS); expect(res).toEqual(BranchStatus.green);
}); });
}); });
describe('setBranchStatus', () => { describe('setBranchStatus', () => {
it('sets branch status', async () => { it.each([BranchStatus.green, BranchStatus.yellow, BranchStatus.red])(
await initRepo(); 'sets branch status yellow',
await gitlab.setBranchStatus({ async state => {
branchName: 'some-branch', await initRepo();
context: 'some-context', await gitlab.setBranchStatus({
description: 'some-description', branchName: 'some-branch',
state: 'some-state', context: 'some-context',
url: 'some-url', description: 'some-description',
}); state,
expect(api.post).toHaveBeenCalledTimes(1); url: 'some-url',
}); });
expect(api.post).toHaveBeenCalledTimes(1);
}
);
}); });
describe('mergeBranch()', () => { describe('mergeBranch()', () => {
it('sends to gitFs', async () => { it('sends to gitFs', async () => {

View file

@ -17,7 +17,6 @@ import {
BranchStatusConfig, BranchStatusConfig,
FindPRConfig, FindPRConfig,
EnsureCommentConfig, EnsureCommentConfig,
BranchStatus,
} from '../common'; } from '../common';
import { configFileNames } from '../../config/app-strings'; import { configFileNames } from '../../config/app-strings';
import { logger } from '../../logger'; import { logger } from '../../logger';
@ -36,12 +35,7 @@ import {
} from '../../constants/error-messages'; } from '../../constants/error-messages';
import { PR_STATE_ALL, PR_STATE_OPEN } from '../../constants/pull-requests'; import { PR_STATE_ALL, PR_STATE_OPEN } from '../../constants/pull-requests';
import { PLATFORM_TYPE_GITLAB } from '../../constants/platforms'; import { PLATFORM_TYPE_GITLAB } from '../../constants/platforms';
import { import { BranchStatus } from '../../types';
BRANCH_STATUS_FAILED,
BRANCH_STATUS_FAILURE,
BRANCH_STATUS_PENDING,
BRANCH_STATUS_SUCCESS,
} from '../../constants/branch-constants';
type MergeMethod = 'merge' | 'rebase_merge' | 'ff'; type MergeMethod = 'merge' | 'rebase_merge' | 'ff';
const defaultConfigFile = configFileNames[0]; const defaultConfigFile = configFileNames[0];
@ -315,6 +309,14 @@ async function getStatus(
return (await api.get(url, { paginate: true, useCache })).body; return (await api.get(url, { paginate: true, useCache })).body;
} }
const gitlabToRenovateStatusMapping: Record<string, BranchStatus> = {
pending: BranchStatus.yellow,
running: BranchStatus.yellow,
success: BranchStatus.green,
failed: BranchStatus.red,
canceled: BranchStatus.red,
};
// Returns the combined status for a branch. // Returns the combined status for a branch.
export async function getBranchStatus( export async function getBranchStatus(
branchName: string, branchName: string,
@ -323,12 +325,12 @@ export async function getBranchStatus(
logger.debug(`getBranchStatus(${branchName})`); logger.debug(`getBranchStatus(${branchName})`);
if (!requiredStatusChecks) { if (!requiredStatusChecks) {
// null means disable status checks, so it always succeeds // null means disable status checks, so it always succeeds
return BRANCH_STATUS_SUCCESS; return BranchStatus.green;
} }
if (Array.isArray(requiredStatusChecks) && requiredStatusChecks.length) { if (Array.isArray(requiredStatusChecks) && requiredStatusChecks.length) {
// This is Unsupported // This is Unsupported
logger.warn({ requiredStatusChecks }, `Unsupported requiredStatusChecks`); logger.warn({ requiredStatusChecks }, `Unsupported requiredStatusChecks`);
return BRANCH_STATUS_FAILED; return BranchStatus.red;
} }
if (!(await branchExists(branchName))) { if (!(await branchExists(branchName))) {
@ -339,22 +341,29 @@ export async function getBranchStatus(
logger.debug(`Got res with ${res.length} results`); logger.debug(`Got res with ${res.length} results`);
if (res.length === 0) { if (res.length === 0) {
// Return 'pending' if we have no status checks // Return 'pending' if we have no status checks
return BRANCH_STATUS_PENDING; return BranchStatus.yellow;
} }
let status: BranchStatus = BRANCH_STATUS_SUCCESS; let status: BranchStatus = BranchStatus.green; // default to green
// Return 'success' if all are success res
res.forEach(check => { .filter(check => !check.allow_failure)
// If one is failed then don't overwrite that .forEach(check => {
if (status !== 'failure') { if (status !== BranchStatus.red) {
if (!check.allow_failure) { // if red, stay red
if (check.status === 'failed' || check.status === 'canceled') { let mappedStatus: BranchStatus =
status = BRANCH_STATUS_FAILURE; gitlabToRenovateStatusMapping[check.status];
} else if (check.status !== 'success') { if (!mappedStatus) {
({ status } = check); logger.warn(
{ check },
'Could not map GitLab check.status to Renovate status'
);
mappedStatus = BranchStatus.yellow;
}
if (mappedStatus !== BranchStatus.green) {
logger.trace({ check }, 'Found non-green check');
status = mappedStatus;
} }
} }
} });
});
return status; return status;
} }
@ -430,7 +439,7 @@ export async function getPr(iid: number): Promise<Pr> {
pr.isConflicted = true; pr.isConflicted = true;
} else if (pr.state === PR_STATE_OPEN) { } else if (pr.state === PR_STATE_OPEN) {
const branchStatus = await getBranchStatus(pr.branchName, []); const branchStatus = await getBranchStatus(pr.branchName, []);
if (branchStatus === BRANCH_STATUS_SUCCESS) { if (branchStatus === BranchStatus.green) {
pr.canMerge = true; pr.canMerge = true;
} }
} }
@ -623,13 +632,13 @@ export function getRepoStatus(): Promise<StatusResult> {
export async function getBranchStatusCheck( export async function getBranchStatusCheck(
branchName: string, branchName: string,
context: string context: string
): Promise<string | null> { ): Promise<BranchStatus | null> {
// cache-bust in case we have rebased // cache-bust in case we have rebased
const res = await getStatus(branchName, false); const res = await getStatus(branchName, false);
logger.debug(`Got res with ${res.length} results`); logger.debug(`Got res with ${res.length} results`);
for (const check of res) { for (const check of res) {
if (check.name === context) { if (check.name === context) {
return check.status; return gitlabToRenovateStatusMapping[check.status] || BranchStatus.yellow;
} }
} }
return null; return null;
@ -639,15 +648,21 @@ export async function setBranchStatus({
branchName, branchName,
context, context,
description, description,
state, state: renovateState,
url: targetUrl, url: targetUrl,
}: BranchStatusConfig): Promise<void> { }: BranchStatusConfig): Promise<void> {
// First, get the branch commit SHA // First, get the branch commit SHA
const branchSha = await config.storage.getBranchCommit(branchName); const branchSha = await config.storage.getBranchCommit(branchName);
// Now, check the statuses for that commit // Now, check the statuses for that commit
const url = `projects/${config.repository}/statuses/${branchSha}`; const url = `projects/${config.repository}/statuses/${branchSha}`;
let state = 'success';
if (renovateState === BranchStatus.yellow) {
state = 'pending';
} else if (renovateState === BranchStatus.red) {
state = 'failed';
}
const options: any = { const options: any = {
state: state.replace('failure', 'failed'), // GitLab uses 'failed', not 'failure' state,
description, description,
context, context,
}; };

View file

@ -0,0 +1,5 @@
export enum BranchStatus {
green = 'green', // 'success'
yellow = 'yellow', // 'created', 'running'
red = 'red', // 'error', 'failed'
}

View file

@ -1,2 +1,3 @@
export * from './host-rules'; export * from './host-rules';
export * from './versioning'; export * from './versioning';
export * from './branch-status';

View file

@ -1,11 +1,7 @@
import { tryBranchAutomerge } from './automerge'; import { tryBranchAutomerge } from './automerge';
import { defaultConfig, platform } from '../../../test/util'; import { defaultConfig, platform } from '../../../test/util';
import { RenovateConfig } from '../../config'; import { RenovateConfig } from '../../config';
import { import { BranchStatus } from '../../types';
BRANCH_STATUS_FAILURE,
BRANCH_STATUS_PENDING,
BRANCH_STATUS_SUCCESS,
} from '../../constants/branch-constants';
describe('workers/branch/automerge', () => { describe('workers/branch/automerge', () => {
describe('tryBranchAutomerge', () => { describe('tryBranchAutomerge', () => {
@ -27,20 +23,20 @@ describe('workers/branch/automerge', () => {
it('returns false if branch status is not success', async () => { it('returns false if branch status is not success', async () => {
config.automerge = true; config.automerge = true;
config.automergeType = 'branch'; config.automergeType = 'branch';
platform.getBranchStatus.mockResolvedValueOnce(BRANCH_STATUS_PENDING); platform.getBranchStatus.mockResolvedValueOnce(BranchStatus.yellow);
expect(await tryBranchAutomerge(config)).toBe('no automerge'); expect(await tryBranchAutomerge(config)).toBe('no automerge');
}); });
it('returns branch status error if branch status is failure', async () => { it('returns branch status error if branch status is failure', async () => {
config.automerge = true; config.automerge = true;
config.automergeType = 'branch'; config.automergeType = 'branch';
platform.getBranchStatus.mockResolvedValueOnce(BRANCH_STATUS_FAILURE); platform.getBranchStatus.mockResolvedValueOnce(BranchStatus.red);
expect(await tryBranchAutomerge(config)).toBe('branch status error'); expect(await tryBranchAutomerge(config)).toBe('branch status error');
}); });
it('returns false if PR exists', async () => { it('returns false if PR exists', async () => {
platform.getBranchPr.mockResolvedValueOnce({} as never); platform.getBranchPr.mockResolvedValueOnce({} as never);
config.automerge = true; config.automerge = true;
config.automergeType = 'branch'; config.automergeType = 'branch';
platform.getBranchStatus.mockResolvedValueOnce(BRANCH_STATUS_SUCCESS); platform.getBranchStatus.mockResolvedValueOnce(BranchStatus.green);
expect(await tryBranchAutomerge(config)).toBe( expect(await tryBranchAutomerge(config)).toBe(
'automerge aborted - PR exists' 'automerge aborted - PR exists'
); );
@ -48,7 +44,7 @@ describe('workers/branch/automerge', () => {
it('returns false if automerge fails', async () => { it('returns false if automerge fails', async () => {
config.automerge = true; config.automerge = true;
config.automergeType = 'branch'; config.automergeType = 'branch';
platform.getBranchStatus.mockResolvedValueOnce(BRANCH_STATUS_SUCCESS); platform.getBranchStatus.mockResolvedValueOnce(BranchStatus.green);
platform.mergeBranch.mockImplementationOnce(() => { platform.mergeBranch.mockImplementationOnce(() => {
throw new Error('merge error'); throw new Error('merge error');
}); });
@ -57,14 +53,14 @@ describe('workers/branch/automerge', () => {
it('returns true if automerge succeeds', async () => { it('returns true if automerge succeeds', async () => {
config.automerge = true; config.automerge = true;
config.automergeType = 'branch'; config.automergeType = 'branch';
platform.getBranchStatus.mockResolvedValueOnce(BRANCH_STATUS_SUCCESS); platform.getBranchStatus.mockResolvedValueOnce(BranchStatus.green);
expect(await tryBranchAutomerge(config)).toBe('automerged'); expect(await tryBranchAutomerge(config)).toBe('automerged');
}); });
it('returns true if automerge succeeds (dry-run)', async () => { it('returns true if automerge succeeds (dry-run)', async () => {
config.automerge = true; config.automerge = true;
config.automergeType = 'branch'; config.automergeType = 'branch';
config.dryRun = true; config.dryRun = true;
platform.getBranchStatus.mockResolvedValueOnce(BRANCH_STATUS_SUCCESS); platform.getBranchStatus.mockResolvedValueOnce(BranchStatus.green);
expect(await tryBranchAutomerge(config)).toBe('automerged'); expect(await tryBranchAutomerge(config)).toBe('automerged');
}); });
}); });

View file

@ -1,11 +1,7 @@
import { logger } from '../../logger'; import { logger } from '../../logger';
import { RenovateConfig } from '../../config'; import { RenovateConfig } from '../../config';
import { platform } from '../../platform'; import { platform } from '../../platform';
import { import { BranchStatus } from '../../types';
BRANCH_STATUS_ERROR,
BRANCH_STATUS_FAILURE,
BRANCH_STATUS_SUCCESS,
} from '../../constants/branch-constants';
export type AutomergeResult = export type AutomergeResult =
| 'automerged' | 'automerged'
@ -30,7 +26,7 @@ export async function tryBranchAutomerge(
config.branchName, config.branchName,
config.requiredStatusChecks config.requiredStatusChecks
); );
if (branchStatus === BRANCH_STATUS_SUCCESS) { if (branchStatus === BranchStatus.green) {
logger.debug(`Automerging branch`); logger.debug(`Automerging branch`);
try { try {
if (config.dryRun) if (config.dryRun)
@ -47,9 +43,7 @@ export async function tryBranchAutomerge(
logger.info({ err }, `Failed to automerge branch`); logger.info({ err }, `Failed to automerge branch`);
return 'failed'; return 'failed';
} }
} else if ( } else if (branchStatus === BranchStatus.red) {
[BRANCH_STATUS_FAILURE, BRANCH_STATUS_ERROR].includes(branchStatus)
) {
return 'branch status error'; return 'branch status error';
} else { } else {
logger.debug(`Branch status is "${branchStatus}" - skipping automerge`); logger.debug(`Branch status is "${branchStatus}" - skipping automerge`);

View file

@ -21,7 +21,6 @@ import {
PR_STATE_MERGED, PR_STATE_MERGED,
PR_STATE_OPEN, PR_STATE_OPEN,
} from '../../constants/pull-requests'; } from '../../constants/pull-requests';
import { BRANCH_STATUS_PENDING } from '../../constants/branch-constants';
import { StatusResult } from '../../platform/git/storage'; import { StatusResult } from '../../platform/git/storage';
jest.mock('./get-updated'); jest.mock('./get-updated');
@ -94,7 +93,7 @@ describe('workers/branch', () => {
config.prCreation = 'not-pending'; config.prCreation = 'not-pending';
platform.branchExists.mockResolvedValueOnce(true); platform.branchExists.mockResolvedValueOnce(true);
const res = await branchWorker.processBranch(config); const res = await branchWorker.processBranch(config);
expect(res).toEqual(BRANCH_STATUS_PENDING); expect(res).toEqual('pending');
}); });
it('skips branch if not stabilityDays not met', async () => { it('skips branch if not stabilityDays not met', async () => {
schedule.isScheduledNow.mockReturnValueOnce(true); schedule.isScheduledNow.mockReturnValueOnce(true);
@ -106,7 +105,7 @@ describe('workers/branch', () => {
} as never, } as never,
]; ];
const res = await branchWorker.processBranch(config); const res = await branchWorker.processBranch(config);
expect(res).toEqual(BRANCH_STATUS_PENDING); expect(res).toEqual('pending');
}); });
it('processes branch if not scheduled but updating out of schedule', async () => { it('processes branch if not scheduled but updating out of schedule', async () => {
schedule.isScheduledNow.mockReturnValueOnce(false); schedule.isScheduledNow.mockReturnValueOnce(false);
@ -310,9 +309,7 @@ describe('workers/branch', () => {
commit.commitFilesToBranch.mockResolvedValueOnce(null); commit.commitFilesToBranch.mockResolvedValueOnce(null);
automerge.tryBranchAutomerge.mockResolvedValueOnce('failed'); automerge.tryBranchAutomerge.mockResolvedValueOnce('failed');
prWorker.ensurePr.mockResolvedValueOnce('pending'); prWorker.ensurePr.mockResolvedValueOnce('pending');
expect(await branchWorker.processBranch(config)).toEqual( expect(await branchWorker.processBranch(config)).toEqual('pending');
BRANCH_STATUS_PENDING
);
}); });
it('returns if branch exists but updated', async () => { it('returns if branch exists but updated', async () => {
expect.assertions(3); expect.assertions(3);
@ -329,7 +326,7 @@ describe('workers/branch', () => {
requiredStatusChecks: null, requiredStatusChecks: null,
prCreation: 'not-pending', prCreation: 'not-pending',
}) })
).toEqual(BRANCH_STATUS_PENDING); ).toEqual('pending');
expect(automerge.tryBranchAutomerge).toHaveBeenCalledTimes(0); expect(automerge.tryBranchAutomerge).toHaveBeenCalledTimes(0);
expect(prWorker.ensurePr).toHaveBeenCalledTimes(0); expect(prWorker.ensurePr).toHaveBeenCalledTimes(0);

View file

@ -37,7 +37,7 @@ import {
PR_STATE_MERGED, PR_STATE_MERGED,
PR_STATE_OPEN, PR_STATE_OPEN,
} from '../../constants/pull-requests'; } from '../../constants/pull-requests';
import { BRANCH_STATUS_FAILURE } from '../../constants/branch-constants'; import { BranchStatus } from '../../types';
import { exec } from '../../util/exec'; import { exec } from '../../util/exec';
import { regEx } from '../../util/regex'; import { regEx } from '../../util/regex';
@ -607,7 +607,7 @@ export async function processBranch(
} }
const context = `renovate/artifacts`; const context = `renovate/artifacts`;
const description = 'Artifact file update failure'; const description = 'Artifact file update failure';
const state = BRANCH_STATUS_FAILURE; const state = BranchStatus.red;
const existingState = await platform.getBranchStatusCheck( const existingState = await platform.getBranchStatusCheck(
config.branchName, config.branchName,
context context

View file

@ -5,7 +5,7 @@ import {
UnpublishableConfig, UnpublishableConfig,
} from './status-checks'; } from './status-checks';
import { defaultConfig, platform } from '../../../test/util'; import { defaultConfig, platform } from '../../../test/util';
import { BRANCH_STATUS_SUCCESS } from '../../constants/branch-constants'; import { BranchStatus } from '../../types';
describe('workers/branch/status-checks', () => { describe('workers/branch/status-checks', () => {
describe('setStability', () => { describe('setStability', () => {
@ -23,14 +23,14 @@ describe('workers/branch/status-checks', () => {
await setStability(config); await setStability(config);
expect(platform.getBranchStatusCheck).toHaveBeenCalledTimes(0); expect(platform.getBranchStatusCheck).toHaveBeenCalledTimes(0);
}); });
it('sets status pending', async () => { it('sets status yellow', async () => {
config.stabilityStatus = 'pending'; config.stabilityStatus = BranchStatus.yellow;
await setStability(config); await setStability(config);
expect(platform.getBranchStatusCheck).toHaveBeenCalledTimes(1); expect(platform.getBranchStatusCheck).toHaveBeenCalledTimes(1);
expect(platform.setBranchStatus).toHaveBeenCalledTimes(1); expect(platform.setBranchStatus).toHaveBeenCalledTimes(1);
}); });
it('sets status success', async () => { it('sets status green', async () => {
config.stabilityStatus = 'success'; config.stabilityStatus = BranchStatus.green;
await setStability(config); await setStability(config);
expect(platform.getBranchStatusCheck).toHaveBeenCalledTimes(1); expect(platform.getBranchStatusCheck).toHaveBeenCalledTimes(1);
expect(platform.setBranchStatus).toHaveBeenCalledTimes(1); expect(platform.setBranchStatus).toHaveBeenCalledTimes(1);
@ -67,9 +67,7 @@ describe('workers/branch/status-checks', () => {
it('finds canBeUnpublished false and skips status', async () => { it('finds canBeUnpublished false and skips status', async () => {
config.unpublishSafe = true; config.unpublishSafe = true;
config.canBeUnpublished = false; config.canBeUnpublished = false;
platform.getBranchStatusCheck.mockResolvedValueOnce( platform.getBranchStatusCheck.mockResolvedValueOnce(BranchStatus.green);
BRANCH_STATUS_SUCCESS
);
await setUnpublishable(config); await setUnpublishable(config);
expect(platform.getBranchStatusCheck).toHaveBeenCalledTimes(1); expect(platform.getBranchStatusCheck).toHaveBeenCalledTimes(1);
expect(platform.setBranchStatus).toHaveBeenCalledTimes(0); expect(platform.setBranchStatus).toHaveBeenCalledTimes(0);

View file

@ -1,12 +1,13 @@
import { logger } from '../../logger'; import { logger } from '../../logger';
import { RenovateConfig } from '../../config'; import { RenovateConfig } from '../../config';
import { platform } from '../../platform'; import { platform } from '../../platform';
import { BranchStatus } from '../../types';
async function setStatusCheck( async function setStatusCheck(
branchName: string, branchName: string,
context: string, context: string,
description: string, description: string,
state: string, state: BranchStatus,
url: string url: string
): Promise<void> { ): Promise<void> {
const existingState = await platform.getBranchStatusCheck( const existingState = await platform.getBranchStatusCheck(
@ -29,7 +30,7 @@ async function setStatusCheck(
} }
export type StabilityConfig = RenovateConfig & { export type StabilityConfig = RenovateConfig & {
stabilityStatus?: string; stabilityStatus?: BranchStatus;
branchName: string; branchName: string;
}; };
@ -39,7 +40,7 @@ export async function setStability(config: StabilityConfig): Promise<void> {
} }
const context = `renovate/stability-days`; const context = `renovate/stability-days`;
const description = const description =
config.stabilityStatus === 'success' config.stabilityStatus === BranchStatus.green
? 'Updates have met stability days requirement' ? 'Updates have met stability days requirement'
: 'Updates have not met stability days requirement'; : 'Updates have not met stability days requirement';
await setStatusCheck( await setStatusCheck(
@ -65,7 +66,9 @@ export async function setUnpublishable(
} }
const context = `renovate/unpublish-safe`; const context = `renovate/unpublish-safe`;
// Set canBeUnpublished status check // Set canBeUnpublished status check
const state = config.canBeUnpublished ? 'pending' : 'success'; const state = config.canBeUnpublished
? BranchStatus.yellow
: BranchStatus.green;
const description = config.canBeUnpublished const description = config.canBeUnpublished
? 'Packages < 24 hours old can be unpublished' ? 'Packages < 24 hours old can be unpublished'
: 'Packages cannot be unpublished'; : 'Packages cannot be unpublished';

View file

@ -1,7 +1,7 @@
import { platform } from '../../../platform'; import { platform } from '../../../platform';
import { emojify } from '../../../util/emoji'; import { emojify } from '../../../util/emoji';
import { BranchConfig } from '../../common'; import { BranchConfig } from '../../common';
import { BRANCH_STATUS_FAILED } from '../../../constants/branch-constants'; import { BranchStatus } from '../../../types';
export async function getPrConfigDescription( export async function getPrConfigDescription(
config: BranchConfig config: BranchConfig
@ -31,7 +31,7 @@ export async function getPrConfigDescription(
config.requiredStatusChecks config.requiredStatusChecks
); );
// istanbul ignore if // istanbul ignore if
if (branchStatus === BRANCH_STATUS_FAILED) { if (branchStatus === BranchStatus.red) {
prBody += 'Disabled due to failing status checks.'; prBody += 'Disabled due to failing status checks.';
} else { } else {
prBody += 'Enabled.'; prBody += 'Enabled.';

View file

@ -3,11 +3,7 @@ import * as _changelogHelper from './changelog';
import { getConfig } from '../../config/defaults'; import { getConfig } from '../../config/defaults';
import { platform as _platform, Pr } from '../../platform'; import { platform as _platform, Pr } from '../../platform';
import { mocked } from '../../../test/util'; import { mocked } from '../../../test/util';
import { import { BranchStatus } from '../../types';
BRANCH_STATUS_FAILED,
BRANCH_STATUS_PENDING,
BRANCH_STATUS_SUCCESS,
} from '../../constants/branch-constants';
import { PLATFORM_TYPE_GITLAB } from '../../constants/platforms'; import { PLATFORM_TYPE_GITLAB } from '../../constants/platforms';
const changelogHelper = mocked(_changelogHelper); const changelogHelper = mocked(_changelogHelper);
@ -78,7 +74,7 @@ describe('workers/pr', () => {
it('should automerge if enabled and pr is mergeable', async () => { it('should automerge if enabled and pr is mergeable', async () => {
config.automerge = true; config.automerge = true;
pr.isModified = false; pr.isModified = false;
platform.getBranchStatus.mockResolvedValueOnce(BRANCH_STATUS_SUCCESS); platform.getBranchStatus.mockResolvedValueOnce(BranchStatus.green);
platform.mergePr.mockResolvedValueOnce(true); platform.mergePr.mockResolvedValueOnce(true);
await prWorker.checkAutoMerge(pr, config); await prWorker.checkAutoMerge(pr, config);
expect(platform.mergePr).toHaveBeenCalledTimes(1); expect(platform.mergePr).toHaveBeenCalledTimes(1);
@ -88,20 +84,20 @@ describe('workers/pr', () => {
config.automergeType = 'pr-comment'; config.automergeType = 'pr-comment';
config.automergeComment = '!merge'; config.automergeComment = '!merge';
pr.isModified = false; pr.isModified = false;
platform.getBranchStatus.mockResolvedValueOnce(BRANCH_STATUS_SUCCESS); platform.getBranchStatus.mockResolvedValueOnce(BranchStatus.green);
await prWorker.checkAutoMerge(pr, config); await prWorker.checkAutoMerge(pr, config);
expect(platform.ensureComment).toHaveBeenCalledTimes(1); expect(platform.ensureComment).toHaveBeenCalledTimes(1);
}); });
it('should not automerge if enabled and pr is mergeable but cannot rebase', async () => { it('should not automerge if enabled and pr is mergeable but cannot rebase', async () => {
config.automerge = true; config.automerge = true;
pr.isModified = true; pr.isModified = true;
platform.getBranchStatus.mockResolvedValueOnce(BRANCH_STATUS_SUCCESS); platform.getBranchStatus.mockResolvedValueOnce(BranchStatus.green);
await prWorker.checkAutoMerge(pr, config); await prWorker.checkAutoMerge(pr, config);
expect(platform.mergePr).toHaveBeenCalledTimes(0); expect(platform.mergePr).toHaveBeenCalledTimes(0);
}); });
it('should not automerge if enabled and pr is mergeable but branch status is not success', async () => { it('should not automerge if enabled and pr is mergeable but branch status is not success', async () => {
config.automerge = true; config.automerge = true;
platform.getBranchStatus.mockResolvedValueOnce(BRANCH_STATUS_PENDING); platform.getBranchStatus.mockResolvedValueOnce(BranchStatus.yellow);
await prWorker.checkAutoMerge(pr, config); await prWorker.checkAutoMerge(pr, config);
expect(platform.mergePr).toHaveBeenCalledTimes(0); expect(platform.mergePr).toHaveBeenCalledTimes(0);
}); });
@ -167,19 +163,19 @@ describe('workers/pr', () => {
expect(pr).toBeNull(); expect(pr).toBeNull();
}); });
it('should return null if waiting for success', async () => { it('should return null if waiting for success', async () => {
platform.getBranchStatus.mockResolvedValueOnce(BRANCH_STATUS_FAILED); platform.getBranchStatus.mockResolvedValueOnce(BranchStatus.red);
config.prCreation = 'status-success'; config.prCreation = 'status-success';
const pr = await prWorker.ensurePr(config); const pr = await prWorker.ensurePr(config);
expect(pr).toEqual('pending'); expect(pr).toEqual('pending');
}); });
it('should return needs-approval if prCreation set to approval', async () => { it('should return needs-approval if prCreation set to approval', async () => {
platform.getBranchStatus.mockResolvedValueOnce(BRANCH_STATUS_SUCCESS); platform.getBranchStatus.mockResolvedValueOnce(BranchStatus.green);
config.prCreation = 'approval'; config.prCreation = 'approval';
const pr = await prWorker.ensurePr(config); const pr = await prWorker.ensurePr(config);
expect(pr).toBe('needs-pr-approval'); expect(pr).toBe('needs-pr-approval');
}); });
it('should create PR if success', async () => { it('should create PR if success', async () => {
platform.getBranchStatus.mockResolvedValueOnce(BRANCH_STATUS_SUCCESS); platform.getBranchStatus.mockResolvedValueOnce(BranchStatus.green);
config.prCreation = 'status-success'; config.prCreation = 'status-success';
config.automerge = true; config.automerge = true;
config.schedule = 'before 5am'; config.schedule = 'before 5am';
@ -221,7 +217,7 @@ describe('workers/pr', () => {
expect(platform.createPr.mock.calls[0]).toMatchSnapshot(); expect(platform.createPr.mock.calls[0]).toMatchSnapshot();
}); });
it('should add note about Pin', async () => { it('should add note about Pin', async () => {
platform.getBranchStatus.mockResolvedValueOnce(BRANCH_STATUS_SUCCESS); platform.getBranchStatus.mockResolvedValueOnce(BranchStatus.green);
config.prCreation = 'status-success'; config.prCreation = 'status-success';
config.isPin = true; config.isPin = true;
config.updateType = 'pin'; config.updateType = 'pin';
@ -236,7 +232,7 @@ describe('workers/pr', () => {
).toBe(true); ).toBe(true);
}); });
it('should return null if creating PR fails', async () => { it('should return null if creating PR fails', async () => {
platform.getBranchStatus.mockResolvedValueOnce(BRANCH_STATUS_SUCCESS); platform.getBranchStatus.mockResolvedValueOnce(BranchStatus.green);
platform.createPr = jest.fn(); platform.createPr = jest.fn();
platform.createPr.mockImplementationOnce(() => { platform.createPr.mockImplementationOnce(() => {
throw new Error('Validation Failed (422)'); throw new Error('Validation Failed (422)');
@ -246,7 +242,7 @@ describe('workers/pr', () => {
expect(pr).toBeNull(); expect(pr).toBeNull();
}); });
it('should return null if waiting for not pending', async () => { it('should return null if waiting for not pending', async () => {
platform.getBranchStatus.mockResolvedValueOnce(BRANCH_STATUS_PENDING); platform.getBranchStatus.mockResolvedValueOnce(BranchStatus.yellow);
platform.getBranchLastCommitTime.mockImplementationOnce(() => platform.getBranchLastCommitTime.mockImplementationOnce(() =>
Promise.resolve(new Date()) Promise.resolve(new Date())
); );
@ -255,7 +251,7 @@ describe('workers/pr', () => {
expect(pr).toEqual('pending'); expect(pr).toEqual('pending');
}); });
it('should create PR if pending timeout hit', async () => { it('should create PR if pending timeout hit', async () => {
platform.getBranchStatus.mockResolvedValueOnce(BRANCH_STATUS_PENDING); platform.getBranchStatus.mockResolvedValueOnce(BranchStatus.yellow);
platform.getBranchLastCommitTime.mockImplementationOnce(() => platform.getBranchLastCommitTime.mockImplementationOnce(() =>
Promise.resolve(new Date('2017-01-01')) Promise.resolve(new Date('2017-01-01'))
); );
@ -264,7 +260,7 @@ describe('workers/pr', () => {
expect(pr).toMatchObject({ displayNumber: 'New Pull Request' }); expect(pr).toMatchObject({ displayNumber: 'New Pull Request' });
}); });
it('should create PR if no longer pending', async () => { it('should create PR if no longer pending', async () => {
platform.getBranchStatus.mockResolvedValueOnce(BRANCH_STATUS_FAILED); platform.getBranchStatus.mockResolvedValueOnce(BranchStatus.red);
config.prCreation = 'not-pending'; config.prCreation = 'not-pending';
const pr = await prWorker.ensurePr(config); const pr = await prWorker.ensurePr(config);
expect(pr).toMatchObject({ displayNumber: 'New Pull Request' }); expect(pr).toMatchObject({ displayNumber: 'New Pull Request' });
@ -305,7 +301,7 @@ describe('workers/pr', () => {
expect(platform.addAssignees).toHaveBeenCalledTimes(1); expect(platform.addAssignees).toHaveBeenCalledTimes(1);
expect(platform.addReviewers).toHaveBeenCalledTimes(1); expect(platform.addReviewers).toHaveBeenCalledTimes(1);
}); });
it('should not add assignees and reviewers to new PR if automerging enabled', async () => { it('should not add assignees and reviewers to new PR if automerging enabled regularly', async () => {
config.assignees = ['bar']; config.assignees = ['bar'];
config.reviewers = ['baz']; config.reviewers = ['baz'];
config.automerge = true; config.automerge = true;
@ -394,14 +390,14 @@ describe('workers/pr', () => {
config.automerge = true; config.automerge = true;
config.automergeType = 'branch'; config.automergeType = 'branch';
config.branchAutomergeFailureMessage = 'branch status error'; config.branchAutomergeFailureMessage = 'branch status error';
platform.getBranchStatus.mockResolvedValueOnce(BRANCH_STATUS_FAILED); platform.getBranchStatus.mockResolvedValueOnce(BranchStatus.red);
const pr = await prWorker.ensurePr(config); const pr = await prWorker.ensurePr(config);
expect(pr).toMatchObject({ displayNumber: 'New Pull Request' }); expect(pr).toMatchObject({ displayNumber: 'New Pull Request' });
}); });
it('should create PR if branch automerging failed', async () => { it('should create PR if branch automerging failed', async () => {
config.automerge = true; config.automerge = true;
config.automergeType = 'branch'; config.automergeType = 'branch';
platform.getBranchStatus.mockResolvedValueOnce(BRANCH_STATUS_SUCCESS); platform.getBranchStatus.mockResolvedValueOnce(BranchStatus.green);
config.forcePr = true; config.forcePr = true;
const pr = await prWorker.ensurePr(config); const pr = await prWorker.ensurePr(config);
expect(pr).toMatchObject({ displayNumber: 'New Pull Request' }); expect(pr).toMatchObject({ displayNumber: 'New Pull Request' });
@ -409,7 +405,7 @@ describe('workers/pr', () => {
it('should return null if branch automerging not failed', async () => { it('should return null if branch automerging not failed', async () => {
config.automerge = true; config.automerge = true;
config.automergeType = 'branch'; config.automergeType = 'branch';
platform.getBranchStatus.mockResolvedValueOnce(BRANCH_STATUS_PENDING); platform.getBranchStatus.mockResolvedValueOnce(BranchStatus.yellow);
platform.getBranchLastCommitTime.mockResolvedValueOnce(new Date()); platform.getBranchLastCommitTime.mockResolvedValueOnce(new Date());
const pr = await prWorker.ensurePr(config); const pr = await prWorker.ensurePr(config);
expect(pr).toBeNull(); expect(pr).toBeNull();
@ -417,7 +413,7 @@ describe('workers/pr', () => {
it('should not return null if branch automerging taking too long', async () => { it('should not return null if branch automerging taking too long', async () => {
config.automerge = true; config.automerge = true;
config.automergeType = 'branch'; config.automergeType = 'branch';
platform.getBranchStatus.mockResolvedValueOnce(BRANCH_STATUS_PENDING); platform.getBranchStatus.mockResolvedValueOnce(BranchStatus.yellow);
platform.getBranchLastCommitTime.mockResolvedValueOnce( platform.getBranchLastCommitTime.mockResolvedValueOnce(
new Date('2018-01-01') new Date('2018-01-01')
); );
@ -430,7 +426,7 @@ describe('workers/pr', () => {
expect(pr).toMatchObject({ displayNumber: 'New Pull Request' }); expect(pr).toMatchObject({ displayNumber: 'New Pull Request' });
}); });
it('should create privateRepo PR if success', async () => { it('should create privateRepo PR if success', async () => {
platform.getBranchStatus.mockResolvedValueOnce(BRANCH_STATUS_SUCCESS); platform.getBranchStatus.mockResolvedValueOnce(BranchStatus.green);
config.prCreation = 'status-success'; config.prCreation = 'status-success';
config.privateRepo = false; config.privateRepo = false;
const pr = await prWorker.ensurePr(config); const pr = await prWorker.ensurePr(config);
@ -439,7 +435,7 @@ describe('workers/pr', () => {
existingPr.body = platform.createPr.mock.calls[0][0].prBody; existingPr.body = platform.createPr.mock.calls[0][0].prBody;
}); });
it('should create PR if waiting for not pending but artifactErrors', async () => { it('should create PR if waiting for not pending but artifactErrors', async () => {
platform.getBranchStatus.mockResolvedValueOnce(BRANCH_STATUS_PENDING); platform.getBranchStatus.mockResolvedValueOnce(BranchStatus.yellow);
platform.getBranchLastCommitTime.mockResolvedValueOnce(new Date()); platform.getBranchLastCommitTime.mockResolvedValueOnce(new Date());
config.prCreation = 'not-pending'; config.prCreation = 'not-pending';
config.artifactErrors = [{}]; config.artifactErrors = [{}];

View file

@ -3,7 +3,7 @@ import uniq from 'lodash/uniq';
import { logger } from '../../logger'; import { logger } from '../../logger';
import { ChangeLogError, getChangeLogJSON } from './changelog'; import { ChangeLogError, getChangeLogJSON } from './changelog';
import { getPrBody } from './body'; import { getPrBody } from './body';
import { BranchStatus, platform, Pr, PlatformPrOptions } from '../../platform'; import { platform, Pr, PlatformPrOptions } from '../../platform';
import { BranchConfig } from '../common'; import { BranchConfig } from '../common';
import { import {
PLATFORM_FAILURE, PLATFORM_FAILURE,
@ -11,15 +11,7 @@ import {
PLATFORM_RATE_LIMIT_EXCEEDED, PLATFORM_RATE_LIMIT_EXCEEDED,
REPOSITORY_CHANGED, REPOSITORY_CHANGED,
} from '../../constants/error-messages'; } from '../../constants/error-messages';
import { import { BranchStatus } from '../../types';
BRANCH_STATUS_CREATED,
BRANCH_STATUS_ERROR,
BRANCH_STATUS_FAILED,
BRANCH_STATUS_FAILURE,
BRANCH_STATUS_PENDING,
BRANCH_STATUS_RUNNING,
BRANCH_STATUS_SUCCESS,
} from '../../constants/branch-constants';
function noWhitespace(input: string): string { function noWhitespace(input: string): string {
return input.replace(/\r?\n|\r|\s/g, ''); return input.replace(/\r?\n|\r|\s/g, '');
@ -121,13 +113,7 @@ export async function ensurePr(
logger.debug( logger.debug(
`Branch is configured for branch automerge, branch status) is: ${await getBranchStatus()}` `Branch is configured for branch automerge, branch status) is: ${await getBranchStatus()}`
); );
if ( if ((await getBranchStatus()) === BranchStatus.yellow) {
[
BRANCH_STATUS_CREATED,
BRANCH_STATUS_PENDING,
BRANCH_STATUS_RUNNING,
].includes(await getBranchStatus())
) {
logger.debug('Checking how long this branch has been pending'); logger.debug('Checking how long this branch has been pending');
const lastCommitTime = await platform.getBranchLastCommitTime(branchName); const lastCommitTime = await platform.getBranchLastCommitTime(branchName);
const currentTime = new Date(); const currentTime = new Date();
@ -140,14 +126,7 @@ export async function ensurePr(
config.forcePr = true; config.forcePr = true;
} }
} }
if ( if (config.forcePr || (await getBranchStatus()) === BranchStatus.red) {
config.forcePr ||
[
BRANCH_STATUS_FAILURE,
BRANCH_STATUS_ERROR,
BRANCH_STATUS_FAILED,
].includes(await getBranchStatus())
) {
logger.debug(`Branch tests failed, so will create PR`); logger.debug(`Branch tests failed, so will create PR`);
} else { } else {
return null; return null;
@ -155,11 +134,11 @@ export async function ensurePr(
} }
if (config.prCreation === 'status-success') { if (config.prCreation === 'status-success') {
logger.debug('Checking branch combined status'); logger.debug('Checking branch combined status');
if ((await getBranchStatus()) !== BRANCH_STATUS_SUCCESS) { if ((await getBranchStatus()) !== BranchStatus.green) {
logger.debug( logger.debug(
`Branch status is "${await getBranchStatus()}" - not creating PR` `Branch status is "${await getBranchStatus()}" - not creating PR`
); );
return BRANCH_STATUS_PENDING; return 'pending';
} }
logger.debug('Branch status success'); logger.debug('Branch status success');
} else if ( } else if (
@ -174,10 +153,7 @@ export async function ensurePr(
!config.forcePr !config.forcePr
) { ) {
logger.debug('Checking branch combined status'); logger.debug('Checking branch combined status');
if ( if ((await getBranchStatus()) === BranchStatus.yellow) {
(await getBranchStatus()) === BRANCH_STATUS_PENDING ||
(await getBranchStatus()) === BRANCH_STATUS_RUNNING
) {
logger.debug( logger.debug(
`Branch status is "${await getBranchStatus()}" - checking timeout` `Branch status is "${await getBranchStatus()}" - checking timeout`
); );
@ -191,7 +167,7 @@ export async function ensurePr(
logger.debug( logger.debug(
`Branch is ${elapsedHours} hours old - skipping PR creation` `Branch is ${elapsedHours} hours old - skipping PR creation`
); );
return BRANCH_STATUS_PENDING; return 'pending';
} }
logger.debug( logger.debug(
`prNotPendingHours=${config.prNotPendingHours} threshold hit - creating PR` `prNotPendingHours=${config.prNotPendingHours} threshold hit - creating PR`
@ -274,14 +250,7 @@ export async function ensurePr(
if (existingPr) { if (existingPr) {
logger.debug('Processing existing PR'); logger.debug('Processing existing PR');
// istanbul ignore if // istanbul ignore if
if ( if (config.automerge && (await getBranchStatus()) === BranchStatus.red) {
config.automerge &&
[
BRANCH_STATUS_FAILURE,
BRANCH_STATUS_ERROR,
BRANCH_STATUS_FAILED,
].includes(await getBranchStatus())
) {
logger.debug(`Setting assignees and reviewers as status checks failed`); logger.debug(`Setting assignees and reviewers as status checks failed`);
await addAssigneesReviewers(config, existingPr); await addAssigneesReviewers(config, existingPr);
} }
@ -416,11 +385,7 @@ export async function ensurePr(
if ( if (
config.automerge && config.automerge &&
!config.assignAutomerge && !config.assignAutomerge &&
![ (await getBranchStatus()) !== BranchStatus.red
BRANCH_STATUS_FAILURE,
BRANCH_STATUS_ERROR,
BRANCH_STATUS_FAILED,
].includes(await getBranchStatus())
) { ) {
logger.debug( logger.debug(
`Skipping assignees and reviewers as automerge=${config.automerge}` `Skipping assignees and reviewers as automerge=${config.automerge}`
@ -478,7 +443,7 @@ export async function checkAutoMerge(pr: Pr, config): Promise<boolean> {
branchName, branchName,
requiredStatusChecks requiredStatusChecks
); );
if (branchStatus !== BRANCH_STATUS_SUCCESS) { if (branchStatus !== BranchStatus.green) {
logger.debug( logger.debug(
`PR is not ready for merge (branch status is ${branchStatus})` `PR is not ready for merge (branch status is ${branchStatus})`
); );

View file

@ -1,10 +1,7 @@
import { PR_STATE_OPEN } from '../../../constants/pull-requests'; import { PR_STATE_OPEN } from '../../../constants/pull-requests';
import * as validate from './validate'; import * as validate from './validate';
import { platform } from '../../../../test/util'; import { platform } from '../../../../test/util';
import { import { BranchStatus } from '../../../types';
BRANCH_STATUS_FAILURE,
BRANCH_STATUS_SUCCESS,
} from '../../../constants/branch-constants';
beforeEach(() => { beforeEach(() => {
jest.resetAllMocks(); jest.resetAllMocks();
@ -55,7 +52,7 @@ describe('workers/repository/validate', () => {
await validate.validatePrs({}); await validate.validatePrs({});
expect(platform.setBranchStatus).toHaveBeenCalledTimes(1); expect(platform.setBranchStatus).toHaveBeenCalledTimes(1);
expect(platform.setBranchStatus.mock.calls[0][0].state).toEqual( expect(platform.setBranchStatus.mock.calls[0][0].state).toEqual(
BRANCH_STATUS_FAILURE BranchStatus.red
); );
expect(platform.ensureComment).toHaveBeenCalledTimes(1); expect(platform.ensureComment).toHaveBeenCalledTimes(1);
expect(platform.ensureCommentRemoval).toHaveBeenCalledTimes(0); expect(platform.ensureCommentRemoval).toHaveBeenCalledTimes(0);
@ -73,7 +70,7 @@ describe('workers/repository/validate', () => {
await validate.validatePrs({}); await validate.validatePrs({});
expect(platform.setBranchStatus).toHaveBeenCalledTimes(1); expect(platform.setBranchStatus).toHaveBeenCalledTimes(1);
expect(platform.setBranchStatus.mock.calls[0][0].state).toEqual( expect(platform.setBranchStatus.mock.calls[0][0].state).toEqual(
BRANCH_STATUS_FAILURE BranchStatus.red
); );
expect(platform.ensureComment).toHaveBeenCalledTimes(1); expect(platform.ensureComment).toHaveBeenCalledTimes(1);
expect(platform.ensureCommentRemoval).toHaveBeenCalledTimes(0); expect(platform.ensureCommentRemoval).toHaveBeenCalledTimes(0);
@ -91,7 +88,7 @@ describe('workers/repository/validate', () => {
await validate.validatePrs({}); await validate.validatePrs({});
expect(platform.setBranchStatus).toHaveBeenCalledTimes(1); expect(platform.setBranchStatus).toHaveBeenCalledTimes(1);
expect(platform.setBranchStatus.mock.calls[0][0].state).toEqual( expect(platform.setBranchStatus.mock.calls[0][0].state).toEqual(
BRANCH_STATUS_SUCCESS BranchStatus.green
); );
expect(platform.ensureComment).toHaveBeenCalledTimes(0); expect(platform.ensureComment).toHaveBeenCalledTimes(0);
expect(platform.ensureCommentRemoval).toHaveBeenCalledTimes(1); expect(platform.ensureCommentRemoval).toHaveBeenCalledTimes(1);

View file

@ -6,10 +6,7 @@ import { platform, Pr } from '../../../platform';
import { RenovateConfig } from '../../../config'; import { RenovateConfig } from '../../../config';
import { PR_STATE_OPEN } from '../../../constants/pull-requests'; import { PR_STATE_OPEN } from '../../../constants/pull-requests';
import { REPOSITORY_CHANGED } from '../../../constants/error-messages'; import { REPOSITORY_CHANGED } from '../../../constants/error-messages';
import { import { BranchStatus } from '../../../types';
BRANCH_STATUS_FAILURE,
BRANCH_STATUS_SUCCESS,
} from '../../../constants/branch-constants';
async function getRenovatePrs(branchPrefix: string): Promise<Pr[]> { async function getRenovatePrs(branchPrefix: string): Promise<Pr[]> {
return (await platform.getPrList()) return (await platform.getPrList())
@ -91,7 +88,7 @@ export async function validatePrs(config: RenovateConfig): Promise<void> {
} }
} }
// if the PR has renovate files then we set a status no matter what // if the PR has renovate files then we set a status no matter what
let status: 'failure' | 'success'; let status: BranchStatus;
let description: string; let description: string;
const topic = `Renovate Configuration Errors`; const topic = `Renovate Configuration Errors`;
if (validations.length) { if (validations.length) {
@ -103,11 +100,11 @@ export async function validatePrs(config: RenovateConfig): Promise<void> {
topic, topic,
content, content,
}); });
status = BRANCH_STATUS_FAILURE; status = BranchStatus.red;
description = `Renovate config validation failed`; // GitHub limit description = `Renovate config validation failed`; // GitHub limit
} else { } else {
description = `Renovate config is valid`; description = `Renovate config is valid`;
status = BRANCH_STATUS_SUCCESS; status = BranchStatus.green;
await platform.ensureCommentRemoval(pr.number, topic); await platform.ensureCommentRemoval(pr.number, topic);
} }
// istanbul ignore else // istanbul ignore else