UNPKG

renovate

Version:

Automated dependency updates. Flexible so you don't need to be.

209 lines • 8.56 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.bumpVersions = bumpVersions; const semver_1 = require("semver"); const logger_1 = require("../../../../logger"); const scm_1 = require("../../../../modules/platform/scm"); const array_1 = require("../../../../util/array"); const fs_1 = require("../../../../util/fs"); const regex_1 = require("../../../../util/regex"); const string_match_1 = require("../../../../util/string-match"); const template_1 = require("../../../../util/template"); const file_match_1 = require("../../extract/file-match"); async function bumpVersions(config) { const bumpVersions = config.bumpVersions; if (!bumpVersions?.length) { return; } // skip if no packageFiles or artifacts have been updated if (!config.updatedPackageFiles?.length && !config.updatedArtifacts?.length) { return; } const allFiles = await scm_1.scm.getFileList(); const fileList = (0, file_match_1.getFilteredFileList)(config, allFiles); const packageFileChanges = fileChangeListToMap(config.updatedPackageFiles); const artifactFileChanges = fileChangeListToMap(config.updatedArtifacts); for (const bumpVersionConfig of bumpVersions) { await bumpVersion(bumpVersionConfig, config, fileList, packageFileChanges, artifactFileChanges); } // update the config with the new files config.updatedPackageFiles = Object.values(packageFileChanges).flat(); config.updatedArtifacts = Object.values(artifactFileChanges).flat(); } async function bumpVersion(config, branchConfig, fileList, packageFiles, artifactFiles) { const rawBumpType = config.bumpType ?? 'patch'; // all log messages should be prefixed with this string to facilitate easier logLevelRemapping const bumpVersionsDescr = config.name ? `bumpVersions(${config.name})` : 'bumpVersions'; const files = []; try { files.push(...getMatchedFiles(bumpVersionsDescr, config.filePatterns, branchConfig, fileList)); } catch (e) { addArtifactError(branchConfig, `Failed to calculate matched files for bumpVersions: ${e.message}`); return; } if (!files.length) { logger_1.logger.debug(`${bumpVersionsDescr}: filePatterns did not match any files`); return; } logger_1.logger.trace({ files }, `${bumpVersionsDescr}: Found ${files.length} files to bump versions`); // keeping this only for logging purposes const matchStrings = []; // prepare the matchStrings const matchStringsRegexes = []; for (const matchString of config.matchStrings) { try { const templated = (0, template_1.compile)(matchString, branchConfig); matchStrings.push(templated); matchStringsRegexes.push((0, regex_1.regEx)(templated)); } catch (e) { addArtifactError(branchConfig, `Failed to compile matchString for ${bumpVersionsDescr}: ${e.message}`, matchString); } } logger_1.logger.trace({ matchStrings }, `${bumpVersionsDescr}: Compiled matchStrings`); for (const filePath of files) { let fileBumped = false; const fileContents = await getFileContent(bumpVersionsDescr, filePath, packageFiles, artifactFiles); if (!fileContents) { continue; } for (const matchStringRegex of matchStringsRegexes) { // extracting the version from the file const regexResult = matchStringRegex.exec(fileContents); if (!regexResult) { continue; } const version = regexResult.groups?.version; if (!version) { logger_1.logger.debug({ file: filePath }, `${bumpVersionsDescr}: No version found`); continue; } // getting new version let newVersion = null; try { const bumpType = (0, template_1.compile)(rawBumpType, branchConfig); newVersion = (0, semver_1.inc)(version, bumpType); } catch (e) { addArtifactError(branchConfig, `Failed to calculate new version for ${bumpVersionsDescr}: ${e.message}`, filePath); } if (!newVersion) { logger_1.logger.debug({ file: filePath }, `${bumpVersionsDescr}: Could not bump version`); continue; } // replace the content of the `version` group with newVersion const newFileContents = fileContents .toString() .replace(matchStringRegex, (match, ...groups) => { const { version } = groups.pop(); return match.replace(version, newVersion); }); // update the file. Add it to the buckets if exists or create a new artifact update if (packageFiles[filePath]) { packageFiles[filePath].push({ type: 'addition', path: filePath, contents: newFileContents, }); } else { artifactFiles[filePath] ??= []; artifactFiles[filePath].push({ type: 'addition', path: filePath, contents: newFileContents, }); } fileBumped = true; } if (!fileBumped) { logger_1.logger.debug({ file: filePath }, `${bumpVersionsDescr}: No match found for bumping version`); } } } /** * Get files that match ANY of the fileMatches pattern. fileMatches are compiled with the branchConfig. * @param bumpVersionsDescr log description for the bump version config * @param filePatternTemplates list of regex patterns * @param branchConfig compile metadata * @param fileList list of files to match against */ function getMatchedFiles(bumpVersionsDescr, filePatternTemplates, branchConfig, fileList) { // prepare file regex const filePatterns = []; for (const filePatternTemplateElement of filePatternTemplates) { const filePattern = (0, template_1.compile)(filePatternTemplateElement, branchConfig); filePatterns.push(filePattern); } logger_1.logger.trace({ filePatterns }, `${bumpVersionsDescr}: Compiled filePatterns`); // get files that match the fileMatch const files = []; for (const file of fileList) { if ((0, string_match_1.matchRegexOrGlobList)(file, filePatterns)) { files.push(file); } } return files; } function fileChangeListToMap(list) { const record = {}; for (const fileChange of (0, array_1.coerceArray)(list)) { record[fileChange.path] ??= []; record[fileChange.path].push(fileChange); } return record; } function addArtifactError(branchConfig, message, fileName) { branchConfig.artifactErrors ??= []; branchConfig.artifactErrors.push({ stderr: message, fileName, }); } async function getFileContent(bumpVersionsDescr, filePath, packageFiles, artifactFiles) { const packageFileChanges = parseFileChanges(filePath, packageFiles); const artifactFileChanges = parseFileChanges(filePath, artifactFiles); // skip if the file is deleted as it virtually doesn't exist if (packageFileChanges.state === 'deleted' || artifactFileChanges.state === 'deleted') { return null; } if (packageFileChanges.state === 'modified') { const lastChange = packageFileChanges.content; if (lastChange) { return lastChange; } } if (artifactFileChanges.state === 'modified') { const lastChange = artifactFileChanges.content; if (lastChange) { return lastChange; } } try { return await (0, fs_1.readLocalFile)(filePath, 'utf8'); } catch (e) { logger_1.logger.warn({ file: filePath }, `${bumpVersionsDescr}: Could not read file: ${e.message}`); return null; } } function parseFileChanges(filePath, changeRecord) { const changes = (0, array_1.coerceArray)(changeRecord[filePath]); // skip if we can fetch from record if (!changes.length) { return { state: 'unmodified' }; } const lastChange = changes[changes.length - 1]; if (lastChange.type === 'deletion') { return { state: 'deleted' }; } return { state: 'modified', content: lastChange.contents?.toString() ?? null, }; } //# sourceMappingURL=bump-versions.js.map