mirror of
https://github.com/renovatebot/renovate.git
synced 2026-10-25 23:11:31 +00:00
19306f7e17
* refactor(manager/helmv3): share generateHelmEnvs with kustomize Move kustomize's generateHelmEnvs into helmv3/common.ts and delete the kustomize copy. The merged function always sets the three HELM_* path variables and sets HELM_EXPERIMENTAL_OCI unless a helm constraint is present and proves helm >= 3.8 (which ignores the variable). Behaviour change: kustomize now sets HELM_EXPERIMENTAL_OCI when the helm constraint is unknown (previously it only set it for a known constraint below 3.8). helmv3 and helmfile now omit the variable once a resolved helm constraint proves helm >= 3.8. * refactor(manager/helmv3): share OCI registry login helper with helmfile Extract a shared generateRegistryLoginCmd(name, registry) helper in helmv3/common.ts that strips the oci:// prefix, derives the host and looks up the matching host rule before delegating to generateLoginCmd. helmv3/artifacts.ts and helmfile/artifacts.ts now both call this helper instead of each building a RepositoryRule inline, removing the stale oci:// TODO. helmfile/utils.ts loses its duplicate generateRegistryLoginCmd, and its unrelated isOCIRegistry(repository) (checking the oci flag) is renamed to isOciRepositoryFlagSet so it no longer collides in name with helmv3/oci.ts's prefix-based isOCIRegistry(string), which helmfile/extract.ts also imports. Addresses audit finding M8. Generated `helm registry login` commands are unchanged, proved by the existing artifacts specs passing with their original expectations untouched. * fix(manager): share one local Helm chart path check helmfile, flux, fleet and terraform each decided differently whether a Helm chart reference points at a local path. fleet and terraform used terraform's checkIfStringIsPath, whose regex was unanchored with unescaped dots, so it matched any string containing a slash followed by a non-slash character. Add isLocalChartPath to helmv3/utils.ts with helmfile's prefix check and use it in all four managers. This drops the fleet to terraform dependency and removes checkIfStringIsPath, which had no other users. * refactor(manager/helm-requirements): reuse helmv3 alias and repository helpers Replace the duplicated alias-resolution and repository-classification logic in helm-requirements/extract.ts with the shared isAlias, resolveAlias and parseRepository helpers from helmv3/utils.ts (audit finding M9). Behaviour is unchanged: same skipReasons, same registryUrls, same handling of a missing repository or missing registryAliases config. * refactor(manager/dockerfile): add an options form of getDep for CI managers `getDep()` gains an overload taking a `GetDepOptions` object with `specifyReplaceString`, `registryAliases` and `depType`, replacing the opaque boolean second positional argument at the CI manager call sites. The positional form keeps working for all other callers. Migrated: bitbucket-pipelines, droneci, circleci, github-actions, azure-pipelines and woodpecker. Behaviour changes: - azure-pipelines container resources now honour `registryAliases`, which `extractContainer()` previously ignored - woodpecker dependencies now carry `depType: 'docker'`, matching the other CI managers * refactor(manager/woodpecker): do not set depType on docker image deps * refactor(manager/dockerfile): drop the positional getDep signature * refactor(manager/helm-requirements): reuse helmv3 alias and repository helpers Replace the duplicated alias-resolution and repository-classification logic in helm-requirements/extract.ts with the shared isAlias, resolveAlias and parseRepository helpers from helmv3/utils.ts (audit finding M9). Behaviour is unchanged: same skipReasons, same registryUrls, same handling of a missing repository or missing registryAliases config.
87 lines
2.9 KiB
TypeScript
87 lines
2.9 KiB
TypeScript
import { isString, isTruthy } from '@sindresorhus/is';
|
|
import { logger } from '../../../logger/index.ts';
|
|
import { coerceObject } from '../../../util/object.ts';
|
|
import { newlineRegex, regEx } from '../../../util/regex.ts';
|
|
import { parseSingleYaml } from '../../../util/yaml.ts';
|
|
import { getDep } from '../dockerfile/extract.ts';
|
|
import type { ExtractConfig, PackageFileContent } from '../types.ts';
|
|
import { DockerComposeFile } from './schema.ts';
|
|
|
|
class LineMapper {
|
|
private imageLines: { line: string; lineNumber: number; used: boolean }[];
|
|
|
|
constructor(content: string, filter: RegExp) {
|
|
this.imageLines = [...content.split(newlineRegex).entries()]
|
|
.filter((entry) => filter.test(entry[1]))
|
|
.map(([lineNumber, line]) => ({ lineNumber, line, used: false }));
|
|
}
|
|
|
|
pluckLineNumber(imageName: string | undefined): number | null {
|
|
const lineMeta = this.imageLines.find(
|
|
({ line, used }) => !used && imageName && line.includes(imageName),
|
|
);
|
|
// istanbul ignore if
|
|
if (!lineMeta) {
|
|
return null;
|
|
}
|
|
lineMeta.used = true; // unset plucked lines so duplicates are skipped
|
|
return lineMeta.lineNumber;
|
|
}
|
|
}
|
|
|
|
export function extractPackageFile(
|
|
content: string,
|
|
packageFile: string,
|
|
extractConfig: ExtractConfig,
|
|
): PackageFileContent | null {
|
|
logger.debug(`docker-compose.extractPackageFile(${packageFile})`);
|
|
let config: DockerComposeFile;
|
|
try {
|
|
config = parseSingleYaml(content, {
|
|
customSchema: DockerComposeFile,
|
|
removeTemplates: true,
|
|
});
|
|
} catch (err) {
|
|
logger.debug(
|
|
{ err, packageFile },
|
|
`Parsing Docker Compose config YAML failed`,
|
|
);
|
|
return null;
|
|
}
|
|
try {
|
|
const lineMapper = new LineMapper(content, regEx(/^\s*image:/));
|
|
|
|
// docker-compose v1 places the services at the top level,
|
|
// docker-compose v2+ places the services within a 'services' key
|
|
// since docker-compose spec version 1.27, the 'version' key has
|
|
// become optional and can no longer be used to differentiate
|
|
// between v1 and v2.
|
|
const services = config.services ?? config;
|
|
const extensions = coerceObject(config.extensions);
|
|
|
|
// Image name/tags for services are only eligible for update if they don't
|
|
// use variables and if the image is not built locally
|
|
const deps = Object.values(services)
|
|
.concat(Object.values(extensions))
|
|
.filter((service) => isString(service?.image) && !service?.build)
|
|
.map((service) => {
|
|
const dep = getDep(service.image, {
|
|
registryAliases: extractConfig.registryAliases,
|
|
});
|
|
const lineNumber = lineMapper.pluckLineNumber(service.image);
|
|
// istanbul ignore if
|
|
if (!lineNumber) {
|
|
return null;
|
|
}
|
|
return dep;
|
|
})
|
|
.filter(isTruthy);
|
|
|
|
logger.trace({ deps }, 'Docker Compose image');
|
|
return { deps };
|
|
} catch (err) /* istanbul ignore next */ {
|
|
logger.debug({ packageFile, err }, 'Error extracting Docker Compose file');
|
|
return null;
|
|
}
|
|
}
|