mirror of
https://github.com/renovatebot/renovate.git
synced 2025-01-14 16:46:25 +00:00
214 lines
6.7 KiB
JavaScript
214 lines
6.7 KiB
JavaScript
const is = require('@sindresorhus/is');
|
|
const handlebars = require('handlebars');
|
|
const releaseNotesHbs = require('./changelog/hbs-template');
|
|
const { getPrConfigDescription } = require('./pr-body-config');
|
|
|
|
const versioning = require('../../versioning');
|
|
|
|
const { appName, appSlug } = require('../../config/app-strings');
|
|
|
|
handlebars.registerHelper('encodeURIComponent', encodeURIComponent);
|
|
|
|
module.exports = {
|
|
getPrBody,
|
|
};
|
|
|
|
function getTableDefinition(config) {
|
|
const res = [];
|
|
for (const header of config.prBodyColumns) {
|
|
const value = config.prBodyDefinitions[header];
|
|
res.push({ header, value });
|
|
}
|
|
return res;
|
|
}
|
|
|
|
function getNonEmptyColumns(definitions, rows) {
|
|
const res = [];
|
|
for (const column of definitions) {
|
|
const { header } = column;
|
|
for (const row of rows) {
|
|
if (row[header] && row[header].length) {
|
|
if (!res.includes(header)) {
|
|
res.push(header);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return res;
|
|
}
|
|
|
|
async function getPrBody(config) {
|
|
config.upgrades.forEach(upgrade => {
|
|
/* eslint-disable no-param-reassign */
|
|
const { homepage, sourceUrl, sourceDirectory, changelogUrl } = upgrade;
|
|
const references = [];
|
|
if (homepage) {
|
|
references.push(`[homepage](${homepage})`);
|
|
}
|
|
if (sourceUrl) {
|
|
let fullUrl = sourceUrl;
|
|
if (sourceDirectory) {
|
|
fullUrl =
|
|
sourceUrl.replace(/\/?$/, '/') +
|
|
'tree/HEAD/' +
|
|
sourceDirectory.replace('^/?/', '');
|
|
}
|
|
references.push(`[source](${fullUrl})`);
|
|
}
|
|
if (changelogUrl) {
|
|
references.push(`[changelog](${changelogUrl})`);
|
|
}
|
|
upgrade.references = references.join(', ');
|
|
const {
|
|
fromVersion,
|
|
toVersion,
|
|
newValue,
|
|
newDigestShort,
|
|
updateType,
|
|
versionScheme,
|
|
} = upgrade;
|
|
// istanbul ignore if
|
|
if (updateType === 'minor') {
|
|
try {
|
|
const { getMinor } = versioning.get(versionScheme);
|
|
if (getMinor(fromVersion) === getMinor(toVersion)) {
|
|
upgrade.updateType = 'patch';
|
|
}
|
|
} catch (err) {
|
|
// do nothing
|
|
}
|
|
}
|
|
if (newDigestShort) {
|
|
if (updateType === 'pin') {
|
|
upgrade.newValue = config.newDigestShort;
|
|
}
|
|
if (newValue) {
|
|
upgrade.newValue = newValue + '@' + newDigestShort;
|
|
} else {
|
|
upgrade.newValue = newDigestShort;
|
|
}
|
|
} else if (updateType !== 'lockFileMaintenance') {
|
|
upgrade.newValue = newValue;
|
|
}
|
|
/* eslint-enable no-param-reassign */
|
|
});
|
|
const tableDefinitions = getTableDefinition(config);
|
|
const tableValues = config.upgrades.map(upgrade => {
|
|
const res = {};
|
|
for (const column of tableDefinitions) {
|
|
const { header, value } = column;
|
|
try {
|
|
// istanbul ignore else
|
|
if (value) {
|
|
res[header] = handlebars
|
|
.compile(value)(upgrade)
|
|
.replace(/^``$/, '');
|
|
} else {
|
|
res[header] = '';
|
|
}
|
|
} catch (err) /* istanbul ignore next */ {
|
|
logger.warn({ header, value, err }, 'Handlebars compilation error');
|
|
}
|
|
}
|
|
return res;
|
|
});
|
|
const tableColumns = getNonEmptyColumns(tableDefinitions, tableValues);
|
|
let prBody = '';
|
|
// istanbul ignore if
|
|
if (config.prBanner && !config.isGroup) {
|
|
prBody += handlebars.compile(config.prBanner)(config) + '\n\n';
|
|
}
|
|
prBody += '\n\nThis PR contains the following updates:\n\n';
|
|
prBody += '| ' + tableColumns.join(' | ') + ' |\n';
|
|
prBody += '|' + tableColumns.map(() => '---|').join('') + '\n';
|
|
const rows = [];
|
|
for (const row of tableValues) {
|
|
let val = '|';
|
|
for (const column of tableColumns) {
|
|
val += ` ${row[column].replace(/^@/, '@​')} |`;
|
|
}
|
|
val += '\n';
|
|
rows.push(val);
|
|
}
|
|
const uniqueRows = [...new Set(rows)];
|
|
prBody += uniqueRows.join('');
|
|
prBody += '\n\n';
|
|
|
|
const notes = [];
|
|
for (const upgrade of config.upgrades) {
|
|
if (is.nonEmptyArray(upgrade.prBodyNotes)) {
|
|
for (const note of upgrade.prBodyNotes) {
|
|
try {
|
|
const res = handlebars
|
|
.compile(note)(upgrade)
|
|
.trim();
|
|
if (res && res.length) {
|
|
notes.push(res);
|
|
}
|
|
} catch (err) {
|
|
logger.warn({ note }, 'Error compiling upgrade note');
|
|
}
|
|
}
|
|
}
|
|
}
|
|
const uniqueNotes = [...new Set(notes)];
|
|
prBody += uniqueNotes.join('\n\n');
|
|
prBody += '\n\n';
|
|
|
|
if (config.upgrades.some(upgrade => upgrade.gitRef)) {
|
|
prBody +=
|
|
':abcd: If you wish to disable git hash updates, add `":disableDigestUpdates"` to the extends array in your config.\n\n';
|
|
}
|
|
|
|
if (config.updateType === 'lockFileMaintenance') {
|
|
prBody +=
|
|
':wrench: This Pull Request updates `package.json` lock files to use the latest dependency versions.\n\n';
|
|
}
|
|
|
|
if (config.isPin) {
|
|
prBody += `:pushpin: **Important**: ${appName} will wait until you have merged this Pin PR before creating any *upgrade* PRs for the affected packages. Add the preset \`:preserveSemverRanges\` your config if you instead don't wish to pin dependencies.\n\n`;
|
|
}
|
|
if (config.hasReleaseNotes) {
|
|
let releaseNotes =
|
|
'\n\n---\n\n' + handlebars.compile(releaseNotesHbs)(config) + '\n\n';
|
|
releaseNotes = releaseNotes.replace(/### \[`vv/g, '### [`v');
|
|
// Generic replacements/link-breakers
|
|
|
|
// Put a zero width space after every # followed by a digit
|
|
releaseNotes = releaseNotes.replace(/#(\d)/gi, '#​$1');
|
|
// Put a zero width space after every @ symbol to prevent unintended hyperlinking
|
|
releaseNotes = releaseNotes.replace(/@/g, '@​');
|
|
releaseNotes = releaseNotes.replace(/(`\[?@)​/g, '$1');
|
|
releaseNotes = releaseNotes.replace(/([a-z]@)​/gi, '$1');
|
|
releaseNotes = releaseNotes.replace(/\/compare\/@​/g, '/compare/@');
|
|
releaseNotes = releaseNotes.replace(
|
|
/(\(https:\/\/[^)]*?)\.\.\.@​/g,
|
|
'$1...@'
|
|
);
|
|
releaseNotes = releaseNotes.replace(
|
|
/([\s(])#(\d+)([)\s]?)/g,
|
|
'$1#​$2$3'
|
|
);
|
|
// convert escaped backticks back to `
|
|
const backTickRe = /`([^/]*?)`/g;
|
|
releaseNotes = releaseNotes.replace(backTickRe, '`$1`');
|
|
releaseNotes = releaseNotes.replace(/`#​(\d+)`/g, '`#$1`');
|
|
prBody += releaseNotes;
|
|
}
|
|
prBody += await getPrConfigDescription(config);
|
|
prBody += `\n\n---\n\n - [ ] <!-- ${appSlug}-rebase -->If you want to rebase/retry this PR, check this box\n\n`;
|
|
// istanbul ignore if
|
|
if (config.global) {
|
|
if (config.global.prBanner) {
|
|
prBody = config.global.prBanner + '\n\n' + prBody;
|
|
}
|
|
if (config.global.prFooter) {
|
|
prBody = prBody + '\n---\n\n' + config.global.prFooter;
|
|
}
|
|
}
|
|
prBody = prBody.trim();
|
|
prBody = prBody.replace(/\n\n\n+/g, '\n\n');
|
|
|
|
prBody = platform.getPrBody(prBody);
|
|
return prBody;
|
|
}
|