renovate
Version:
Automated dependency updates. Flexible so you don't need to be.
285 lines • 12.2 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.extractPackageFile = extractPackageFile;
exports.extractAllPackageFiles = extractAllPackageFiles;
const tslib_1 = require("tslib");
const is_1 = tslib_1.__importDefault(require("@sindresorhus/is"));
const logger_1 = require("../../../logger");
const array_1 = require("../../../util/array");
const fs_1 = require("../../../util/fs");
const regex_1 = require("../../../util/regex");
const url_1 = require("../../../util/url");
const yaml_1 = require("../../../util/yaml");
const bitbucket_tags_1 = require("../../datasource/bitbucket-tags");
const docker_1 = require("../../datasource/docker");
const git_refs_1 = require("../../datasource/git-refs");
const git_tags_1 = require("../../datasource/git-tags");
const github_releases_1 = require("../../datasource/github-releases");
const github_tags_1 = require("../../datasource/github-tags");
const gitlab_tags_1 = require("../../datasource/gitlab-tags");
const helm_1 = require("../../datasource/helm");
const extract_1 = require("../dockerfile/extract");
const extract_2 = require("../helm-values/extract");
const oci_1 = require("../helmv3/oci");
const extract_3 = require("../kustomize/extract");
const common_1 = require("./common");
const schema_1 = require("./schema");
function readManifest(content, packageFile) {
if ((0, common_1.isSystemManifest)(packageFile)) {
const versionMatch = (0, regex_1.regEx)(common_1.systemManifestHeaderRegex).exec(content);
if (!versionMatch) {
return null;
}
return {
kind: 'system',
file: packageFile,
version: versionMatch[1],
components: versionMatch[2],
};
}
return {
kind: 'resource',
file: packageFile,
resources: (0, yaml_1.parseYaml)(content, {
customSchema: schema_1.FluxResource,
failureBehaviour: 'filter',
}),
};
}
const githubUrlRegex = (0, regex_1.regEx)(/^(?:https:\/\/|git@)github\.com[/:](?<packageName>[^/]+\/[^/]+?)(?:\.git)?$/);
const gitlabUrlRegex = (0, regex_1.regEx)(/^(?:https:\/\/|git@)gitlab\.com[/:](?<packageName>[^/]+\/[^/]+?)(?:\.git)?$/);
const bitbucketUrlRegex = (0, regex_1.regEx)(/^(?:https:\/\/|git@)bitbucket\.org[/:](?<packageName>[^/]+\/[^/]+?)(?:\.git)?$/);
function resolveGitRepositoryPerSourceTag(dep, gitUrl) {
const githubMatchGroups = githubUrlRegex.exec(gitUrl)?.groups;
if (githubMatchGroups) {
dep.datasource = github_tags_1.GithubTagsDatasource.id;
dep.packageName = githubMatchGroups.packageName;
dep.sourceUrl = `https://github.com/${dep.packageName}`;
return;
}
const gitlabMatchGroups = gitlabUrlRegex.exec(gitUrl)?.groups;
if (gitlabMatchGroups) {
dep.datasource = gitlab_tags_1.GitlabTagsDatasource.id;
dep.packageName = gitlabMatchGroups.packageName;
dep.sourceUrl = `https://gitlab.com/${dep.packageName}`;
return;
}
const bitbucketMatchGroups = bitbucketUrlRegex.exec(gitUrl)?.groups;
if (bitbucketMatchGroups) {
dep.datasource = bitbucket_tags_1.BitbucketTagsDatasource.id;
dep.packageName = bitbucketMatchGroups.packageName;
dep.sourceUrl = `https://bitbucket.org/${dep.packageName}`;
return;
}
dep.datasource = git_tags_1.GitTagsDatasource.id;
dep.packageName = gitUrl;
if ((0, url_1.isHttpUrl)(gitUrl)) {
dep.sourceUrl = gitUrl.replace(/\.git$/, '');
}
}
function resolveHelmRepository(dep, matchingRepositories, registryAliases) {
if (matchingRepositories.length) {
dep.registryUrls = matchingRepositories
.map((repo) => {
if (repo.spec.type === 'oci' || (0, oci_1.isOCIRegistry)(repo.spec.url)) {
// Change datasource to Docker
dep.datasource = docker_1.DockerDatasource.id;
// Ensure the URL is a valid OCI path
dep.packageName = (0, extract_1.getDep)(`${(0, oci_1.removeOCIPrefix)(repo.spec.url)}/${dep.depName}`, false, registryAliases).packageName;
return null;
}
else {
return repo.spec.url;
}
})
.filter(is_1.default.string);
// if registryUrls is empty, delete it from dep
if (!dep.registryUrls?.length) {
delete dep.registryUrls;
}
}
else {
dep.skipReason = 'unknown-registry';
}
}
function resolveSystemManifest(manifest) {
return [
{
depName: 'fluxcd/flux2',
datasource: github_releases_1.GithubReleasesDatasource.id,
currentValue: manifest.version,
managerData: {
components: manifest.components,
},
},
];
}
function resolveResourceManifest(manifest, helmRepositories, registryAliases) {
const deps = [];
for (const resource of manifest.resources) {
switch (resource.kind) {
case 'HelmRelease': {
if (resource.spec.chartRef) {
logger_1.logger.trace('HelmRelease using chartRef was found, skipping as version will be handled via referenced resource directly');
}
else if (resource.spec.chart) {
const chartSpec = resource.spec.chart.spec;
const depName = chartSpec.chart;
const dep = {
depName,
currentValue: resource.spec.chart.spec.version,
datasource: helm_1.HelmDatasource.id,
};
if (depName.startsWith('./')) {
dep.skipReason = 'local-chart';
delete dep.datasource;
}
else {
const matchingRepositories = helmRepositories.filter((rep) => rep.kind === chartSpec.sourceRef?.kind &&
rep.metadata.name === chartSpec.sourceRef.name &&
rep.metadata.namespace ===
(chartSpec.sourceRef.namespace ??
resource.metadata?.namespace));
resolveHelmRepository(dep, matchingRepositories, registryAliases);
}
deps.push(dep);
}
else {
logger_1.logger.debug(`invalid or incomplete ${resource.metadata.name} HelmRelease spec, skipping`);
}
if (resource.spec.values) {
logger_1.logger.trace('detecting dependencies in HelmRelease values');
deps.push(...(0, extract_2.findDependencies)(resource.spec.values, registryAliases));
}
break;
}
case 'HelmChart': {
if (resource.spec.sourceRef.kind === 'GitRepository') {
logger_1.logger.trace('HelmChart using GitRepository was found, skipping as version will be handled via referenced resource directly');
continue;
}
const dep = {
depName: resource.spec.chart,
};
if (resource.spec.sourceRef.kind === 'HelmRepository') {
dep.currentValue = resource.spec.version;
dep.datasource = helm_1.HelmDatasource.id;
const matchingRepositories = helmRepositories.filter((rep) => rep.kind === resource.spec.sourceRef?.kind &&
rep.metadata.name === resource.spec.sourceRef.name &&
rep.metadata.namespace === resource.metadata?.namespace);
resolveHelmRepository(dep, matchingRepositories, registryAliases);
}
else {
dep.skipReason = 'unsupported-datasource';
}
deps.push(dep);
break;
}
case 'GitRepository': {
const dep = {
depName: resource.metadata.name,
};
if (resource.spec.ref?.commit) {
const gitUrl = resource.spec.url;
dep.currentDigest = resource.spec.ref.commit;
dep.datasource = git_refs_1.GitRefsDatasource.id;
dep.packageName = gitUrl;
dep.replaceString = resource.spec.ref.commit;
if ((0, url_1.isHttpUrl)(gitUrl)) {
dep.sourceUrl = gitUrl.replace(/\.git$/, '');
}
}
else if (resource.spec.ref?.tag) {
dep.currentValue = resource.spec.ref.tag;
resolveGitRepositoryPerSourceTag(dep, resource.spec.url);
}
else {
dep.skipReason = 'unversioned-reference';
}
deps.push(dep);
break;
}
case 'OCIRepository': {
const container = (0, oci_1.removeOCIPrefix)(resource.spec.url);
let dep = (0, extract_1.getDep)(container, false, registryAliases);
if (resource.spec.ref?.digest) {
dep = (0, extract_1.getDep)(`${container}@${resource.spec.ref.digest}`, false, registryAliases);
if (resource.spec.ref?.tag) {
logger_1.logger.debug('A digest and tag was found, ignoring tag');
}
}
else if (resource.spec.ref?.tag) {
dep = (0, extract_1.getDep)(`${container}:${resource.spec.ref.tag}`, false, registryAliases);
dep.autoReplaceStringTemplate =
'{{#if newValue}}{{newValue}}{{/if}}{{#if newDigest}}@{{newDigest}}{{/if}}';
dep.replaceString = resource.spec.ref.tag;
}
else {
dep.skipReason = 'unversioned-reference';
}
deps.push(dep);
break;
}
case 'Kustomization': {
for (const image of (0, array_1.coerceArray)(resource.spec.images)) {
const dep = (0, extract_3.extractImage)(image, registryAliases);
if (dep) {
deps.push(dep);
}
}
}
}
}
return deps;
}
function extractPackageFile(content, packageFile, config) {
const manifest = readManifest(content, packageFile);
if (!manifest) {
return null;
}
const helmRepositories = (0, common_1.collectHelmRepos)([manifest]);
let deps = null;
switch (manifest.kind) {
case 'system':
deps = resolveSystemManifest(manifest);
break;
case 'resource': {
deps = resolveResourceManifest(manifest, helmRepositories, config?.registryAliases);
break;
}
}
return deps?.length ? { deps } : null;
}
async function extractAllPackageFiles(config, packageFiles) {
const manifests = [];
const results = [];
for (const file of packageFiles) {
const content = await (0, fs_1.readLocalFile)(file, 'utf8');
// TODO #22198
const manifest = readManifest(content, file);
if (manifest) {
manifests.push(manifest);
}
}
const helmRepositories = (0, common_1.collectHelmRepos)(manifests);
for (const manifest of manifests) {
let deps = null;
switch (manifest.kind) {
case 'system':
deps = resolveSystemManifest(manifest);
break;
case 'resource': {
deps = resolveResourceManifest(manifest, helmRepositories, config.registryAliases);
break;
}
}
if (deps?.length) {
results.push({
packageFile: manifest.file,
deps,
});
}
}
return results.length ? results : null;
}
//# sourceMappingURL=extract.js.map