renovate
Version:
Automated dependency updates. Flexible so you don't need to be.
168 lines • 7.79 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.extractPackageFile = extractPackageFile;
const tslib_1 = require("tslib");
const is_1 = tslib_1.__importDefault(require("@sindresorhus/is"));
const logger_1 = require("../../../logger");
const common_1 = require("../../../util/common");
const host_rules_1 = require("../../../util/host-rules");
const regex_1 = require("../../../util/regex");
const yaml_1 = require("../../../util/yaml");
const github_tags_1 = require("../../datasource/github-tags");
const gitlab_tags_1 = require("../../datasource/gitlab-tags");
const utils_1 = require("../pep621/utils");
const parsing_1 = require("./parsing");
/**
* Determines the datasource(id) to be used for this dependency
* @param repository the full git url, ie git@github.com/user/project.
* Used in debug statements to clearly indicate the related dependency.
* @param hostname the hostname (ie github.com)
* Used to determine which renovate datasource should be used.
* Is matched literally against `github.com` and `gitlab.com`.
* If that doesn't match, `hostRules.find()` is used to find related sources.
* In that case, the hostname is passed on as registryUrl to the corresponding datasource.
*/
function determineDatasource(repository, hostname) {
if (hostname === 'github.com' || (0, common_1.detectPlatform)(repository) === 'github') {
logger_1.logger.debug({ repository, hostname }, 'Found github dependency');
return { datasource: github_tags_1.GithubTagsDatasource.id };
}
if (hostname === 'gitlab.com') {
logger_1.logger.debug({ repository, hostname }, 'Found gitlab dependency');
return { datasource: gitlab_tags_1.GitlabTagsDatasource.id };
}
if ((0, common_1.detectPlatform)(repository) === 'gitlab') {
logger_1.logger.debug({ repository, hostname }, 'Found gitlab dependency with custom registryUrl');
return {
datasource: gitlab_tags_1.GitlabTagsDatasource.id,
registryUrls: ['https://' + hostname],
};
}
const hostUrl = 'https://' + hostname;
const res = (0, host_rules_1.find)({ url: hostUrl });
if (is_1.default.emptyObject(res)) {
// 1 check, to possibly prevent 3 failures in combined query of hostType & url.
logger_1.logger.debug({ repository, hostUrl }, 'Provided hostname does not match any hostRules. Ignoring');
return { skipReason: 'unknown-registry', registryUrls: [hostname] };
}
for (const [hostType, sourceId] of [
['github', github_tags_1.GithubTagsDatasource.id],
['gitlab', gitlab_tags_1.GitlabTagsDatasource.id],
]) {
if (is_1.default.nonEmptyObject((0, host_rules_1.find)({ hostType, url: hostUrl }))) {
logger_1.logger.debug({ repository, hostUrl, hostType }, `Provided hostname matches a ${hostType} hostrule.`);
return { datasource: sourceId, registryUrls: [hostname] };
}
}
logger_1.logger.debug({ repository, registry: hostUrl }, 'Provided hostname did not match any of the hostRules of hostType github nor gitlab');
return { skipReason: 'unknown-registry', registryUrls: [hostname] };
}
function extractDependency(tag, repository) {
logger_1.logger.debug(`Found version ${tag}`);
const urlMatchers = [
// This splits "http://my.github.com/user/repo" -> "my.github.com" "user/repo
(0, regex_1.regEx)('^https?://(?<hostname>[^/]+)/(?<depName>\\S*)'),
// This splits "git@private.registry.com:user/repo" -> "private.registry.com" "user/repo
(0, regex_1.regEx)('^git@(?<hostname>[^:]+):(?<depName>\\S*)'),
// This split "git://github.com/pre-commit/pre-commit-hooks" -> "github.com" "pre-commit/pre-commit-hooks"
(0, regex_1.regEx)(/^git:\/\/(?<hostname>[^/]+)\/(?<depName>\S*)/),
// This splits "ssh://git@github.com/pre-commit/pre-commit-hooks" -> "github.com" "pre-commit/pre-commit-hooks"
(0, regex_1.regEx)(/^ssh:\/\/git@(?<hostname>[^/]+)\/(?<depName>\S*)/),
];
for (const urlMatcher of urlMatchers) {
const match = urlMatcher.exec(repository);
if (match?.groups) {
const hostname = match.groups.hostname;
const depName = match.groups.depName.replace((0, regex_1.regEx)(/\.git$/i), ''); // TODO 12071
const sourceDef = determineDatasource(repository, hostname);
return {
...sourceDef,
depName,
depType: 'repository',
packageName: depName,
currentValue: tag,
};
}
}
logger_1.logger.info({ repository }, 'Could not separate hostname from full dependency url.');
return {
depName: undefined,
depType: 'repository',
datasource: undefined,
packageName: undefined,
skipReason: 'invalid-url',
currentValue: tag,
};
}
/**
* Find all supported dependencies in the pre-commit yaml object.
*
* @param precommitFile the parsed yaml config file
*/
function findDependencies(precommitFile) {
if (!precommitFile.repos) {
logger_1.logger.debug(`No repos section found, skipping file`);
return [];
}
const packageDependencies = [];
precommitFile.repos.forEach((item) => {
// meta hooks is defined from pre-commit and doesn't support `additional_dependencies`
if (item.repo !== 'meta') {
item.hooks?.forEach((hook) => {
// normally language are not defined in yaml
// only support it when it's explicitly defined.
// this avoid to parse hooks from pre-commit-hooks.yaml from git repo
if (hook.language === 'python') {
hook.additional_dependencies?.map((req) => {
const dep = (0, utils_1.pep508ToPackageDependency)('pre-commit-python', req);
if (dep) {
packageDependencies.push(dep);
}
});
}
});
}
if ((0, parsing_1.matchesPrecommitDependencyHeuristic)(item)) {
logger_1.logger.trace(item, 'Matched pre-commit dependency spec');
const repository = String(item.repo);
const tag = String(item.rev);
const dep = extractDependency(tag, repository);
packageDependencies.push(dep);
}
else {
logger_1.logger.trace(item, 'Did not find pre-commit repo spec');
}
});
return packageDependencies;
}
function extractPackageFile(content, packageFile) {
let parsedContent;
try {
// TODO: use schema (#9610)
parsedContent = (0, yaml_1.parseSingleYaml)(content);
}
catch (err) {
logger_1.logger.debug({ filename: packageFile, err }, 'Failed to parse pre-commit config YAML');
return null;
}
if (!is_1.default.plainObject(parsedContent)) {
logger_1.logger.debug({ packageFile }, `Parsing of pre-commit config YAML returned invalid result`);
return null;
}
if (!(0, parsing_1.matchesPrecommitConfigHeuristic)(parsedContent)) {
logger_1.logger.debug({ packageFile }, `File does not look like a pre-commit config file`);
return null;
}
try {
const deps = findDependencies(parsedContent);
if (deps.length) {
logger_1.logger.trace({ deps }, 'Found dependencies in pre-commit config');
return { deps };
}
}
catch (err) /* istanbul ignore next */ {
logger_1.logger.debug({ packageFile, err }, 'Error scanning parsed pre-commit config');
}
return null;
}
//# sourceMappingURL=extract.js.map