-
Notifications
You must be signed in to change notification settings - Fork 2.5k
/
Copy pathbranchify.ts
135 lines (132 loc) · 4.71 KB
/
branchify.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
// TODO #7154
import type { Merge } from 'type-fest';
import type { RenovateConfig, ValidationMessage } from '../../../config/types';
import { addMeta, logger, removeMeta } from '../../../logger';
import type { BranchConfig, BranchUpgradeConfig } from '../../types';
import { embedChangelogs, needsChangelogs } from '../changelog';
import { flattenUpdates } from './flatten';
import { generateBranchConfig } from './generate';
export type BranchifiedConfig = Merge<
RenovateConfig,
{
branches: BranchConfig[];
branchList: string[];
}
>;
export async function branchifyUpgrades(
config: RenovateConfig,
packageFiles: Record<string, any[]>
): Promise<BranchifiedConfig> {
logger.debug('branchifyUpgrades');
const updates = await flattenUpdates(config, packageFiles);
logger.debug(
`${updates.length} flattened updates found: ${updates
.map((u) => u.depName)
.filter((txt) => txt?.trim().length)
.join(', ')}`
);
const errors: ValidationMessage[] = [];
const warnings: ValidationMessage[] = [];
const branchUpgrades: Record<string, BranchUpgradeConfig[]> = {};
const branches: BranchConfig[] = [];
for (const u of updates) {
const update: BranchUpgradeConfig = { ...u } as any;
branchUpgrades[update.branchName] = branchUpgrades[update.branchName] || [];
branchUpgrades[update.branchName] = [update].concat(
branchUpgrades[update.branchName]
);
}
logger.debug(`Returning ${Object.keys(branchUpgrades).length} branch(es)`);
for (const branchName of Object.keys(branchUpgrades)) {
// Add branch name to metadata before generating branch config
addMeta({
branch: branchName,
});
const seenUpdates: Record<string, string> = {};
// Filter out duplicates
branchUpgrades[branchName] = branchUpgrades[branchName]
.reverse()
.filter((upgrade) => {
const { manager, packageFile, depName, currentValue, newValue } =
upgrade;
// TODO: types (#7154)
const upgradeKey = `${packageFile!}:${depName!}:${currentValue!}`;
const previousNewValue = seenUpdates[upgradeKey];
if (previousNewValue && previousNewValue !== newValue) {
logger.info(
{
manager,
packageFile,
depName,
currentValue,
previousNewValue,
thisNewValue: newValue,
},
'Ignoring upgrade collision'
);
return false;
}
seenUpdates[upgradeKey] = newValue!;
return true;
})
.reverse();
if (config.fetchReleaseNotes && config.repoIsOnboarded) {
const branches = branchUpgrades[branchName].filter((upg) =>
needsChangelogs(upg)
);
if (branches.length) {
logger.warn(
{
branches: branches.map((b) => b.branchName),
docs: 'https://docs.renovatebot.com/templates/',
},
'Fetching changelogs early is deprecated. Remove `logJSON` and `releases` from config templates. They are only allowed in `commitBody` template. See template docs for allowed templates'
);
await embedChangelogs(branches);
}
}
const branch = generateBranchConfig(branchUpgrades[branchName]);
branch.branchName = branchName;
branch.packageFiles = packageFiles;
branches.push(branch);
}
removeMeta(['branch']);
// TODO: types (#7154)
logger.debug(`config.repoIsOnboarded=${config.repoIsOnboarded!}`);
const branchList = config.repoIsOnboarded
? branches.map((upgrade) => upgrade.branchName)
: config.branchList;
// istanbul ignore next
try {
// Here we check if there are updates from the same source repo
// that are not grouped into the same branch
const branchUpdates: Record<string, Record<string, string>> = {};
for (const branch of branches) {
const { sourceUrl, branchName, depName, newVersion } = branch;
if (sourceUrl && newVersion) {
const key = `${sourceUrl}|${newVersion}`;
branchUpdates[key] = branchUpdates[key] || {};
if (!branchUpdates[key][branchName]) {
branchUpdates[key][branchName] = depName!;
}
}
}
for (const [key, value] of Object.entries(branchUpdates)) {
if (Object.keys(value).length > 1) {
const [sourceUrl, newVersion] = key.split('|');
logger.debug(
{ sourceUrl, newVersion, branches: value },
'Found sourceUrl with multiple branches that should probably be combined into a group'
);
}
}
} catch (err) {
logger.debug({ err }, 'Error checking branch duplicates');
}
return {
errors: config.errors!.concat(errors),
warnings: config.warnings!.concat(warnings),
branches,
branchList: branchList!,
};
}