diff --git a/lib/workers/branch/index.spec.ts b/lib/workers/branch/index.spec.ts index 0dd6a38f43bf1df4b5939b7c2bb35a557344b0b3..1a3c3a941111a5cc7da5e9cbbcf88d9ac76c2482 100644 --- a/lib/workers/branch/index.spec.ts +++ b/lib/workers/branch/index.spec.ts @@ -106,14 +106,14 @@ describe(getName(__filename), () => { it('skips branch if not scheduled and branch does not exist', async () => { schedule.isScheduledNow.mockReturnValueOnce(false); const res = await branchWorker.processBranch(config); - expect(res).toEqual(BranchResult.NotScheduled); + expect(res).toEqual({ result: BranchResult.NotScheduled }); }); it('skips branch if not scheduled and not updating out of schedule', async () => { schedule.isScheduledNow.mockReturnValueOnce(false); config.updateNotScheduled = false; git.branchExists.mockReturnValue(true); const res = await branchWorker.processBranch(config); - expect(res).toEqual(BranchResult.NotScheduled); + expect(res).toEqual({ result: BranchResult.NotScheduled }); }); it('skips branch for fresh release with stabilityDays', async () => { schedule.isScheduledNow.mockReturnValueOnce(true); @@ -136,7 +136,7 @@ describe(getName(__filename), () => { git.branchExists.mockReturnValue(false); const res = await branchWorker.processBranch(config); - expect(res).toEqual(BranchResult.Pending); + expect(res).toEqual({ result: BranchResult.Pending }); }); it('skips branch if not stabilityDays not met', async () => { schedule.isScheduledNow.mockReturnValueOnce(true); @@ -148,7 +148,7 @@ describe(getName(__filename), () => { }, ]; const res = await branchWorker.processBranch(config); - expect(res).toEqual(BranchResult.Pending); + expect(res).toEqual({ result: BranchResult.Pending }); }); it('processes branch if not scheduled but updating out of schedule', async () => { schedule.isScheduledNow.mockReturnValueOnce(false); @@ -223,7 +223,7 @@ describe(getName(__filename), () => { } as Pr); git.isBranchModified.mockResolvedValueOnce(true); const res = await branchWorker.processBranch(config); - expect(res).not.toEqual(BranchResult.PrEdited); + expect(res).not.toEqual({ result: BranchResult.PrEdited }); }); it('skips branch if edited PR found', async () => { schedule.isScheduledNow.mockReturnValueOnce(false); @@ -234,7 +234,7 @@ describe(getName(__filename), () => { } as Pr); git.isBranchModified.mockResolvedValueOnce(true); const res = await branchWorker.processBranch(config); - expect(res).toEqual(BranchResult.PrEdited); + expect(res).toEqual({ result: BranchResult.PrEdited }); }); it('skips branch if target branch changed', async () => { schedule.isScheduledNow.mockReturnValueOnce(false); @@ -246,13 +246,13 @@ describe(getName(__filename), () => { git.isBranchModified.mockResolvedValueOnce(false); config.baseBranch = 'master'; const res = await branchWorker.processBranch(config); - expect(res).toEqual(BranchResult.PrEdited); + expect(res).toEqual({ result: BranchResult.PrEdited }); }); it('skips branch if branch edited and no PR found', async () => { git.branchExists.mockReturnValue(true); git.isBranchModified.mockResolvedValueOnce(true); const res = await branchWorker.processBranch(config); - expect(res).toEqual(BranchResult.PrEdited); + expect(res).toEqual({ result: BranchResult.PrEdited }); }); it('continues branch if branch edited and but PR found', async () => { git.branchExists.mockReturnValue(true); @@ -260,7 +260,7 @@ describe(getName(__filename), () => { git.getBranchCommit.mockReturnValueOnce('abc123'); platform.findPr.mockResolvedValueOnce({ sha: 'abc123' } as any); const res = await branchWorker.processBranch(config); - expect(res).toEqual(BranchResult.Error); + expect(res).toEqual({ result: BranchResult.Error }); }); it('skips branch if branch edited and and PR found with sha mismatch', async () => { git.branchExists.mockReturnValue(true); @@ -268,7 +268,7 @@ describe(getName(__filename), () => { git.getBranchCommit.mockReturnValueOnce('abc123'); platform.findPr.mockResolvedValueOnce({ sha: 'def456' } as any); const res = await branchWorker.processBranch(config); - expect(res).toEqual(BranchResult.PrEdited); + expect(res).toEqual({ result: BranchResult.PrEdited }); }); it('returns if branch creation limit exceeded', async () => { getUpdated.getUpdatedPackageFiles.mockResolvedValueOnce({ @@ -280,9 +280,9 @@ describe(getName(__filename), () => { }); limits.isLimitReached.mockReturnValueOnce(true); limits.isLimitReached.mockReturnValueOnce(false); - expect(await branchWorker.processBranch(config)).toEqual( - BranchResult.BranchLimitReached - ); + expect(await branchWorker.processBranch(config)).toEqual({ + result: BranchResult.BranchLimitReached, + }); }); it('returns if pr creation limit exceeded and branch exists', async () => { getUpdated.getUpdatedPackageFiles.mockResolvedValueOnce({ @@ -297,9 +297,9 @@ describe(getName(__filename), () => { prResult: PrResult.LimitReached, }); limits.isLimitReached.mockReturnValue(false); - expect(await branchWorker.processBranch(config)).toEqual( - BranchResult.PrLimitReached - ); + expect(await branchWorker.processBranch(config)).toEqual({ + result: BranchResult.PrLimitReached, + }); }); it('returns if commit limit exceeded', async () => { getUpdated.getUpdatedPackageFiles.mockResolvedValueOnce({ @@ -312,9 +312,9 @@ describe(getName(__filename), () => { git.branchExists.mockReturnValue(false); limits.isLimitReached.mockReturnValueOnce(false); limits.isLimitReached.mockReturnValueOnce(true); - expect(await branchWorker.processBranch(config)).toEqual( - BranchResult.CommitLimitReached - ); + expect(await branchWorker.processBranch(config)).toEqual({ + result: BranchResult.CommitLimitReached, + }); }); it('returns if no work', async () => { getUpdated.getUpdatedPackageFiles.mockResolvedValueOnce({ @@ -326,9 +326,9 @@ describe(getName(__filename), () => { }); git.branchExists.mockReturnValue(false); commit.commitFilesToBranch.mockResolvedValueOnce(null); - expect(await branchWorker.processBranch(config)).toEqual( - BranchResult.NoWork - ); + expect(await branchWorker.processBranch(config)).toEqual({ + result: BranchResult.NoWork, + }); }); it('returns if branch automerged', async () => { getUpdated.getUpdatedPackageFiles.mockResolvedValueOnce({ @@ -394,9 +394,9 @@ describe(getName(__filename), () => { prWorker.ensurePr.mockResolvedValueOnce({ prResult: PrResult.AwaitingApproval, }); - expect(await branchWorker.processBranch(config)).toEqual( - BranchResult.NeedsPrApproval - ); + expect(await branchWorker.processBranch(config)).toEqual({ + result: BranchResult.NeedsPrApproval, + }); }); it('returns if branch exists but pending', async () => { expect.assertions(1); @@ -413,9 +413,9 @@ describe(getName(__filename), () => { prWorker.ensurePr.mockResolvedValueOnce({ prResult: PrResult.AwaitingNotPending, }); - expect(await branchWorker.processBranch(config)).toEqual( - BranchResult.Pending - ); + expect(await branchWorker.processBranch(config)).toEqual({ + result: BranchResult.Pending, + }); }); it('returns if branch exists but updated', async () => { expect.assertions(3); @@ -432,7 +432,7 @@ describe(getName(__filename), () => { requiredStatusChecks: null, prCreation: 'not-pending', }) - ).toEqual(BranchResult.Pending); + ).toEqual({ result: BranchResult.Pending }); expect(automerge.tryBranchAutomerge).toHaveBeenCalledTimes(0); expect(prWorker.ensurePr).toHaveBeenCalledTimes(0); @@ -606,9 +606,9 @@ describe(getName(__filename), () => { state: PrState.Closed, } as Pr); setAdminConfig({ dryRun: true }); - expect(await branchWorker.processBranch(config)).toEqual( - BranchResult.AlreadyExisted - ); + expect(await branchWorker.processBranch(config)).toEqual({ + result: BranchResult.AlreadyExisted, + }); }); it('branch pr no rebase (dry run)', async () => { @@ -618,9 +618,9 @@ describe(getName(__filename), () => { } as Pr); git.isBranchModified.mockResolvedValueOnce(true); setAdminConfig({ dryRun: true }); - expect(await branchWorker.processBranch(config)).toEqual( - BranchResult.PrEdited - ); + expect(await branchWorker.processBranch(config)).toEqual({ + result: BranchResult.PrEdited, + }); }); it('branch pr no schedule lockfile (dry run)', async () => { @@ -649,7 +649,7 @@ describe(getName(__filename), () => { reuseExistingBranch: false, updatedArtifacts: [{ name: '|delete|', contents: 'dummy' }], }) - ).toEqual(BranchResult.Done); + ).toEqual({ result: BranchResult.Done }); }); it('branch pr no schedule (dry run)', async () => { @@ -680,7 +680,7 @@ describe(getName(__filename), () => { ...config, artifactErrors: [{}], }) - ).toEqual(BranchResult.Done); + ).toEqual({ result: BranchResult.Done }); }); it('branch pr no schedule', async () => { @@ -708,7 +708,7 @@ describe(getName(__filename), () => { reuseExistingBranch: false, updatedArtifacts: [{ name: '|delete|', contents: 'dummy' }], }) - ).toEqual(BranchResult.Done); + ).toEqual({ result: BranchResult.Done }); }); it('executes post-upgrade tasks if trust is high', async () => { @@ -776,7 +776,7 @@ describe(getName(__filename), () => { ], }); - expect(result).toEqual(BranchResult.Done); + expect(result).toEqual({ result: BranchResult.Done }); expect(exec.exec).toHaveBeenCalledWith('echo semver', { cwd: '/localDir', }); @@ -924,7 +924,7 @@ describe(getName(__filename), () => { ], }); - expect(result).toEqual(BranchResult.Done); + expect(result).toEqual({ result: BranchResult.Done }); expect(exec.exec).toHaveBeenCalledWith('echo {{{versioning}}}', { cwd: '/localDir', }); @@ -1031,7 +1031,7 @@ describe(getName(__filename), () => { const result = await branchWorker.processBranch(inconfig); - expect(result).toEqual(BranchResult.Done); + expect(result).toEqual({ result: BranchResult.Done }); expect(exec.exec).toHaveBeenNthCalledWith(1, 'echo some-dep-name-1', { cwd: '/localDir', }); @@ -1160,7 +1160,7 @@ describe(getName(__filename), () => { }; const result = await branchWorker.processBranch(inconfig); - expect(result).toEqual(BranchResult.Done); + expect(result).toEqual({ result: BranchResult.Done }); expect(exec.exec).toHaveBeenNthCalledWith(1, 'echo hardcoded-string', { cwd: '/localDir', }); diff --git a/lib/workers/branch/index.ts b/lib/workers/branch/index.ts index 2b24446f372822ef8483e1234cb1dcd468cd31e8..c11e5782efcb86d50aa773bd30cb02b84145e252 100644 --- a/lib/workers/branch/index.ts +++ b/lib/workers/branch/index.ts @@ -60,9 +60,13 @@ async function deleteBranchSilently(branchName: string): Promise<void> { } } +export interface ProcessBranchResult { + result: BranchResult; +} + export async function processBranch( branchConfig: BranchConfig -): Promise<BranchResult> { +): Promise<ProcessBranchResult> { let config: BranchConfig = { ...branchConfig }; logger.trace({ config }, 'processBranch()'); await checkoutBranch(config.baseBranch); @@ -86,7 +90,7 @@ export async function processBranch( 'Closed PR already exists. Skipping branch.' ); await handlepr(config, existingPr); - return BranchResult.AlreadyExisted; + return { result: BranchResult.AlreadyExisted }; } // istanbul ignore if if (!branchExists && config.dependencyDashboardApproval) { @@ -94,7 +98,7 @@ export async function processBranch( logger.debug(`Branch ${config.branchName} is approved for creation`); } else { logger.debug(`Branch ${config.branchName} needs approval`); - return BranchResult.NeedsApproval; + return { result: BranchResult.NeedsApproval }; } } if ( @@ -104,7 +108,7 @@ export async function processBranch( !config.isVulnerabilityAlert ) { logger.debug('Reached branch limit - skipping branch creation'); - return BranchResult.BranchLimitReached; + return { result: BranchResult.BranchLimitReached }; } if ( isLimitReached(Limit.Commits) && @@ -112,7 +116,7 @@ export async function processBranch( !config.isVulnerabilityAlert ) { logger.debug('Reached commits limit - skipping branch'); - return BranchResult.CommitLimitReached; + return { result: BranchResult.CommitLimitReached }; } if (branchExists) { logger.debug('Checking if PR has been edited'); @@ -149,7 +153,7 @@ export async function processBranch( platformOptions: getPlatformPrOptions(config), }); } - return BranchResult.PrEdited; + return { result: BranchResult.PrEdited }; } } } else if (branchIsModified) { @@ -159,7 +163,7 @@ export async function processBranch( }); if (!oldPr) { logger.debug('Branch has been edited but found no PR - skipping'); - return BranchResult.PrEdited; + return { result: BranchResult.PrEdited }; } const branchSha = getBranchCommit(config.branchName); const oldPrSha = oldPr?.sha; @@ -173,7 +177,7 @@ export async function processBranch( { oldPrNumber: oldPr.number, oldPrSha, branchSha }, 'Found old PR but the SHA is different' ); - return BranchResult.PrEdited; + return { result: BranchResult.PrEdited }; } } } @@ -183,16 +187,16 @@ export async function processBranch( if (!config.isScheduledNow && !dependencyDashboardCheck) { if (!branchExists) { logger.debug('Skipping branch creation as not within schedule'); - return BranchResult.NotScheduled; + return { result: BranchResult.NotScheduled }; } if (config.updateNotScheduled === false && !config.rebaseRequested) { logger.debug('Skipping branch update as not within schedule'); - return BranchResult.NotScheduled; + return { result: BranchResult.NotScheduled }; } // istanbul ignore if if (!branchPr) { logger.debug('Skipping PR creation out of schedule'); - return BranchResult.NotScheduled; + return { result: BranchResult.NotScheduled }; } logger.debug( 'Branch + PR exists but is not scheduled -- will update if necessary' @@ -240,7 +244,7 @@ export async function processBranch( ['not-pending', 'status-success'].includes(config.prCreation) ) { logger.debug('Skipping branch creation due to stability days not met'); - return BranchResult.Pending; + return { result: BranchResult.Pending }; } } @@ -346,7 +350,7 @@ export async function processBranch( await platform.refreshPr(branchPr.number); } if (!commitSha && !branchExists) { - return BranchResult.NoWork; + return { result: BranchResult.NoWork }; } if (commitSha) { const action = branchExists ? 'updated' : 'created'; @@ -363,7 +367,7 @@ export async function processBranch( (config.requiredStatusChecks?.length || config.prCreation !== 'immediate') ) { logger.debug({ commitSha }, `Branch status pending`); - return BranchResult.Pending; + return { result: BranchResult.Pending }; } // Try to automerge branch and finish if successful, but only if branch already existed before this run @@ -373,7 +377,7 @@ export async function processBranch( if (mergeStatus === 'automerged') { await deleteBranchSilently(config.branchName); logger.debug('Branch is automerged - returning'); - return BranchResult.Automerged; + return { result: BranchResult.Automerged }; } if ( mergeStatus === 'automerge aborted - PR exists' || @@ -437,7 +441,7 @@ export async function processBranch( logger.warn('Error updating branch: update failure'); } else if (err.message.startsWith('bundler-')) { // we have already warned inside the bundler artifacts error handling, so just return - return BranchResult.Error; + return { result: BranchResult.Error }; } else if ( err.messagee && err.message.includes('fatal: Authentication failed') @@ -456,7 +460,7 @@ export async function processBranch( logger.warn({ err }, `Error updating branch`); } // Don't throw here - we don't want to stop the other renovations - return BranchResult.Error; + return { result: BranchResult.Error }; } try { logger.debug('Ensuring PR'); @@ -466,17 +470,17 @@ export async function processBranch( const { prResult: result, pr } = await ensurePr(config); if (result === PrResult.LimitReached && !config.isVulnerabilityAlert) { logger.debug('Reached PR limit - skipping PR creation'); - return BranchResult.PrLimitReached; + return { result: BranchResult.PrLimitReached }; } // TODO: ensurePr should check for automerge itself if (result === PrResult.AwaitingApproval) { - return BranchResult.NeedsPrApproval; + return { result: BranchResult.NeedsPrApproval }; } if ( result === PrResult.AwaitingGreenBranch || result === PrResult.AwaitingNotPending ) { - return BranchResult.Pending; + return { result: BranchResult.Pending }; } if (pr) { if (config.artifactErrors?.length) { @@ -550,7 +554,7 @@ export async function processBranch( logger.debug('PR is configured for automerge'); const prAutomergeResult = await checkAutoMerge(pr, config); if (prAutomergeResult?.automerged) { - return BranchResult.Automerged; + return { result: BranchResult.Automerged }; } } else { logger.debug('PR is not configured for automerge'); @@ -568,7 +572,7 @@ export async function processBranch( logger.error({ err }, `Error ensuring PR: ${String(err.message)}`); } if (!branchExists) { - return BranchResult.PrCreated; + return { result: BranchResult.PrCreated }; } - return BranchResult.Done; + return { result: BranchResult.Done }; } diff --git a/lib/workers/repository/process/write.spec.ts b/lib/workers/repository/process/write.spec.ts index 22a5b1caa132ec2d9e0fa9c009b5f561032c6a1b..3b0722aa108c68e8cc3c83369e11f412b9cebc17 100644 --- a/lib/workers/repository/process/write.spec.ts +++ b/lib/workers/repository/process/write.spec.ts @@ -49,19 +49,27 @@ describe(getName(__filename), () => { {}, ] as never; git.branchExists.mockReturnValue(true); - branchWorker.processBranch.mockResolvedValueOnce(BranchResult.PrCreated); - branchWorker.processBranch.mockResolvedValueOnce( - BranchResult.AlreadyExisted - ); - branchWorker.processBranch.mockResolvedValueOnce(BranchResult.Automerged); - branchWorker.processBranch.mockResolvedValueOnce(BranchResult.Automerged); + branchWorker.processBranch.mockResolvedValueOnce({ + result: BranchResult.PrCreated, + }); + branchWorker.processBranch.mockResolvedValueOnce({ + result: BranchResult.AlreadyExisted, + }); + branchWorker.processBranch.mockResolvedValueOnce({ + result: BranchResult.Automerged, + }); + branchWorker.processBranch.mockResolvedValueOnce({ + result: BranchResult.Automerged, + }); const res = await writeUpdates(config, branches); expect(res).toEqual('automerged'); expect(branchWorker.processBranch).toHaveBeenCalledTimes(4); }); it('increments branch counter', async () => { const branches: BranchConfig[] = [{}] as never; - branchWorker.processBranch.mockResolvedValueOnce(BranchResult.PrCreated); + branchWorker.processBranch.mockResolvedValueOnce({ + result: BranchResult.PrCreated, + }); git.branchExists.mockReturnValueOnce(false); git.branchExists.mockReturnValueOnce(true); limits.getBranchesRemaining.mockReturnValueOnce(1); diff --git a/lib/workers/repository/process/write.ts b/lib/workers/repository/process/write.ts index de95d94e5ba44c3a87e867e34dfd6daa7e5abcbf..7fe130b45813b0281f55632f18fa8e005b17a6c3 100644 --- a/lib/workers/repository/process/write.ts +++ b/lib/workers/repository/process/write.ts @@ -44,9 +44,9 @@ export async function writeUpdates( addMeta({ branch: branch.branchName }); const branchExisted = branchExists(branch.branchName); const res = await processBranch(branch); - branch.result = res; + branch.result = res?.result; if ( - res === BranchResult.Automerged && + branch.result === BranchResult.Automerged && branch.automergeType !== 'pr-comment' ) { // Stop processing other branches because base branch has been changed