mirror of
https://github.com/renovatebot/renovate.git
synced 2025-01-11 22:46:27 +00:00
feat: branch status unification (#5658)
This commit is contained in:
parent
51a89a3107
commit
588616f669
30 changed files with 358 additions and 382 deletions
|
@ -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';
|
|
@ -2,11 +2,7 @@ import is from '@sindresorhus/is';
|
|||
import * as _hostRules from '../../util/host-rules';
|
||||
import { RepoParams, Platform } from '../common';
|
||||
import { REPOSITORY_DISABLED } from '../../constants/error-messages';
|
||||
import {
|
||||
BRANCH_STATUS_FAILED,
|
||||
BRANCH_STATUS_PENDING,
|
||||
BRANCH_STATUS_SUCCESS,
|
||||
} from '../../constants/branch-constants';
|
||||
import { BranchStatus } from '../../types';
|
||||
|
||||
describe('platform/azure', () => {
|
||||
let hostRules: jest.Mocked<typeof _hostRules>;
|
||||
|
@ -416,12 +412,12 @@ describe('platform/azure', () => {
|
|||
it('return success if requiredStatusChecks null', async () => {
|
||||
await initRepo('some-repo');
|
||||
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 () => {
|
||||
await initRepo('some-repo');
|
||||
const res = await azure.getBranchStatus('somebranch', ['foo']);
|
||||
expect(res).toEqual(BRANCH_STATUS_FAILED);
|
||||
expect(res).toEqual(BranchStatus.red);
|
||||
});
|
||||
it('should pass through success', async () => {
|
||||
await initRepo({ repository: 'some/repo' });
|
||||
|
@ -432,7 +428,7 @@ describe('platform/azure', () => {
|
|||
} as any)
|
||||
);
|
||||
const res = await azure.getBranchStatus('somebranch', []);
|
||||
expect(res).toEqual(BRANCH_STATUS_SUCCESS);
|
||||
expect(res).toEqual(BranchStatus.green);
|
||||
});
|
||||
it('should pass through failed', async () => {
|
||||
await initRepo({ repository: 'some/repo' });
|
||||
|
@ -443,7 +439,7 @@ describe('platform/azure', () => {
|
|||
} as any)
|
||||
);
|
||||
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',
|
||||
context: 'test',
|
||||
description: 'test',
|
||||
state: 'test',
|
||||
state: BranchStatus.yellow,
|
||||
url: 'test',
|
||||
});
|
||||
expect(res).toBeUndefined();
|
||||
|
|
|
@ -20,7 +20,6 @@ import {
|
|||
FindPRConfig,
|
||||
EnsureCommentConfig,
|
||||
EnsureIssueResult,
|
||||
BranchStatus,
|
||||
} from '../common';
|
||||
import { sanitize } from '../../util/sanitize';
|
||||
import { smartTruncate } from '../utils/pr-body';
|
||||
|
@ -31,11 +30,7 @@ import {
|
|||
PR_STATE_NOT_OPEN,
|
||||
PR_STATE_OPEN,
|
||||
} from '../../constants/pull-requests';
|
||||
import {
|
||||
BRANCH_STATUS_FAILED,
|
||||
BRANCH_STATUS_PENDING,
|
||||
BRANCH_STATUS_SUCCESS,
|
||||
} from '../../constants/branch-constants';
|
||||
import { BranchStatus } from '../../types';
|
||||
import { RenovateConfig } from '../../config';
|
||||
|
||||
interface Config {
|
||||
|
@ -393,7 +388,7 @@ export /* istanbul ignore next */ function getCommitMessages(): Promise<
|
|||
|
||||
export async function getBranchStatusCheck(
|
||||
branchName: string,
|
||||
context?: string
|
||||
context: string
|
||||
): Promise<BranchStatus> {
|
||||
logger.trace(`getBranchStatusCheck(${branchName}, ${context})`);
|
||||
const azureApiGit = await azureApi.gitApi();
|
||||
|
@ -402,9 +397,9 @@ export async function getBranchStatusCheck(
|
|||
azureHelper.getBranchNameWithoutRefsheadsPrefix(branchName)!
|
||||
);
|
||||
if (branch.aheadCount === 0) {
|
||||
return BRANCH_STATUS_SUCCESS;
|
||||
return BranchStatus.green;
|
||||
}
|
||||
return BRANCH_STATUS_PENDING;
|
||||
return BranchStatus.yellow;
|
||||
}
|
||||
|
||||
export async function getBranchStatus(
|
||||
|
@ -414,14 +409,14 @@ export async function getBranchStatus(
|
|||
logger.debug(`getBranchStatus(${branchName})`);
|
||||
if (!requiredStatusChecks) {
|
||||
// null means disable status checks, so it always succeeds
|
||||
return BRANCH_STATUS_SUCCESS;
|
||||
return BranchStatus.green;
|
||||
}
|
||||
if (requiredStatusChecks.length) {
|
||||
// This is Unsupported
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -7,12 +7,7 @@ import {
|
|||
REPOSITORY_NOT_FOUND,
|
||||
} from '../../constants/error-messages';
|
||||
import { PR_STATE_CLOSED, PR_STATE_OPEN } from '../../constants/pull-requests';
|
||||
import {
|
||||
BRANCH_STATUS_FAILED,
|
||||
BRANCH_STATUS_FAILURE,
|
||||
BRANCH_STATUS_PENDING,
|
||||
BRANCH_STATUS_SUCCESS,
|
||||
} from '../../constants/branch-constants';
|
||||
import { BranchStatus } from '../../types';
|
||||
|
||||
describe('platform/bitbucket-server', () => {
|
||||
Object.entries(responses).forEach(([scenarioName, mockResponses]) => {
|
||||
|
@ -787,11 +782,11 @@ Followed by some information.
|
|||
|
||||
await expect(
|
||||
bitbucket.getBranchStatus('somebranch', [])
|
||||
).resolves.toEqual(BRANCH_STATUS_SUCCESS);
|
||||
).resolves.toEqual(BranchStatus.green);
|
||||
|
||||
await expect(
|
||||
bitbucket.getBranchStatus('somebranch')
|
||||
).resolves.toEqual(BRANCH_STATUS_SUCCESS);
|
||||
).resolves.toEqual(BranchStatus.green);
|
||||
|
||||
expect(api.get.mock.calls).toMatchSnapshot();
|
||||
});
|
||||
|
@ -809,7 +804,7 @@ Followed by some information.
|
|||
|
||||
await expect(
|
||||
bitbucket.getBranchStatus('somebranch', [])
|
||||
).resolves.toEqual(BRANCH_STATUS_PENDING);
|
||||
).resolves.toEqual(BranchStatus.yellow);
|
||||
|
||||
api.get.mockReturnValueOnce({
|
||||
body: {
|
||||
|
@ -821,7 +816,7 @@ Followed by some information.
|
|||
|
||||
await expect(
|
||||
bitbucket.getBranchStatus('somebranch', [])
|
||||
).resolves.toEqual(BRANCH_STATUS_PENDING);
|
||||
).resolves.toEqual(BranchStatus.yellow);
|
||||
|
||||
expect(api.get.mock.calls).toMatchSnapshot();
|
||||
});
|
||||
|
@ -840,7 +835,7 @@ Followed by some information.
|
|||
|
||||
await expect(
|
||||
bitbucket.getBranchStatus('somebranch', [])
|
||||
).resolves.toEqual(BRANCH_STATUS_FAILED);
|
||||
).resolves.toEqual(BranchStatus.red);
|
||||
|
||||
api.get.mockImplementationOnce(() => {
|
||||
throw new Error('requst-failed');
|
||||
|
@ -848,7 +843,7 @@ Followed by some information.
|
|||
|
||||
await expect(
|
||||
bitbucket.getBranchStatus('somebranch', [])
|
||||
).resolves.toEqual(BRANCH_STATUS_FAILED);
|
||||
).resolves.toEqual(BranchStatus.red);
|
||||
|
||||
expect(api.get.mock.calls).toMatchSnapshot();
|
||||
});
|
||||
|
@ -889,7 +884,7 @@ Followed by some information.
|
|||
|
||||
await expect(
|
||||
bitbucket.getBranchStatusCheck('somebranch', 'context-2')
|
||||
).resolves.toEqual(BRANCH_STATUS_SUCCESS);
|
||||
).resolves.toEqual(BranchStatus.green);
|
||||
|
||||
expect(api.get.mock.calls).toMatchSnapshot();
|
||||
});
|
||||
|
@ -912,7 +907,7 @@ Followed by some information.
|
|||
|
||||
await expect(
|
||||
bitbucket.getBranchStatusCheck('somebranch', 'context-2')
|
||||
).resolves.toEqual(BRANCH_STATUS_PENDING);
|
||||
).resolves.toEqual(BranchStatus.yellow);
|
||||
|
||||
expect(api.get.mock.calls).toMatchSnapshot();
|
||||
});
|
||||
|
@ -935,7 +930,7 @@ Followed by some information.
|
|||
|
||||
await expect(
|
||||
bitbucket.getBranchStatusCheck('somebranch', 'context-2')
|
||||
).resolves.toEqual(BRANCH_STATUS_FAILURE);
|
||||
).resolves.toEqual(BranchStatus.red);
|
||||
|
||||
expect(api.get.mock.calls).toMatchSnapshot();
|
||||
});
|
||||
|
@ -976,28 +971,28 @@ Followed by some information.
|
|||
branchName: 'somebranch',
|
||||
context: 'context-2',
|
||||
description: null as any,
|
||||
state: BRANCH_STATUS_SUCCESS,
|
||||
state: BranchStatus.green,
|
||||
});
|
||||
|
||||
await bitbucket.setBranchStatus({
|
||||
branchName: 'somebranch',
|
||||
context: 'context-2',
|
||||
description: null as any,
|
||||
state: BRANCH_STATUS_FAILED,
|
||||
state: BranchStatus.red,
|
||||
});
|
||||
|
||||
await bitbucket.setBranchStatus({
|
||||
branchName: 'somebranch',
|
||||
context: 'context-2',
|
||||
description: null as any,
|
||||
state: BRANCH_STATUS_FAILURE,
|
||||
state: BranchStatus.red,
|
||||
});
|
||||
|
||||
await bitbucket.setBranchStatus({
|
||||
branchName: 'somebranch',
|
||||
context: 'context-2',
|
||||
description: null as any,
|
||||
state: BRANCH_STATUS_PENDING,
|
||||
state: BranchStatus.yellow,
|
||||
});
|
||||
|
||||
api.post.mockImplementationOnce(() => {
|
||||
|
@ -1008,14 +1003,14 @@ Followed by some information.
|
|||
branchName: 'somebranch',
|
||||
context: 'context-2',
|
||||
description: null as any,
|
||||
state: BRANCH_STATUS_SUCCESS,
|
||||
state: BranchStatus.green,
|
||||
});
|
||||
|
||||
await bitbucket.setBranchStatus({
|
||||
branchName: 'somebranch',
|
||||
context: 'context-1',
|
||||
description: null as any,
|
||||
state: BRANCH_STATUS_SUCCESS,
|
||||
state: BranchStatus.green,
|
||||
});
|
||||
|
||||
expect(api.get.mock.calls).toMatchSnapshot();
|
||||
|
|
|
@ -20,7 +20,6 @@ import {
|
|||
EnsureCommentConfig,
|
||||
EnsureIssueResult,
|
||||
EnsureIssueConfig,
|
||||
BranchStatus,
|
||||
} from '../common';
|
||||
import { sanitize } from '../../util/sanitize';
|
||||
import { smartTruncate } from '../utils/pr-body';
|
||||
|
@ -31,12 +30,7 @@ import {
|
|||
REPOSITORY_NOT_FOUND,
|
||||
} from '../../constants/error-messages';
|
||||
import { PR_STATE_ALL, PR_STATE_OPEN } from '../../constants/pull-requests';
|
||||
import {
|
||||
BRANCH_STATUS_FAILED,
|
||||
BRANCH_STATUS_FAILURE,
|
||||
BRANCH_STATUS_PENDING,
|
||||
BRANCH_STATUS_SUCCESS,
|
||||
} from '../../constants/branch-constants';
|
||||
import { BranchStatus } from '../../types';
|
||||
import { RenovateConfig } from '../../config';
|
||||
/*
|
||||
* Version: 5.3 (EOL Date: 15 Aug 2019)
|
||||
|
@ -536,7 +530,7 @@ export async function getBranchStatus(
|
|||
if (!requiredStatusChecks) {
|
||||
// null means disable status checks, so it always succeeds
|
||||
logger.debug('Status checks disabled = returning "success"');
|
||||
return BRANCH_STATUS_SUCCESS;
|
||||
return BranchStatus.green;
|
||||
}
|
||||
|
||||
if (!(await branchExists(branchName))) {
|
||||
|
@ -548,14 +542,14 @@ export async function getBranchStatus(
|
|||
|
||||
logger.debug({ commitStatus }, 'branch status check result');
|
||||
|
||||
if (commitStatus.failed > 0) return BRANCH_STATUS_FAILED;
|
||||
if (commitStatus.inProgress > 0) return BRANCH_STATUS_PENDING;
|
||||
if (commitStatus.failed > 0) return BranchStatus.red;
|
||||
if (commitStatus.inProgress > 0) return BranchStatus.yellow;
|
||||
return commitStatus.successful > 0
|
||||
? BRANCH_STATUS_SUCCESS
|
||||
: BRANCH_STATUS_PENDING;
|
||||
? BranchStatus.green
|
||||
: BranchStatus.yellow;
|
||||
} catch (err) {
|
||||
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(
|
||||
branchName: string,
|
||||
context: string
|
||||
): Promise<string | null> {
|
||||
): Promise<BranchStatus | null> {
|
||||
logger.debug(`getBranchStatusCheck(${branchName}, context=${context})`);
|
||||
|
||||
try {
|
||||
|
@ -586,12 +580,12 @@ export async function getBranchStatusCheck(
|
|||
if (state.key === context) {
|
||||
switch (state.state) {
|
||||
case 'SUCCESSFUL':
|
||||
return BRANCH_STATUS_SUCCESS;
|
||||
return BranchStatus.green;
|
||||
case 'INPROGRESS':
|
||||
return BRANCH_STATUS_PENDING;
|
||||
return BranchStatus.yellow;
|
||||
case 'FAILED':
|
||||
default:
|
||||
return BRANCH_STATUS_FAILURE;
|
||||
return BranchStatus.red;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -626,13 +620,13 @@ export async function setBranchStatus({
|
|||
};
|
||||
|
||||
switch (state) {
|
||||
case BRANCH_STATUS_SUCCESS:
|
||||
case BranchStatus.green:
|
||||
body.state = 'SUCCESSFUL';
|
||||
break;
|
||||
case BRANCH_STATUS_PENDING:
|
||||
case BranchStatus.yellow:
|
||||
body.state = 'INPROGRESS';
|
||||
break;
|
||||
case BRANCH_STATUS_FAILURE:
|
||||
case BranchStatus.red:
|
||||
default:
|
||||
body.state = 'FAILED';
|
||||
break;
|
||||
|
|
|
@ -2,11 +2,7 @@ import URL from 'url';
|
|||
import responses from './__fixtures__/responses';
|
||||
import { GotApi, RepoParams, Platform } from '../common';
|
||||
import { REPOSITORY_DISABLED } from '../../constants/error-messages';
|
||||
import {
|
||||
BRANCH_STATUS_FAILED,
|
||||
BRANCH_STATUS_PENDING,
|
||||
BRANCH_STATUS_SUCCESS,
|
||||
} from '../../constants/branch-constants';
|
||||
import { BranchStatus } from '../../types';
|
||||
|
||||
describe('platform/bitbucket', () => {
|
||||
let bitbucket: Platform;
|
||||
|
@ -197,17 +193,15 @@ describe('platform/bitbucket', () => {
|
|||
const getBranchStatus = wrap('getBranchStatus');
|
||||
it('works', async () => {
|
||||
await initRepo();
|
||||
expect(await getBranchStatus('master', null)).toBe(BRANCH_STATUS_SUCCESS);
|
||||
expect(await getBranchStatus('master', ['foo'])).toBe(
|
||||
BRANCH_STATUS_FAILED
|
||||
);
|
||||
expect(await getBranchStatus('master', true)).toBe(BRANCH_STATUS_FAILED);
|
||||
expect(await getBranchStatus('branch', true)).toBe(BRANCH_STATUS_SUCCESS);
|
||||
expect(await getBranchStatus('master', null)).toBe(BranchStatus.green);
|
||||
expect(await getBranchStatus('master', ['foo'])).toBe(BranchStatus.red);
|
||||
expect(await getBranchStatus('master', true)).toBe(BranchStatus.red);
|
||||
expect(await getBranchStatus('branch', true)).toBe(BranchStatus.green);
|
||||
expect(await getBranchStatus('pending/branch', true)).toBe(
|
||||
BRANCH_STATUS_PENDING
|
||||
BranchStatus.yellow
|
||||
);
|
||||
expect(await getBranchStatus('branch-with-empty-status', true)).toBe(
|
||||
BRANCH_STATUS_PENDING
|
||||
BranchStatus.yellow
|
||||
);
|
||||
});
|
||||
});
|
||||
|
@ -217,7 +211,9 @@ describe('platform/bitbucket', () => {
|
|||
it('works', async () => {
|
||||
await initRepo();
|
||||
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();
|
||||
});
|
||||
});
|
||||
|
@ -230,7 +226,7 @@ describe('platform/bitbucket', () => {
|
|||
branchName: 'branch',
|
||||
context: 'context',
|
||||
description: 'description',
|
||||
state: BRANCH_STATUS_FAILED,
|
||||
state: BranchStatus.red,
|
||||
url: 'targetUrl',
|
||||
});
|
||||
expect(api.post.mock.calls).toMatchSnapshot();
|
||||
|
|
|
@ -20,7 +20,6 @@ import {
|
|||
FindPRConfig,
|
||||
EnsureCommentConfig,
|
||||
EnsureIssueResult,
|
||||
BranchStatus,
|
||||
} from '../common';
|
||||
import { sanitize } from '../../util/sanitize';
|
||||
import { smartTruncate } from '../utils/pr-body';
|
||||
|
@ -30,11 +29,7 @@ import {
|
|||
} from '../../constants/error-messages';
|
||||
import { PR_STATE_ALL, PR_STATE_OPEN } from '../../constants/pull-requests';
|
||||
import { PLATFORM_TYPE_BITBUCKET } from '../../constants/platforms';
|
||||
import {
|
||||
BRANCH_STATUS_FAILED,
|
||||
BRANCH_STATUS_PENDING,
|
||||
BRANCH_STATUS_SUCCESS,
|
||||
} from '../../constants/branch-constants';
|
||||
import { BranchStatus } from '../../types';
|
||||
import { RenovateConfig } from '../../config';
|
||||
|
||||
let config: utils.Config = {} as any;
|
||||
|
@ -415,46 +410,47 @@ export async function getBranchStatus(
|
|||
if (!requiredStatusChecks) {
|
||||
// null means disable status checks, so it always succeeds
|
||||
logger.debug('Status checks disabled = returning "success"');
|
||||
return BRANCH_STATUS_SUCCESS;
|
||||
return BranchStatus.green;
|
||||
}
|
||||
if (requiredStatusChecks.length) {
|
||||
// This is Unsupported
|
||||
logger.warn({ requiredStatusChecks }, `Unsupported requiredStatusChecks`);
|
||||
return BRANCH_STATUS_FAILED;
|
||||
return BranchStatus.red;
|
||||
}
|
||||
const statuses = await getStatus(branchName);
|
||||
logger.debug({ branch: branchName, statuses }, 'branch status check result');
|
||||
if (!statuses.length) {
|
||||
logger.debug('empty branch status check result = returning "pending"');
|
||||
return BRANCH_STATUS_PENDING;
|
||||
return BranchStatus.yellow;
|
||||
}
|
||||
const noOfFailures = statuses.filter(
|
||||
(status: { state: string }) => status.state === 'FAILED'
|
||||
).length;
|
||||
if (noOfFailures) {
|
||||
return BRANCH_STATUS_FAILED;
|
||||
return BranchStatus.red;
|
||||
}
|
||||
const noOfPending = statuses.filter(
|
||||
(status: { state: string }) => status.state === 'INPROGRESS'
|
||||
).length;
|
||||
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(
|
||||
branchName: string,
|
||||
context: string
|
||||
): Promise<string | null> {
|
||||
): Promise<BranchStatus | null> {
|
||||
const statuses = await getStatus(branchName);
|
||||
const bbState = (statuses.find(status => status.key === context) || {}).state;
|
||||
|
||||
return (
|
||||
Object.keys(utils.buildStates).find(
|
||||
stateKey => utils.buildStates[stateKey] === bbState
|
||||
) || null
|
||||
);
|
||||
return bbToRenovateStatusMapping[bbState] || null;
|
||||
}
|
||||
|
||||
export async function setBranchStatus({
|
||||
|
|
|
@ -3,6 +3,7 @@ import { api } from './bb-got-wrapper';
|
|||
import { Storage } from '../git/storage';
|
||||
import { GotResponse, Pr } from '../common';
|
||||
import { PR_STATE_CLOSED } from '../../constants/pull-requests';
|
||||
import { BranchStatus } from '../../types';
|
||||
|
||||
export interface Config {
|
||||
baseBranch: string;
|
||||
|
@ -59,15 +60,10 @@ export const prStates = {
|
|||
all: ['OPEN', 'MERGED', 'DECLINED', 'SUPERSEDED'],
|
||||
};
|
||||
|
||||
export const buildStates: {
|
||||
[key: string]: BitbucketBranchState;
|
||||
success: BitbucketBranchState;
|
||||
failed: BitbucketBranchState;
|
||||
pending: BitbucketBranchState;
|
||||
} = {
|
||||
success: 'SUCCESSFUL',
|
||||
failed: 'FAILED',
|
||||
pending: 'INPROGRESS',
|
||||
export const buildStates: Record<BranchStatus, BitbucketBranchState> = {
|
||||
green: 'SUCCESSFUL',
|
||||
red: 'FAILED',
|
||||
yellow: 'INPROGRESS',
|
||||
};
|
||||
|
||||
const addMaxLength = (inputUrl: string, pagelen = 100): string => {
|
||||
|
|
|
@ -2,6 +2,7 @@ import got from 'got';
|
|||
import Git from 'simple-git/promise';
|
||||
import { RenovateConfig } from '../config/common';
|
||||
import { CommitFilesConfig } from './git/storage';
|
||||
import { BranchStatus } from '../types';
|
||||
|
||||
export interface FileData {
|
||||
name: string;
|
||||
|
@ -95,14 +96,6 @@ export interface Issue {
|
|||
state?: string;
|
||||
title?: string;
|
||||
}
|
||||
|
||||
export type BranchStatus =
|
||||
| 'pending'
|
||||
| 'success'
|
||||
| 'failed'
|
||||
| 'running'
|
||||
| 'failure';
|
||||
|
||||
export type PlatformPrOptions = {
|
||||
azureAutoComplete?: boolean;
|
||||
statusCheckVerify?: boolean;
|
||||
|
@ -126,7 +119,7 @@ export interface BranchStatusConfig {
|
|||
branchName: string;
|
||||
context: string;
|
||||
description: string;
|
||||
state: string | null;
|
||||
state: BranchStatus;
|
||||
url?: string;
|
||||
}
|
||||
export interface FindPRConfig {
|
||||
|
@ -175,7 +168,10 @@ export interface Platform {
|
|||
getRepoForceRebase(): Promise<boolean>;
|
||||
deleteLabel(number: number, label: string): 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>;
|
||||
deleteBranch(branchName: string, closePr?: boolean): Promise<void>;
|
||||
ensureComment(ensureComment: EnsureCommentConfig): Promise<boolean>;
|
||||
|
|
|
@ -2,6 +2,7 @@ import { URLSearchParams } from 'url';
|
|||
import { api, GiteaGotOptions } from './gitea-got-wrapper';
|
||||
import { GotResponse } from '../common';
|
||||
import { PR_STATE_CLOSED } from '../../constants/pull-requests';
|
||||
import { BranchStatus } from '../../types';
|
||||
|
||||
export type PRState = 'open' | 'closed' | 'all';
|
||||
export type IssueState = 'open' | 'closed' | 'all';
|
||||
|
@ -474,6 +475,27 @@ export async function createCommitStatus(
|
|||
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(
|
||||
repoPath: string,
|
||||
branchName: string,
|
||||
|
|
|
@ -10,7 +10,6 @@ import {
|
|||
REPOSITORY_MIRRORED,
|
||||
} from '../../constants/error-messages';
|
||||
import {
|
||||
BranchStatus,
|
||||
BranchStatusConfig,
|
||||
GotResponse,
|
||||
RepoConfig,
|
||||
|
@ -18,11 +17,7 @@ import {
|
|||
Platform,
|
||||
} from '..';
|
||||
import { logger as _logger } from '../../logger';
|
||||
import {
|
||||
BRANCH_STATUS_FAILED,
|
||||
BRANCH_STATUS_PENDING,
|
||||
BRANCH_STATUS_SUCCESS,
|
||||
} from '../../constants/branch-constants';
|
||||
import { BranchStatus } from '../../types';
|
||||
import { GiteaGotApi } from './gitea-got-wrapper';
|
||||
import { CommitFilesConfig, File } from '../git/storage';
|
||||
|
||||
|
@ -371,7 +366,7 @@ describe('platform/gitea', () => {
|
|||
await initFakeRepo();
|
||||
await gitea.setBranchStatus({
|
||||
branchName: 'some-branch',
|
||||
state: 'some-state',
|
||||
state: BranchStatus.green,
|
||||
context: 'some-context',
|
||||
description: 'some-description',
|
||||
...bsc,
|
||||
|
@ -386,7 +381,7 @@ describe('platform/gitea', () => {
|
|||
mockRepo.full_name,
|
||||
mockCommitHash,
|
||||
{
|
||||
state: 'some-state',
|
||||
state: 'success',
|
||||
context: 'some-context',
|
||||
description: 'some-description',
|
||||
}
|
||||
|
@ -416,7 +411,7 @@ describe('platform/gitea', () => {
|
|||
mockRepo.full_name,
|
||||
mockCommitHash,
|
||||
{
|
||||
state: 'some-state',
|
||||
state: 'success',
|
||||
context: 'some-context',
|
||||
description: 'some-description',
|
||||
target_url: 'some-url',
|
||||
|
@ -446,30 +441,30 @@ describe('platform/gitea', () => {
|
|||
|
||||
it('should return success if requiredStatusChecks null', async () => {
|
||||
expect(await gitea.getBranchStatus('some-branch', null)).toEqual(
|
||||
BRANCH_STATUS_SUCCESS
|
||||
BranchStatus.green
|
||||
);
|
||||
});
|
||||
|
||||
it('should return failed if unsupported requiredStatusChecks', async () => {
|
||||
expect(await gitea.getBranchStatus('some-branch', ['foo'])).toEqual(
|
||||
BRANCH_STATUS_FAILED
|
||||
BranchStatus.red
|
||||
);
|
||||
});
|
||||
|
||||
it('should return pending state for unknown result', async () => {
|
||||
expect(await getBranchStatus('unknown')).toEqual(BRANCH_STATUS_PENDING);
|
||||
it('should return yellow for unknown result', async () => {
|
||||
expect(await getBranchStatus('unknown')).toEqual(BranchStatus.yellow);
|
||||
});
|
||||
|
||||
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 () => {
|
||||
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 () => {
|
||||
expect(await getBranchStatus('invalid')).toEqual(BRANCH_STATUS_FAILED);
|
||||
it('should return null for all other results', async () => {
|
||||
expect(await getBranchStatus('invalid')).toEqual(BranchStatus.yellow);
|
||||
});
|
||||
|
||||
it('should abort when branch status returns 404', async () => {
|
||||
|
@ -515,8 +510,23 @@ describe('platform/gitea', () => {
|
|||
await gitea.getBranchStatusCheck('some-branch', 'some-context')
|
||||
).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(
|
||||
partial<ght.CombinedCommitStatus>({
|
||||
statuses: [
|
||||
|
@ -530,7 +540,7 @@ describe('platform/gitea', () => {
|
|||
|
||||
expect(
|
||||
await gitea.getBranchStatusCheck('some-branch', 'some-context')
|
||||
).toEqual('success');
|
||||
).toEqual(BranchStatus.green);
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -2,7 +2,6 @@ import URL from 'url';
|
|||
import GitStorage, { CommitFilesConfig, StatusResult } from '../git/storage';
|
||||
import * as hostRules from '../../util/host-rules';
|
||||
import {
|
||||
BranchStatus,
|
||||
BranchStatusConfig,
|
||||
CreatePRConfig,
|
||||
EnsureCommentConfig,
|
||||
|
@ -32,11 +31,7 @@ import { RenovateConfig } from '../../config';
|
|||
import { configFileNames } from '../../config/app-strings';
|
||||
import { smartTruncate } from '../utils/pr-body';
|
||||
import { sanitize } from '../../util/sanitize';
|
||||
import {
|
||||
BRANCH_STATUS_FAILED,
|
||||
BRANCH_STATUS_PENDING,
|
||||
BRANCH_STATUS_SUCCESS,
|
||||
} from '../../constants/branch-constants';
|
||||
import { BranchStatus } from '../../types';
|
||||
import * as helper from './gitea-helper';
|
||||
import { PR_STATE_ALL, PR_STATE_OPEN } from '../../constants/pull-requests';
|
||||
|
||||
|
@ -360,7 +355,7 @@ const platform: Platform = {
|
|||
// Create new status for branch commit
|
||||
const branchCommit = await config.storage.getBranchCommit(branchName);
|
||||
await helper.createCommitStatus(config.repository, branchCommit, {
|
||||
state: state ? (state as helper.CommitStatusType) : 'pending',
|
||||
state: helper.renovateToGiteaStatusMapping[state] || 'pending',
|
||||
context,
|
||||
description,
|
||||
...(target_url && { target_url }),
|
||||
|
@ -380,12 +375,12 @@ const platform: Platform = {
|
|||
requiredStatusChecks?: string[] | null
|
||||
): Promise<BranchStatus> {
|
||||
if (!requiredStatusChecks) {
|
||||
return BRANCH_STATUS_SUCCESS;
|
||||
return BranchStatus.green;
|
||||
}
|
||||
|
||||
if (Array.isArray(requiredStatusChecks) && requiredStatusChecks.length) {
|
||||
logger.warn({ requiredStatusChecks }, 'Unsupported requiredStatusChecks');
|
||||
return BRANCH_STATUS_FAILED;
|
||||
return BranchStatus.red;
|
||||
}
|
||||
|
||||
let ccs: helper.CombinedCommitStatus;
|
||||
|
@ -404,28 +399,29 @@ const platform: Platform = {
|
|||
}
|
||||
|
||||
logger.debug({ ccs }, 'Branch status check result');
|
||||
switch (ccs.worstStatus) {
|
||||
case 'unknown':
|
||||
case 'pending':
|
||||
return BRANCH_STATUS_PENDING;
|
||||
case 'success':
|
||||
return BRANCH_STATUS_SUCCESS;
|
||||
default:
|
||||
return BRANCH_STATUS_FAILED;
|
||||
}
|
||||
return (
|
||||
helper.giteaToRenovateStatusMapping[ccs.worstStatus] ||
|
||||
BranchStatus.yellow
|
||||
);
|
||||
},
|
||||
|
||||
async getBranchStatusCheck(
|
||||
branchName: string,
|
||||
context: string
|
||||
): Promise<string> {
|
||||
): Promise<BranchStatus | null> {
|
||||
const ccs = await helper.getCombinedCommitStatus(
|
||||
config.repository,
|
||||
branchName
|
||||
);
|
||||
const cs = ccs.statuses.find(s => s.context === context);
|
||||
|
||||
return cs ? cs.status : null;
|
||||
if (!cs) return null; // no status check exists
|
||||
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(
|
||||
|
|
|
@ -72,7 +72,7 @@ Array [
|
|||
"body": Object {
|
||||
"context": "renovate/verify",
|
||||
"description": "Renovate verified pull request",
|
||||
"state": "success",
|
||||
"state": "green",
|
||||
"target_url": "https://github.com/renovatebot/renovate",
|
||||
},
|
||||
},
|
||||
|
|
|
@ -5,11 +5,7 @@ import {
|
|||
REPOSITORY_NOT_FOUND,
|
||||
REPOSITORY_RENAMED,
|
||||
} from '../../constants/error-messages';
|
||||
import {
|
||||
BRANCH_STATUS_FAILED,
|
||||
BRANCH_STATUS_PENDING,
|
||||
BRANCH_STATUS_SUCCESS,
|
||||
} from '../../constants/branch-constants';
|
||||
import { BranchStatus } from '../../types';
|
||||
import { mocked } from '../../../test/util';
|
||||
|
||||
describe('platform/github', () => {
|
||||
|
@ -612,14 +608,14 @@ describe('platform/github', () => {
|
|||
repository: 'some/repo',
|
||||
});
|
||||
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 () => {
|
||||
await initRepo({
|
||||
repository: 'some/repo',
|
||||
});
|
||||
const res = await github.getBranchStatus('somebranch', ['foo']);
|
||||
expect(res).toEqual(BRANCH_STATUS_FAILED);
|
||||
expect(res).toEqual(BranchStatus.red);
|
||||
});
|
||||
it('should pass through success', async () => {
|
||||
await initRepo({
|
||||
|
@ -634,7 +630,7 @@ describe('platform/github', () => {
|
|||
} as any)
|
||||
);
|
||||
const res = await github.getBranchStatus('somebranch', []);
|
||||
expect(res).toEqual(BRANCH_STATUS_SUCCESS);
|
||||
expect(res).toEqual(BranchStatus.green);
|
||||
});
|
||||
it('should pass through failed', async () => {
|
||||
await initRepo({
|
||||
|
@ -649,7 +645,22 @@ describe('platform/github', () => {
|
|||
} as any)
|
||||
);
|
||||
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 () => {
|
||||
await initRepo({
|
||||
|
@ -687,7 +698,7 @@ describe('platform/github', () => {
|
|||
} as any)
|
||||
);
|
||||
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 () => {
|
||||
await initRepo({
|
||||
|
@ -725,7 +736,7 @@ describe('platform/github', () => {
|
|||
} as any)
|
||||
);
|
||||
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 () => {
|
||||
await initRepo({
|
||||
|
@ -762,7 +773,7 @@ describe('platform/github', () => {
|
|||
} as any)
|
||||
);
|
||||
const res = await github.getBranchStatus('somebranch', []);
|
||||
expect(res).toEqual(BRANCH_STATUS_PENDING);
|
||||
expect(res).toEqual(BranchStatus.yellow);
|
||||
});
|
||||
});
|
||||
describe('getBranchStatusCheck', () => {
|
||||
|
@ -777,15 +788,15 @@ describe('platform/github', () => {
|
|||
body: [
|
||||
{
|
||||
context: 'context-1',
|
||||
state: 'state-1',
|
||||
state: 'success',
|
||||
},
|
||||
{
|
||||
context: 'context-2',
|
||||
state: 'state-2',
|
||||
state: 'pending',
|
||||
},
|
||||
{
|
||||
context: 'context-3',
|
||||
state: 'state-3',
|
||||
state: 'failed',
|
||||
},
|
||||
],
|
||||
} as any)
|
||||
|
@ -794,7 +805,7 @@ describe('platform/github', () => {
|
|||
'renovate/future_branch',
|
||||
'context-2'
|
||||
);
|
||||
expect(res).toEqual('state-2');
|
||||
expect(res).toEqual(BranchStatus.yellow);
|
||||
});
|
||||
it('returns null', async () => {
|
||||
await initRepo({
|
||||
|
@ -806,15 +817,15 @@ describe('platform/github', () => {
|
|||
body: [
|
||||
{
|
||||
context: 'context-1',
|
||||
state: 'state-1',
|
||||
state: 'success',
|
||||
},
|
||||
{
|
||||
context: 'context-2',
|
||||
state: 'state-2',
|
||||
state: 'pending',
|
||||
},
|
||||
{
|
||||
context: 'context-3',
|
||||
state: 'state-3',
|
||||
state: 'failed',
|
||||
},
|
||||
],
|
||||
} as any)
|
||||
|
@ -834,7 +845,7 @@ describe('platform/github', () => {
|
|||
body: [
|
||||
{
|
||||
context: 'some-context',
|
||||
state: 'some-state',
|
||||
state: 'pending',
|
||||
},
|
||||
],
|
||||
} as any)
|
||||
|
@ -843,7 +854,7 @@ describe('platform/github', () => {
|
|||
branchName: 'some-branch',
|
||||
context: 'some-context',
|
||||
description: 'some-description',
|
||||
state: 'some-state',
|
||||
state: BranchStatus.yellow,
|
||||
url: 'some-url',
|
||||
});
|
||||
expect(api.post).toHaveBeenCalledTimes(0);
|
||||
|
@ -892,7 +903,7 @@ describe('platform/github', () => {
|
|||
branchName: 'some-branch',
|
||||
context: 'some-context',
|
||||
description: 'some-description',
|
||||
state: 'some-state',
|
||||
state: BranchStatus.green,
|
||||
url: 'some-url',
|
||||
});
|
||||
expect(api.post).toHaveBeenCalledTimes(1);
|
||||
|
|
|
@ -19,7 +19,6 @@ import {
|
|||
FindPRConfig,
|
||||
EnsureCommentConfig,
|
||||
EnsureIssueResult,
|
||||
BranchStatus,
|
||||
} from '../common';
|
||||
|
||||
import { configFileNames } from '../../config/app-strings';
|
||||
|
@ -41,11 +40,7 @@ import {
|
|||
REPOSITORY_RENAMED,
|
||||
} from '../../constants/error-messages';
|
||||
import { PLATFORM_TYPE_GITHUB } from '../../constants/platforms';
|
||||
import {
|
||||
BRANCH_STATUS_FAILED,
|
||||
BRANCH_STATUS_PENDING,
|
||||
BRANCH_STATUS_SUCCESS,
|
||||
} from '../../constants/branch-constants';
|
||||
import { BranchStatus } from '../../types';
|
||||
import {
|
||||
PR_STATE_ALL,
|
||||
PR_STATE_CLOSED,
|
||||
|
@ -1095,12 +1090,12 @@ export async function getBranchStatus(
|
|||
if (!requiredStatusChecks) {
|
||||
// null means disable status checks, so it always succeeds
|
||||
logger.debug('Status checks disabled = returning "success"');
|
||||
return BRANCH_STATUS_SUCCESS;
|
||||
return BranchStatus.green;
|
||||
}
|
||||
if (requiredStatusChecks.length) {
|
||||
// This is Unsupported
|
||||
logger.warn({ requiredStatusChecks }, `Unsupported requiredStatusChecks`);
|
||||
return BRANCH_STATUS_FAILED;
|
||||
return BranchStatus.red;
|
||||
}
|
||||
let commitStatus;
|
||||
try {
|
||||
|
@ -1159,21 +1154,27 @@ export async function getBranchStatus(
|
|||
}
|
||||
}
|
||||
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 (
|
||||
commitStatus.state === 'failed' ||
|
||||
checkRuns.some(run => run.conclusion === 'failed')
|
||||
) {
|
||||
return BRANCH_STATUS_FAILED;
|
||||
return BranchStatus.red;
|
||||
}
|
||||
if (
|
||||
(commitStatus.state === 'success' || commitStatus.statuses.length === 0) &&
|
||||
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(
|
||||
|
@ -1187,15 +1188,23 @@ async function getStatusCheck(
|
|||
return (await api.get(url, { useCache })).body;
|
||||
}
|
||||
|
||||
const githubToRenovateStatusMapping = {
|
||||
success: BranchStatus.green,
|
||||
failed: BranchStatus.red,
|
||||
pending: BranchStatus.yellow,
|
||||
};
|
||||
|
||||
export async function getBranchStatusCheck(
|
||||
branchName: string,
|
||||
context: string
|
||||
): Promise<string> {
|
||||
): Promise<BranchStatus | null> {
|
||||
try {
|
||||
const res = await getStatusCheck(branchName);
|
||||
for (const check of res) {
|
||||
if (check.context === context) {
|
||||
return check.state;
|
||||
return (
|
||||
githubToRenovateStatusMapping[check.state] || BranchStatus.yellow
|
||||
);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
|
@ -1696,7 +1705,7 @@ export async function createPr({
|
|||
branchName,
|
||||
context: `renovate/verify`,
|
||||
description: `Renovate verified pull request`,
|
||||
state: BRANCH_STATUS_SUCCESS,
|
||||
state: BranchStatus.green,
|
||||
url: 'https://github.com/renovatebot/renovate',
|
||||
});
|
||||
}
|
||||
|
|
|
@ -10,12 +10,7 @@ import {
|
|||
PR_STATE_NOT_OPEN,
|
||||
PR_STATE_OPEN,
|
||||
} from '../../constants/pull-requests';
|
||||
import {
|
||||
BRANCH_STATUS_FAILED,
|
||||
BRANCH_STATUS_FAILURE,
|
||||
BRANCH_STATUS_PENDING,
|
||||
BRANCH_STATUS_SUCCESS,
|
||||
} from '../../constants/branch-constants';
|
||||
import { BranchStatus } from '../../types';
|
||||
import { GotResponse, Platform } from '..';
|
||||
import { partial } from '../../../test/util';
|
||||
|
||||
|
@ -438,11 +433,11 @@ describe('platform/gitlab', () => {
|
|||
describe('getBranchStatus(branchName, requiredStatusChecks)', () => {
|
||||
it('returns success if requiredStatusChecks null', async () => {
|
||||
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 () => {
|
||||
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 () => {
|
||||
await initRepo();
|
||||
|
@ -452,7 +447,7 @@ describe('platform/gitlab', () => {
|
|||
})
|
||||
);
|
||||
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 () => {
|
||||
await initRepo();
|
||||
|
@ -462,7 +457,7 @@ describe('platform/gitlab', () => {
|
|||
})
|
||||
);
|
||||
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 () => {
|
||||
await initRepo();
|
||||
|
@ -475,7 +470,17 @@ describe('platform/gitlab', () => {
|
|||
})
|
||||
);
|
||||
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 () => {
|
||||
await initRepo();
|
||||
|
@ -489,9 +494,9 @@ describe('platform/gitlab', () => {
|
|||
})
|
||||
);
|
||||
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();
|
||||
api.get.mockResolvedValueOnce(
|
||||
partial<GotResponse>({
|
||||
|
@ -499,7 +504,7 @@ describe('platform/gitlab', () => {
|
|||
})
|
||||
);
|
||||
const res = await gitlab.getBranchStatus('somebranch', []);
|
||||
expect(res).toEqual('foo');
|
||||
expect(res).toEqual(BranchStatus.yellow);
|
||||
});
|
||||
it('throws repository-changed', async () => {
|
||||
expect.assertions(1);
|
||||
|
@ -554,21 +559,24 @@ describe('platform/gitlab', () => {
|
|||
'somebranch',
|
||||
'some-context'
|
||||
);
|
||||
expect(res).toEqual(BRANCH_STATUS_SUCCESS);
|
||||
expect(res).toEqual(BranchStatus.green);
|
||||
});
|
||||
});
|
||||
describe('setBranchStatus', () => {
|
||||
it('sets branch status', async () => {
|
||||
await initRepo();
|
||||
await gitlab.setBranchStatus({
|
||||
branchName: 'some-branch',
|
||||
context: 'some-context',
|
||||
description: 'some-description',
|
||||
state: 'some-state',
|
||||
url: 'some-url',
|
||||
});
|
||||
expect(api.post).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
it.each([BranchStatus.green, BranchStatus.yellow, BranchStatus.red])(
|
||||
'sets branch status yellow',
|
||||
async state => {
|
||||
await initRepo();
|
||||
await gitlab.setBranchStatus({
|
||||
branchName: 'some-branch',
|
||||
context: 'some-context',
|
||||
description: 'some-description',
|
||||
state,
|
||||
url: 'some-url',
|
||||
});
|
||||
expect(api.post).toHaveBeenCalledTimes(1);
|
||||
}
|
||||
);
|
||||
});
|
||||
describe('mergeBranch()', () => {
|
||||
it('sends to gitFs', async () => {
|
||||
|
|
|
@ -17,7 +17,6 @@ import {
|
|||
BranchStatusConfig,
|
||||
FindPRConfig,
|
||||
EnsureCommentConfig,
|
||||
BranchStatus,
|
||||
} from '../common';
|
||||
import { configFileNames } from '../../config/app-strings';
|
||||
import { logger } from '../../logger';
|
||||
|
@ -36,12 +35,7 @@ import {
|
|||
} from '../../constants/error-messages';
|
||||
import { PR_STATE_ALL, PR_STATE_OPEN } from '../../constants/pull-requests';
|
||||
import { PLATFORM_TYPE_GITLAB } from '../../constants/platforms';
|
||||
import {
|
||||
BRANCH_STATUS_FAILED,
|
||||
BRANCH_STATUS_FAILURE,
|
||||
BRANCH_STATUS_PENDING,
|
||||
BRANCH_STATUS_SUCCESS,
|
||||
} from '../../constants/branch-constants';
|
||||
import { BranchStatus } from '../../types';
|
||||
|
||||
type MergeMethod = 'merge' | 'rebase_merge' | 'ff';
|
||||
const defaultConfigFile = configFileNames[0];
|
||||
|
@ -315,6 +309,14 @@ async function getStatus(
|
|||
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.
|
||||
export async function getBranchStatus(
|
||||
branchName: string,
|
||||
|
@ -323,12 +325,12 @@ export async function getBranchStatus(
|
|||
logger.debug(`getBranchStatus(${branchName})`);
|
||||
if (!requiredStatusChecks) {
|
||||
// null means disable status checks, so it always succeeds
|
||||
return BRANCH_STATUS_SUCCESS;
|
||||
return BranchStatus.green;
|
||||
}
|
||||
if (Array.isArray(requiredStatusChecks) && requiredStatusChecks.length) {
|
||||
// This is Unsupported
|
||||
logger.warn({ requiredStatusChecks }, `Unsupported requiredStatusChecks`);
|
||||
return BRANCH_STATUS_FAILED;
|
||||
return BranchStatus.red;
|
||||
}
|
||||
|
||||
if (!(await branchExists(branchName))) {
|
||||
|
@ -339,22 +341,29 @@ export async function getBranchStatus(
|
|||
logger.debug(`Got res with ${res.length} results`);
|
||||
if (res.length === 0) {
|
||||
// Return 'pending' if we have no status checks
|
||||
return BRANCH_STATUS_PENDING;
|
||||
return BranchStatus.yellow;
|
||||
}
|
||||
let status: BranchStatus = BRANCH_STATUS_SUCCESS;
|
||||
// Return 'success' if all are success
|
||||
res.forEach(check => {
|
||||
// If one is failed then don't overwrite that
|
||||
if (status !== 'failure') {
|
||||
if (!check.allow_failure) {
|
||||
if (check.status === 'failed' || check.status === 'canceled') {
|
||||
status = BRANCH_STATUS_FAILURE;
|
||||
} else if (check.status !== 'success') {
|
||||
({ status } = check);
|
||||
let status: BranchStatus = BranchStatus.green; // default to green
|
||||
res
|
||||
.filter(check => !check.allow_failure)
|
||||
.forEach(check => {
|
||||
if (status !== BranchStatus.red) {
|
||||
// if red, stay red
|
||||
let mappedStatus: BranchStatus =
|
||||
gitlabToRenovateStatusMapping[check.status];
|
||||
if (!mappedStatus) {
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -430,7 +439,7 @@ export async function getPr(iid: number): Promise<Pr> {
|
|||
pr.isConflicted = true;
|
||||
} else if (pr.state === PR_STATE_OPEN) {
|
||||
const branchStatus = await getBranchStatus(pr.branchName, []);
|
||||
if (branchStatus === BRANCH_STATUS_SUCCESS) {
|
||||
if (branchStatus === BranchStatus.green) {
|
||||
pr.canMerge = true;
|
||||
}
|
||||
}
|
||||
|
@ -623,13 +632,13 @@ export function getRepoStatus(): Promise<StatusResult> {
|
|||
export async function getBranchStatusCheck(
|
||||
branchName: string,
|
||||
context: string
|
||||
): Promise<string | null> {
|
||||
): Promise<BranchStatus | null> {
|
||||
// cache-bust in case we have rebased
|
||||
const res = await getStatus(branchName, false);
|
||||
logger.debug(`Got res with ${res.length} results`);
|
||||
for (const check of res) {
|
||||
if (check.name === context) {
|
||||
return check.status;
|
||||
return gitlabToRenovateStatusMapping[check.status] || BranchStatus.yellow;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
|
@ -639,15 +648,21 @@ export async function setBranchStatus({
|
|||
branchName,
|
||||
context,
|
||||
description,
|
||||
state,
|
||||
state: renovateState,
|
||||
url: targetUrl,
|
||||
}: BranchStatusConfig): Promise<void> {
|
||||
// First, get the branch commit SHA
|
||||
const branchSha = await config.storage.getBranchCommit(branchName);
|
||||
// Now, check the statuses for that commit
|
||||
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 = {
|
||||
state: state.replace('failure', 'failed'), // GitLab uses 'failed', not 'failure'
|
||||
state,
|
||||
description,
|
||||
context,
|
||||
};
|
||||
|
|
5
lib/types/branch-status.ts
Normal file
5
lib/types/branch-status.ts
Normal file
|
@ -0,0 +1,5 @@
|
|||
export enum BranchStatus {
|
||||
green = 'green', // 'success'
|
||||
yellow = 'yellow', // 'created', 'running'
|
||||
red = 'red', // 'error', 'failed'
|
||||
}
|
|
@ -1,2 +1,3 @@
|
|||
export * from './host-rules';
|
||||
export * from './versioning';
|
||||
export * from './branch-status';
|
||||
|
|
|
@ -1,11 +1,7 @@
|
|||
import { tryBranchAutomerge } from './automerge';
|
||||
import { defaultConfig, platform } from '../../../test/util';
|
||||
import { RenovateConfig } from '../../config';
|
||||
import {
|
||||
BRANCH_STATUS_FAILURE,
|
||||
BRANCH_STATUS_PENDING,
|
||||
BRANCH_STATUS_SUCCESS,
|
||||
} from '../../constants/branch-constants';
|
||||
import { BranchStatus } from '../../types';
|
||||
|
||||
describe('workers/branch/automerge', () => {
|
||||
describe('tryBranchAutomerge', () => {
|
||||
|
@ -27,20 +23,20 @@ describe('workers/branch/automerge', () => {
|
|||
it('returns false if branch status is not success', async () => {
|
||||
config.automerge = true;
|
||||
config.automergeType = 'branch';
|
||||
platform.getBranchStatus.mockResolvedValueOnce(BRANCH_STATUS_PENDING);
|
||||
platform.getBranchStatus.mockResolvedValueOnce(BranchStatus.yellow);
|
||||
expect(await tryBranchAutomerge(config)).toBe('no automerge');
|
||||
});
|
||||
it('returns branch status error if branch status is failure', async () => {
|
||||
config.automerge = true;
|
||||
config.automergeType = 'branch';
|
||||
platform.getBranchStatus.mockResolvedValueOnce(BRANCH_STATUS_FAILURE);
|
||||
platform.getBranchStatus.mockResolvedValueOnce(BranchStatus.red);
|
||||
expect(await tryBranchAutomerge(config)).toBe('branch status error');
|
||||
});
|
||||
it('returns false if PR exists', async () => {
|
||||
platform.getBranchPr.mockResolvedValueOnce({} as never);
|
||||
config.automerge = true;
|
||||
config.automergeType = 'branch';
|
||||
platform.getBranchStatus.mockResolvedValueOnce(BRANCH_STATUS_SUCCESS);
|
||||
platform.getBranchStatus.mockResolvedValueOnce(BranchStatus.green);
|
||||
expect(await tryBranchAutomerge(config)).toBe(
|
||||
'automerge aborted - PR exists'
|
||||
);
|
||||
|
@ -48,7 +44,7 @@ describe('workers/branch/automerge', () => {
|
|||
it('returns false if automerge fails', async () => {
|
||||
config.automerge = true;
|
||||
config.automergeType = 'branch';
|
||||
platform.getBranchStatus.mockResolvedValueOnce(BRANCH_STATUS_SUCCESS);
|
||||
platform.getBranchStatus.mockResolvedValueOnce(BranchStatus.green);
|
||||
platform.mergeBranch.mockImplementationOnce(() => {
|
||||
throw new Error('merge error');
|
||||
});
|
||||
|
@ -57,14 +53,14 @@ describe('workers/branch/automerge', () => {
|
|||
it('returns true if automerge succeeds', async () => {
|
||||
config.automerge = true;
|
||||
config.automergeType = 'branch';
|
||||
platform.getBranchStatus.mockResolvedValueOnce(BRANCH_STATUS_SUCCESS);
|
||||
platform.getBranchStatus.mockResolvedValueOnce(BranchStatus.green);
|
||||
expect(await tryBranchAutomerge(config)).toBe('automerged');
|
||||
});
|
||||
it('returns true if automerge succeeds (dry-run)', async () => {
|
||||
config.automerge = true;
|
||||
config.automergeType = 'branch';
|
||||
config.dryRun = true;
|
||||
platform.getBranchStatus.mockResolvedValueOnce(BRANCH_STATUS_SUCCESS);
|
||||
platform.getBranchStatus.mockResolvedValueOnce(BranchStatus.green);
|
||||
expect(await tryBranchAutomerge(config)).toBe('automerged');
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,11 +1,7 @@
|
|||
import { logger } from '../../logger';
|
||||
import { RenovateConfig } from '../../config';
|
||||
import { platform } from '../../platform';
|
||||
import {
|
||||
BRANCH_STATUS_ERROR,
|
||||
BRANCH_STATUS_FAILURE,
|
||||
BRANCH_STATUS_SUCCESS,
|
||||
} from '../../constants/branch-constants';
|
||||
import { BranchStatus } from '../../types';
|
||||
|
||||
export type AutomergeResult =
|
||||
| 'automerged'
|
||||
|
@ -30,7 +26,7 @@ export async function tryBranchAutomerge(
|
|||
config.branchName,
|
||||
config.requiredStatusChecks
|
||||
);
|
||||
if (branchStatus === BRANCH_STATUS_SUCCESS) {
|
||||
if (branchStatus === BranchStatus.green) {
|
||||
logger.debug(`Automerging branch`);
|
||||
try {
|
||||
if (config.dryRun)
|
||||
|
@ -47,9 +43,7 @@ export async function tryBranchAutomerge(
|
|||
logger.info({ err }, `Failed to automerge branch`);
|
||||
return 'failed';
|
||||
}
|
||||
} else if (
|
||||
[BRANCH_STATUS_FAILURE, BRANCH_STATUS_ERROR].includes(branchStatus)
|
||||
) {
|
||||
} else if (branchStatus === BranchStatus.red) {
|
||||
return 'branch status error';
|
||||
} else {
|
||||
logger.debug(`Branch status is "${branchStatus}" - skipping automerge`);
|
||||
|
|
|
@ -21,7 +21,6 @@ import {
|
|||
PR_STATE_MERGED,
|
||||
PR_STATE_OPEN,
|
||||
} from '../../constants/pull-requests';
|
||||
import { BRANCH_STATUS_PENDING } from '../../constants/branch-constants';
|
||||
import { StatusResult } from '../../platform/git/storage';
|
||||
|
||||
jest.mock('./get-updated');
|
||||
|
@ -94,7 +93,7 @@ describe('workers/branch', () => {
|
|||
config.prCreation = 'not-pending';
|
||||
platform.branchExists.mockResolvedValueOnce(true);
|
||||
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 () => {
|
||||
schedule.isScheduledNow.mockReturnValueOnce(true);
|
||||
|
@ -106,7 +105,7 @@ describe('workers/branch', () => {
|
|||
} as never,
|
||||
];
|
||||
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 () => {
|
||||
schedule.isScheduledNow.mockReturnValueOnce(false);
|
||||
|
@ -310,9 +309,7 @@ describe('workers/branch', () => {
|
|||
commit.commitFilesToBranch.mockResolvedValueOnce(null);
|
||||
automerge.tryBranchAutomerge.mockResolvedValueOnce('failed');
|
||||
prWorker.ensurePr.mockResolvedValueOnce('pending');
|
||||
expect(await branchWorker.processBranch(config)).toEqual(
|
||||
BRANCH_STATUS_PENDING
|
||||
);
|
||||
expect(await branchWorker.processBranch(config)).toEqual('pending');
|
||||
});
|
||||
it('returns if branch exists but updated', async () => {
|
||||
expect.assertions(3);
|
||||
|
@ -329,7 +326,7 @@ describe('workers/branch', () => {
|
|||
requiredStatusChecks: null,
|
||||
prCreation: 'not-pending',
|
||||
})
|
||||
).toEqual(BRANCH_STATUS_PENDING);
|
||||
).toEqual('pending');
|
||||
|
||||
expect(automerge.tryBranchAutomerge).toHaveBeenCalledTimes(0);
|
||||
expect(prWorker.ensurePr).toHaveBeenCalledTimes(0);
|
||||
|
|
|
@ -37,7 +37,7 @@ import {
|
|||
PR_STATE_MERGED,
|
||||
PR_STATE_OPEN,
|
||||
} from '../../constants/pull-requests';
|
||||
import { BRANCH_STATUS_FAILURE } from '../../constants/branch-constants';
|
||||
import { BranchStatus } from '../../types';
|
||||
import { exec } from '../../util/exec';
|
||||
import { regEx } from '../../util/regex';
|
||||
|
||||
|
@ -607,7 +607,7 @@ export async function processBranch(
|
|||
}
|
||||
const context = `renovate/artifacts`;
|
||||
const description = 'Artifact file update failure';
|
||||
const state = BRANCH_STATUS_FAILURE;
|
||||
const state = BranchStatus.red;
|
||||
const existingState = await platform.getBranchStatusCheck(
|
||||
config.branchName,
|
||||
context
|
||||
|
|
|
@ -5,7 +5,7 @@ import {
|
|||
UnpublishableConfig,
|
||||
} from './status-checks';
|
||||
import { defaultConfig, platform } from '../../../test/util';
|
||||
import { BRANCH_STATUS_SUCCESS } from '../../constants/branch-constants';
|
||||
import { BranchStatus } from '../../types';
|
||||
|
||||
describe('workers/branch/status-checks', () => {
|
||||
describe('setStability', () => {
|
||||
|
@ -23,14 +23,14 @@ describe('workers/branch/status-checks', () => {
|
|||
await setStability(config);
|
||||
expect(platform.getBranchStatusCheck).toHaveBeenCalledTimes(0);
|
||||
});
|
||||
it('sets status pending', async () => {
|
||||
config.stabilityStatus = 'pending';
|
||||
it('sets status yellow', async () => {
|
||||
config.stabilityStatus = BranchStatus.yellow;
|
||||
await setStability(config);
|
||||
expect(platform.getBranchStatusCheck).toHaveBeenCalledTimes(1);
|
||||
expect(platform.setBranchStatus).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
it('sets status success', async () => {
|
||||
config.stabilityStatus = 'success';
|
||||
it('sets status green', async () => {
|
||||
config.stabilityStatus = BranchStatus.green;
|
||||
await setStability(config);
|
||||
expect(platform.getBranchStatusCheck).toHaveBeenCalledTimes(1);
|
||||
expect(platform.setBranchStatus).toHaveBeenCalledTimes(1);
|
||||
|
@ -67,9 +67,7 @@ describe('workers/branch/status-checks', () => {
|
|||
it('finds canBeUnpublished false and skips status', async () => {
|
||||
config.unpublishSafe = true;
|
||||
config.canBeUnpublished = false;
|
||||
platform.getBranchStatusCheck.mockResolvedValueOnce(
|
||||
BRANCH_STATUS_SUCCESS
|
||||
);
|
||||
platform.getBranchStatusCheck.mockResolvedValueOnce(BranchStatus.green);
|
||||
await setUnpublishable(config);
|
||||
expect(platform.getBranchStatusCheck).toHaveBeenCalledTimes(1);
|
||||
expect(platform.setBranchStatus).toHaveBeenCalledTimes(0);
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
import { logger } from '../../logger';
|
||||
import { RenovateConfig } from '../../config';
|
||||
import { platform } from '../../platform';
|
||||
import { BranchStatus } from '../../types';
|
||||
|
||||
async function setStatusCheck(
|
||||
branchName: string,
|
||||
context: string,
|
||||
description: string,
|
||||
state: string,
|
||||
state: BranchStatus,
|
||||
url: string
|
||||
): Promise<void> {
|
||||
const existingState = await platform.getBranchStatusCheck(
|
||||
|
@ -29,7 +30,7 @@ async function setStatusCheck(
|
|||
}
|
||||
|
||||
export type StabilityConfig = RenovateConfig & {
|
||||
stabilityStatus?: string;
|
||||
stabilityStatus?: BranchStatus;
|
||||
branchName: string;
|
||||
};
|
||||
|
||||
|
@ -39,7 +40,7 @@ export async function setStability(config: StabilityConfig): Promise<void> {
|
|||
}
|
||||
const context = `renovate/stability-days`;
|
||||
const description =
|
||||
config.stabilityStatus === 'success'
|
||||
config.stabilityStatus === BranchStatus.green
|
||||
? 'Updates have met stability days requirement'
|
||||
: 'Updates have not met stability days requirement';
|
||||
await setStatusCheck(
|
||||
|
@ -65,7 +66,9 @@ export async function setUnpublishable(
|
|||
}
|
||||
const context = `renovate/unpublish-safe`;
|
||||
// Set canBeUnpublished status check
|
||||
const state = config.canBeUnpublished ? 'pending' : 'success';
|
||||
const state = config.canBeUnpublished
|
||||
? BranchStatus.yellow
|
||||
: BranchStatus.green;
|
||||
const description = config.canBeUnpublished
|
||||
? 'Packages < 24 hours old can be unpublished'
|
||||
: 'Packages cannot be unpublished';
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { platform } from '../../../platform';
|
||||
import { emojify } from '../../../util/emoji';
|
||||
import { BranchConfig } from '../../common';
|
||||
import { BRANCH_STATUS_FAILED } from '../../../constants/branch-constants';
|
||||
import { BranchStatus } from '../../../types';
|
||||
|
||||
export async function getPrConfigDescription(
|
||||
config: BranchConfig
|
||||
|
@ -31,7 +31,7 @@ export async function getPrConfigDescription(
|
|||
config.requiredStatusChecks
|
||||
);
|
||||
// istanbul ignore if
|
||||
if (branchStatus === BRANCH_STATUS_FAILED) {
|
||||
if (branchStatus === BranchStatus.red) {
|
||||
prBody += 'Disabled due to failing status checks.';
|
||||
} else {
|
||||
prBody += 'Enabled.';
|
||||
|
|
|
@ -3,11 +3,7 @@ import * as _changelogHelper from './changelog';
|
|||
import { getConfig } from '../../config/defaults';
|
||||
import { platform as _platform, Pr } from '../../platform';
|
||||
import { mocked } from '../../../test/util';
|
||||
import {
|
||||
BRANCH_STATUS_FAILED,
|
||||
BRANCH_STATUS_PENDING,
|
||||
BRANCH_STATUS_SUCCESS,
|
||||
} from '../../constants/branch-constants';
|
||||
import { BranchStatus } from '../../types';
|
||||
import { PLATFORM_TYPE_GITLAB } from '../../constants/platforms';
|
||||
|
||||
const changelogHelper = mocked(_changelogHelper);
|
||||
|
@ -78,7 +74,7 @@ describe('workers/pr', () => {
|
|||
it('should automerge if enabled and pr is mergeable', async () => {
|
||||
config.automerge = true;
|
||||
pr.isModified = false;
|
||||
platform.getBranchStatus.mockResolvedValueOnce(BRANCH_STATUS_SUCCESS);
|
||||
platform.getBranchStatus.mockResolvedValueOnce(BranchStatus.green);
|
||||
platform.mergePr.mockResolvedValueOnce(true);
|
||||
await prWorker.checkAutoMerge(pr, config);
|
||||
expect(platform.mergePr).toHaveBeenCalledTimes(1);
|
||||
|
@ -88,20 +84,20 @@ describe('workers/pr', () => {
|
|||
config.automergeType = 'pr-comment';
|
||||
config.automergeComment = '!merge';
|
||||
pr.isModified = false;
|
||||
platform.getBranchStatus.mockResolvedValueOnce(BRANCH_STATUS_SUCCESS);
|
||||
platform.getBranchStatus.mockResolvedValueOnce(BranchStatus.green);
|
||||
await prWorker.checkAutoMerge(pr, config);
|
||||
expect(platform.ensureComment).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
it('should not automerge if enabled and pr is mergeable but cannot rebase', async () => {
|
||||
config.automerge = true;
|
||||
pr.isModified = true;
|
||||
platform.getBranchStatus.mockResolvedValueOnce(BRANCH_STATUS_SUCCESS);
|
||||
platform.getBranchStatus.mockResolvedValueOnce(BranchStatus.green);
|
||||
await prWorker.checkAutoMerge(pr, config);
|
||||
expect(platform.mergePr).toHaveBeenCalledTimes(0);
|
||||
});
|
||||
it('should not automerge if enabled and pr is mergeable but branch status is not success', async () => {
|
||||
config.automerge = true;
|
||||
platform.getBranchStatus.mockResolvedValueOnce(BRANCH_STATUS_PENDING);
|
||||
platform.getBranchStatus.mockResolvedValueOnce(BranchStatus.yellow);
|
||||
await prWorker.checkAutoMerge(pr, config);
|
||||
expect(platform.mergePr).toHaveBeenCalledTimes(0);
|
||||
});
|
||||
|
@ -167,19 +163,19 @@ describe('workers/pr', () => {
|
|||
expect(pr).toBeNull();
|
||||
});
|
||||
it('should return null if waiting for success', async () => {
|
||||
platform.getBranchStatus.mockResolvedValueOnce(BRANCH_STATUS_FAILED);
|
||||
platform.getBranchStatus.mockResolvedValueOnce(BranchStatus.red);
|
||||
config.prCreation = 'status-success';
|
||||
const pr = await prWorker.ensurePr(config);
|
||||
expect(pr).toEqual('pending');
|
||||
});
|
||||
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';
|
||||
const pr = await prWorker.ensurePr(config);
|
||||
expect(pr).toBe('needs-pr-approval');
|
||||
});
|
||||
it('should create PR if success', async () => {
|
||||
platform.getBranchStatus.mockResolvedValueOnce(BRANCH_STATUS_SUCCESS);
|
||||
platform.getBranchStatus.mockResolvedValueOnce(BranchStatus.green);
|
||||
config.prCreation = 'status-success';
|
||||
config.automerge = true;
|
||||
config.schedule = 'before 5am';
|
||||
|
@ -221,7 +217,7 @@ describe('workers/pr', () => {
|
|||
expect(platform.createPr.mock.calls[0]).toMatchSnapshot();
|
||||
});
|
||||
it('should add note about Pin', async () => {
|
||||
platform.getBranchStatus.mockResolvedValueOnce(BRANCH_STATUS_SUCCESS);
|
||||
platform.getBranchStatus.mockResolvedValueOnce(BranchStatus.green);
|
||||
config.prCreation = 'status-success';
|
||||
config.isPin = true;
|
||||
config.updateType = 'pin';
|
||||
|
@ -236,7 +232,7 @@ describe('workers/pr', () => {
|
|||
).toBe(true);
|
||||
});
|
||||
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.mockImplementationOnce(() => {
|
||||
throw new Error('Validation Failed (422)');
|
||||
|
@ -246,7 +242,7 @@ describe('workers/pr', () => {
|
|||
expect(pr).toBeNull();
|
||||
});
|
||||
it('should return null if waiting for not pending', async () => {
|
||||
platform.getBranchStatus.mockResolvedValueOnce(BRANCH_STATUS_PENDING);
|
||||
platform.getBranchStatus.mockResolvedValueOnce(BranchStatus.yellow);
|
||||
platform.getBranchLastCommitTime.mockImplementationOnce(() =>
|
||||
Promise.resolve(new Date())
|
||||
);
|
||||
|
@ -255,7 +251,7 @@ describe('workers/pr', () => {
|
|||
expect(pr).toEqual('pending');
|
||||
});
|
||||
it('should create PR if pending timeout hit', async () => {
|
||||
platform.getBranchStatus.mockResolvedValueOnce(BRANCH_STATUS_PENDING);
|
||||
platform.getBranchStatus.mockResolvedValueOnce(BranchStatus.yellow);
|
||||
platform.getBranchLastCommitTime.mockImplementationOnce(() =>
|
||||
Promise.resolve(new Date('2017-01-01'))
|
||||
);
|
||||
|
@ -264,7 +260,7 @@ describe('workers/pr', () => {
|
|||
expect(pr).toMatchObject({ displayNumber: 'New Pull Request' });
|
||||
});
|
||||
it('should create PR if no longer pending', async () => {
|
||||
platform.getBranchStatus.mockResolvedValueOnce(BRANCH_STATUS_FAILED);
|
||||
platform.getBranchStatus.mockResolvedValueOnce(BranchStatus.red);
|
||||
config.prCreation = 'not-pending';
|
||||
const pr = await prWorker.ensurePr(config);
|
||||
expect(pr).toMatchObject({ displayNumber: 'New Pull Request' });
|
||||
|
@ -305,7 +301,7 @@ describe('workers/pr', () => {
|
|||
expect(platform.addAssignees).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.reviewers = ['baz'];
|
||||
config.automerge = true;
|
||||
|
@ -394,14 +390,14 @@ describe('workers/pr', () => {
|
|||
config.automerge = true;
|
||||
config.automergeType = 'branch';
|
||||
config.branchAutomergeFailureMessage = 'branch status error';
|
||||
platform.getBranchStatus.mockResolvedValueOnce(BRANCH_STATUS_FAILED);
|
||||
platform.getBranchStatus.mockResolvedValueOnce(BranchStatus.red);
|
||||
const pr = await prWorker.ensurePr(config);
|
||||
expect(pr).toMatchObject({ displayNumber: 'New Pull Request' });
|
||||
});
|
||||
it('should create PR if branch automerging failed', async () => {
|
||||
config.automerge = true;
|
||||
config.automergeType = 'branch';
|
||||
platform.getBranchStatus.mockResolvedValueOnce(BRANCH_STATUS_SUCCESS);
|
||||
platform.getBranchStatus.mockResolvedValueOnce(BranchStatus.green);
|
||||
config.forcePr = true;
|
||||
const pr = await prWorker.ensurePr(config);
|
||||
expect(pr).toMatchObject({ displayNumber: 'New Pull Request' });
|
||||
|
@ -409,7 +405,7 @@ describe('workers/pr', () => {
|
|||
it('should return null if branch automerging not failed', async () => {
|
||||
config.automerge = true;
|
||||
config.automergeType = 'branch';
|
||||
platform.getBranchStatus.mockResolvedValueOnce(BRANCH_STATUS_PENDING);
|
||||
platform.getBranchStatus.mockResolvedValueOnce(BranchStatus.yellow);
|
||||
platform.getBranchLastCommitTime.mockResolvedValueOnce(new Date());
|
||||
const pr = await prWorker.ensurePr(config);
|
||||
expect(pr).toBeNull();
|
||||
|
@ -417,7 +413,7 @@ describe('workers/pr', () => {
|
|||
it('should not return null if branch automerging taking too long', async () => {
|
||||
config.automerge = true;
|
||||
config.automergeType = 'branch';
|
||||
platform.getBranchStatus.mockResolvedValueOnce(BRANCH_STATUS_PENDING);
|
||||
platform.getBranchStatus.mockResolvedValueOnce(BranchStatus.yellow);
|
||||
platform.getBranchLastCommitTime.mockResolvedValueOnce(
|
||||
new Date('2018-01-01')
|
||||
);
|
||||
|
@ -430,7 +426,7 @@ describe('workers/pr', () => {
|
|||
expect(pr).toMatchObject({ displayNumber: 'New Pull Request' });
|
||||
});
|
||||
it('should create privateRepo PR if success', async () => {
|
||||
platform.getBranchStatus.mockResolvedValueOnce(BRANCH_STATUS_SUCCESS);
|
||||
platform.getBranchStatus.mockResolvedValueOnce(BranchStatus.green);
|
||||
config.prCreation = 'status-success';
|
||||
config.privateRepo = false;
|
||||
const pr = await prWorker.ensurePr(config);
|
||||
|
@ -439,7 +435,7 @@ describe('workers/pr', () => {
|
|||
existingPr.body = platform.createPr.mock.calls[0][0].prBody;
|
||||
});
|
||||
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());
|
||||
config.prCreation = 'not-pending';
|
||||
config.artifactErrors = [{}];
|
||||
|
|
|
@ -3,7 +3,7 @@ import uniq from 'lodash/uniq';
|
|||
import { logger } from '../../logger';
|
||||
import { ChangeLogError, getChangeLogJSON } from './changelog';
|
||||
import { getPrBody } from './body';
|
||||
import { BranchStatus, platform, Pr, PlatformPrOptions } from '../../platform';
|
||||
import { platform, Pr, PlatformPrOptions } from '../../platform';
|
||||
import { BranchConfig } from '../common';
|
||||
import {
|
||||
PLATFORM_FAILURE,
|
||||
|
@ -11,15 +11,7 @@ import {
|
|||
PLATFORM_RATE_LIMIT_EXCEEDED,
|
||||
REPOSITORY_CHANGED,
|
||||
} from '../../constants/error-messages';
|
||||
import {
|
||||
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';
|
||||
import { BranchStatus } from '../../types';
|
||||
|
||||
function noWhitespace(input: string): string {
|
||||
return input.replace(/\r?\n|\r|\s/g, '');
|
||||
|
@ -121,13 +113,7 @@ export async function ensurePr(
|
|||
logger.debug(
|
||||
`Branch is configured for branch automerge, branch status) is: ${await getBranchStatus()}`
|
||||
);
|
||||
if (
|
||||
[
|
||||
BRANCH_STATUS_CREATED,
|
||||
BRANCH_STATUS_PENDING,
|
||||
BRANCH_STATUS_RUNNING,
|
||||
].includes(await getBranchStatus())
|
||||
) {
|
||||
if ((await getBranchStatus()) === BranchStatus.yellow) {
|
||||
logger.debug('Checking how long this branch has been pending');
|
||||
const lastCommitTime = await platform.getBranchLastCommitTime(branchName);
|
||||
const currentTime = new Date();
|
||||
|
@ -140,14 +126,7 @@ export async function ensurePr(
|
|||
config.forcePr = true;
|
||||
}
|
||||
}
|
||||
if (
|
||||
config.forcePr ||
|
||||
[
|
||||
BRANCH_STATUS_FAILURE,
|
||||
BRANCH_STATUS_ERROR,
|
||||
BRANCH_STATUS_FAILED,
|
||||
].includes(await getBranchStatus())
|
||||
) {
|
||||
if (config.forcePr || (await getBranchStatus()) === BranchStatus.red) {
|
||||
logger.debug(`Branch tests failed, so will create PR`);
|
||||
} else {
|
||||
return null;
|
||||
|
@ -155,11 +134,11 @@ export async function ensurePr(
|
|||
}
|
||||
if (config.prCreation === 'status-success') {
|
||||
logger.debug('Checking branch combined status');
|
||||
if ((await getBranchStatus()) !== BRANCH_STATUS_SUCCESS) {
|
||||
if ((await getBranchStatus()) !== BranchStatus.green) {
|
||||
logger.debug(
|
||||
`Branch status is "${await getBranchStatus()}" - not creating PR`
|
||||
);
|
||||
return BRANCH_STATUS_PENDING;
|
||||
return 'pending';
|
||||
}
|
||||
logger.debug('Branch status success');
|
||||
} else if (
|
||||
|
@ -174,10 +153,7 @@ export async function ensurePr(
|
|||
!config.forcePr
|
||||
) {
|
||||
logger.debug('Checking branch combined status');
|
||||
if (
|
||||
(await getBranchStatus()) === BRANCH_STATUS_PENDING ||
|
||||
(await getBranchStatus()) === BRANCH_STATUS_RUNNING
|
||||
) {
|
||||
if ((await getBranchStatus()) === BranchStatus.yellow) {
|
||||
logger.debug(
|
||||
`Branch status is "${await getBranchStatus()}" - checking timeout`
|
||||
);
|
||||
|
@ -191,7 +167,7 @@ export async function ensurePr(
|
|||
logger.debug(
|
||||
`Branch is ${elapsedHours} hours old - skipping PR creation`
|
||||
);
|
||||
return BRANCH_STATUS_PENDING;
|
||||
return 'pending';
|
||||
}
|
||||
logger.debug(
|
||||
`prNotPendingHours=${config.prNotPendingHours} threshold hit - creating PR`
|
||||
|
@ -274,14 +250,7 @@ export async function ensurePr(
|
|||
if (existingPr) {
|
||||
logger.debug('Processing existing PR');
|
||||
// istanbul ignore if
|
||||
if (
|
||||
config.automerge &&
|
||||
[
|
||||
BRANCH_STATUS_FAILURE,
|
||||
BRANCH_STATUS_ERROR,
|
||||
BRANCH_STATUS_FAILED,
|
||||
].includes(await getBranchStatus())
|
||||
) {
|
||||
if (config.automerge && (await getBranchStatus()) === BranchStatus.red) {
|
||||
logger.debug(`Setting assignees and reviewers as status checks failed`);
|
||||
await addAssigneesReviewers(config, existingPr);
|
||||
}
|
||||
|
@ -416,11 +385,7 @@ export async function ensurePr(
|
|||
if (
|
||||
config.automerge &&
|
||||
!config.assignAutomerge &&
|
||||
![
|
||||
BRANCH_STATUS_FAILURE,
|
||||
BRANCH_STATUS_ERROR,
|
||||
BRANCH_STATUS_FAILED,
|
||||
].includes(await getBranchStatus())
|
||||
(await getBranchStatus()) !== BranchStatus.red
|
||||
) {
|
||||
logger.debug(
|
||||
`Skipping assignees and reviewers as automerge=${config.automerge}`
|
||||
|
@ -478,7 +443,7 @@ export async function checkAutoMerge(pr: Pr, config): Promise<boolean> {
|
|||
branchName,
|
||||
requiredStatusChecks
|
||||
);
|
||||
if (branchStatus !== BRANCH_STATUS_SUCCESS) {
|
||||
if (branchStatus !== BranchStatus.green) {
|
||||
logger.debug(
|
||||
`PR is not ready for merge (branch status is ${branchStatus})`
|
||||
);
|
||||
|
|
|
@ -1,10 +1,7 @@
|
|||
import { PR_STATE_OPEN } from '../../../constants/pull-requests';
|
||||
import * as validate from './validate';
|
||||
import { platform } from '../../../../test/util';
|
||||
import {
|
||||
BRANCH_STATUS_FAILURE,
|
||||
BRANCH_STATUS_SUCCESS,
|
||||
} from '../../../constants/branch-constants';
|
||||
import { BranchStatus } from '../../../types';
|
||||
|
||||
beforeEach(() => {
|
||||
jest.resetAllMocks();
|
||||
|
@ -55,7 +52,7 @@ describe('workers/repository/validate', () => {
|
|||
await validate.validatePrs({});
|
||||
expect(platform.setBranchStatus).toHaveBeenCalledTimes(1);
|
||||
expect(platform.setBranchStatus.mock.calls[0][0].state).toEqual(
|
||||
BRANCH_STATUS_FAILURE
|
||||
BranchStatus.red
|
||||
);
|
||||
expect(platform.ensureComment).toHaveBeenCalledTimes(1);
|
||||
expect(platform.ensureCommentRemoval).toHaveBeenCalledTimes(0);
|
||||
|
@ -73,7 +70,7 @@ describe('workers/repository/validate', () => {
|
|||
await validate.validatePrs({});
|
||||
expect(platform.setBranchStatus).toHaveBeenCalledTimes(1);
|
||||
expect(platform.setBranchStatus.mock.calls[0][0].state).toEqual(
|
||||
BRANCH_STATUS_FAILURE
|
||||
BranchStatus.red
|
||||
);
|
||||
expect(platform.ensureComment).toHaveBeenCalledTimes(1);
|
||||
expect(platform.ensureCommentRemoval).toHaveBeenCalledTimes(0);
|
||||
|
@ -91,7 +88,7 @@ describe('workers/repository/validate', () => {
|
|||
await validate.validatePrs({});
|
||||
expect(platform.setBranchStatus).toHaveBeenCalledTimes(1);
|
||||
expect(platform.setBranchStatus.mock.calls[0][0].state).toEqual(
|
||||
BRANCH_STATUS_SUCCESS
|
||||
BranchStatus.green
|
||||
);
|
||||
expect(platform.ensureComment).toHaveBeenCalledTimes(0);
|
||||
expect(platform.ensureCommentRemoval).toHaveBeenCalledTimes(1);
|
||||
|
|
|
@ -6,10 +6,7 @@ import { platform, Pr } from '../../../platform';
|
|||
import { RenovateConfig } from '../../../config';
|
||||
import { PR_STATE_OPEN } from '../../../constants/pull-requests';
|
||||
import { REPOSITORY_CHANGED } from '../../../constants/error-messages';
|
||||
import {
|
||||
BRANCH_STATUS_FAILURE,
|
||||
BRANCH_STATUS_SUCCESS,
|
||||
} from '../../../constants/branch-constants';
|
||||
import { BranchStatus } from '../../../types';
|
||||
|
||||
async function getRenovatePrs(branchPrefix: string): Promise<Pr[]> {
|
||||
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
|
||||
let status: 'failure' | 'success';
|
||||
let status: BranchStatus;
|
||||
let description: string;
|
||||
const topic = `Renovate Configuration Errors`;
|
||||
if (validations.length) {
|
||||
|
@ -103,11 +100,11 @@ export async function validatePrs(config: RenovateConfig): Promise<void> {
|
|||
topic,
|
||||
content,
|
||||
});
|
||||
status = BRANCH_STATUS_FAILURE;
|
||||
status = BranchStatus.red;
|
||||
description = `Renovate config validation failed`; // GitHub limit
|
||||
} else {
|
||||
description = `Renovate config is valid`;
|
||||
status = BRANCH_STATUS_SUCCESS;
|
||||
status = BranchStatus.green;
|
||||
await platform.ensureCommentRemoval(pr.number, topic);
|
||||
}
|
||||
// istanbul ignore else
|
||||
|
|
Loading…
Reference in a new issue