renovate/lib/manager/docker/extract.js
Rhys Arkins b724a411da
feat: Docker Compose support (#1729)
Adds support for renovating Docker Compose files (e.g. `docker-compose.yml`). Functionality is essentially the same as the existing `Dockerfile` capabilities, so config for `docker` is shared with `docker-compose` but may also be overridden.

Merging as disabled by default - will wait for some opt-in testing before turning it on by default.

Closes #832
2018-03-28 15:24:42 +02:00

84 lines
2.3 KiB
JavaScript

module.exports = {
splitImageParts,
extractDependencies,
};
function groupedRegex(string, pattern) {
const matches = string.match(new RegExp(pattern.source, pattern.flags));
if (!matches) {
return [];
}
return matches.map(
match => new RegExp(pattern.source, pattern.flags).exec(match)[1]
);
}
function splitImageParts(currentFrom) {
let dockerRegistry;
const split = currentFrom.split('/');
if (split.length > 1 && split[0].includes('.')) {
[dockerRegistry] = split;
split.shift();
}
const currentDepTagDigest = split.join('/');
const [currentDepTag, currentDigest] = currentDepTagDigest.split('@');
const [depName, currentTag] = currentDepTag.split(':');
return {
dockerRegistry,
depName,
currentTag,
currentDigest,
currentDepTagDigest,
currentDepTag,
};
}
function extractDependencies(content) {
logger.debug('docker.extractDependencies()');
const deps = [];
const fromMatches = groupedRegex(content, /(?:^|\n)(FROM .+)\n/gi);
if (!fromMatches.length) {
logger.warn({ content }, 'No FROM found');
return [];
}
logger.debug({ fromMatches }, 'Found matches');
const stageNames = [];
fromMatches.forEach(fromLine => {
logger.debug({ fromLine }, 'fromLine');
const [fromPrefix, currentFrom, ...fromRest] = fromLine.match(/\S+/g);
if (fromRest.length === 2 && fromRest[0].toLowerCase() === 'as') {
logger.debug('Found a multistage build stage name');
stageNames.push(fromRest[1]);
}
const fromSuffix = fromRest.join(' ');
const {
dockerRegistry,
depName,
currentTag,
currentDigest,
currentDepTagDigest,
currentDepTag,
} = splitImageParts(currentFrom);
logger.info({ depName, currentTag, currentDigest }, 'Dockerfile FROM');
if (currentFrom === 'scratch') {
logger.debug('Skipping scratch');
} else if (stageNames.includes(currentFrom)) {
logger.debug({ currentFrom }, 'Skipping alias FROM');
} else {
deps.push({
depType: 'Dockerfile',
fromLine,
fromPrefix,
currentFrom,
fromSuffix,
currentDepTagDigest,
dockerRegistry,
currentDepTag,
currentDigest,
depName,
currentTag,
});
}
});
return deps;
}