UNPKG

renovate

Version:

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

203 lines • 8.29 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.updateArtifacts = updateArtifacts; const tslib_1 = require("tslib"); const is_1 = tslib_1.__importDefault(require("@sindresorhus/is")); const shlex_1 = require("shlex"); const error_messages_1 = require("../../../constants/error-messages"); const logger_1 = require("../../../logger"); const memCache = tslib_1.__importStar(require("../../../util/cache/memory")); const exec_1 = require("../../../util/exec"); const fs_1 = require("../../../util/fs"); const git_1 = require("../../../util/git"); const regex_1 = require("../../../util/regex"); const common_1 = require("./common"); const host_rules_1 = require("./host-rules"); const hostConfigVariablePrefix = 'BUNDLE_'; function buildBundleHostVariable(hostRule) { // istanbul ignore if: doesn't happen in practice if (!hostRule.resolvedHost) { return {}; } const varName = hostConfigVariablePrefix.concat(hostRule.resolvedHost .toUpperCase() .split('.') .join('__') .split('-') .join('___')); return { [varName]: `${(0, host_rules_1.getAuthenticationHeaderValue)(hostRule)}`, }; } const resolvedPkgRegex = (0, regex_1.regEx)(/(?<pkg>\S+)(?:\s*\([^)]+\)\s*)? was resolved to/); function getResolvedPackages(input) { const lines = input.split(regex_1.newlineRegex); const result = []; for (const line of lines) { const resolveMatchGroups = line.match(resolvedPkgRegex)?.groups; if (resolveMatchGroups) { const { pkg } = resolveMatchGroups; result.push(pkg); } } return [...new Set(result)]; } async function updateArtifacts(updateArtifact, recursionLimit = 10) { const { packageFileName, updatedDeps, newPackageFileContent, config } = updateArtifact; logger_1.logger.debug(`bundler.updateArtifacts(${packageFileName})`); const existingError = memCache.get('bundlerArtifactsError'); // istanbul ignore if if (existingError) { logger_1.logger.debug('Aborting Bundler artifacts due to previous failed attempt'); throw new Error(existingError); } const lockFileName = await (0, common_1.getLockFilePath)(packageFileName); const existingLockFileContent = await (0, fs_1.readLocalFile)(lockFileName, 'utf8'); if (!existingLockFileContent) { logger_1.logger.debug('No Gemfile.lock found'); return null; } const updatedDepNames = updatedDeps .map(({ depName }) => depName) .filter(is_1.default.nonEmptyStringAndNotWhitespace); try { await (0, fs_1.writeLocalFile)(packageFileName, newPackageFileContent); const commands = []; if (config.isLockFileMaintenance) { commands.push('bundler lock --update'); } else { const bundlerUpgraded = updatedDeps .map((dep) => dep.depName) .includes('bundler'); if (bundlerUpgraded) { commands.push('bundler lock --update --bundler'); } const updateTypes = { patch: '--patch ', minor: '--minor ', major: '', }; for (const [updateType, updateArg] of Object.entries(updateTypes)) { const deps = updatedDeps .filter((dep) => (dep.updateType ?? 'major') === updateType) .map((dep) => dep.depName) .filter(is_1.default.string) .filter((dep) => dep !== 'ruby' && dep !== 'bundler'); let additionalArgs = ''; if (config.postUpdateOptions?.includes('bundlerConservative')) { additionalArgs = '--conservative '; } if (deps.length) { const cmd = `bundler lock ${updateArg}${additionalArgs}--update ${deps .map(shlex_1.quote) .join(' ')}`; commands.push(cmd); } } const rubyUpgraded = updatedDeps .map((dep) => dep.depName) .includes('ruby'); if (rubyUpgraded) { commands.push('bundler lock'); } } const bundlerHostRules = (0, host_rules_1.findAllAuthenticatable)({ hostType: 'rubygems', }); const bundlerHostRulesVariables = bundlerHostRules.reduce((variables, hostRule) => ({ ...variables, ...buildBundleHostVariable(hostRule), }), {}); const bundler = (0, common_1.getBundlerConstraint)(updateArtifact, existingLockFileContent); const preCommands = ['ruby --version']; const execOptions = { cwdFile: lockFileName, extraEnv: { ...bundlerHostRulesVariables, GEM_HOME: await (0, fs_1.ensureCacheDir)('bundler'), }, docker: {}, toolConstraints: [ { toolName: 'ruby', constraint: await (0, common_1.getRubyConstraint)(updateArtifact), }, { toolName: 'bundler', constraint: bundler, }, ], preCommands, }; await (0, exec_1.exec)(commands, execOptions); const status = await (0, git_1.getRepoStatus)(); if (!status.modified.includes(lockFileName)) { return null; } logger_1.logger.debug('Returning updated Gemfile.lock'); const lockFileContent = await (0, fs_1.readLocalFile)(lockFileName); return [ { file: { type: 'addition', path: lockFileName, contents: lockFileContent, }, }, ]; } catch (err) { if (err.message === error_messages_1.TEMPORARY_ERROR) { throw err; } const output = `${String(err.stdout)}\n${String(err.stderr)}`; if (err.message.includes('fatal: Could not parse object') || output.includes('but that version could not be found')) { return [ { artifactError: { lockFile: lockFileName, stderr: output, }, }, ]; } if (err.stdout?.includes('Please supply credentials for this source') || err.stderr?.includes('Authentication is required') || err.stderr?.includes('Please make sure you have the correct access rights')) { logger_1.logger.debug({ err }, 'Gemfile.lock update failed due to missing credentials - skipping branch'); // Do not generate these PRs because we don't yet support Bundler authentication memCache.set('bundlerArtifactsError', error_messages_1.BUNDLER_INVALID_CREDENTIALS); throw new Error(error_messages_1.BUNDLER_INVALID_CREDENTIALS); } const resolveMatches = getResolvedPackages(output).filter((depName) => !updatedDepNames.includes(depName)); if (recursionLimit > 0 && resolveMatches.length && !config.isLockFileMaintenance) { logger_1.logger.debug({ resolveMatches, updatedDeps }, 'Found new resolve matches - reattempting recursively'); const newUpdatedDeps = [ ...new Set([ ...updatedDeps, ...resolveMatches.map((match) => ({ depName: match })), ]), ]; return updateArtifacts({ packageFileName, updatedDeps: newUpdatedDeps, newPackageFileContent, config, }, recursionLimit - 1); } logger_1.logger.info({ err }, 'Gemfile.lock update failed due to an unknown reason'); return [ { artifactError: { lockFile: lockFileName, stderr: `${String(err.stdout)}\n${String(err.stderr)}`, }, }, ]; } } //# sourceMappingURL=artifacts.js.map