diff --git a/lib/config/definitions.ts b/lib/config/definitions.ts index 93608fa3314c0b7db761d2dd67d7315e340a12a0..558c95c862de641e4d9eb678be30ab60c779177f 100644 --- a/lib/config/definitions.ts +++ b/lib/config/definitions.ts @@ -1630,7 +1630,6 @@ const options: RenovateOptions[] = [ 'artifactErrors', 'deprecationWarningIssues', 'onboardingClose', - 'prValidation', ], cli: false, env: false, diff --git a/lib/platform/__snapshots__/index.spec.ts.snap b/lib/platform/__snapshots__/index.spec.ts.snap index b7eb3bbe15110cec990a477d89d7c7b26da17449..98fa1383a4e99cf854347411ef54df3fce8da5f4 100644 --- a/lib/platform/__snapshots__/index.spec.ts.snap +++ b/lib/platform/__snapshots__/index.spec.ts.snap @@ -27,7 +27,6 @@ Array [ "getIssueList", "getPr", "getPrBody", - "getPrFiles", "getPrList", "getRepoForceRebase", "getRepoStatus", @@ -72,7 +71,6 @@ Array [ "getIssueList", "getPr", "getPrBody", - "getPrFiles", "getPrList", "getRepoForceRebase", "getRepoStatus", @@ -117,7 +115,6 @@ Array [ "getIssueList", "getPr", "getPrBody", - "getPrFiles", "getPrList", "getRepoForceRebase", "getRepoStatus", @@ -162,7 +159,6 @@ Array [ "getIssueList", "getPr", "getPrBody", - "getPrFiles", "getPrList", "getRepoForceRebase", "getRepoStatus", diff --git a/lib/platform/azure/index.spec.ts b/lib/platform/azure/index.spec.ts index 075e162cb2dda328fe89d1f5098222c462eec98e..ae79418894ebb30828ac55a65f8a2dfd879960f0 100644 --- a/lib/platform/azure/index.spec.ts +++ b/lib/platform/azure/index.spec.ts @@ -887,56 +887,6 @@ describe('platform/azure', () => { }); }); - describe('getPrFiles', () => { - it('single change', async () => { - azureApi.gitApi.mockImplementationOnce( - () => - ({ - getPullRequestIterations: jest.fn(() => [{ id: 1 }]), - getPullRequestIterationChanges: jest.fn(() => ({ - changeEntries: [{ item: { path: '/index.js' } }], - })), - } as any) - ); - const res = await azure.getPrFiles(46); - expect(res).toHaveLength(1); - expect(res).toEqual(['index.js']); - }); - it('multiple changes', async () => { - azureApi.gitApi.mockImplementationOnce( - () => - ({ - getPullRequestIterations: jest.fn(() => [{ id: 1 }, { id: 2 }]), - getPullRequestIterationChanges: jest - .fn() - .mockResolvedValueOnce({ - changeEntries: [{ item: { path: '/index.js' } }], - }) - .mockResolvedValueOnce({ - changeEntries: [{ item: { path: '/package.json' } }], - }), - } as any) - ); - const res = await azure.getPrFiles(46); - expect(res).toHaveLength(2); - expect(res).toEqual(['index.js', 'package.json']); - }); - it('deduplicate changes', async () => { - azureApi.gitApi.mockImplementationOnce( - () => - ({ - getPullRequestIterations: jest.fn(() => [{ id: 1 }, { id: 2 }]), - getPullRequestIterationChanges: jest.fn().mockResolvedValue({ - changeEntries: [{ item: { path: '/index.js' } }], - }), - } as any) - ); - const res = await azure.getPrFiles(46); - expect(res).toHaveLength(1); - expect(res).toEqual(['index.js']); - }); - }); - describe('Not supported by Azure DevOps (yet!)', () => { it('setBranchStatus', async () => { const res = await azure.setBranchStatus({ diff --git a/lib/platform/azure/index.ts b/lib/platform/azure/index.ts index cdfcb1cd981fe6485e3599f9453ee80df31ca33c..f45c5dfb3d0fbcce3d6ab2142b4443589161ae76 100644 --- a/lib/platform/azure/index.ts +++ b/lib/platform/azure/index.ts @@ -757,34 +757,6 @@ export /* istanbul ignore next */ async function deleteLabel( await azureApiGit.deletePullRequestLabels(config.repoId, prNumber, label); } -export async function getPrFiles(prId: number): Promise<string[]> { - const azureApiGit = await azureApi.gitApi(); - const prIterations = await azureApiGit.getPullRequestIterations( - config.repoId, - prId - ); - return [ - ...new Set( - ( - await Promise.all( - prIterations.map( - async (iteration) => - ( - await azureApiGit.getPullRequestIterationChanges( - config.repoId, - prId, - iteration.id - ) - ).changeEntries - ) - ) - ) - .reduce((acc, val) => acc.concat(val), []) - .map((change) => change.item.path.slice(1)) - ), - ]; -} - export function getVulnerabilityAlerts(): Promise<VulnerabilityAlert[]> { return Promise.resolve([]); } diff --git a/lib/platform/bitbucket-server/__snapshots__/index.spec.ts.snap b/lib/platform/bitbucket-server/__snapshots__/index.spec.ts.snap index d1f24607eb05110189aedcb0b98dbf8b949c1cd3..1dcb15dbae1c05f7d48b7ee4999fed64794312a7 100644 --- a/lib/platform/bitbucket-server/__snapshots__/index.spec.ts.snap +++ b/lib/platform/bitbucket-server/__snapshots__/index.spec.ts.snap @@ -999,21 +999,6 @@ Followed by some information. " `; -exports[`platform/bitbucket-server endpoint with no path getPrFiles() returns one file 1`] = ` -Array [ - Array [ - "./rest/api/1.0/projects/SOME/repos/repo", - ], - Array [ - "./rest/api/1.0/projects/SOME/repos/repo/branches/default", - ], - Array [ - "./rest/api/1.0/projects/SOME/repos/repo/pull-requests/5/changes?withComments=false&limit=100", - undefined, - ], -] -`; - exports[`platform/bitbucket-server endpoint with no path getPrList() has pr 1`] = ` Array [ Object { @@ -2602,21 +2587,6 @@ Followed by some information. " `; -exports[`platform/bitbucket-server endpoint with path getPrFiles() returns one file 1`] = ` -Array [ - Array [ - "./rest/api/1.0/projects/SOME/repos/repo", - ], - Array [ - "./rest/api/1.0/projects/SOME/repos/repo/branches/default", - ], - Array [ - "./rest/api/1.0/projects/SOME/repos/repo/pull-requests/5/changes?withComments=false&limit=100", - undefined, - ], -] -`; - exports[`platform/bitbucket-server endpoint with path getPrList() has pr 1`] = ` Array [ Object { diff --git a/lib/platform/bitbucket-server/index.spec.ts b/lib/platform/bitbucket-server/index.spec.ts index 13d27fe513164a3bef5a155d7954ed39bbc2f8da..a21c5e69be4111fe98ee9898639ad62528abb1ee 100644 --- a/lib/platform/bitbucket-server/index.spec.ts +++ b/lib/platform/bitbucket-server/index.spec.ts @@ -668,20 +668,6 @@ describe('platform/bitbucket-server', () => { }); }); - describe('getPrFiles()', () => { - it('returns empty files', async () => { - expect.assertions(1); - expect(await bitbucket.getPrFiles(null as any)).toHaveLength(0); - }); - - it('returns one file', async () => { - expect.assertions(2); - await initRepo(); - expect(await bitbucket.getPrFiles(5)).toHaveLength(1); - expect(api.get.mock.calls).toMatchSnapshot(); - }); - }); - describe('updatePr()', () => { it('puts PR', async () => { expect.assertions(2); diff --git a/lib/platform/bitbucket-server/index.ts b/lib/platform/bitbucket-server/index.ts index 60f141ada746cb84388323a1107e28e7ba22c7ed..d9990be694624d3c1b0f6098378718ed507e9d21 100644 --- a/lib/platform/bitbucket-server/index.ts +++ b/lib/platform/bitbucket-server/index.ts @@ -983,21 +983,6 @@ export async function createPr({ return pr; } -// Return a list of all modified files in a PR -// https://docs.atlassian.com/bitbucket-server/rest/6.0.0/bitbucket-rest.html -export async function getPrFiles(prNo: number): Promise<string[]> { - logger.debug(`getPrFiles(${prNo})`); - if (!prNo) { - return []; - } - - // GET /rest/api/1.0/projects/{projectKey}/repos/{repositorySlug}/pull-requests/{pullRequestId}/changes - const values = await utils.accumulateValues<{ path: { toString: string } }>( - `./rest/api/1.0/projects/${config.projectKey}/repos/${config.repositorySlug}/pull-requests/${prNo}/changes?withComments=false` - ); - return values.map((f) => f.path.toString); -} - export async function updatePr( prNo: number, title: string, diff --git a/lib/platform/bitbucket/__snapshots__/index.spec.ts.snap b/lib/platform/bitbucket/__snapshots__/index.spec.ts.snap index 07c808a839e8d675f5ef06c8e7b5fe5d7618e2fd..041bca3797f3a6d94abd716bb378d870a97e7326 100644 --- a/lib/platform/bitbucket/__snapshots__/index.spec.ts.snap +++ b/lib/platform/bitbucket/__snapshots__/index.spec.ts.snap @@ -290,12 +290,6 @@ Object { exports[`platform/bitbucket getPrBody() returns diff files 1`] = `"**foo**bartext"`; -exports[`platform/bitbucket getPrFiles() returns diff files 1`] = ` -Array [ - "requirements.txt", -] -`; - exports[`platform/bitbucket getRepoStatus() sends to gitFs 1`] = `undefined`; exports[`platform/bitbucket initPlatform() should init 1`] = ` diff --git a/lib/platform/bitbucket/index.spec.ts b/lib/platform/bitbucket/index.spec.ts index 118372a6e4429689d9006c0193a041c51c97e002..7d96778a75a7ef82ca638e6abe693979171dafac 100644 --- a/lib/platform/bitbucket/index.spec.ts +++ b/lib/platform/bitbucket/index.spec.ts @@ -461,14 +461,6 @@ describe('platform/bitbucket', () => { }); }); - describe('getPrFiles()', () => { - const getPrFiles = wrap('getPrFiles'); - it('returns diff files', async () => { - await initRepo(); - expect(await getPrFiles(5)).toMatchSnapshot(); - }); - }); - describe('getPrBody()', () => { it('returns diff files', () => { expect( diff --git a/lib/platform/bitbucket/index.ts b/lib/platform/bitbucket/index.ts index 68d6380f838f1e9b888479f7b544439e99f793ae..0d7f8b80621b9b1d8a67b396d9e470a284e091bf 100644 --- a/lib/platform/bitbucket/index.ts +++ b/lib/platform/bitbucket/index.ts @@ -789,19 +789,6 @@ interface Commit { author: { raw: string }; } -// Return a list of all modified files in a PR -export async function getPrFiles(prNo: number): Promise<string[]> { - logger.debug({ prNo }, 'getPrFiles'); - const diff = ( - await api.get( - `/2.0/repositories/${config.repository}/pullrequests/${prNo}/diff`, - { json: false } as any - ) - ).body; - const files = parseDiff(diff).map((file) => file.to); - return files; -} - export async function updatePr( prNo: number, title: string, diff --git a/lib/platform/common.ts b/lib/platform/common.ts index 285dde288589d837cd74a855ef4c748da7c055dd..77ba0ff1048fcedffb8f0e88f1aedfa9bca16ed5 100644 --- a/lib/platform/common.ts +++ b/lib/platform/common.ts @@ -190,7 +190,6 @@ export interface Platform { setBranchPrefix(branchPrefix: string): Promise<void>; initRepo(config: RepoParams): Promise<RepoConfig>; cleanRepo(): Promise<void>; - getPrFiles(prNo: number): Promise<string[]>; getPrList(): Promise<Pr[]>; getAllRenovateBranches(branchPrefix: string): Promise<string[]>; ensureIssueClosing(title: string): Promise<void>; diff --git a/lib/platform/gitea/index.spec.ts b/lib/platform/gitea/index.spec.ts index b69db5552e0e2d7fc29ab87d79aa0324350721f1..09debc993465eea598ce7380915efb5522b257ca 100644 --- a/lib/platform/gitea/index.spec.ts +++ b/lib/platform/gitea/index.spec.ts @@ -2,7 +2,6 @@ import { BranchStatusConfig, CommitFilesConfig, File, - GotResponse, Platform, RepoConfig, RepoParams, @@ -19,13 +18,11 @@ import { } from '../../constants/error-messages'; import { logger as _logger } from '../../logger'; import { BranchStatus } from '../../types'; -import { GiteaGotApi } from './gitea-got-wrapper'; import * as ght from './gitea-helper'; describe('platform/gitea', () => { let gitea: Platform; let helper: jest.Mocked<typeof import('./gitea-helper')>; - let api: jest.Mocked<GiteaGotApi>; let logger: jest.Mocked<typeof _logger>; let GitStorage: jest.Mocked<typeof import('../git/storage').Storage> & jest.Mock; @@ -182,7 +179,6 @@ describe('platform/gitea', () => { gitea = await import('.'); helper = (await import('./gitea-helper')) as any; - api = (await import('./gitea-got-wrapper')).api as any; logger = (await import('../../logger')).logger as any; GitStorage = (await import('../git/storage')).Storage as any; @@ -937,47 +933,6 @@ describe('platform/gitea', () => { }); }); - describe('getPrFiles', () => { - it('should return empty list without passing a pull request', async () => { - await initFakeRepo(); - - expect(await gitea.getPrFiles(undefined)).toEqual([]); - }); - - it('should return modified files when passing a pull request', async () => { - const mockPR = mockPRs[0]; - const mockDiff = ` -diff --git a/test b/test -deleted file mode 100644 -index 60fffd1..0000000 ---- a/test -+++ /dev/null -@@ -1 +0,0 @@ --previously -diff --git a/this is spaces b/this is spaces -new file mode 100644 -index 0000000..2173594 ---- /dev/null -+++ b/this is spacey -@@ -0,0 +1 @@ -+nowadays -`; - - helper.getPR.mockResolvedValueOnce(mockPR); - api.get.mockResolvedValueOnce( - partial<GotResponse>({ - body: mockDiff, - }) - ); - await initFakeRepo(); - - expect(await gitea.getPrFiles(mockPR.number)).toEqual([ - 'test', - 'this is spaces', - ]); - }); - }); - describe('findIssue', () => { it('should return existing open issue', async () => { const mockIssue = mockIssues.find((i) => i.title === 'open-issue'); diff --git a/lib/platform/gitea/index.ts b/lib/platform/gitea/index.ts index 5e9ce871b83a03a076c7f6ae6b72119a44f7724f..f470d407c701f07c9aa154ef17fe95b0bd679cce 100644 --- a/lib/platform/gitea/index.ts +++ b/lib/platform/gitea/index.ts @@ -625,30 +625,6 @@ const platform: Platform = { } }, - async getPrFiles(prNo: number): Promise<string[]> { - if (!prNo) { - return []; - } - - // Retrieving a diff for a PR is not officially supported by Gitea as of today - // See tracking issue: https://github.com/go-gitea/gitea/issues/5561 - // Workaround: Parse new paths in .diff file using regular expressions - const regex = /^diff --git a\/.+ b\/(.+)$/gm; - const pr = await helper.getPR(config.repository, prNo); - const diff = (await api.get(pr.diff_url)).body as string; - - const changedFiles: string[] = []; - let match: string[]; - do { - match = regex.exec(diff); - if (match) { - changedFiles.push(match[1]); - } - } while (match); - - return changedFiles; - }, - getIssueList(): Promise<Issue[]> { if (config.issueList === null) { config.issueList = helper @@ -983,7 +959,6 @@ export const { getIssueList, getPr, getPrBody, - getPrFiles, getPrList, getRepoForceRebase, getRepoStatus, diff --git a/lib/platform/github/__snapshots__/index.spec.ts.snap b/lib/platform/github/__snapshots__/index.spec.ts.snap index ed2b5c883451c0e502225ad58fe33f3faf77680c..47717b36c70982a8c5d9167728bb2f0d72c031bd 100644 --- a/lib/platform/github/__snapshots__/index.spec.ts.snap +++ b/lib/platform/github/__snapshots__/index.spec.ts.snap @@ -4225,29 +4225,6 @@ Array [ exports[`platform/github getPrBody(input) returns updated pr body 1`] = `"https://github.com/foo/bar/issues/5 plus also [a link](https://togithub.com/foo/bar/issues/5)"`; -exports[`platform/github getPrFiles() returns files 1`] = ` -Array [ - "renovate.json", - "not renovate.json", -] -`; - -exports[`platform/github getPrFiles() returns files 2`] = ` -Array [ - Object { - "headers": Object { - "accept": "application/json", - "accept-encoding": "gzip, deflate", - "authorization": "token abc123", - "host": "api.github.com", - "user-agent": "https://github.com/renovatebot/renovate", - }, - "method": "GET", - "url": "https://api.github.com/repos/undefined/pulls/123/files", - }, -] -`; - exports[`platform/github getRepoForceRebase should detect repoForceRebase 1`] = ` Array [ Object { diff --git a/lib/platform/github/index.spec.ts b/lib/platform/github/index.spec.ts index 759b0940c83979ce025182a4e00636af669e9ce1..37d7ffc7f63e81fd628b3a7b5c4705e7372da727 100644 --- a/lib/platform/github/index.spec.ts +++ b/lib/platform/github/index.spec.ts @@ -1933,25 +1933,6 @@ describe('platform/github', () => { expect(httpMock.getTrace()).toMatchSnapshot(); }); }); - describe('getPrFiles()', () => { - it('should return empty if no prNo is passed', async () => { - const prFiles = await github.getPrFiles(0); - expect(prFiles).toEqual([]); - }); - it('returns files', async () => { - httpMock - .scope(githubApiHost) - .get('/repos/undefined/pulls/123/files') - .reply(200, [ - { filename: 'renovate.json' }, - { filename: 'not renovate.json' }, - ]); - const prFiles = await github.getPrFiles(123); - expect(prFiles).toMatchSnapshot(); - expect(prFiles).toHaveLength(2); - expect(httpMock.getTrace()).toMatchSnapshot(); - }); - }); describe('updatePr(prNo, title, body)', () => { it('should update the PR', async () => { const scope = httpMock.scope(githubApiHost); diff --git a/lib/platform/github/index.ts b/lib/platform/github/index.ts index 93da5144f3a135eeced01e87861ff44ffe8b1087..8b94795b151699cc642d860ae1cefa89cb67eb70 100644 --- a/lib/platform/github/index.ts +++ b/lib/platform/github/index.ts @@ -1662,20 +1662,6 @@ export async function createPr({ return pr; } -// Return a list of all modified files in a PR -export async function getPrFiles(prNo: number): Promise<string[]> { - logger.debug({ prNo }, 'getPrFiles'); - if (!prNo) { - return []; - } - const files = ( - await githubApi.getJson<{ filename: string }[]>( - `repos/${config.parentRepo || config.repository}/pulls/${prNo}/files` - ) - ).body; - return files.map((f) => f.filename); -} - export async function updatePr( prNo: number, title: string, diff --git a/lib/platform/gitlab/__snapshots__/index.spec.ts.snap b/lib/platform/gitlab/__snapshots__/index.spec.ts.snap index a4d391bed3a88ce9fb9db834bee19e197cd1cf99..0c807d80bc25e34f7de103345e6c0ece241ea932 100644 --- a/lib/platform/gitlab/__snapshots__/index.spec.ts.snap +++ b/lib/platform/gitlab/__snapshots__/index.spec.ts.snap @@ -1692,29 +1692,6 @@ These updates have all been created already. Click a checkbox below to force a r " `; -exports[`platform/gitlab getPrFiles() returns files 1`] = ` -Array [ - "renovate.json", - "not renovate.json", -] -`; - -exports[`platform/gitlab getPrFiles() returns files 2`] = ` -Array [ - Object { - "headers": Object { - "accept": "application/json", - "accept-encoding": "gzip, deflate", - "host": "gitlab.com", - "private-token": "abc123", - "user-agent": "https://github.com/renovatebot/renovate", - }, - "method": "GET", - "url": "https://gitlab.com/api/v4/projects/undefined/merge_requests/123/changes", - }, -] -`; - exports[`platform/gitlab getRepoForceRebase should return false 1`] = ` Array [ Object { diff --git a/lib/platform/gitlab/index.ts b/lib/platform/gitlab/index.ts index bbfcfc600d7fc2ad3fa9aaae8ac99c7d1159e078..38dff081af8419b2cc597b8122601f9d572943f4 100644 --- a/lib/platform/gitlab/index.ts +++ b/lib/platform/gitlab/index.ts @@ -479,20 +479,6 @@ export async function getPr(iid: number): Promise<Pr> { return pr; } -// Return a list of all modified files in a PR -export async function getPrFiles(mrNo: number): Promise<string[]> { - logger.debug({ mrNo }, 'getPrFiles'); - if (!mrNo) { - return []; - } - const files = ( - await api.get( - `projects/${config.repository}/merge_requests/${mrNo}/changes` - ) - ).body.changes; - return files.map((f: { new_path: string }) => f.new_path); -} - // istanbul ignore next async function closePr(iid: number): Promise<void> { await api.put(`projects/${config.repository}/merge_requests/${iid}`, { diff --git a/lib/workers/repository/finalise/index.ts b/lib/workers/repository/finalise/index.ts index 8ae76928448eccd2dc6f6344ceb794b8b9a824dd..1d893607437ac5c35876dc2dcbcd19a4f9b013f0 100644 --- a/lib/workers/repository/finalise/index.ts +++ b/lib/workers/repository/finalise/index.ts @@ -1,15 +1,12 @@ import { RenovateConfig } from '../../../config'; import { platform } from '../../../platform'; import { pruneStaleBranches } from './prune'; -import { validatePrs } from './validate'; // istanbul ignore next export async function finaliseRepo( config: RenovateConfig, branchList: string[] ): Promise<void> { - // TODO: Promise.all - await validatePrs(config); await pruneStaleBranches(config, branchList); await platform.ensureIssueClosing( `Action Required: Fix Renovate Configuration` diff --git a/lib/workers/repository/finalise/validate.spec.ts b/lib/workers/repository/finalise/validate.spec.ts deleted file mode 100644 index 406f36648cd89b9fc5e0ecc5022794d74b8387a6..0000000000000000000000000000000000000000 --- a/lib/workers/repository/finalise/validate.spec.ts +++ /dev/null @@ -1,115 +0,0 @@ -import { platform } from '../../../../test/util'; -import { PR_STATE_OPEN } from '../../../constants/pull-requests'; -import { BranchStatus } from '../../../types'; -import * as validate from './validate'; - -beforeEach(() => { - jest.resetAllMocks(); -}); - -describe('workers/repository/validate', () => { - describe('validatePrs()', () => { - it('returns if disabled', async () => { - await expect( - validate.validatePrs({ suppressNotifications: ['prValidation'] }) - ).resolves.not.toThrow(); - }); - it('catches error', async () => { - platform.getPrList.mockResolvedValueOnce([ - { - state: PR_STATE_OPEN, - branchName: 'some/branch', - title: 'Update Renovate', - }, - ]); - await validate.validatePrs({}); - expect(platform.setBranchStatus).toHaveBeenCalledTimes(0); - expect(platform.ensureComment).toHaveBeenCalledTimes(0); - expect(platform.ensureCommentRemoval).toHaveBeenCalledTimes(0); - }); - it('returns if no matching files', async () => { - platform.getPrList.mockResolvedValueOnce([ - { - state: PR_STATE_OPEN, - branchName: 'some/branch', - title: 'Update Renovate', - }, - ]); - platform.getPrFiles.mockResolvedValueOnce(['readme.md']); - await validate.validatePrs({}); - expect(platform.setBranchStatus).toHaveBeenCalledTimes(0); - expect(platform.ensureComment).toHaveBeenCalledTimes(0); - expect(platform.ensureCommentRemoval).toHaveBeenCalledTimes(0); - }); - it('validates failures if cannot parse', async () => { - platform.getPrList.mockResolvedValueOnce([ - { - state: PR_STATE_OPEN, - branchName: 'some/branch', - title: 'Update Renovate', - }, - ]); - platform.getPrFiles.mockResolvedValueOnce(['renovate.json']); - platform.getFile.mockResolvedValue('not JSON'); - await validate.validatePrs({}); - expect(platform.setBranchStatus).toHaveBeenCalledTimes(1); - expect(platform.setBranchStatus.mock.calls[0][0].state).toEqual( - BranchStatus.red - ); - expect(platform.ensureComment).toHaveBeenCalledTimes(1); - expect(platform.ensureCommentRemoval).toHaveBeenCalledTimes(0); - }); - it('validates failures if config validation fails', async () => { - platform.getPrList.mockResolvedValueOnce([ - { - state: PR_STATE_OPEN, - branchName: 'some/branch', - title: 'Update Renovate', - }, - ]); - platform.getPrFiles.mockResolvedValueOnce(['renovate.json']); - platform.getFile.mockResolvedValue('{"foo":1}'); - await validate.validatePrs({}); - expect(platform.setBranchStatus).toHaveBeenCalledTimes(1); - expect(platform.setBranchStatus.mock.calls[0][0].state).toEqual( - BranchStatus.red - ); - expect(platform.ensureComment).toHaveBeenCalledTimes(1); - expect(platform.ensureCommentRemoval).toHaveBeenCalledTimes(0); - }); - it('validates successfully', async () => { - platform.getPrList.mockResolvedValueOnce([ - { - state: PR_STATE_OPEN, - branchName: 'some/branch', - title: 'Update Renovate', - }, - ]); - platform.getPrFiles.mockResolvedValueOnce(['renovate.json']); - platform.getFile.mockResolvedValue('{}'); - await validate.validatePrs({}); - expect(platform.setBranchStatus).toHaveBeenCalledTimes(1); - expect(platform.setBranchStatus.mock.calls[0][0].state).toEqual( - BranchStatus.green - ); - expect(platform.ensureComment).toHaveBeenCalledTimes(0); - expect(platform.ensureCommentRemoval).toHaveBeenCalledTimes(1); - }); - - it('validates successfully (dry-run)', async () => { - platform.getPrList.mockResolvedValueOnce([ - { - state: PR_STATE_OPEN, - branchName: 'some/branch', - title: 'Update Renovate', - }, - ]); - platform.getPrFiles.mockResolvedValueOnce(['renovate.json']); - platform.getFile.mockResolvedValue('{}'); - await validate.validatePrs({ dryRun: true }); - expect(platform.setBranchStatus).toHaveBeenCalledTimes(0); - expect(platform.ensureComment).toHaveBeenCalledTimes(0); - expect(platform.ensureCommentRemoval).toHaveBeenCalledTimes(0); - }); - }); -}); diff --git a/lib/workers/repository/finalise/validate.ts b/lib/workers/repository/finalise/validate.ts deleted file mode 100644 index 3d42669b9ccd1babd0c0594990e203dcc36eca23..0000000000000000000000000000000000000000 --- a/lib/workers/repository/finalise/validate.ts +++ /dev/null @@ -1,150 +0,0 @@ -import JSON5 from 'json5'; -import { RenovateConfig } from '../../../config'; -import { configFileNames } from '../../../config/app-strings'; -import { migrateAndValidate } from '../../../config/migrate-validate'; -import { REPOSITORY_CHANGED } from '../../../constants/error-messages'; -import { PR_STATE_OPEN } from '../../../constants/pull-requests'; -import { logger } from '../../../logger'; -import { Pr, platform } from '../../../platform'; -import { BranchStatus } from '../../../types'; - -async function getRenovatePrs(branchPrefix: string): Promise<Pr[]> { - return (await platform.getPrList()) - .filter((pr) => pr.state === PR_STATE_OPEN) - .filter((pr) => pr.branchName && !pr.branchName.startsWith(branchPrefix)) - .filter((pr) => new RegExp('renovate', 'i').test(pr.title)); -} - -async function getRenovateFiles(prNo: number): Promise<string[]> { - return (await platform.getPrFiles(prNo)).filter((file) => - configFileNames.includes(file) - ); -} - -export async function validatePrs(config: RenovateConfig): Promise<void> { - if ( - config.suppressNotifications && - config.suppressNotifications.includes('prValidation') - ) { - return; - } - logger.debug('branchPrefix: ' + config.branchPrefix); - const renovatePrs = await getRenovatePrs(config.branchPrefix); - logger.debug({ renovatePrs }, `Found ${renovatePrs.length} Renovate PRs`); - let validations: { file: string; message: string }[] = []; - for (const pr of renovatePrs) { - try { - const renovateFiles = await getRenovateFiles(pr.number); - if (!renovateFiles.length) { - continue; // eslint-disable-line no-continue - } - logger.debug( - { prNo: pr.number, title: pr.title, renovateFiles }, - 'PR has renovate files' - ); - for (const file of renovateFiles) { - let content: string; - try { - content = await platform.getFile(file, pr.sha || pr.branchName); - } catch (err) /* istanbul ignore next */ { - content = await platform.getFile(file, pr.branchName); - } - // TODO: proper typing - let parsed: { - renovate?: RenovateConfig; - 'renovate-config'?: RenovateConfig; - } & RenovateConfig; - try { - // istanbul ignore if - if (file.endsWith('.json5')) { - parsed = JSON5.parse(content); - } else { - parsed = JSON.parse(content); - } - } catch (err) { - validations.push({ - file, - message: 'Invalid JSON', - }); - } - if (parsed) { - const toValidate = - file === 'package.json' - ? /* istanbul ignore next */ parsed.renovate || - parsed['renovate-config'] - : parsed; - // istanbul ignore else - if (toValidate) { - logger.debug({ config: toValidate }, 'Validating config'); - const { errors } = await migrateAndValidate(config, toValidate); - if (errors && errors.length) { - validations = validations.concat( - errors.map((error) => ({ - file, - message: error.message, - })) - ); - } - } - } - } - // if the PR has renovate files then we set a status no matter what - let status: BranchStatus; - let description: string; - const topic = `Renovate Configuration Errors`; - if (validations.length) { - const content = validations - .map((v) => `\`${v.file}\`: ${v.message}`) - .join('\n\n'); - await platform.ensureComment({ - number: pr.number, - topic, - content, - }); - status = BranchStatus.red; - description = `Renovate config validation failed`; // GitHub limit - } else { - description = `Renovate config is valid`; - status = BranchStatus.green; - if (config.dryRun) { - logger.info( - `DRY-RUN: Would ensure validation comment removal in PR #${pr.number}` - ); - } else { - await platform.ensureCommentRemoval({ number: pr.number, topic }); - } - } - // istanbul ignore else - if (pr.sourceRepo === config.repository) { - logger.debug({ status, description }, 'Setting PR validation status'); - const context = `renovate/validate`; - if (config.dryRun) { - logger.info(`DRY-RUN: Would set branch status in PR #${pr.number}`); - } else { - await platform.setBranchStatus({ - branchName: pr.branchName, - context, - description, - state: status, - }); - } - } else { - logger.debug('Skipping branch status for forked PR'); - } - } catch (err) { - // istanbul ignore if - if (err.message === REPOSITORY_CHANGED) { - logger.debug('Cannot access PR files to check them'); - } else { - logger.warn( - { - err, - prNo: pr.number, - branchName: pr.branchName, - }, - 'Error checking PR' - ); - } - } - } -}