From 012561f69afe0baebc689b045df7a1c65b31a567 Mon Sep 17 00:00:00 2001 From: Rhys Arkins <rhys@arkins.net> Date: Sun, 30 Aug 2020 22:03:58 +0200 Subject: [PATCH] feat(git): get branch commit without cloning (#7130) Co-authored-by: Michael Kriese <michael.kriese@visualon.de> --- lib/manager/npm/post-update/index.ts | 2 +- lib/platform/azure/index.spec.ts | 2 +- lib/platform/azure/index.ts | 2 +- lib/platform/bitbucket-server/index.spec.ts | 6 +- lib/platform/bitbucket-server/index.ts | 12 +- lib/platform/bitbucket/index.spec.ts | 2 +- lib/platform/bitbucket/index.ts | 2 +- lib/platform/gitea/index.spec.ts | 2 +- lib/platform/gitea/index.ts | 4 +- lib/platform/github/index.spec.ts | 4 +- lib/platform/github/index.ts | 6 +- lib/platform/gitlab/index.spec.ts | 6 +- lib/platform/gitlab/index.ts | 10 +- lib/util/git/__snapshots__/index.spec.ts.snap | 10 -- lib/util/git/index.spec.ts | 63 ++++------- lib/util/git/index.ts | 104 ++++-------------- lib/workers/branch/index.spec.ts | 66 +++++------ lib/workers/branch/index.ts | 2 +- lib/workers/branch/lock-files/index.spec.ts | 2 +- lib/workers/branch/reuse.spec.ts | 24 ++-- lib/workers/branch/reuse.ts | 2 +- lib/workers/repository/finalise/prune.spec.ts | 28 ++--- lib/workers/repository/finalise/prune.ts | 6 +- lib/workers/repository/process/index.spec.ts | 8 +- lib/workers/repository/process/index.ts | 4 +- lib/workers/repository/process/limits.spec.ts | 10 +- lib/workers/repository/process/limits.ts | 8 +- 27 files changed, 159 insertions(+), 238 deletions(-) diff --git a/lib/manager/npm/post-update/index.ts b/lib/manager/npm/post-update/index.ts index 33e5302d76..0a8b3e1de0 100644 --- a/lib/manager/npm/post-update/index.ts +++ b/lib/manager/npm/post-update/index.ts @@ -359,7 +359,7 @@ export async function getAdditionalFiles( if ( config.updateType === 'lockFileMaintenance' && config.reuseExistingBranch && - (await branchExists(config.branchName)) + branchExists(config.branchName) ) { logger.debug('Skipping lockFileMaintenance update'); return { artifactErrors, updatedArtifacts }; diff --git a/lib/platform/azure/index.spec.ts b/lib/platform/azure/index.spec.ts index 134c13e94f..0ad83f30b1 100644 --- a/lib/platform/azure/index.spec.ts +++ b/lib/platform/azure/index.spec.ts @@ -24,7 +24,7 @@ describe('platform/azure', () => { azureApi = require('./azure-got-wrapper'); azureHelper = require('./azure-helper'); git = require('../../util/git'); - git.branchExists.mockResolvedValue(true); + git.branchExists.mockReturnValue(true); git.isBranchStale.mockResolvedValue(false); hostRules.find.mockReturnValue({ token: 'token', diff --git a/lib/platform/azure/index.ts b/lib/platform/azure/index.ts index 33e8458b53..c527dd7d5f 100644 --- a/lib/platform/azure/index.ts +++ b/lib/platform/azure/index.ts @@ -149,7 +149,7 @@ export async function initRepo({ const url = defaults.endpoint + `${encodeURIComponent(projectName)}/_git/${encodeURIComponent(repoName)}`; - git.initRepo({ + await git.initRepo({ ...config, localDir, url, diff --git a/lib/platform/bitbucket-server/index.spec.ts b/lib/platform/bitbucket-server/index.spec.ts index b7354b5894..0b063b1e36 100644 --- a/lib/platform/bitbucket-server/index.spec.ts +++ b/lib/platform/bitbucket-server/index.spec.ts @@ -184,9 +184,9 @@ describe(getName(__filename), () => { hostRules = require('../../util/host-rules'); bitbucket = await import('.'); git = require('../../util/git'); - git.branchExists.mockResolvedValue(true); + git.branchExists.mockReturnValue(true); git.isBranchStale.mockResolvedValue(false); - git.getBranchCommit.mockResolvedValue( + git.getBranchCommit.mockReturnValue( '0d9c7726c3d628b7e28af234595cfd20febdbf8e' ); const endpoint = @@ -1646,7 +1646,7 @@ Followed by some information. }); it('throws repository-changed', async () => { - git.branchExists.mockResolvedValue(false); + git.branchExists.mockReturnValue(false); await initRepo(); await expect( bitbucket.getBranchStatus('somebranch', []) diff --git a/lib/platform/bitbucket-server/index.ts b/lib/platform/bitbucket-server/index.ts index 487c56c50f..f26061594f 100644 --- a/lib/platform/bitbucket-server/index.ts +++ b/lib/platform/bitbucket-server/index.ts @@ -177,7 +177,7 @@ export async function initRepo({ repository, }); - git.initRepo({ + await git.initRepo({ ...config, localDir, url: gitUrl, @@ -365,7 +365,7 @@ async function getStatus( branchName: string, useCache = true ): Promise<utils.BitbucketCommitStatus> { - const branchCommit = await git.getBranchCommit(branchName); + const branchCommit = git.getBranchCommit(branchName); return ( await bitbucketServerHttp.getJson<utils.BitbucketCommitStatus>( @@ -394,7 +394,7 @@ export async function getBranchStatus( return BranchStatus.green; } - if (!(await git.branchExists(branchName))) { + if (!git.branchExists(branchName)) { throw new Error(REPOSITORY_CHANGED); } @@ -418,11 +418,11 @@ export async function getBranchStatus( } } -async function getStatusCheck( +function getStatusCheck( branchName: string, useCache = true ): Promise<utils.BitbucketStatus[]> { - const branchCommit = await git.getBranchCommit(branchName); + const branchCommit = git.getBranchCommit(branchName); return utils.accumulateValues( `./rest/build-status/1.0/commits/${branchCommit}`, @@ -475,7 +475,7 @@ export async function setBranchStatus({ } logger.debug({ branch: branchName, context, state }, 'Setting branch status'); - const branchCommit = await git.getBranchCommit(branchName); + const branchCommit = git.getBranchCommit(branchName); try { const body: any = { diff --git a/lib/platform/bitbucket/index.spec.ts b/lib/platform/bitbucket/index.spec.ts index b5400c74b7..44c291b43b 100644 --- a/lib/platform/bitbucket/index.spec.ts +++ b/lib/platform/bitbucket/index.spec.ts @@ -52,7 +52,7 @@ describe('platform/bitbucket', () => { bitbucket = await import('.'); logger = (await import('../../logger')).logger as any; git = require('../../util/git'); - git.branchExists.mockResolvedValue(true); + git.branchExists.mockReturnValue(true); git.isBranchStale.mockResolvedValue(false); // clean up hostRules hostRules.clear(); diff --git a/lib/platform/bitbucket/index.ts b/lib/platform/bitbucket/index.ts index 86e1134f18..9c169c6b24 100644 --- a/lib/platform/bitbucket/index.ts +++ b/lib/platform/bitbucket/index.ts @@ -157,7 +157,7 @@ export async function initRepo({ repository, }); - git.initRepo({ + await git.initRepo({ ...config, localDir, url, diff --git a/lib/platform/gitea/index.spec.ts b/lib/platform/gitea/index.spec.ts index 8e786a34f3..7ef78ebc29 100644 --- a/lib/platform/gitea/index.spec.ts +++ b/lib/platform/gitea/index.spec.ts @@ -158,7 +158,7 @@ describe('platform/gitea', () => { logger = (await import('../../logger')).logger as any; gitvcs = require('../../util/git'); gitvcs.isBranchStale.mockResolvedValue(false); - gitvcs.getBranchCommit.mockResolvedValue(mockCommitHash); + gitvcs.getBranchCommit.mockReturnValue(mockCommitHash); global.gitAuthor = { name: 'Renovate', email: 'renovate@example.com' }; diff --git a/lib/platform/gitea/index.ts b/lib/platform/gitea/index.ts index 56e8eb350d..b76cdd85d1 100644 --- a/lib/platform/gitea/index.ts +++ b/lib/platform/gitea/index.ts @@ -301,7 +301,7 @@ const platform: Platform = { gitEndpoint.auth = opts.token; // Initialize Git storage - git.initRepo({ + await git.initRepo({ ...config, url: URL.format(gitEndpoint), gitAuthorName: global.gitAuthor?.name, @@ -339,7 +339,7 @@ const platform: Platform = { }: BranchStatusConfig): Promise<void> { try { // Create new status for branch commit - const branchCommit = await git.getBranchCommit(branchName); + const branchCommit = git.getBranchCommit(branchName); await helper.createCommitStatus(config.repository, branchCommit, { state: helper.renovateToGiteaStatusMapping[state] || 'pending', context, diff --git a/lib/platform/github/index.spec.ts b/lib/platform/github/index.spec.ts index 6f23e1b9f8..ea9c07c292 100644 --- a/lib/platform/github/index.spec.ts +++ b/lib/platform/github/index.spec.ts @@ -26,9 +26,9 @@ describe('platform/github', () => { hostRules = mocked(await import('../../util/host-rules')); jest.mock('../../util/git'); git = mocked(await import('../../util/git')); - git.branchExists.mockResolvedValue(true); + git.branchExists.mockReturnValue(true); git.isBranchStale.mockResolvedValue(true); - git.getBranchCommit.mockResolvedValue( + git.getBranchCommit.mockReturnValue( '0d9c7726c3d628b7e28af234595cfd20febdbf8e' ); delete global.gitAuthor; diff --git a/lib/platform/github/index.ts b/lib/platform/github/index.ts index fc4e7e8af4..464965f1af 100644 --- a/lib/platform/github/index.ts +++ b/lib/platform/github/index.ts @@ -401,7 +401,7 @@ export async function initRepo({ ); parsedEndpoint.pathname = config.repository + '.git'; const url = URL.format(parsedEndpoint); - git.initRepo({ + await git.initRepo({ ...config, url, gitAuthorName: global.gitAuthor?.name, @@ -898,7 +898,7 @@ async function getStatusCheck( branchName: string, useCache = true ): Promise<GhBranchStatus[]> { - const branchCommit = await git.getBranchCommit(branchName); + const branchCommit = git.getBranchCommit(branchName); const url = `repos/${config.repository}/commits/${branchCommit}/statuses`; @@ -953,7 +953,7 @@ export async function setBranchStatus({ } logger.debug({ branch: branchName, context, state }, 'Setting branch status'); try { - const branchCommit = await git.getBranchCommit(branchName); + const branchCommit = git.getBranchCommit(branchName); const url = `repos/${config.repository}/statuses/${branchCommit}`; const renovateToGitHubStateMapping = { green: 'success', diff --git a/lib/platform/gitlab/index.spec.ts b/lib/platform/gitlab/index.spec.ts index 804934013a..b5bc54e26c 100644 --- a/lib/platform/gitlab/index.spec.ts +++ b/lib/platform/gitlab/index.spec.ts @@ -29,9 +29,9 @@ describe('platform/gitlab', () => { hostRules = require('../../util/host-rules'); jest.mock('../../util/git'); git = require('../../util/git'); - git.branchExists.mockResolvedValue(true); + git.branchExists.mockReturnValue(true); git.isBranchStale.mockResolvedValue(true); - git.getBranchCommit.mockResolvedValue( + git.getBranchCommit.mockReturnValue( '0d9c7726c3d628b7e28af234595cfd20febdbf8e' ); hostRules.find.mockReturnValue({ @@ -464,7 +464,7 @@ describe('platform/gitlab', () => { }); it('throws repository-changed', async () => { expect.assertions(2); - git.branchExists.mockResolvedValue(false); + git.branchExists.mockReturnValue(false); await initRepo(); await expect(gitlab.getBranchStatus('somebranch', [])).rejects.toThrow( REPOSITORY_CHANGED diff --git a/lib/platform/gitlab/index.ts b/lib/platform/gitlab/index.ts index 16fac4a0a3..ec70b09e69 100644 --- a/lib/platform/gitlab/index.ts +++ b/lib/platform/gitlab/index.ts @@ -211,7 +211,7 @@ export async function initRepo({ repoUrl.auth = 'oauth2:' + opts.token; url = URL.format(repoUrl); } - git.initRepo({ + await git.initRepo({ ...config, url, gitAuthorName: global.gitAuthor?.name, @@ -260,7 +260,7 @@ async function getStatus( branchName: string, useCache = true ): Promise<GitlabBranchStatus[]> { - const branchSha = await git.getBranchCommit(branchName); + const branchSha = git.getBranchCommit(branchName); const url = `projects/${config.repository}/repository/commits/${branchSha}/statuses`; return ( @@ -298,7 +298,7 @@ export async function getBranchStatus( return BranchStatus.red; } - if (!(await git.branchExists(branchName))) { + if (!git.branchExists(branchName)) { throw new Error(REPOSITORY_CHANGED); } @@ -505,7 +505,7 @@ export function getPrBody(input: string): string { export async function getBranchPr(branchName: string): Promise<Pr> { logger.debug(`getBranchPr(${branchName})`); // istanbul ignore if - if (!(await git.branchExists(branchName))) { + if (!git.branchExists(branchName)) { return null; } const query = new URLSearchParams({ @@ -553,7 +553,7 @@ export async function setBranchStatus({ url: targetUrl, }: BranchStatusConfig): Promise<void> { // First, get the branch commit SHA - const branchSha = await git.getBranchCommit(branchName); + const branchSha = git.getBranchCommit(branchName); // Now, check the statuses for that commit const url = `projects/${config.repository}/statuses/${branchSha}`; let state = 'success'; diff --git a/lib/util/git/__snapshots__/index.spec.ts.snap b/lib/util/git/__snapshots__/index.spec.ts.snap index fe56ac8e3e..4f03a4baee 100644 --- a/lib/util/git/__snapshots__/index.spec.ts.snap +++ b/lib/util/git/__snapshots__/index.spec.ts.snap @@ -1,9 +1,5 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`platform/git checkoutBranch(branchName) should throw if branch does not exist 1`] = `[Error: config-validation]`; - -exports[`platform/git getBranchCommit(branchName) should throw if branch does not exist 1`] = `[Error: Cannot fetch commit for branch that does not exist: not_found]`; - exports[`platform/git getBranchFiles(branchName) detects changed files compared to current base branch 1`] = ` Array [ "some-new-file", @@ -17,8 +13,6 @@ Array [ ] `; -exports[`platform/git getFile(filePath, branchName) returns null for 404 1`] = `[Error: repository-changed]`; - exports[`platform/git getFileList() should exclude submodules 1`] = ` Array [ ".gitmodules", @@ -49,7 +43,3 @@ Array [ "master message", ] `; - -exports[`platform/git isBranchModified() should throw if branch does not exist 1`] = `[Error: Cannot check modification for branch that does not exist: not_found]`; - -exports[`platform/git isBranchStale() should throw if branch does not exist 1`] = `[Error: Cannot check staleness for branch that does not exist: not_found]`; diff --git a/lib/util/git/index.spec.ts b/lib/util/git/index.spec.ts index 971ec39d8f..04e1b95c94 100644 --- a/lib/util/git/index.spec.ts +++ b/lib/util/git/index.spec.ts @@ -62,7 +62,7 @@ describe('platform/git', () => { const repo = Git(origin.path); await repo.clone(base.path, '.', ['--bare']); tmpDir = await tmp.dir({ unsafeCleanup: true }); - git.initRepo({ + await git.initRepo({ localDir: tmpDir.path, url: origin.path, extraCloneOpts: { @@ -91,11 +91,7 @@ describe('platform/git', () => { it('sets non-master base branch', async () => { await expect(git.checkoutBranch('develop')).resolves.not.toThrow(); }); - it('should throw if branch does not exist', async () => { - await expect(git.checkoutBranch('not_found')).rejects.toMatchSnapshot(); - }); }); - describe('getFileList()', () => { it('should return the correct files', async () => { expect(await git.getFileList()).toMatchSnapshot(); @@ -104,7 +100,7 @@ describe('platform/git', () => { const repo = Git(base.path).silent(true); await repo.submoduleAdd(base.path, 'submodule'); await repo.commit('Add submodule'); - git.initRepo({ + await git.initRepo({ localDir: tmpDir.path, url: base.path, }); @@ -115,20 +111,19 @@ describe('platform/git', () => { }); }); describe('branchExists(branchName)', () => { - it('should return true if found', async () => { - expect(await git.branchExists('renovate/future_branch')).toBe(true); - expect(await git.branchExists('renovate/future_branch')).toBe(true); // should come from cache + it('should return true if found', () => { + expect(git.branchExists('renovate/future_branch')).toBe(true); }); - it('should return false if not found', async () => { - expect(await git.branchExists('not_found')).toBe(false); + it('should return false if not found', () => { + expect(git.branchExists('not_found')).toBe(false); }); }); - describe('getAllRenovateBranches()', () => { - it('should return all renovate branches', async () => { - const res = await git.getAllRenovateBranches('renovate/'); + describe('getBranchList()', () => { + it('should return all branches', () => { + const res = git.getBranchList(); expect(res).toContain('renovate/past_branch'); expect(res).toContain('renovate/future_branch'); - expect(res).not.toContain('master'); + expect(res).toContain('master'); }); }); describe('isBranchStale()', () => { @@ -138,14 +133,8 @@ describe('platform/git', () => { it('should return true if SHA different from master', async () => { expect(await git.isBranchStale('renovate/past_branch')).toBe(true); }); - it('should throw if branch does not exist', async () => { - await expect(git.isBranchStale('not_found')).rejects.toMatchSnapshot(); - }); }); describe('isBranchModified()', () => { - it('should throw if branch does not exist', async () => { - await expect(git.isBranchModified('not_found')).rejects.toMatchSnapshot(); - }); it('should return true when author matches', async () => { expect(await git.isBranchModified('renovate/future_branch')).toBe(false); expect(await git.isBranchModified('renovate/future_branch')).toBe(false); @@ -156,13 +145,13 @@ describe('platform/git', () => { }); describe('getBranchCommit(branchName)', () => { - it('should return same value for equal refs', async () => { - const hex = await git.getBranchCommit('renovate/equal_branch'); - expect(hex).toBe(await git.getBranchCommit('master')); + it('should return same value for equal refs', () => { + const hex = git.getBranchCommit('renovate/equal_branch'); + expect(hex).toBe(git.getBranchCommit('master')); expect(hex).toHaveLength(40); }); - it('should throw if branch does not exist', async () => { - await expect(git.getBranchCommit('not_found')).rejects.toMatchSnapshot(); + it('should return null', () => { + expect(git.getBranchCommit('not_found')).toBeNull(); }); }); @@ -225,9 +214,7 @@ describe('platform/git', () => { expect(res).toBeNull(); }); it('returns null for 404', async () => { - await expect( - git.getFile('some-path', 'some-branch') - ).rejects.toMatchSnapshot(); + expect(await git.getFile('some-path', 'some-branch')).toBeNull(); }); }); describe('commitFiles({branchName, files, message})', () => { @@ -352,18 +339,18 @@ describe('platform/git', () => { await repo.commit('past message2'); await repo.checkout('master'); - expect(await git.branchExists('test')).toBeFalsy(); + expect(git.branchExists('test')).toBeFalsy(); expect(await git.getCommitMessages()).toMatchSnapshot(); await git.checkoutBranch('develop'); - git.initRepo({ + await git.initRepo({ localDir: tmpDir.path, url: base.path, }); - expect(await git.branchExists('test')).toBeTruthy(); + expect(git.branchExists('test')).toBeTruthy(); await git.checkoutBranch('test'); @@ -380,16 +367,15 @@ describe('platform/git', () => { await repo.commit('past message2'); await repo.checkout('master'); - git.initRepo({ + await git.initRepo({ localDir: tmpDir.path, url: base.path, }); await git.setBranchPrefix('renovate/'); - expect(await git.branchExists('renovate/test')).toBe(true); - const cid = await git.getBranchCommit('renovate/test'); + expect(git.branchExists('renovate/test')).toBe(true); - git.initRepo({ + await git.initRepo({ localDir: tmpDir.path, url: base.path, }); @@ -398,8 +384,7 @@ describe('platform/git', () => { await repo.commit('past message3', ['--amend']); await git.setBranchPrefix('renovate/'); - expect(await git.branchExists('renovate/test')).toBe(true); - expect(await git.getBranchCommit('renovate/test')).not.toEqual(cid); + expect(git.branchExists('renovate/test')).toBe(true); }); it('should fail clone ssh submodule', async () => { @@ -418,7 +403,7 @@ describe('platform/git', () => { 'test', ]); await repo.commit('Add submodule'); - git.initRepo({ + await git.initRepo({ localDir: tmpDir.path, url: base.path, }); diff --git a/lib/util/git/index.ts b/lib/util/git/index.ts index a442df648f..cea22cc2bc 100644 --- a/lib/util/git/index.ts +++ b/lib/util/git/index.ts @@ -8,7 +8,6 @@ import Git, { StatusResult as StatusResult_, } from 'simple-git'; import { - CONFIG_VALIDATION, REPOSITORY_CHANGED, REPOSITORY_EMPTY, REPOSITORY_TEMPORARY_ERROR, @@ -44,7 +43,7 @@ interface StorageConfig { interface LocalConfig extends StorageConfig { currentBranch: string; currentBranchSha: string; - branchExists: Record<string, boolean>; + branchCommits: Record<string, CommitSha>; branchIsModified: Record<string, boolean>; branchPrefix: string; } @@ -76,14 +75,6 @@ function localName(branchName: string): string { return branchName.replace(/^origin\//, ''); } -function throwBranchValidationError(branchName: string): never { - const error = new Error(CONFIG_VALIDATION); - error.validationError = 'branch not found'; - error.validationMessage = - 'The following branch could not be found: ' + branchName; - throw error; -} - async function isDirectory(dir: string): Promise<boolean> { try { return (await fs.stat(dir)).isDirectory(); @@ -117,12 +108,23 @@ let gitInitialized: boolean; let privateKeySet = false; -export function initRepo(args: StorageConfig): void { +async function fetchBranchCommits(): Promise<void> { + config.branchCommits = {}; + (await git.listRemote(['--heads', config.url])) + .split('\n') + .filter(Boolean) + .map((line) => line.trim().split(/\s+/)) + .forEach(([sha, ref]) => { + config.branchCommits[ref.replace('refs/heads/', '')] = sha; + }); +} + +export async function initRepo(args: StorageConfig): Promise<void> { config = { ...args } as any; - config.branchExists = {}; config.branchIsModified = {}; git = Git(config.localDir).silent(true); gitInitialized = false; + await fetchBranchCommits(); } async function resetToBranch(branchName: string): Promise<void> { @@ -290,40 +292,19 @@ async function syncBranch(branchName: string): Promise<void> { try { await git.raw(['remote', 'set-branches', '--add', 'origin', branchName]); await git.fetch(['origin', branchName, '--depth=2']); - } catch (err) { + } catch (err) /* istanbul ignore next */ { checkForPlatformFailure(err); } } } -export async function branchExists(branchName: string): Promise<boolean> { - await syncGit(); - // First check cache - if (config.branchExists[branchName] !== undefined) { - return config.branchExists[branchName]; - } - await syncBranch(branchName); - try { - await git.raw(['show-branch', 'origin/' + branchName]); - config.branchExists[branchName] = true; - return true; - } catch (err) { - checkForPlatformFailure(err); - config.branchExists[branchName] = false; - return false; - } +export function branchExists(branchName: string): boolean { + return !!config.branchCommits[branchName]; } // Return the commit SHA for a branch -export async function getBranchCommit(branchName: string): Promise<CommitSha> { - await syncGit(); - if (!(await branchExists(branchName))) { - throw Error( - 'Cannot fetch commit for branch that does not exist: ' + branchName - ); - } - const res = await git.revparse(['origin/' + branchName]); - return res.trim(); +export function getBranchCommit(branchName: string): CommitSha | null { + return config.branchCommits[branchName] || null; } export async function getCommitMessages(): Promise<string[]> { @@ -338,10 +319,8 @@ export async function getCommitMessages(): Promise<string[]> { export async function checkoutBranch(branchName: string): Promise<CommitSha> { await syncGit(); - if (!(await branchExists(branchName))) { - throwBranchValidationError(branchName); - } logger.debug(`Setting current branch to ${branchName}`); + await syncBranch(branchName); try { config.currentBranch = branchName; config.currentBranchSha = ( @@ -356,14 +335,6 @@ export async function checkoutBranch(branchName: string): Promise<CommitSha> { return config.currentBranchSha; } catch (err) /* istanbul ignore next */ { checkForPlatformFailure(err); - if ( - err.message.includes( - 'unknown revision or path not in the working tree' - ) || - err.message.includes('did not match any file(s) known to git') - ) { - throwBranchValidationError(branchName); - } throw err; } } @@ -387,27 +358,12 @@ export async function getFileList(): Promise<string[]> { ); } -export async function getAllRenovateBranches( - branchPrefix: string -): Promise<string[]> { - // istanbul ignore if - if (!gitInitialized) { - logger.debug('git is uninitialized so returning empty branch set'); - return []; - } - const branches = await git.branch(['--remotes', '--verbose']); - return branches.all - .map(localName) - .filter((branchName) => branchName.startsWith(branchPrefix)); +export function getBranchList(): string[] { + return Object.keys(config.branchCommits); } export async function isBranchStale(branchName: string): Promise<boolean> { await syncGit(); - if (!(await branchExists(branchName))) { - throw Error( - 'Cannot check staleness for branch that does not exist: ' + branchName - ); - } const branches = await git.branch([ '--remotes', '--verbose', @@ -423,11 +379,6 @@ export async function isBranchModified(branchName: string): Promise<boolean> { if (config.branchIsModified[branchName] !== undefined) { return config.branchIsModified[branchName]; } - if (!(await branchExists(branchName))) { - throw Error( - 'Cannot check modification for branch that does not exist: ' + branchName - ); - } // Retrieve the author of the most recent commit const lastAuthor = ( await git.raw(['log', '-1', '--pretty=format:%ae', `origin/${branchName}`]) @@ -466,7 +417,7 @@ export async function deleteBranch(branchName: string): Promise<void> { checkForPlatformFailure(err); logger.debug({ branchName }, 'No local branch to delete'); } - config.branchExists[branchName] = false; + delete config.branchCommits[branchName]; } export async function mergeBranch(branchName: string): Promise<void> { @@ -508,13 +459,6 @@ export async function getFile( branchName?: string ): Promise<string | null> { await syncGit(); - if (branchName) { - const exists = await branchExists(branchName); - if (!exists) { - logger.debug({ branchName }, 'branch no longer exists - aborting'); - throw new Error(REPOSITORY_CHANGED); - } - } try { const content = await git.show([ 'origin/' + (branchName || config.currentBranch) + ':' + filePath, @@ -630,7 +574,7 @@ export async function commitFiles({ // Fetch it after create const ref = `refs/heads/${branchName}:refs/remotes/origin/${branchName}`; await git.fetch(['origin', ref, '--depth=2', '--force']); - config.branchExists[branchName] = true; + config.branchCommits[branchName] = commit; config.branchIsModified[branchName] = false; limits.incrementLimit('prCommitsPerRunLimit'); return commit; diff --git a/lib/workers/branch/index.spec.ts b/lib/workers/branch/index.spec.ts index 43329a15d8..8288816800 100644 --- a/lib/workers/branch/index.spec.ts +++ b/lib/workers/branch/index.spec.ts @@ -79,7 +79,7 @@ describe('workers/branch', () => { it('skips branch if not scheduled and not updating out of schedule', async () => { schedule.isScheduledNow.mockReturnValueOnce(false); config.updateNotScheduled = false; - git.branchExists.mockResolvedValueOnce(true); + git.branchExists.mockReturnValueOnce(true); const res = await branchWorker.processBranch(config); expect(res).toEqual('not-scheduled'); }); @@ -88,7 +88,7 @@ describe('workers/branch', () => { config.unpublishSafe = true; config.canBeUnpublished = true; config.prCreation = 'not-pending'; - git.branchExists.mockResolvedValueOnce(true); + git.branchExists.mockReturnValueOnce(true); const res = await branchWorker.processBranch(config); expect(res).toEqual('pending'); }); @@ -107,7 +107,7 @@ describe('workers/branch', () => { it('processes branch if not scheduled but updating out of schedule', async () => { schedule.isScheduledNow.mockReturnValueOnce(false); config.updateNotScheduled = true; - git.branchExists.mockResolvedValueOnce(true); + git.branchExists.mockReturnValueOnce(true); platform.getBranchPr.mockResolvedValueOnce({ state: PrState.Open, } as never); @@ -117,7 +117,7 @@ describe('workers/branch', () => { }); it('skips branch if closed major PR found', async () => { schedule.isScheduledNow.mockReturnValueOnce(false); - git.branchExists.mockResolvedValueOnce(true); + git.branchExists.mockReturnValueOnce(true); config.updateType = 'major'; checkExisting.prAlreadyExisted.mockResolvedValueOnce({ number: 13, @@ -128,7 +128,7 @@ describe('workers/branch', () => { }); it('skips branch if closed digest PR found', async () => { schedule.isScheduledNow.mockReturnValueOnce(false); - git.branchExists.mockResolvedValueOnce(true); + git.branchExists.mockReturnValueOnce(true); config.updateType = 'digest'; checkExisting.prAlreadyExisted.mockResolvedValueOnce({ number: 13, @@ -139,7 +139,7 @@ describe('workers/branch', () => { }); it('skips branch if closed minor PR found', async () => { schedule.isScheduledNow.mockReturnValueOnce(false); - git.branchExists.mockResolvedValueOnce(true); + git.branchExists.mockReturnValueOnce(true); checkExisting.prAlreadyExisted.mockResolvedValueOnce({ number: 13, state: PrState.Closed, @@ -149,7 +149,7 @@ describe('workers/branch', () => { }); it('skips branch if merged PR found', async () => { schedule.isScheduledNow.mockReturnValueOnce(false); - git.branchExists.mockResolvedValueOnce(true); + git.branchExists.mockReturnValueOnce(true); checkExisting.prAlreadyExisted.mockResolvedValueOnce({ number: 13, state: PrState.Merged, @@ -159,7 +159,7 @@ describe('workers/branch', () => { }); it('throws error if closed PR found', async () => { schedule.isScheduledNow.mockReturnValueOnce(false); - git.branchExists.mockResolvedValueOnce(true); + git.branchExists.mockReturnValueOnce(true); platform.getBranchPr.mockResolvedValueOnce({ state: PrState.Merged, } as never); @@ -170,7 +170,7 @@ describe('workers/branch', () => { }); it('does not skip branch if edited PR found with rebaseLabel', async () => { schedule.isScheduledNow.mockReturnValueOnce(false); - git.branchExists.mockResolvedValueOnce(true); + git.branchExists.mockReturnValueOnce(true); platform.getBranchPr.mockResolvedValueOnce({ state: PrState.Open, labels: ['rebase'], @@ -181,7 +181,7 @@ describe('workers/branch', () => { }); it('skips branch if edited PR found', async () => { schedule.isScheduledNow.mockReturnValueOnce(false); - git.branchExists.mockResolvedValueOnce(true); + git.branchExists.mockReturnValueOnce(true); platform.getBranchPr.mockResolvedValueOnce({ state: PrState.Open, body: '**Rebasing**: something', @@ -192,7 +192,7 @@ describe('workers/branch', () => { }); it('skips branch if target branch changed', async () => { schedule.isScheduledNow.mockReturnValueOnce(false); - git.branchExists.mockResolvedValueOnce(true); + git.branchExists.mockReturnValueOnce(true); platform.getBranchPr.mockResolvedValueOnce({ state: PrState.Open, targetBranch: 'v6', @@ -210,7 +210,7 @@ describe('workers/branch', () => { artifactErrors: [], updatedArtifacts: [], }); - git.branchExists.mockResolvedValue(false); + git.branchExists.mockReturnValue(false); expect(await branchWorker.processBranch(config, true)).toEqual( 'pr-limit-reached' ); @@ -223,7 +223,7 @@ describe('workers/branch', () => { artifactErrors: [], updatedArtifacts: [], }); - git.branchExists.mockResolvedValue(true); + git.branchExists.mockReturnValue(true); prWorker.ensurePr.mockResolvedValueOnce({ prResult: PrResult.LimitReached, }); @@ -239,7 +239,7 @@ describe('workers/branch', () => { artifactErrors: [], updatedArtifacts: [], }); - git.branchExists.mockResolvedValue(false); + git.branchExists.mockReturnValue(false); expect(await branchWorker.processBranch(config, false, true)).toEqual( 'commit-limit-reached' ); @@ -252,7 +252,7 @@ describe('workers/branch', () => { artifactErrors: [], updatedArtifacts: [], }); - git.branchExists.mockResolvedValueOnce(false); + git.branchExists.mockReturnValueOnce(false); commit.commitFilesToBranch.mockResolvedValueOnce(null); expect(await branchWorker.processBranch(config)).toEqual('no-work'); }); @@ -264,7 +264,7 @@ describe('workers/branch', () => { artifactErrors: [], updatedArtifacts: [{}], } as never); - git.branchExists.mockResolvedValueOnce(true); + git.branchExists.mockReturnValueOnce(true); commit.commitFilesToBranch.mockResolvedValueOnce(null); automerge.tryBranchAutomerge.mockResolvedValueOnce('automerged'); await branchWorker.processBranch(config); @@ -281,7 +281,7 @@ describe('workers/branch', () => { artifactErrors: [], updatedArtifacts: [{}], } as never); - git.branchExists.mockResolvedValueOnce(false); + git.branchExists.mockReturnValueOnce(false); automerge.tryBranchAutomerge.mockResolvedValueOnce('automerged'); await branchWorker.processBranch({ ...config, @@ -300,7 +300,7 @@ describe('workers/branch', () => { artifactErrors: [], updatedArtifacts: [{}], } as never); - git.branchExists.mockResolvedValueOnce(true); + git.branchExists.mockReturnValueOnce(true); commit.commitFilesToBranch.mockResolvedValueOnce(null); automerge.tryBranchAutomerge.mockResolvedValueOnce('automerged'); await branchWorker.processBranch({ ...config, dryRun: true }); @@ -316,7 +316,7 @@ describe('workers/branch', () => { artifactErrors: [], updatedArtifacts: [{}], } as never); - git.branchExists.mockResolvedValueOnce(true); + git.branchExists.mockReturnValueOnce(true); commit.commitFilesToBranch.mockResolvedValueOnce(null); automerge.tryBranchAutomerge.mockResolvedValueOnce('failed'); prWorker.ensurePr.mockResolvedValueOnce({ @@ -335,7 +335,7 @@ describe('workers/branch', () => { artifactErrors: [], updatedArtifacts: [{}], } as never); - git.branchExists.mockResolvedValueOnce(true); + git.branchExists.mockReturnValueOnce(true); commit.commitFilesToBranch.mockResolvedValueOnce(null); automerge.tryBranchAutomerge.mockResolvedValueOnce('failed'); prWorker.ensurePr.mockResolvedValueOnce({ @@ -371,7 +371,7 @@ describe('workers/branch', () => { artifactErrors: [], updatedArtifacts: [{}], } as never); - git.branchExists.mockResolvedValueOnce(true); + git.branchExists.mockReturnValueOnce(true); automerge.tryBranchAutomerge.mockResolvedValueOnce('failed'); prWorker.ensurePr.mockResolvedValueOnce({ result: PrResult.Created, @@ -392,7 +392,7 @@ describe('workers/branch', () => { artifactErrors: [{}], updatedArtifacts: [{}], } as never); - git.branchExists.mockResolvedValueOnce(true); + git.branchExists.mockReturnValueOnce(true); automerge.tryBranchAutomerge.mockResolvedValueOnce('failed'); prWorker.ensurePr.mockResolvedValueOnce({ result: PrResult.Created, @@ -413,7 +413,7 @@ describe('workers/branch', () => { artifactErrors: [{}], updatedArtifacts: [{}], } as never); - git.branchExists.mockResolvedValueOnce(true); + git.branchExists.mockReturnValueOnce(true); automerge.tryBranchAutomerge.mockResolvedValueOnce('failed'); prWorker.ensurePr.mockResolvedValueOnce({ result: PrResult.Created, @@ -435,7 +435,7 @@ describe('workers/branch', () => { artifactErrors: [{}], updatedArtifacts: [{}], } as never); - git.branchExists.mockResolvedValueOnce(true); + git.branchExists.mockReturnValueOnce(true); automerge.tryBranchAutomerge.mockResolvedValueOnce('failed'); prWorker.ensurePr.mockResolvedValueOnce({ result: PrResult.Created, @@ -457,7 +457,7 @@ describe('workers/branch', () => { artifactErrors: [{}], updatedArtifacts: [{}], } as never); - git.branchExists.mockResolvedValueOnce(false); + git.branchExists.mockReturnValueOnce(false); automerge.tryBranchAutomerge.mockResolvedValueOnce('failed'); prWorker.ensurePr.mockResolvedValueOnce({ result: PrResult.Created, @@ -478,7 +478,7 @@ describe('workers/branch', () => { updatedArtifacts: [{}], } as never); config.recreateClosed = true; - git.branchExists.mockResolvedValueOnce(true); + git.branchExists.mockReturnValueOnce(true); automerge.tryBranchAutomerge.mockResolvedValueOnce('failed'); prWorker.ensurePr.mockResolvedValueOnce({ result: PrResult.Created, @@ -517,7 +517,7 @@ describe('workers/branch', () => { artifactErrors: [], updatedArtifacts: [{}], } as never); - git.branchExists.mockResolvedValueOnce(true); + git.branchExists.mockReturnValueOnce(true); automerge.tryBranchAutomerge.mockResolvedValueOnce(false as never); prWorker.ensurePr.mockImplementationOnce(() => { throw new Error('some error'); @@ -527,7 +527,7 @@ describe('workers/branch', () => { }); it('closed pr (dry run)', async () => { - git.branchExists.mockResolvedValueOnce(true); + git.branchExists.mockReturnValueOnce(true); checkExisting.prAlreadyExisted.mockResolvedValueOnce({ state: PrState.Closed, }); @@ -537,7 +537,7 @@ describe('workers/branch', () => { }); it('branch pr no rebase (dry run)', async () => { - git.branchExists.mockResolvedValueOnce(true); + git.branchExists.mockReturnValueOnce(true); platform.getBranchPr.mockResolvedValueOnce({ state: PrState.Open, } as never); @@ -556,7 +556,7 @@ describe('workers/branch', () => { artifactErrors: [], updatedArtifacts: [{}], } as never); - git.branchExists.mockResolvedValueOnce(true); + git.branchExists.mockReturnValueOnce(true); platform.getBranchPr.mockResolvedValueOnce({ title: 'rebase!', state: PrState.Open, @@ -586,7 +586,7 @@ describe('workers/branch', () => { artifactErrors: [], updatedArtifacts: [{}], } as never); - git.branchExists.mockResolvedValueOnce(true); + git.branchExists.mockReturnValueOnce(true); platform.getBranchPr.mockResolvedValueOnce({ title: 'rebase!', state: PrState.Open, @@ -617,7 +617,7 @@ describe('workers/branch', () => { artifactErrors: [], updatedArtifacts: [{}], } as never); - git.branchExists.mockResolvedValueOnce(true); + git.branchExists.mockReturnValueOnce(true); platform.getBranchPr.mockResolvedValueOnce({ title: 'rebase!', state: PrState.Open, @@ -654,7 +654,7 @@ describe('workers/branch', () => { }, ], } as never); - git.branchExists.mockResolvedValueOnce(true); + git.branchExists.mockReturnValueOnce(true); platform.getBranchPr.mockResolvedValueOnce({ title: 'rebase!', state: PrState.Open, diff --git a/lib/workers/branch/index.ts b/lib/workers/branch/index.ts index 10e7f3bed8..cf95ac21bb 100644 --- a/lib/workers/branch/index.ts +++ b/lib/workers/branch/index.ts @@ -67,7 +67,7 @@ export async function processBranch( ); logger.trace({ config }, 'branch config'); await checkoutBranch(config.baseBranch); - const branchExists = await gitBranchExists(config.branchName); + const branchExists = gitBranchExists(config.branchName); const branchPr = await platform.getBranchPr(config.branchName); logger.debug(`branchExists=${branchExists}`); const dependencyDashboardCheck = (config.dependencyDashboardChecks || {})[ diff --git a/lib/workers/branch/lock-files/index.spec.ts b/lib/workers/branch/lock-files/index.spec.ts index 9963de3e3f..dfbfffdfff 100644 --- a/lib/workers/branch/lock-files/index.spec.ts +++ b/lib/workers/branch/lock-files/index.spec.ts @@ -105,7 +105,7 @@ describe('manager/npm/post-update', () => { it('returns no error and empty lockfiles if lock file maintenance exists', async () => { config.updateType = 'lockFileMaintenance'; config.reuseExistingBranch = true; - git.branchExists.mockResolvedValueOnce(true); + git.branchExists.mockReturnValueOnce(true); const res = await getAdditionalFiles(config, { npm: [{}] }); expect(res).toMatchSnapshot(); expect(res.artifactErrors).toHaveLength(0); diff --git a/lib/workers/branch/reuse.spec.ts b/lib/workers/branch/reuse.spec.ts index d8fd9a5da5..f9b77d45c5 100644 --- a/lib/workers/branch/reuse.spec.ts +++ b/lib/workers/branch/reuse.spec.ts @@ -22,18 +22,18 @@ describe('workers/branch/parent', () => { }; }); it('returns undefined if branch does not exist', async () => { - git.branchExists.mockResolvedValueOnce(false); + git.branchExists.mockReturnValueOnce(false); const res = await shouldReuseExistingBranch(config); expect(res.reuseExistingBranch).toBe(false); }); it('returns branchName if no PR', async () => { - git.branchExists.mockResolvedValueOnce(true); + git.branchExists.mockReturnValueOnce(true); platform.getBranchPr.mockReturnValue(null); const res = await shouldReuseExistingBranch(config); expect(res.reuseExistingBranch).toBe(true); }); it('returns branchName if does not need rebaseing', async () => { - git.branchExists.mockResolvedValueOnce(true); + git.branchExists.mockReturnValueOnce(true); platform.getBranchPr.mockResolvedValueOnce({ ...pr, isConflicted: false, @@ -42,7 +42,7 @@ describe('workers/branch/parent', () => { expect(res.reuseExistingBranch).toBe(true); }); it('returns branchName if unmergeable and cannot rebase', async () => { - git.branchExists.mockResolvedValueOnce(true); + git.branchExists.mockReturnValueOnce(true); platform.getBranchPr.mockResolvedValueOnce({ ...pr, isConflicted: true, @@ -53,7 +53,7 @@ describe('workers/branch/parent', () => { }); it('returns branchName if unmergeable and can rebase, but rebaseWhen is never', async () => { config.rebaseWhen = 'never'; - git.branchExists.mockResolvedValueOnce(true); + git.branchExists.mockReturnValueOnce(true); platform.getBranchPr.mockResolvedValueOnce({ ...pr, isConflicted: true, @@ -63,7 +63,7 @@ describe('workers/branch/parent', () => { expect(res.reuseExistingBranch).toBe(true); }); it('returns undefined if PR title rebase!', async () => { - git.branchExists.mockResolvedValueOnce(true); + git.branchExists.mockReturnValueOnce(true); platform.getBranchPr.mockResolvedValueOnce({ ...pr, title: 'rebase!Update foo to v4', @@ -72,7 +72,7 @@ describe('workers/branch/parent', () => { expect(res.reuseExistingBranch).toBe(false); }); it('returns undefined if PR body check rebase', async () => { - git.branchExists.mockResolvedValueOnce(true); + git.branchExists.mockReturnValueOnce(true); platform.getBranchPr.mockResolvedValueOnce({ ...pr, title: 'Update foo to v4', @@ -82,7 +82,7 @@ describe('workers/branch/parent', () => { expect(res.reuseExistingBranch).toBe(false); }); it('aaa2 returns undefined if manual rebase by label', async () => { - git.branchExists.mockResolvedValueOnce(true); + git.branchExists.mockReturnValueOnce(true); platform.getBranchPr.mockResolvedValueOnce({ ...pr, labels: ['rebase'], @@ -91,7 +91,7 @@ describe('workers/branch/parent', () => { expect(res.reuseExistingBranch).toBe(false); }); it('aaa1 returns undefined if unmergeable and can rebase', async () => { - git.branchExists.mockResolvedValueOnce(true); + git.branchExists.mockReturnValueOnce(true); platform.getBranchPr.mockResolvedValueOnce({ ...pr, isConflicted: true, @@ -103,21 +103,21 @@ describe('workers/branch/parent', () => { it('returns branchName if automerge branch and not stale', async () => { config.automerge = true; config.automergeType = 'branch'; - git.branchExists.mockResolvedValueOnce(true); + git.branchExists.mockReturnValueOnce(true); const res = await shouldReuseExistingBranch(config); expect(res.reuseExistingBranch).toBe(true); }); it('returns undefined if automerge branch and stale', async () => { config.automerge = true; config.automergeType = 'branch'; - git.branchExists.mockResolvedValueOnce(true); + git.branchExists.mockReturnValueOnce(true); git.isBranchStale.mockResolvedValueOnce(true); const res = await shouldReuseExistingBranch(config); expect(res.reuseExistingBranch).toBe(false); }); it('returns branch if rebaseWhen=behind-base-branch but cannot rebase', async () => { config.rebaseWhen = 'behind-base-branch'; - git.branchExists.mockResolvedValueOnce(true); + git.branchExists.mockReturnValueOnce(true); git.isBranchStale.mockResolvedValueOnce(true); platform.getBranchPr.mockResolvedValueOnce({ ...pr, diff --git a/lib/workers/branch/reuse.ts b/lib/workers/branch/reuse.ts index 8a86a235df..0d2c0e4e70 100644 --- a/lib/workers/branch/reuse.ts +++ b/lib/workers/branch/reuse.ts @@ -13,7 +13,7 @@ export async function shouldReuseExistingBranch( ): Promise<ParentBranch> { const { branchName } = config; // Check if branch exists - if (!(await branchExists(branchName))) { + if (!branchExists(branchName)) { logger.debug(`Branch needs creating`); return { reuseExistingBranch: false }; } diff --git a/lib/workers/repository/finalise/prune.spec.ts b/lib/workers/repository/finalise/prune.spec.ts index acb64146c5..a58de04933 100644 --- a/lib/workers/repository/finalise/prune.spec.ts +++ b/lib/workers/repository/finalise/prune.spec.ts @@ -23,42 +23,42 @@ describe('workers/repository/finalise/prune', () => { it('returns if no branchList', async () => { delete config.branchList; await cleanup.pruneStaleBranches(config, config.branchList); - expect(git.getAllRenovateBranches).toHaveBeenCalledTimes(0); + expect(git.getBranchList).toHaveBeenCalledTimes(0); }); it('returns if no renovate branches', async () => { config.branchList = []; - git.getAllRenovateBranches.mockResolvedValueOnce([]); + git.getBranchList.mockReturnValueOnce([]); await expect( cleanup.pruneStaleBranches(config, config.branchList) ).resolves.not.toThrow(); }); it('returns if no remaining branches', async () => { config.branchList = ['renovate/a', 'renovate/b']; - git.getAllRenovateBranches.mockResolvedValueOnce(config.branchList); + git.getBranchList.mockReturnValueOnce(config.branchList); await cleanup.pruneStaleBranches(config, config.branchList); - expect(git.getAllRenovateBranches).toHaveBeenCalledTimes(1); + expect(git.getBranchList).toHaveBeenCalledTimes(1); expect(git.deleteBranch).toHaveBeenCalledTimes(0); }); it('renames deletes remaining branch', async () => { config.branchList = ['renovate/a', 'renovate/b']; - git.getAllRenovateBranches.mockResolvedValueOnce( + git.getBranchList.mockReturnValueOnce( config.branchList.concat(['renovate/c']) ); platform.findPr.mockResolvedValueOnce({ title: 'foo' } as never); await cleanup.pruneStaleBranches(config, config.branchList); - expect(git.getAllRenovateBranches).toHaveBeenCalledTimes(1); + expect(git.getBranchList).toHaveBeenCalledTimes(1); expect(git.deleteBranch).toHaveBeenCalledTimes(1); expect(platform.updatePr).toHaveBeenCalledTimes(1); }); it('does nothing on dryRun', async () => { config.branchList = ['renovate/a', 'renovate/b']; config.dryRun = true; - git.getAllRenovateBranches.mockResolvedValueOnce( + git.getBranchList.mockReturnValueOnce( config.branchList.concat(['renovate/c']) ); platform.findPr.mockResolvedValueOnce({ title: 'foo' } as never); await cleanup.pruneStaleBranches(config, config.branchList); - expect(git.getAllRenovateBranches).toHaveBeenCalledTimes(1); + expect(git.getBranchList).toHaveBeenCalledTimes(1); expect(git.deleteBranch).toHaveBeenCalledTimes(0); expect(platform.updatePr).toHaveBeenCalledTimes(0); }); @@ -66,26 +66,26 @@ describe('workers/repository/finalise/prune', () => { config.branchList = ['renovate/a', 'renovate/b']; config.dryRun = false; config.pruneStaleBranches = false; - git.getAllRenovateBranches.mockResolvedValueOnce( + git.getBranchList.mockReturnValueOnce( config.branchList.concat(['renovate/c']) ); platform.findPr.mockResolvedValueOnce({ title: 'foo' } as never); await cleanup.pruneStaleBranches(config, config.branchList); - expect(git.getAllRenovateBranches).toHaveBeenCalledTimes(1); + expect(git.getBranchList).toHaveBeenCalledTimes(1); expect(git.deleteBranch).toHaveBeenCalledTimes(0); expect(platform.updatePr).toHaveBeenCalledTimes(0); }); it('posts comment if someone pushed to PR', async () => { config.branchList = ['renovate/a', 'renovate/b']; config.dryRun = false; - git.getAllRenovateBranches.mockResolvedValueOnce( + git.getBranchList.mockReturnValueOnce( config.branchList.concat(['renovate/c']) ); platform.getBranchPr.mockResolvedValueOnce({} as never); git.isBranchModified.mockResolvedValueOnce(true); platform.findPr.mockResolvedValueOnce({ title: 'foo' } as never); await cleanup.pruneStaleBranches(config, config.branchList); - expect(git.getAllRenovateBranches).toHaveBeenCalledTimes(1); + expect(git.getBranchList).toHaveBeenCalledTimes(1); expect(git.deleteBranch).toHaveBeenCalledTimes(0); expect(platform.updatePr).toHaveBeenCalledTimes(0); expect(platform.ensureComment).toHaveBeenCalledTimes(1); @@ -93,14 +93,14 @@ describe('workers/repository/finalise/prune', () => { it('skips comment if dry run', async () => { config.branchList = ['renovate/a', 'renovate/b']; config.dryRun = true; - git.getAllRenovateBranches.mockResolvedValueOnce( + git.getBranchList.mockReturnValueOnce( config.branchList.concat(['renovate/c']) ); platform.getBranchPr.mockResolvedValueOnce({} as never); git.isBranchModified.mockResolvedValueOnce(true); platform.findPr.mockResolvedValueOnce({ title: 'foo' } as never); await cleanup.pruneStaleBranches(config, config.branchList); - expect(git.getAllRenovateBranches).toHaveBeenCalledTimes(1); + expect(git.getBranchList).toHaveBeenCalledTimes(1); expect(git.deleteBranch).toHaveBeenCalledTimes(0); expect(platform.updatePr).toHaveBeenCalledTimes(0); expect(platform.ensureComment).toHaveBeenCalledTimes(0); diff --git a/lib/workers/repository/finalise/prune.ts b/lib/workers/repository/finalise/prune.ts index 616266170c..207b99000a 100644 --- a/lib/workers/repository/finalise/prune.ts +++ b/lib/workers/repository/finalise/prune.ts @@ -5,7 +5,7 @@ import { platform } from '../../../platform'; import { PrState } from '../../../types'; import { deleteBranch, - getAllRenovateBranches, + getBranchList, isBranchModified, } from '../../../util/git'; @@ -89,7 +89,9 @@ export async function pruneStaleBranches( logger.debug('No branchList'); return; } - let renovateBranches = await getAllRenovateBranches(config.branchPrefix); + let renovateBranches = getBranchList().filter((branchName) => + branchName.startsWith(config.branchPrefix) + ); if (!renovateBranches?.length) { logger.debug('No renovate branches found'); return; diff --git a/lib/workers/repository/process/index.spec.ts b/lib/workers/repository/process/index.spec.ts index 40e09c939e..bad4c22815 100644 --- a/lib/workers/repository/process/index.spec.ts +++ b/lib/workers/repository/process/index.spec.ts @@ -22,10 +22,10 @@ describe('workers/repository/process/index', () => { it('processes baseBranches', async () => { extract.mockResolvedValue({} as never); config.baseBranches = ['branch1', 'branch2']; - git.branchExists.mockResolvedValueOnce(false); - git.branchExists.mockResolvedValueOnce(true); - git.branchExists.mockResolvedValueOnce(false); - git.branchExists.mockResolvedValueOnce(true); + git.branchExists.mockReturnValueOnce(false); + git.branchExists.mockReturnValueOnce(true); + git.branchExists.mockReturnValueOnce(false); + git.branchExists.mockReturnValueOnce(true); const res = await extractDependencies(config); await updateRepo(config, res.branches, res.branchList); expect(res).toMatchSnapshot(); diff --git a/lib/workers/repository/process/index.ts b/lib/workers/repository/process/index.ts index 02e8307c5e..cd7fcdf731 100644 --- a/lib/workers/repository/process/index.ts +++ b/lib/workers/repository/process/index.ts @@ -66,7 +66,7 @@ export async function extractDependencies( logger.debug({ baseBranches: config.baseBranches }, 'baseBranches'); const extracted: Record<string, Record<string, PackageFile[]>> = {}; for (const baseBranch of config.baseBranches) { - if (await branchExists(baseBranch)) { + if (branchExists(baseBranch)) { const baseBranchConfig = await getBaseBranchConfig(baseBranch, config); extracted[baseBranch] = await extract(baseBranchConfig); } else { @@ -75,7 +75,7 @@ export async function extractDependencies( } addSplit('extract'); for (const baseBranch of config.baseBranches) { - if (await branchExists(baseBranch)) { + if (branchExists(baseBranch)) { const baseBranchConfig = await getBaseBranchConfig(baseBranch, config); const packageFiles = extracted[baseBranch]; const baseBranchRes = await lookup(baseBranchConfig, packageFiles); diff --git a/lib/workers/repository/process/limits.spec.ts b/lib/workers/repository/process/limits.spec.ts index 056aa0a5d6..5dfbb4eae2 100644 --- a/lib/workers/repository/process/limits.spec.ts +++ b/lib/workers/repository/process/limits.spec.ts @@ -39,18 +39,18 @@ describe('workers/repository/process/limits', () => { }); }); describe('getConcurrentPrsRemaining()', () => { - it('calculates concurrent limit remaining', async () => { + it('calculates concurrent limit remaining', () => { config.prConcurrentLimit = 20; - git.branchExists.mockResolvedValueOnce(true); + git.branchExists.mockReturnValueOnce(true); const branches: BranchConfig[] = [ { branchName: 'test', upgrades: [] }, { branchName: undefined, upgrades: [] }, ]; - const res = await limits.getConcurrentPrsRemaining(config, branches); + const res = limits.getConcurrentPrsRemaining(config, branches); expect(res).toEqual(19); }); - it('returns 99 if no concurrent limit', async () => { - const res = await limits.getConcurrentPrsRemaining(config, []); + it('returns 99 if no concurrent limit', () => { + const res = limits.getConcurrentPrsRemaining(config, []); expect(res).toEqual(99); }); }); diff --git a/lib/workers/repository/process/limits.ts b/lib/workers/repository/process/limits.ts index 9d279476fd..0911eaaede 100644 --- a/lib/workers/repository/process/limits.ts +++ b/lib/workers/repository/process/limits.ts @@ -40,15 +40,15 @@ export async function getPrHourlyRemaining( return 99; } -export async function getConcurrentPrsRemaining( +export function getConcurrentPrsRemaining( config: RenovateConfig, branches: BranchConfig[] -): Promise<number> { +): number { if (config.prConcurrentLimit) { logger.debug(`Enforcing prConcurrentLimit (${config.prConcurrentLimit})`); let currentlyOpen = 0; for (const branch of branches) { - if (await branchExists(branch.branchName)) { + if (branchExists(branch.branchName)) { currentlyOpen += 1; } } @@ -65,7 +65,7 @@ export async function getPrsRemaining( branches: BranchConfig[] ): Promise<number> { const hourlyRemaining = await getPrHourlyRemaining(config); - const concurrentRemaining = await getConcurrentPrsRemaining(config, branches); + const concurrentRemaining = getConcurrentPrsRemaining(config, branches); return hourlyRemaining < concurrentRemaining ? hourlyRemaining : concurrentRemaining; -- GitLab