2021-11-23 21:10:45 +01:00
|
|
|
import { GlobalConfig } from '../../../config/global';
|
2023-06-06 01:03:30 +05:45
|
|
|
import type { Pr } from '../../../modules/platform/types';
|
2020-05-01 18:03:48 +02:00
|
|
|
import * as cleanup from './prune';
|
2025-03-13 18:52:09 +01:00
|
|
|
import { git, partial, platform, scm } from '~test/util';
|
|
|
|
import type { RenovateConfig } from '~test/util';
|
2017-11-05 05:45:49 +01:00
|
|
|
|
2019-12-21 21:11:59 +01:00
|
|
|
let config: RenovateConfig;
|
2022-04-12 16:49:49 +02:00
|
|
|
|
2017-11-05 05:45:49 +01:00
|
|
|
beforeEach(() => {
|
2023-06-15 10:18:56 +05:45
|
|
|
config = partial<RenovateConfig>({
|
|
|
|
repoIsOnboarded: true,
|
|
|
|
branchPrefix: `renovate/`,
|
|
|
|
pruneStaleBranches: true,
|
|
|
|
ignoredAuthors: [],
|
|
|
|
platform: 'github',
|
|
|
|
errors: [],
|
|
|
|
warnings: [],
|
|
|
|
});
|
2017-11-05 05:45:49 +01:00
|
|
|
});
|
2017-07-05 11:57:22 +02:00
|
|
|
|
2023-04-01 12:00:42 +02:00
|
|
|
describe('workers/repository/finalize/prune', () => {
|
2017-11-05 05:45:49 +01:00
|
|
|
describe('pruneStaleBranches()', () => {
|
2021-02-05 22:21:24 +01:00
|
|
|
beforeEach(() => {
|
2021-11-23 21:10:45 +01:00
|
|
|
GlobalConfig.reset();
|
2021-02-05 22:21:24 +01:00
|
|
|
});
|
2022-04-12 16:49:49 +02:00
|
|
|
|
2017-11-05 05:45:49 +01:00
|
|
|
it('returns if no branchList', async () => {
|
|
|
|
delete config.branchList;
|
|
|
|
await cleanup.pruneStaleBranches(config, config.branchList);
|
2020-08-30 22:03:58 +02:00
|
|
|
expect(git.getBranchList).toHaveBeenCalledTimes(0);
|
2017-07-05 11:57:22 +02:00
|
|
|
});
|
2022-04-12 16:49:49 +02:00
|
|
|
|
2023-11-03 19:16:49 +05:45
|
|
|
it('ignores reconfigure branch', async () => {
|
|
|
|
delete config.branchList;
|
|
|
|
await cleanup.pruneStaleBranches(config, config.branchList);
|
|
|
|
expect(git.getBranchList).toHaveBeenCalledTimes(0);
|
|
|
|
});
|
|
|
|
|
2018-02-03 12:06:25 +01:00
|
|
|
it('returns if no renovate branches', async () => {
|
2017-11-05 05:45:49 +01:00
|
|
|
config.branchList = [];
|
2020-08-30 22:03:58 +02:00
|
|
|
git.getBranchList.mockReturnValueOnce([]);
|
2020-05-18 14:33:44 +02:00
|
|
|
await expect(
|
2023-11-07 12:50:29 -03:00
|
|
|
cleanup.pruneStaleBranches(config, config.branchList),
|
2020-05-18 14:33:44 +02:00
|
|
|
).resolves.not.toThrow();
|
2017-07-05 11:57:22 +02:00
|
|
|
});
|
2022-04-12 16:49:49 +02:00
|
|
|
|
2017-07-05 11:57:22 +02:00
|
|
|
it('returns if no remaining branches', async () => {
|
2017-11-05 05:45:49 +01:00
|
|
|
config.branchList = ['renovate/a', 'renovate/b'];
|
2020-08-30 22:03:58 +02:00
|
|
|
git.getBranchList.mockReturnValueOnce(config.branchList);
|
2017-11-05 05:45:49 +01:00
|
|
|
await cleanup.pruneStaleBranches(config, config.branchList);
|
2020-08-30 22:03:58 +02:00
|
|
|
expect(git.getBranchList).toHaveBeenCalledTimes(1);
|
2023-02-22 09:18:53 +01:00
|
|
|
expect(scm.deleteBranch).toHaveBeenCalledTimes(0);
|
2017-07-05 11:57:22 +02:00
|
|
|
});
|
2022-04-12 16:49:49 +02:00
|
|
|
|
2017-10-19 07:36:09 +02:00
|
|
|
it('renames deletes remaining branch', async () => {
|
2017-11-05 05:45:49 +01:00
|
|
|
config.branchList = ['renovate/a', 'renovate/b'];
|
2020-08-30 22:03:58 +02:00
|
|
|
git.getBranchList.mockReturnValueOnce(
|
2023-11-07 12:50:29 -03:00
|
|
|
config.branchList.concat(['renovate/c']),
|
2017-07-05 11:57:22 +02:00
|
|
|
);
|
2023-06-06 01:03:30 +05:45
|
|
|
platform.findPr.mockResolvedValueOnce(partial<Pr>({ title: 'foo' }));
|
2017-11-05 05:45:49 +01:00
|
|
|
await cleanup.pruneStaleBranches(config, config.branchList);
|
2020-08-30 22:03:58 +02:00
|
|
|
expect(git.getBranchList).toHaveBeenCalledTimes(1);
|
2023-02-22 09:18:53 +01:00
|
|
|
expect(scm.deleteBranch).toHaveBeenCalledTimes(1);
|
2019-04-02 20:29:27 +05:30
|
|
|
expect(platform.updatePr).toHaveBeenCalledTimes(1);
|
2017-07-05 11:57:22 +02:00
|
|
|
});
|
2022-04-12 16:49:49 +02:00
|
|
|
|
2020-10-14 16:29:45 +02:00
|
|
|
it('skips rename but still deletes branch', async () => {
|
|
|
|
config.branchList = ['renovate/a', 'renovate/b'];
|
|
|
|
git.getBranchList.mockReturnValueOnce(
|
2023-11-07 12:50:29 -03:00
|
|
|
config.branchList.concat(['renovate/c']),
|
2020-10-14 16:29:45 +02:00
|
|
|
);
|
2023-06-06 01:03:30 +05:45
|
|
|
platform.findPr.mockResolvedValueOnce(
|
|
|
|
partial<Pr>({
|
|
|
|
title: 'foo - autoclosed',
|
2023-11-07 12:50:29 -03:00
|
|
|
}),
|
2023-06-06 01:03:30 +05:45
|
|
|
);
|
2020-10-14 16:29:45 +02:00
|
|
|
await cleanup.pruneStaleBranches(config, config.branchList);
|
|
|
|
expect(git.getBranchList).toHaveBeenCalledTimes(1);
|
2023-02-22 09:18:53 +01:00
|
|
|
expect(scm.deleteBranch).toHaveBeenCalledTimes(1);
|
2020-10-14 16:29:45 +02:00
|
|
|
expect(platform.updatePr).toHaveBeenCalledTimes(1);
|
|
|
|
});
|
2022-04-12 16:49:49 +02:00
|
|
|
|
2024-09-12 13:50:16 +02:00
|
|
|
it('deletes with base branches', async () => {
|
|
|
|
config.branchList = ['renovate/main-a'];
|
|
|
|
config.baseBranches = ['main', 'maint/v7'];
|
|
|
|
git.getBranchList.mockReturnValueOnce(
|
|
|
|
config.branchList.concat([
|
|
|
|
'renovate/main-b',
|
|
|
|
'renovate/maint/v7-a',
|
|
|
|
'renovate/maint/v7-b',
|
|
|
|
]),
|
|
|
|
);
|
|
|
|
scm.isBranchModified.mockResolvedValueOnce(true);
|
|
|
|
scm.isBranchModified.mockResolvedValueOnce(false);
|
|
|
|
scm.isBranchModified.mockResolvedValueOnce(true);
|
|
|
|
await cleanup.pruneStaleBranches(config, config.branchList);
|
|
|
|
expect(git.getBranchList).toHaveBeenCalledTimes(1);
|
|
|
|
expect(scm.deleteBranch).toHaveBeenCalledTimes(1);
|
|
|
|
expect(scm.deleteBranch).toHaveBeenCalledWith('renovate/maint/v7-a');
|
|
|
|
expect(scm.isBranchModified).toHaveBeenCalledTimes(3);
|
|
|
|
expect(scm.isBranchModified).toHaveBeenCalledWith(
|
|
|
|
'renovate/main-b',
|
|
|
|
'main',
|
|
|
|
);
|
|
|
|
expect(scm.isBranchModified).toHaveBeenCalledWith(
|
|
|
|
'renovate/maint/v7-a',
|
|
|
|
'maint/v7',
|
|
|
|
);
|
|
|
|
expect(scm.isBranchModified).toHaveBeenCalledWith(
|
|
|
|
'renovate/maint/v7-b',
|
|
|
|
'maint/v7',
|
|
|
|
);
|
|
|
|
});
|
|
|
|
|
2019-05-17 09:28:10 +02:00
|
|
|
it('does nothing on dryRun', async () => {
|
|
|
|
config.branchList = ['renovate/a', 'renovate/b'];
|
2022-04-11 23:29:02 +03:00
|
|
|
GlobalConfig.set({ dryRun: 'full' });
|
2020-08-30 22:03:58 +02:00
|
|
|
git.getBranchList.mockReturnValueOnce(
|
2023-11-07 12:50:29 -03:00
|
|
|
config.branchList.concat(['renovate/c']),
|
2019-05-17 09:28:10 +02:00
|
|
|
);
|
2023-06-06 01:03:30 +05:45
|
|
|
platform.findPr.mockResolvedValueOnce(partial<Pr>({ title: 'foo' }));
|
2019-05-17 09:28:10 +02:00
|
|
|
await cleanup.pruneStaleBranches(config, config.branchList);
|
2020-08-30 22:03:58 +02:00
|
|
|
expect(git.getBranchList).toHaveBeenCalledTimes(1);
|
2023-02-22 09:18:53 +01:00
|
|
|
expect(scm.deleteBranch).toHaveBeenCalledTimes(0);
|
2019-05-17 09:28:10 +02:00
|
|
|
expect(platform.updatePr).toHaveBeenCalledTimes(0);
|
|
|
|
});
|
2022-04-12 16:49:49 +02:00
|
|
|
|
2019-07-17 14:48:08 +02:00
|
|
|
it('does nothing on prune stale branches disabled', async () => {
|
|
|
|
config.branchList = ['renovate/a', 'renovate/b'];
|
|
|
|
config.pruneStaleBranches = false;
|
2020-08-30 22:03:58 +02:00
|
|
|
git.getBranchList.mockReturnValueOnce(
|
2023-11-07 12:50:29 -03:00
|
|
|
config.branchList.concat(['renovate/c']),
|
2019-07-17 14:48:08 +02:00
|
|
|
);
|
2023-06-06 01:03:30 +05:45
|
|
|
platform.findPr.mockResolvedValueOnce(partial<Pr>({ title: 'foo' }));
|
2019-07-17 14:48:08 +02:00
|
|
|
await cleanup.pruneStaleBranches(config, config.branchList);
|
2020-08-30 22:03:58 +02:00
|
|
|
expect(git.getBranchList).toHaveBeenCalledTimes(1);
|
2023-02-22 09:18:53 +01:00
|
|
|
expect(scm.deleteBranch).toHaveBeenCalledTimes(0);
|
2019-07-17 14:48:08 +02:00
|
|
|
expect(platform.updatePr).toHaveBeenCalledTimes(0);
|
|
|
|
});
|
2022-04-12 16:49:49 +02:00
|
|
|
|
2022-11-07 02:15:29 +05:30
|
|
|
it('notifies via PR changes if someone pushed to PR', async () => {
|
2019-08-15 15:15:09 +04:00
|
|
|
config.branchList = ['renovate/a', 'renovate/b'];
|
2020-08-30 22:03:58 +02:00
|
|
|
git.getBranchList.mockReturnValueOnce(
|
2023-11-07 12:50:29 -03:00
|
|
|
config.branchList.concat(['renovate/c']),
|
2019-08-15 15:15:09 +04:00
|
|
|
);
|
2023-06-06 01:03:30 +05:45
|
|
|
platform.getBranchPr.mockResolvedValueOnce(partial<Pr>());
|
2023-02-22 09:18:53 +01:00
|
|
|
scm.isBranchModified.mockResolvedValueOnce(true);
|
2023-06-06 01:03:30 +05:45
|
|
|
platform.findPr.mockResolvedValueOnce(partial<Pr>({ title: 'foo' }));
|
2019-08-15 15:15:09 +04:00
|
|
|
await cleanup.pruneStaleBranches(config, config.branchList);
|
2020-08-30 22:03:58 +02:00
|
|
|
expect(git.getBranchList).toHaveBeenCalledTimes(1);
|
2023-02-22 09:18:53 +01:00
|
|
|
expect(scm.deleteBranch).toHaveBeenCalledTimes(0);
|
2022-11-07 02:15:29 +05:30
|
|
|
expect(platform.updatePr).toHaveBeenCalledTimes(1);
|
2019-08-15 15:15:09 +04:00
|
|
|
expect(platform.ensureComment).toHaveBeenCalledTimes(1);
|
|
|
|
});
|
2022-04-12 16:49:49 +02:00
|
|
|
|
2022-11-07 02:15:29 +05:30
|
|
|
it('skips appending - abandoned to PR title if already present', async () => {
|
|
|
|
config.branchList = ['renovate/a', 'renovate/b'];
|
|
|
|
git.getBranchList.mockReturnValueOnce(
|
2023-11-07 12:50:29 -03:00
|
|
|
config.branchList.concat(['renovate/c']),
|
2022-11-07 02:15:29 +05:30
|
|
|
);
|
2023-06-06 01:03:30 +05:45
|
|
|
platform.getBranchPr.mockResolvedValueOnce(partial<Pr>());
|
2023-02-22 09:18:53 +01:00
|
|
|
scm.isBranchModified.mockResolvedValueOnce(true);
|
2023-06-06 01:03:30 +05:45
|
|
|
platform.findPr.mockResolvedValueOnce(
|
2023-11-07 12:50:29 -03:00
|
|
|
partial<Pr>({ title: 'foo - abandoned' }),
|
2023-06-06 01:03:30 +05:45
|
|
|
);
|
2022-11-07 02:15:29 +05:30
|
|
|
await cleanup.pruneStaleBranches(config, config.branchList);
|
|
|
|
expect(platform.updatePr).toHaveBeenCalledTimes(0);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('skips changes to PR if dry run', async () => {
|
2019-08-15 15:15:09 +04:00
|
|
|
config.branchList = ['renovate/a', 'renovate/b'];
|
2022-04-11 23:29:02 +03:00
|
|
|
GlobalConfig.set({ dryRun: 'full' });
|
2020-08-30 22:03:58 +02:00
|
|
|
git.getBranchList.mockReturnValueOnce(
|
2023-11-07 12:50:29 -03:00
|
|
|
config.branchList.concat(['renovate/c']),
|
2019-08-15 15:15:09 +04:00
|
|
|
);
|
2023-06-06 01:03:30 +05:45
|
|
|
platform.getBranchPr.mockResolvedValueOnce(partial<Pr>());
|
2023-02-22 09:18:53 +01:00
|
|
|
scm.isBranchModified.mockResolvedValueOnce(true);
|
2023-06-06 01:03:30 +05:45
|
|
|
platform.findPr.mockResolvedValueOnce(partial<Pr>({ title: 'foo' }));
|
2019-08-15 15:15:09 +04:00
|
|
|
await cleanup.pruneStaleBranches(config, config.branchList);
|
2020-08-30 22:03:58 +02:00
|
|
|
expect(git.getBranchList).toHaveBeenCalledTimes(1);
|
2023-02-22 09:18:53 +01:00
|
|
|
expect(scm.deleteBranch).toHaveBeenCalledTimes(0);
|
2019-08-15 15:15:09 +04:00
|
|
|
expect(platform.updatePr).toHaveBeenCalledTimes(0);
|
|
|
|
expect(platform.ensureComment).toHaveBeenCalledTimes(0);
|
|
|
|
});
|
2022-04-12 16:49:49 +02:00
|
|
|
|
2020-10-14 16:29:45 +02:00
|
|
|
it('dry run delete branch no PR', async () => {
|
|
|
|
config.branchList = ['renovate/a', 'renovate/b'];
|
2022-04-11 23:29:02 +03:00
|
|
|
GlobalConfig.set({ dryRun: 'full' });
|
2020-10-14 16:29:45 +02:00
|
|
|
git.getBranchList.mockReturnValueOnce(
|
2023-11-07 12:50:29 -03:00
|
|
|
config.branchList.concat(['renovate/c']),
|
2020-10-14 16:29:45 +02:00
|
|
|
);
|
|
|
|
platform.findPr.mockResolvedValueOnce(null as never);
|
|
|
|
await cleanup.pruneStaleBranches(config, config.branchList);
|
|
|
|
expect(git.getBranchList).toHaveBeenCalledTimes(1);
|
2023-02-22 09:18:53 +01:00
|
|
|
expect(scm.deleteBranch).toHaveBeenCalledTimes(0);
|
2020-10-14 16:29:45 +02:00
|
|
|
expect(platform.updatePr).toHaveBeenCalledTimes(0);
|
|
|
|
});
|
2022-04-12 16:49:49 +02:00
|
|
|
|
2020-10-14 16:29:45 +02:00
|
|
|
it('delete branch no PR', async () => {
|
|
|
|
config.branchList = ['renovate/a', 'renovate/b'];
|
|
|
|
git.getBranchList.mockReturnValueOnce(
|
2023-11-07 12:50:29 -03:00
|
|
|
config.branchList.concat(['renovate/c']),
|
2020-10-14 16:29:45 +02:00
|
|
|
);
|
|
|
|
platform.findPr.mockResolvedValueOnce(null as never);
|
|
|
|
await cleanup.pruneStaleBranches(config, config.branchList);
|
|
|
|
expect(git.getBranchList).toHaveBeenCalledTimes(1);
|
2023-02-22 09:18:53 +01:00
|
|
|
expect(scm.deleteBranch).toHaveBeenCalledTimes(1);
|
2020-10-14 16:29:45 +02:00
|
|
|
expect(platform.updatePr).toHaveBeenCalledTimes(0);
|
|
|
|
});
|
2022-06-13 02:45:35 +03:00
|
|
|
|
|
|
|
it('does not delete modified orphan branch', async () => {
|
|
|
|
config.branchList = ['renovate/a', 'renovate/b'];
|
|
|
|
git.getBranchList.mockReturnValueOnce(
|
2023-11-07 12:50:29 -03:00
|
|
|
config.branchList.concat(['renovate/c']),
|
2022-06-13 02:45:35 +03:00
|
|
|
);
|
2023-02-22 09:18:53 +01:00
|
|
|
scm.isBranchModified.mockResolvedValueOnce(true);
|
2022-06-13 02:45:35 +03:00
|
|
|
platform.findPr.mockResolvedValueOnce(null as never);
|
|
|
|
await cleanup.pruneStaleBranches(config, config.branchList);
|
|
|
|
expect(git.getBranchList).toHaveBeenCalledTimes(1);
|
2023-02-22 09:18:53 +01:00
|
|
|
expect(scm.deleteBranch).toHaveBeenCalledTimes(0);
|
2022-06-13 02:45:35 +03:00
|
|
|
expect(platform.updatePr).toHaveBeenCalledTimes(0);
|
|
|
|
});
|
2017-07-05 11:57:22 +02:00
|
|
|
});
|
|
|
|
});
|