UNPKG

renovate

Version:

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

211 lines • 8.98 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.extractPackageFile = extractPackageFile; const tslib_1 = require("tslib"); const global_1 = require("../../../config/global"); const logger_1 = require("../../../logger"); const common_1 = require("../../../util/common"); const regex_1 = require("../../../util/regex"); const gitea_tags_1 = require("../../datasource/gitea-tags"); const github_releases_1 = require("../../datasource/github-releases"); const github_runners_1 = require("../../datasource/github-runners"); const github_tags_1 = require("../../datasource/github-tags"); const dockerVersioning = tslib_1.__importStar(require("../../versioning/docker")); const nodeVersioning = tslib_1.__importStar(require("../../versioning/node")); const npmVersioning = tslib_1.__importStar(require("../../versioning/npm")); const extract_1 = require("../dockerfile/extract"); const schema_1 = require("./schema"); const dockerActionRe = (0, regex_1.regEx)(/^\s+uses\s*: ['"]?docker:\/\/([^'"]+)\s*$/); const actionRe = (0, regex_1.regEx)(/^\s+-?\s+?uses\s*: (?<replaceString>['"]?(?<depName>(?<registryUrl>https:\/\/[.\w-]+\/)?(?<packageName>[\w-]+\/[.\w-]+))(?<path>\/.*)?@(?<currentValue>[^\s'"]+)['"]?(?:(?<commentWhiteSpaces>\s+)#\s*(((?:renovate\s*:\s*)?(?:pin\s+|tag\s*=\s*)?|(?:ratchet:[\w-]+\/[.\w-]+)?)@?(?<tag>([\w-]*[-/])?v?\d+(?:\.\d+(?:\.\d+)?)?)|(?:ratchet:exclude)))?)/); // SHA1 or SHA256, see https://github.blog/2020-10-19-git-2-29-released/ const shaRe = (0, regex_1.regEx)(/^(?:[a-f0-9]{40}|[a-f0-9]{64})$/); const shaShortRe = (0, regex_1.regEx)(/^[a-f0-9]{6,7}$/); // detects if we run against a Github Enterprise Server and adds the URL to the beginning of the registryURLs for looking up Actions // This reflects the behavior of how GitHub looks up Actions // First on the Enterprise Server, then on GitHub.com function detectCustomGitHubRegistryUrlsForActions() { const endpoint = global_1.GlobalConfig.get('endpoint'); const registryUrls = ['https://github.com']; if (endpoint && global_1.GlobalConfig.get('platform') === 'github') { const parsedEndpoint = new URL(endpoint); if (parsedEndpoint.host !== 'github.com' && parsedEndpoint.host !== 'api.github.com') { registryUrls.unshift(`${parsedEndpoint.protocol}//${parsedEndpoint.host}`); return { registryUrls }; } } return {}; } function extractWithRegex(content, config) { const customRegistryUrlsPackageDependency = detectCustomGitHubRegistryUrlsForActions(); logger_1.logger.trace('github-actions.extractWithRegex()'); const deps = []; for (const line of content.split(regex_1.newlineRegex)) { if (line.trim().startsWith('#')) { continue; } const dockerMatch = dockerActionRe.exec(line); if (dockerMatch) { const [, currentFrom] = dockerMatch; const dep = (0, extract_1.getDep)(currentFrom, true, config.registryAliases); dep.depType = 'docker'; deps.push(dep); continue; } const tagMatch = actionRe.exec(line); if (tagMatch?.groups) { const { depName, packageName, currentValue, path = '', tag, replaceString, registryUrl = '', commentWhiteSpaces = ' ', } = tagMatch.groups; let quotes = ''; if (replaceString.includes("'")) { quotes = "'"; } if (replaceString.includes('"')) { quotes = '"'; } const dep = { depName, ...(packageName !== depName && { packageName }), commitMessageTopic: '{{{depName}}} action', datasource: github_tags_1.GithubTagsDatasource.id, versioning: dockerVersioning.id, depType: 'action', replaceString, autoReplaceStringTemplate: `${quotes}{{depName}}${path}@{{#if newDigest}}{{newDigest}}${quotes}{{#if newValue}}${commentWhiteSpaces}# {{newValue}}{{/if}}{{/if}}{{#unless newDigest}}{{newValue}}${quotes}{{/unless}}`, ...(registryUrl ? detectDatasource(registryUrl) : customRegistryUrlsPackageDependency), }; if (shaRe.test(currentValue)) { dep.currentValue = tag; dep.currentDigest = currentValue; } else if (shaShortRe.test(currentValue)) { dep.currentValue = tag; dep.currentDigestShort = currentValue; } else { dep.currentValue = currentValue; } deps.push(dep); } } return deps; } function detectDatasource(registryUrl) { const platform = (0, common_1.detectPlatform)(registryUrl); switch (platform) { case 'github': return { registryUrls: [registryUrl] }; case 'gitea': return { registryUrls: [registryUrl], datasource: gitea_tags_1.GiteaTagsDatasource.id, }; } return { skipReason: 'unsupported-url', }; } const runnerVersionRegex = (0, regex_1.regEx)(/^\s*(?<depName>[a-zA-Z]+)-(?<currentValue>[^\s]+)/); function extractRunner(runner) { const runnerVersionGroups = runnerVersionRegex.exec(runner)?.groups; if (!runnerVersionGroups) { return null; } const { depName, currentValue } = runnerVersionGroups; if (!github_runners_1.GithubRunnersDatasource.isValidRunner(depName, currentValue)) { return null; } const dependency = { depName, currentValue, replaceString: `${depName}-${currentValue}`, depType: 'github-runner', datasource: github_runners_1.GithubRunnersDatasource.id, autoReplaceStringTemplate: '{{depName}}-{{newValue}}', }; if (!dockerVersioning.api.isValid(currentValue)) { dependency.skipReason = 'invalid-version'; } return dependency; } const versionedActions = { go: npmVersioning.id, node: nodeVersioning.id, python: npmVersioning.id, // Not covered yet because they use different datasources/packageNames: // - dotnet // - java }; function extractSteps(steps, deps) { for (const step of steps) { for (const [action, versioning] of Object.entries(versionedActions)) { const actionName = `actions/setup-${action}`; if (step.uses === actionName || step.uses?.startsWith(`${actionName}@`)) { const fieldName = `${action}-version`; const currentValue = step.with?.[fieldName]; if (currentValue) { deps.push({ datasource: github_releases_1.GithubReleasesDatasource.id, depName: action, packageName: `actions/${action}-versions`, versioning, extractVersion: '^(?<version>\\d+\\.\\d+\\.\\d+)(-\\d+)?$', // Actions release tags are like 1.24.1-13667719799 currentValue, depType: 'uses-with', }); } } } } } function extractWithYAMLParser(content, packageFile, config) { logger_1.logger.trace('github-actions.extractWithYAMLParser()'); const deps = []; const obj = (0, logger_1.withMeta)({ packageFile }, () => schema_1.WorkflowSchema.parse(content)); if (!obj) { return deps; } // composite action if ('runs' in obj && obj.runs.steps) { extractSteps(obj.runs.steps, deps); } else if ('jobs' in obj) { for (const job of Object.values(obj.jobs)) { if (job.container) { const dep = (0, extract_1.getDep)(job.container, true, config.registryAliases); if (dep) { dep.depType = 'container'; deps.push(dep); } } for (const service of job.services) { const dep = (0, extract_1.getDep)(service, true, config.registryAliases); if (dep) { dep.depType = 'service'; deps.push(dep); } } for (const runner of job['runs-on']) { const dep = extractRunner(runner); if (dep) { deps.push(dep); } } extractSteps(job.steps, deps); } } return deps; } function extractPackageFile(content, packageFile, config = {}) { logger_1.logger.trace(`github-actions.extractPackageFile(${packageFile})`); const deps = [ ...extractWithRegex(content, config), ...extractWithYAMLParser(content, packageFile, config), ]; if (!deps.length) { return null; } return { deps }; } //# sourceMappingURL=extract.js.map