mirror of
https://github.com/renovatebot/renovate.git
synced 2025-03-14 00:03:29 +00:00
fix: union types for ensurePR (#14293)
This commit is contained in:
parent
f0ca884903
commit
b08439a6ed
4 changed files with 168 additions and 107 deletions
lib/workers
|
@ -21,7 +21,7 @@ import * as _mergeConfidence from '../../util/merge-confidence';
|
|||
import * as _sanitize from '../../util/sanitize';
|
||||
import * as _limits from '../global/limits';
|
||||
import * as _prWorker from '../pr';
|
||||
import type { EnsurePrResult } from '../pr';
|
||||
import type { ResultWithPr } from '../pr';
|
||||
import * as _prAutomerge from '../pr/automerge';
|
||||
import type { Pr } from '../repository/onboarding/branch/check';
|
||||
import type { BranchConfig, BranchUpgradeConfig } from '../types';
|
||||
|
@ -99,6 +99,7 @@ describe('workers/branch/index', () => {
|
|||
|
||||
platform.massageMarkdown.mockImplementation((prBody) => prBody);
|
||||
prWorker.ensurePr.mockResolvedValue({
|
||||
type: 'with-pr',
|
||||
pr: partial<Pr>({
|
||||
title: '',
|
||||
sourceBranch: '',
|
||||
|
@ -381,6 +382,7 @@ describe('workers/branch/index', () => {
|
|||
});
|
||||
git.branchExists.mockReturnValue(true);
|
||||
prWorker.ensurePr.mockResolvedValueOnce({
|
||||
type: 'without-pr',
|
||||
prBlockedBy: 'RateLimited',
|
||||
});
|
||||
limits.isLimitReached.mockReturnValue(false);
|
||||
|
@ -503,6 +505,7 @@ describe('workers/branch/index', () => {
|
|||
commit.commitFilesToBranch.mockResolvedValueOnce(null);
|
||||
automerge.tryBranchAutomerge.mockResolvedValueOnce('failed');
|
||||
prWorker.ensurePr.mockResolvedValueOnce({
|
||||
type: 'without-pr',
|
||||
prBlockedBy: 'NeedsApproval',
|
||||
});
|
||||
expect(await branchWorker.processBranch(config)).toEqual({
|
||||
|
@ -524,6 +527,7 @@ describe('workers/branch/index', () => {
|
|||
commit.commitFilesToBranch.mockResolvedValueOnce(null);
|
||||
automerge.tryBranchAutomerge.mockResolvedValueOnce('failed');
|
||||
prWorker.ensurePr.mockResolvedValueOnce({
|
||||
type: 'without-pr',
|
||||
prBlockedBy: 'AwaitingTests',
|
||||
});
|
||||
expect(await branchWorker.processBranch(config)).toEqual({
|
||||
|
@ -545,6 +549,7 @@ describe('workers/branch/index', () => {
|
|||
commit.commitFilesToBranch.mockResolvedValueOnce(null);
|
||||
automerge.tryBranchAutomerge.mockResolvedValueOnce('no automerge');
|
||||
prWorker.ensurePr.mockResolvedValueOnce({
|
||||
type: 'without-pr',
|
||||
prBlockedBy: 'BranchAutomerge',
|
||||
});
|
||||
expect(await branchWorker.processBranch(config)).toEqual({
|
||||
|
@ -566,6 +571,7 @@ describe('workers/branch/index', () => {
|
|||
commit.commitFilesToBranch.mockResolvedValueOnce(null);
|
||||
automerge.tryBranchAutomerge.mockResolvedValueOnce('failed');
|
||||
prWorker.ensurePr.mockResolvedValueOnce({
|
||||
type: 'without-pr',
|
||||
prBlockedBy: 'Error',
|
||||
});
|
||||
expect(await branchWorker.processBranch(config)).toEqual({
|
||||
|
@ -587,6 +593,7 @@ describe('workers/branch/index', () => {
|
|||
commit.commitFilesToBranch.mockResolvedValueOnce(null);
|
||||
automerge.tryBranchAutomerge.mockResolvedValueOnce('failed');
|
||||
prWorker.ensurePr.mockResolvedValueOnce({
|
||||
type: 'without-pr',
|
||||
prBlockedBy: 'whoops' as any,
|
||||
});
|
||||
expect(await branchWorker.processBranch(config)).toEqual({
|
||||
|
@ -630,8 +637,9 @@ describe('workers/branch/index', () => {
|
|||
git.branchExists.mockReturnValue(true);
|
||||
automerge.tryBranchAutomerge.mockResolvedValueOnce('failed');
|
||||
prWorker.ensurePr.mockResolvedValueOnce({
|
||||
type: 'with-pr',
|
||||
pr: {},
|
||||
} as EnsurePrResult);
|
||||
} as ResultWithPr);
|
||||
prAutomerge.checkAutoMerge.mockResolvedValueOnce({ automerged: true });
|
||||
commit.commitFilesToBranch.mockResolvedValueOnce(null);
|
||||
await branchWorker.processBranch({ ...config, automerge: true });
|
||||
|
@ -650,8 +658,9 @@ describe('workers/branch/index', () => {
|
|||
git.branchExists.mockReturnValue(true);
|
||||
automerge.tryBranchAutomerge.mockResolvedValueOnce('stale');
|
||||
prWorker.ensurePr.mockResolvedValueOnce({
|
||||
type: 'with-pr',
|
||||
pr: {},
|
||||
} as EnsurePrResult);
|
||||
} as ResultWithPr);
|
||||
prAutomerge.checkAutoMerge.mockResolvedValueOnce({ automerged: false });
|
||||
commit.commitFilesToBranch.mockResolvedValueOnce(null);
|
||||
await branchWorker.processBranch({
|
||||
|
@ -674,8 +683,9 @@ describe('workers/branch/index', () => {
|
|||
git.branchExists.mockReturnValue(true);
|
||||
automerge.tryBranchAutomerge.mockResolvedValueOnce('failed');
|
||||
prWorker.ensurePr.mockResolvedValueOnce({
|
||||
type: 'with-pr',
|
||||
pr: {},
|
||||
} as EnsurePrResult);
|
||||
} as ResultWithPr);
|
||||
prAutomerge.checkAutoMerge.mockResolvedValueOnce({ automerged: true });
|
||||
commit.commitFilesToBranch.mockResolvedValueOnce(null);
|
||||
await branchWorker.processBranch(config);
|
||||
|
@ -694,8 +704,9 @@ describe('workers/branch/index', () => {
|
|||
git.branchExists.mockReturnValue(true);
|
||||
automerge.tryBranchAutomerge.mockResolvedValueOnce('failed');
|
||||
prWorker.ensurePr.mockResolvedValueOnce({
|
||||
type: 'with-pr',
|
||||
pr: {},
|
||||
} as EnsurePrResult);
|
||||
} as ResultWithPr);
|
||||
prAutomerge.checkAutoMerge.mockResolvedValueOnce({ automerged: true });
|
||||
config.releaseTimestamp = '2018-04-26T05:15:51.877Z';
|
||||
commit.commitFilesToBranch.mockResolvedValueOnce(null);
|
||||
|
@ -715,8 +726,9 @@ describe('workers/branch/index', () => {
|
|||
git.branchExists.mockReturnValue(true);
|
||||
automerge.tryBranchAutomerge.mockResolvedValueOnce('failed');
|
||||
prWorker.ensurePr.mockResolvedValueOnce({
|
||||
type: 'with-pr',
|
||||
pr: {},
|
||||
} as EnsurePrResult);
|
||||
} as ResultWithPr);
|
||||
prAutomerge.checkAutoMerge.mockResolvedValueOnce({ automerged: true });
|
||||
config.releaseTimestamp = new Date().toISOString();
|
||||
commit.commitFilesToBranch.mockResolvedValueOnce(null);
|
||||
|
@ -736,8 +748,9 @@ describe('workers/branch/index', () => {
|
|||
git.branchExists.mockReturnValue(false);
|
||||
automerge.tryBranchAutomerge.mockResolvedValueOnce('failed');
|
||||
prWorker.ensurePr.mockResolvedValueOnce({
|
||||
type: 'with-pr',
|
||||
pr: {},
|
||||
} as EnsurePrResult);
|
||||
} as ResultWithPr);
|
||||
prAutomerge.checkAutoMerge.mockResolvedValueOnce({ automerged: true });
|
||||
config.releaseTimestamp = new Date().toISOString();
|
||||
await expect(branchWorker.processBranch(config)).rejects.toThrow(
|
||||
|
@ -756,8 +769,9 @@ describe('workers/branch/index', () => {
|
|||
git.branchExists.mockReturnValue(true);
|
||||
automerge.tryBranchAutomerge.mockResolvedValueOnce('failed');
|
||||
prWorker.ensurePr.mockResolvedValueOnce({
|
||||
type: 'with-pr',
|
||||
pr: {},
|
||||
} as EnsurePrResult);
|
||||
} as ResultWithPr);
|
||||
prAutomerge.checkAutoMerge.mockResolvedValueOnce({ automerged: true });
|
||||
commit.commitFilesToBranch.mockResolvedValueOnce(null);
|
||||
await branchWorker.processBranch(config);
|
||||
|
@ -890,8 +904,9 @@ describe('workers/branch/index', () => {
|
|||
git.isBranchModified.mockResolvedValueOnce(true);
|
||||
schedule.isScheduledNow.mockReturnValueOnce(false);
|
||||
prWorker.ensurePr.mockResolvedValueOnce({
|
||||
type: 'with-pr',
|
||||
pr: {},
|
||||
} as EnsurePrResult);
|
||||
} as ResultWithPr);
|
||||
commit.commitFilesToBranch.mockResolvedValueOnce(null);
|
||||
GlobalConfig.set({ ...adminConfig, dryRun: true });
|
||||
expect(
|
||||
|
|
|
@ -619,9 +619,10 @@ export async function processBranch(
|
|||
logger.debug(
|
||||
`There are ${config.errors.length} errors and ${config.warnings.length} warnings`
|
||||
);
|
||||
const { prBlockedBy, pr } = await ensurePr(config);
|
||||
branchPr = pr;
|
||||
if (prBlockedBy) {
|
||||
const ensurePrResult = await ensurePr(config);
|
||||
if (ensurePrResult.type === 'without-pr') {
|
||||
const { prBlockedBy } = ensurePrResult;
|
||||
branchPr = null;
|
||||
if (prBlockedBy === 'RateLimited' && !config.isVulnerabilityAlert) {
|
||||
logger.debug('Reached PR limit - skipping PR creation');
|
||||
return {
|
||||
|
@ -654,7 +655,9 @@ export async function processBranch(
|
|||
logger.warn({ prBlockedBy }, 'Unknown PrBlockedBy result');
|
||||
return { branchExists, prBlockedBy, result: BranchResult.Error };
|
||||
}
|
||||
if (pr) {
|
||||
if (ensurePrResult.type === 'with-pr') {
|
||||
const { pr } = ensurePrResult;
|
||||
branchPr = pr;
|
||||
if (config.artifactErrors?.length) {
|
||||
logger.warn(
|
||||
{ artifactErrors: config.artifactErrors },
|
||||
|
|
|
@ -9,6 +9,7 @@ import * as _changelogHelper from './changelog';
|
|||
import type { ChangeLogResult } from './changelog';
|
||||
import * as codeOwners from './code-owners';
|
||||
import * as prWorker from '.';
|
||||
import type { EnsurePrResult, ResultWithPr, ResultWithoutPr } from '.';
|
||||
|
||||
const codeOwnersMock = mocked(codeOwners);
|
||||
const changelogHelper = mocked(_changelogHelper);
|
||||
|
@ -94,6 +95,20 @@ function setupGitlabChangelogMock() {
|
|||
gitlabChangelogHelper.getChangeLogJSON.mockResolvedValue(resultValue);
|
||||
}
|
||||
|
||||
function isResultWithPr(value: EnsurePrResult): asserts value is ResultWithPr {
|
||||
if (value.type !== 'with-pr') {
|
||||
throw new TypeError();
|
||||
}
|
||||
}
|
||||
|
||||
function isResultWithoutPr(
|
||||
value: EnsurePrResult
|
||||
): asserts value is ResultWithoutPr {
|
||||
if (value.type !== 'without-pr') {
|
||||
throw new TypeError();
|
||||
}
|
||||
}
|
||||
|
||||
describe('workers/pr/index', () => {
|
||||
describe('checkAutoMerge(pr, config)', () => {
|
||||
let config: BranchConfig;
|
||||
|
@ -205,22 +220,23 @@ describe('workers/pr/index', () => {
|
|||
});
|
||||
config.newValue = '1.2.0';
|
||||
platform.getBranchPr.mockResolvedValueOnce(existingPr);
|
||||
const { pr } = await prWorker.ensurePr(config);
|
||||
expect(pr).toBeDefined();
|
||||
const result = await prWorker.ensurePr(config);
|
||||
isResultWithPr(result);
|
||||
expect(result.pr).toBeDefined();
|
||||
});
|
||||
it('should return null if waiting for success', async () => {
|
||||
platform.getBranchStatus.mockResolvedValueOnce(BranchStatus.red);
|
||||
config.prCreation = 'status-success';
|
||||
const { prBlockedBy, pr } = await prWorker.ensurePr(config);
|
||||
expect(prBlockedBy).toBe('AwaitingTests');
|
||||
expect(pr).toBeUndefined();
|
||||
const result = await prWorker.ensurePr(config);
|
||||
isResultWithoutPr(result);
|
||||
expect(result.prBlockedBy).toBe('AwaitingTests');
|
||||
});
|
||||
it('should return needs-approval if prCreation set to approval', async () => {
|
||||
platform.getBranchStatus.mockResolvedValueOnce(BranchStatus.green);
|
||||
config.prCreation = 'approval';
|
||||
const { prBlockedBy, pr } = await prWorker.ensurePr(config);
|
||||
expect(prBlockedBy).toBe('NeedsApproval');
|
||||
expect(pr).toBeUndefined();
|
||||
const result = await prWorker.ensurePr(config);
|
||||
isResultWithoutPr(result);
|
||||
expect(result.prBlockedBy).toBe('NeedsApproval');
|
||||
});
|
||||
it('should create PR if success for gitlab deps', async () => {
|
||||
setupGitlabChangelogMock();
|
||||
|
@ -233,8 +249,9 @@ describe('workers/pr/index', () => {
|
|||
config.prCreation = 'status-success';
|
||||
config.automerge = true;
|
||||
config.schedule = ['before 5am'];
|
||||
const { pr } = await prWorker.ensurePr(config);
|
||||
expect(pr).toMatchObject({ displayNumber: 'New Pull Request' });
|
||||
const result = await prWorker.ensurePr(config);
|
||||
isResultWithPr(result);
|
||||
expect(result.pr).toMatchObject({ displayNumber: 'New Pull Request' });
|
||||
expect(platform.createPr.mock.calls[0]).toMatchSnapshot([
|
||||
{
|
||||
prTitle: 'Update dependency dummy to v1.1.0',
|
||||
|
@ -253,8 +270,9 @@ describe('workers/pr/index', () => {
|
|||
config.prCreation = 'status-success';
|
||||
config.automerge = true;
|
||||
config.schedule = ['before 5am'];
|
||||
const { pr } = await prWorker.ensurePr(config);
|
||||
expect(pr).toMatchObject({ displayNumber: 'New Pull Request' });
|
||||
const result = await prWorker.ensurePr(config);
|
||||
isResultWithPr(result);
|
||||
expect(result.pr).toMatchObject({ displayNumber: 'New Pull Request' });
|
||||
expect(platform.createPr.mock.calls[0]).toMatchSnapshot([
|
||||
{
|
||||
prTitle: 'Update dependency dummy to v1.1.0',
|
||||
|
@ -270,8 +288,9 @@ describe('workers/pr/index', () => {
|
|||
config.automerge = true;
|
||||
config.schedule = ['before 5am'];
|
||||
limits.isLimitReached.mockReturnValueOnce(true);
|
||||
const { prBlockedBy } = await prWorker.ensurePr(config);
|
||||
expect(prBlockedBy).toBe('RateLimited');
|
||||
const result = await prWorker.ensurePr(config);
|
||||
isResultWithoutPr(result);
|
||||
expect(result.prBlockedBy).toBe('RateLimited');
|
||||
expect(platform.createPr.mock.calls).toBeEmpty();
|
||||
});
|
||||
it('should create PR if limit is reached but dashboard checked', async () => {
|
||||
|
@ -420,8 +439,9 @@ describe('workers/pr/index', () => {
|
|||
};
|
||||
}
|
||||
}
|
||||
const { pr } = await prWorker.ensurePr(config);
|
||||
expect(pr).toMatchObject({ displayNumber: 'New Pull Request' });
|
||||
const result = await prWorker.ensurePr(config);
|
||||
isResultWithPr(result);
|
||||
expect(result.pr).toMatchObject({ displayNumber: 'New Pull Request' });
|
||||
expect(platform.createPr.mock.calls[0]).toMatchSnapshot([
|
||||
{
|
||||
prTitle: 'Update dependency dummy to v1.1.0',
|
||||
|
@ -438,8 +458,9 @@ describe('workers/pr/index', () => {
|
|||
config.timezone = 'some timezone';
|
||||
config.rebaseWhen = 'behind-base-branch';
|
||||
config.logJSON = await changelogHelper.getChangeLogJSON(config);
|
||||
const { pr } = await prWorker.ensurePr(config);
|
||||
expect(pr).toMatchObject({ displayNumber: 'New Pull Request' });
|
||||
const result = await prWorker.ensurePr(config);
|
||||
isResultWithPr(result);
|
||||
expect(result.pr).toMatchObject({ displayNumber: 'New Pull Request' });
|
||||
expect(platform.createPr.mock.calls[0]).toMatchSnapshot([
|
||||
{
|
||||
prTitle: 'Update dependency dummy to v1.1.0',
|
||||
|
@ -456,9 +477,9 @@ describe('workers/pr/index', () => {
|
|||
throw new Error('Validation Failed (422)');
|
||||
});
|
||||
config.prCreation = 'status-success';
|
||||
const { prBlockedBy, pr } = await prWorker.ensurePr(config);
|
||||
expect(prBlockedBy).toBe('Error');
|
||||
expect(pr).toBeUndefined();
|
||||
const result = await prWorker.ensurePr(config);
|
||||
isResultWithoutPr(result);
|
||||
expect(result.prBlockedBy).toBe('Error');
|
||||
});
|
||||
it('should return null if waiting for not pending', async () => {
|
||||
platform.getBranchStatus.mockResolvedValueOnce(BranchStatus.yellow);
|
||||
|
@ -466,9 +487,9 @@ describe('workers/pr/index', () => {
|
|||
Promise.resolve(new Date())
|
||||
);
|
||||
config.prCreation = 'not-pending';
|
||||
const { prBlockedBy, pr } = await prWorker.ensurePr(config);
|
||||
expect(prBlockedBy).toBe('AwaitingTests');
|
||||
expect(pr).toBeUndefined();
|
||||
const result = await prWorker.ensurePr(config);
|
||||
isResultWithoutPr(result);
|
||||
expect(result.prBlockedBy).toBe('AwaitingTests');
|
||||
});
|
||||
it('should not create PR if waiting for not pending with stabilityStatus yellow', async () => {
|
||||
platform.getBranchStatus.mockResolvedValueOnce(BranchStatus.yellow);
|
||||
|
@ -477,9 +498,9 @@ describe('workers/pr/index', () => {
|
|||
);
|
||||
config.prCreation = 'not-pending';
|
||||
config.stabilityStatus = BranchStatus.yellow;
|
||||
const { prBlockedBy, pr } = await prWorker.ensurePr(config);
|
||||
expect(prBlockedBy).toBe('AwaitingTests');
|
||||
expect(pr).toBeUndefined();
|
||||
const result = await prWorker.ensurePr(config);
|
||||
isResultWithoutPr(result);
|
||||
expect(result.prBlockedBy).toBe('AwaitingTests');
|
||||
});
|
||||
it('should create PR if pending timeout hit', async () => {
|
||||
platform.getBranchStatus.mockResolvedValueOnce(BranchStatus.yellow);
|
||||
|
@ -488,24 +509,28 @@ describe('workers/pr/index', () => {
|
|||
);
|
||||
config.prCreation = 'not-pending';
|
||||
config.stabilityStatus = BranchStatus.yellow;
|
||||
const { pr } = await prWorker.ensurePr(config);
|
||||
expect(pr).toMatchObject({ displayNumber: 'New Pull Request' });
|
||||
const result = await prWorker.ensurePr(config);
|
||||
isResultWithPr(result);
|
||||
expect(result.pr).toMatchObject({ displayNumber: 'New Pull Request' });
|
||||
});
|
||||
it('should create PR if no longer pending', async () => {
|
||||
platform.getBranchStatus.mockResolvedValueOnce(BranchStatus.red);
|
||||
config.prCreation = 'not-pending';
|
||||
const { pr } = await prWorker.ensurePr(config);
|
||||
expect(pr).toMatchObject({ displayNumber: 'New Pull Request' });
|
||||
const result = await prWorker.ensurePr(config);
|
||||
isResultWithPr(result);
|
||||
expect(result.pr).toMatchObject({ displayNumber: 'New Pull Request' });
|
||||
});
|
||||
it('should create new branch if none exists', async () => {
|
||||
const { pr } = await prWorker.ensurePr(config);
|
||||
expect(pr).toMatchObject({ displayNumber: 'New Pull Request' });
|
||||
const result = await prWorker.ensurePr(config);
|
||||
isResultWithPr(result);
|
||||
expect(result.pr).toMatchObject({ displayNumber: 'New Pull Request' });
|
||||
});
|
||||
it('should add assignees and reviewers to new PR', async () => {
|
||||
config.assignees = ['@foo', 'bar'];
|
||||
config.reviewers = ['baz', '@boo'];
|
||||
const { pr } = await prWorker.ensurePr(config);
|
||||
expect(pr).toMatchObject({ displayNumber: 'New Pull Request' });
|
||||
const result = await prWorker.ensurePr(config);
|
||||
isResultWithPr(result);
|
||||
expect(result.pr).toMatchObject({ displayNumber: 'New Pull Request' });
|
||||
expect(platform.addAssignees).toHaveBeenCalledTimes(1);
|
||||
expect(platform.addAssignees.mock.calls).toMatchSnapshot();
|
||||
expect(platform.addReviewers).toHaveBeenCalledTimes(1);
|
||||
|
@ -551,8 +576,9 @@ describe('workers/pr/index', () => {
|
|||
});
|
||||
config.assignees = ['@foo', 'bar'];
|
||||
config.reviewers = ['baz', '@boo'];
|
||||
const { pr } = await prWorker.ensurePr(config);
|
||||
expect(pr).toMatchObject({ displayNumber: 'New Pull Request' });
|
||||
const result = await prWorker.ensurePr(config);
|
||||
isResultWithPr(result);
|
||||
expect(result.pr).toMatchObject({ displayNumber: 'New Pull Request' });
|
||||
expect(platform.addAssignees).toHaveBeenCalledTimes(1);
|
||||
expect(platform.addReviewers).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
@ -562,8 +588,9 @@ describe('workers/pr/index', () => {
|
|||
});
|
||||
config.assignees = ['@foo', 'bar'];
|
||||
config.reviewers = ['baz', '@boo'];
|
||||
const { pr } = await prWorker.ensurePr(config);
|
||||
expect(pr).toMatchObject({ displayNumber: 'New Pull Request' });
|
||||
const result = await prWorker.ensurePr(config);
|
||||
isResultWithPr(result);
|
||||
expect(result.pr).toMatchObject({ displayNumber: 'New Pull Request' });
|
||||
expect(platform.addAssignees).toHaveBeenCalledTimes(1);
|
||||
expect(platform.addReviewers).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
@ -571,8 +598,9 @@ describe('workers/pr/index', () => {
|
|||
config.assignees = ['bar'];
|
||||
config.reviewers = ['baz'];
|
||||
config.automerge = true;
|
||||
const { pr } = await prWorker.ensurePr(config);
|
||||
expect(pr).toMatchObject({ displayNumber: 'New Pull Request' });
|
||||
const result = await prWorker.ensurePr(config);
|
||||
isResultWithPr(result);
|
||||
expect(result.pr).toMatchObject({ displayNumber: 'New Pull Request' });
|
||||
expect(platform.addAssignees).toHaveBeenCalledTimes(0);
|
||||
expect(platform.addReviewers).toHaveBeenCalledTimes(0);
|
||||
});
|
||||
|
@ -581,8 +609,9 @@ describe('workers/pr/index', () => {
|
|||
config.reviewers = ['baz'];
|
||||
config.automerge = true;
|
||||
config.assignAutomerge = true;
|
||||
const { pr } = await prWorker.ensurePr(config);
|
||||
expect(pr).toMatchObject({ displayNumber: 'New Pull Request' });
|
||||
const result = await prWorker.ensurePr(config);
|
||||
isResultWithPr(result);
|
||||
expect(result.pr).toMatchObject({ displayNumber: 'New Pull Request' });
|
||||
expect(platform.addAssignees).toHaveBeenCalledTimes(1);
|
||||
expect(platform.addReviewers).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
@ -591,8 +620,9 @@ describe('workers/pr/index', () => {
|
|||
config.assigneesSampleSize = 2;
|
||||
config.reviewers = ['baz', 'boo', 'bor'];
|
||||
config.reviewersSampleSize = 2;
|
||||
const { pr } = await prWorker.ensurePr(config);
|
||||
expect(pr).toMatchObject({ displayNumber: 'New Pull Request' });
|
||||
const result = await prWorker.ensurePr(config);
|
||||
isResultWithPr(result);
|
||||
expect(result.pr).toMatchObject({ displayNumber: 'New Pull Request' });
|
||||
expect(platform.addAssignees).toHaveBeenCalledTimes(1);
|
||||
const assignees = platform.addAssignees.mock.calls[0][1];
|
||||
expect(assignees).toHaveLength(2);
|
||||
|
@ -608,24 +638,27 @@ describe('workers/pr/index', () => {
|
|||
config.assigneesSampleSize = 0;
|
||||
config.reviewers = ['baz', 'boo', 'bor'];
|
||||
config.reviewersSampleSize = 0;
|
||||
const { pr } = await prWorker.ensurePr(config);
|
||||
expect(pr).toMatchObject({ displayNumber: 'New Pull Request' });
|
||||
const result = await prWorker.ensurePr(config);
|
||||
isResultWithPr(result);
|
||||
expect(result.pr).toMatchObject({ displayNumber: 'New Pull Request' });
|
||||
expect(platform.addAssignees).toHaveBeenCalledTimes(0);
|
||||
expect(platform.addReviewers).toHaveBeenCalledTimes(0);
|
||||
});
|
||||
it('should add and deduplicate additionalReviewers on new PR', async () => {
|
||||
config.reviewers = ['@foo', 'bar'];
|
||||
config.additionalReviewers = ['bar', 'baz', '@boo'];
|
||||
const { pr } = await prWorker.ensurePr(config);
|
||||
expect(pr).toMatchObject({ displayNumber: 'New Pull Request' });
|
||||
const result = await prWorker.ensurePr(config);
|
||||
isResultWithPr(result);
|
||||
expect(result.pr).toMatchObject({ displayNumber: 'New Pull Request' });
|
||||
expect(platform.addReviewers).toHaveBeenCalledTimes(1);
|
||||
expect(platform.addReviewers.mock.calls).toMatchSnapshot();
|
||||
});
|
||||
it('should add and deduplicate additionalReviewers to empty reviewers on new PR', async () => {
|
||||
config.reviewers = [];
|
||||
config.additionalReviewers = ['bar', 'baz', '@boo', '@foo', 'bar'];
|
||||
const { pr } = await prWorker.ensurePr(config);
|
||||
expect(pr).toMatchObject({ displayNumber: 'New Pull Request' });
|
||||
const result = await prWorker.ensurePr(config);
|
||||
isResultWithPr(result);
|
||||
expect(result.pr).toMatchObject({ displayNumber: 'New Pull Request' });
|
||||
expect(platform.addReviewers).toHaveBeenCalledTimes(1);
|
||||
expect(platform.addReviewers.mock.calls).toMatchSnapshot();
|
||||
});
|
||||
|
@ -635,10 +668,11 @@ describe('workers/pr/index', () => {
|
|||
config.automerge = true;
|
||||
config.schedule = ['before 5am'];
|
||||
config.logJSON = await changelogHelper.getChangeLogJSON(config);
|
||||
const { pr } = await prWorker.ensurePr(config);
|
||||
const result = await prWorker.ensurePr(config);
|
||||
isResultWithPr(result);
|
||||
expect(platform.updatePr.mock.calls).toMatchSnapshot();
|
||||
expect(platform.updatePr).toHaveBeenCalledTimes(0);
|
||||
expect(pr).toMatchObject(existingPr);
|
||||
expect(result.pr).toMatchObject(existingPr);
|
||||
});
|
||||
it('should return unmodified existing PR if only whitespace changes', async () => {
|
||||
const modifiedPr = JSON.parse(
|
||||
|
@ -649,9 +683,10 @@ describe('workers/pr/index', () => {
|
|||
config.automerge = true;
|
||||
config.schedule = ['before 5am'];
|
||||
config.logJSON = await changelogHelper.getChangeLogJSON(config);
|
||||
const { pr } = await prWorker.ensurePr(config);
|
||||
const result = await prWorker.ensurePr(config);
|
||||
isResultWithPr(result);
|
||||
expect(platform.updatePr).toHaveBeenCalledTimes(0);
|
||||
expect(pr).toMatchObject(modifiedPr);
|
||||
expect(result.pr).toMatchObject(modifiedPr);
|
||||
});
|
||||
it('should return modified existing PR', async () => {
|
||||
config.newValue = '1.2.0';
|
||||
|
@ -659,8 +694,9 @@ describe('workers/pr/index', () => {
|
|||
config.schedule = ['before 5am'];
|
||||
config.logJSON = await changelogHelper.getChangeLogJSON(config);
|
||||
platform.getBranchPr.mockResolvedValueOnce(existingPr);
|
||||
const { pr } = await prWorker.ensurePr(config);
|
||||
expect(pr).toMatchSnapshot({
|
||||
const result = await prWorker.ensurePr(config);
|
||||
isResultWithPr(result);
|
||||
expect(result.pr).toMatchSnapshot({
|
||||
displayNumber: 'Existing PR',
|
||||
title: 'Update dependency dummy to v1.1.0',
|
||||
});
|
||||
|
@ -671,8 +707,9 @@ describe('workers/pr/index', () => {
|
|||
...existingPr,
|
||||
title: 'wrong',
|
||||
});
|
||||
const { pr } = await prWorker.ensurePr(config);
|
||||
expect(pr).toMatchSnapshot({
|
||||
const result = await prWorker.ensurePr(config);
|
||||
isResultWithPr(result);
|
||||
expect(result.pr).toMatchSnapshot({
|
||||
displayNumber: 'Existing PR',
|
||||
title: 'wrong',
|
||||
});
|
||||
|
@ -682,33 +719,36 @@ describe('workers/pr/index', () => {
|
|||
config.automergeType = 'branch';
|
||||
config.branchAutomergeFailureMessage = 'branch status error';
|
||||
platform.getBranchStatus.mockResolvedValueOnce(BranchStatus.red);
|
||||
const { pr } = await prWorker.ensurePr(config);
|
||||
expect(pr).toMatchObject({ displayNumber: 'New Pull Request' });
|
||||
const result = await prWorker.ensurePr(config);
|
||||
isResultWithPr(result);
|
||||
expect(result.pr).toMatchObject({ displayNumber: 'New Pull Request' });
|
||||
});
|
||||
it('should create PR if branch automerging failed', async () => {
|
||||
config.automerge = true;
|
||||
config.automergeType = 'branch';
|
||||
platform.getBranchStatus.mockResolvedValueOnce(BranchStatus.green);
|
||||
config.forcePr = true;
|
||||
const { pr } = await prWorker.ensurePr(config);
|
||||
expect(pr).toMatchObject({ displayNumber: 'New Pull Request' });
|
||||
const result = await prWorker.ensurePr(config);
|
||||
isResultWithPr(result);
|
||||
expect(result.pr).toMatchObject({ displayNumber: 'New Pull Request' });
|
||||
});
|
||||
it('should return no PR if branch automerging not failed', async () => {
|
||||
config.automerge = true;
|
||||
config.automergeType = 'branch';
|
||||
platform.getBranchStatus.mockResolvedValueOnce(BranchStatus.yellow);
|
||||
git.getBranchLastCommitTime.mockResolvedValueOnce(new Date());
|
||||
const { prBlockedBy, pr } = await prWorker.ensurePr(config);
|
||||
expect(prBlockedBy).toBe('BranchAutomerge');
|
||||
expect(pr).toBeUndefined();
|
||||
const result = await prWorker.ensurePr(config);
|
||||
isResultWithoutPr(result);
|
||||
expect(result.prBlockedBy).toBe('BranchAutomerge');
|
||||
});
|
||||
it('should return PR if branch automerging taking too long', async () => {
|
||||
config.automerge = true;
|
||||
config.automergeType = 'branch';
|
||||
platform.getBranchStatus.mockResolvedValueOnce(BranchStatus.yellow);
|
||||
git.getBranchLastCommitTime.mockResolvedValueOnce(new Date('2018-01-01'));
|
||||
const { pr } = await prWorker.ensurePr(config);
|
||||
expect(pr).toBeDefined();
|
||||
const result = await prWorker.ensurePr(config);
|
||||
isResultWithPr(result);
|
||||
expect(result.pr).toBeDefined();
|
||||
});
|
||||
it('should return no PR if stabilityStatus yellow', async () => {
|
||||
config.automerge = true;
|
||||
|
@ -716,14 +756,15 @@ describe('workers/pr/index', () => {
|
|||
config.stabilityStatus = BranchStatus.yellow;
|
||||
platform.getBranchStatus.mockResolvedValueOnce(BranchStatus.yellow);
|
||||
git.getBranchLastCommitTime.mockResolvedValueOnce(new Date('2018-01-01'));
|
||||
const { prBlockedBy, pr } = await prWorker.ensurePr(config);
|
||||
expect(prBlockedBy).toBe('BranchAutomerge');
|
||||
expect(pr).toBeUndefined();
|
||||
const result = await prWorker.ensurePr(config);
|
||||
isResultWithoutPr(result);
|
||||
expect(result.prBlockedBy).toBe('BranchAutomerge');
|
||||
});
|
||||
it('handles duplicate upgrades', async () => {
|
||||
config.upgrades.push(config.upgrades[0]);
|
||||
const { pr } = await prWorker.ensurePr(config);
|
||||
expect(pr).toMatchObject({ displayNumber: 'New Pull Request' });
|
||||
const result = await prWorker.ensurePr(config);
|
||||
isResultWithPr(result);
|
||||
expect(result.pr).toMatchObject({ displayNumber: 'New Pull Request' });
|
||||
});
|
||||
it('should create privateRepo PR if success', async () => {
|
||||
platform.getBranchStatus.mockResolvedValueOnce(BranchStatus.green);
|
||||
|
@ -731,8 +772,9 @@ describe('workers/pr/index', () => {
|
|||
config.privateRepo = false;
|
||||
config.logJSON = await changelogHelper.getChangeLogJSON(config);
|
||||
config.logJSON.project.repository = 'someproject';
|
||||
const { pr } = await prWorker.ensurePr(config);
|
||||
expect(pr).toMatchObject({ displayNumber: 'New Pull Request' });
|
||||
const result = await prWorker.ensurePr(config);
|
||||
isResultWithPr(result);
|
||||
expect(result.pr).toMatchObject({ displayNumber: 'New Pull Request' });
|
||||
expect(platform.createPr.mock.calls[0]).toMatchSnapshot();
|
||||
existingPr.body = platform.createPr.mock.calls[0][0].prBody;
|
||||
});
|
||||
|
@ -742,8 +784,9 @@ describe('workers/pr/index', () => {
|
|||
config.prCreation = 'not-pending';
|
||||
config.artifactErrors = [{}];
|
||||
config.platform = PlatformId.Gitlab;
|
||||
const { pr } = await prWorker.ensurePr(config);
|
||||
expect(pr).toMatchObject({ displayNumber: 'New Pull Request' });
|
||||
const result = await prWorker.ensurePr(config);
|
||||
isResultWithPr(result);
|
||||
expect(result.pr).toMatchObject({ displayNumber: 'New Pull Request' });
|
||||
});
|
||||
|
||||
it('should trigger GitLab automerge when configured', async () => {
|
||||
|
@ -761,8 +804,9 @@ describe('workers/pr/index', () => {
|
|||
it('should create a PR with set of labels and mergeable addLabels', async () => {
|
||||
config.labels = ['deps', 'renovate'];
|
||||
config.addLabels = ['deps', 'js'];
|
||||
const { pr } = await prWorker.ensurePr(config);
|
||||
expect(pr).toBeDefined();
|
||||
const result = await prWorker.ensurePr(config);
|
||||
isResultWithPr(result);
|
||||
expect(result.pr).toBeDefined();
|
||||
expect(platform.createPr.mock.calls[0][0]).toMatchObject({
|
||||
labels: ['deps', 'renovate', 'js'],
|
||||
});
|
||||
|
|
|
@ -145,12 +145,12 @@ export function getPlatformPrOptions(
|
|||
}
|
||||
|
||||
export type ResultWithPr = {
|
||||
type: 'with-pr';
|
||||
pr: Pr;
|
||||
prBlockedBy?: never;
|
||||
};
|
||||
|
||||
export type ResultWithoutPr = {
|
||||
pr?: never;
|
||||
type: 'without-pr';
|
||||
prBlockedBy: PrBlockedBy;
|
||||
};
|
||||
|
||||
|
@ -217,14 +217,14 @@ export async function ensurePr(
|
|||
logger.debug(`Branch tests failed, so will create PR`);
|
||||
} else {
|
||||
// Branch should be automerged, so we don't want to create a PR
|
||||
return { prBlockedBy: 'BranchAutomerge' };
|
||||
return { type: 'without-pr', prBlockedBy: 'BranchAutomerge' };
|
||||
}
|
||||
}
|
||||
if (config.prCreation === 'status-success') {
|
||||
logger.debug('Checking branch combined status');
|
||||
if ((await getBranchStatus()) !== BranchStatus.green) {
|
||||
logger.debug(`Branch status isn't green - not creating PR`);
|
||||
return { prBlockedBy: 'AwaitingTests' };
|
||||
return { type: 'without-pr', prBlockedBy: 'AwaitingTests' };
|
||||
}
|
||||
logger.debug('Branch status success');
|
||||
} else if (
|
||||
|
@ -232,7 +232,7 @@ export async function ensurePr(
|
|||
!existingPr &&
|
||||
dependencyDashboardCheck !== 'approvePr'
|
||||
) {
|
||||
return { prBlockedBy: 'NeedsApproval' };
|
||||
return { type: 'without-pr', prBlockedBy: 'NeedsApproval' };
|
||||
} else if (
|
||||
config.prCreation === 'not-pending' &&
|
||||
!existingPr &&
|
||||
|
@ -257,6 +257,7 @@ export async function ensurePr(
|
|||
`Branch is ${elapsedHours} hours old - skipping PR creation`
|
||||
);
|
||||
return {
|
||||
type: 'without-pr',
|
||||
prBlockedBy: 'AwaitingTests',
|
||||
};
|
||||
}
|
||||
|
@ -385,7 +386,7 @@ export async function ensurePr(
|
|||
noWhitespaceOrHeadings(stripEmojis(prBody))
|
||||
) {
|
||||
logger.debug(`${existingPr.displayNumber} does not need updating`);
|
||||
return { pr: existingPr };
|
||||
return { type: 'with-pr', pr: existingPr };
|
||||
}
|
||||
// PR must need updating
|
||||
if (existingPrTitle !== newPrTitle) {
|
||||
|
@ -417,9 +418,7 @@ export async function ensurePr(
|
|||
});
|
||||
logger.info({ pr: existingPr.number, prTitle }, `PR updated`);
|
||||
}
|
||||
return {
|
||||
pr: existingPr,
|
||||
};
|
||||
return { type: 'with-pr', pr: existingPr };
|
||||
}
|
||||
logger.debug({ branch: branchName, prTitle }, `Creating PR`);
|
||||
// istanbul ignore if
|
||||
|
@ -439,7 +438,7 @@ export async function ensurePr(
|
|||
!config.isVulnerabilityAlert
|
||||
) {
|
||||
logger.debug('Skipping PR - limit reached');
|
||||
return { prBlockedBy: 'RateLimited' };
|
||||
return { type: 'without-pr', prBlockedBy: 'RateLimited' };
|
||||
}
|
||||
pr = await platform.createPr({
|
||||
sourceBranch: branchName,
|
||||
|
@ -463,7 +462,7 @@ export async function ensurePr(
|
|||
)
|
||||
) {
|
||||
logger.warn('A pull requests already exists');
|
||||
return { prBlockedBy: 'Error' };
|
||||
return { type: 'without-pr', prBlockedBy: 'Error' };
|
||||
}
|
||||
if (err.statusCode === 502) {
|
||||
logger.warn(
|
||||
|
@ -476,7 +475,7 @@ export async function ensurePr(
|
|||
await deleteBranch(branchName);
|
||||
}
|
||||
}
|
||||
return { prBlockedBy: 'Error' };
|
||||
return { type: 'without-pr', prBlockedBy: 'Error' };
|
||||
}
|
||||
if (
|
||||
config.branchAutomergeFailureMessage &&
|
||||
|
@ -514,7 +513,7 @@ export async function ensurePr(
|
|||
await addAssigneesReviewers(config, pr);
|
||||
}
|
||||
logger.debug(`Created ${pr.displayNumber}`);
|
||||
return { pr };
|
||||
return { type: 'with-pr', pr };
|
||||
} catch (err) {
|
||||
// istanbul ignore if
|
||||
if (
|
||||
|
@ -529,8 +528,8 @@ export async function ensurePr(
|
|||
logger.error({ err }, 'Failed to ensure PR: ' + prTitle);
|
||||
}
|
||||
if (existingPr) {
|
||||
return { pr: existingPr };
|
||||
return { type: 'with-pr', pr: existingPr };
|
||||
}
|
||||
// istanbul ignore next
|
||||
return { prBlockedBy: 'Error' };
|
||||
return { type: 'without-pr', prBlockedBy: 'Error' };
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue