diff --git a/docs/usage/configuration-options.md b/docs/usage/configuration-options.md index 0c00279e4b93f42c81ef7d950e5b51b7b3d210d8..e308ae82eeca514c5c15a70a8ace988e11d2ba74 100644 --- a/docs/usage/configuration-options.md +++ b/docs/usage/configuration-options.md @@ -2525,6 +2525,11 @@ This feature works with the following managers: - [`helmv3`](/modules/manager/helmv3/) - [`helmfile`](/modules/manager/helmfile/) - [`gitlabci`](/modules/manager/gitlabci/) +- [`dockerfile`](/modules/manager/dockerfile) +- [`docker-compose`](/modules/manager/docker-compose) +- [`kubernetes`](/modules/manager/kubernetes) +- [`ansible`](/modules/manager/ansible) +- [`droneci`](/modules/manager/droneci) ## registryUrls diff --git a/lib/config/options/index.ts b/lib/config/options/index.ts index 4a0439c8530f3ff9b2ff0d87a3d9673f94af02c8..66a5b943950b8e45b8bc03ad577ecf720e77bd7e 100644 --- a/lib/config/options/index.ts +++ b/lib/config/options/index.ts @@ -822,7 +822,17 @@ const options: RenovateOptions[] = [ type: 'string', format: 'uri', }, - supportedManagers: ['helm-requirements', 'helmv3', 'helmfile', 'gitlabci'], + supportedManagers: [ + 'helm-requirements', + 'helmv3', + 'helmfile', + 'gitlabci', + 'dockerfile', + 'docker-compose', + 'kubernetes', + 'ansible', + 'droneci', + ], }, { name: 'defaultRegistryUrls', diff --git a/lib/modules/manager/ansible/extract.spec.ts b/lib/modules/manager/ansible/extract.spec.ts index e7bde92ed9c9fd0f50cf80b3d23ba532e509262d..6730ca20f81234d4040d43f4dc260ea0c9840d3a 100644 --- a/lib/modules/manager/ansible/extract.spec.ts +++ b/lib/modules/manager/ansible/extract.spec.ts @@ -4,19 +4,110 @@ import { extractPackageFile } from '.'; describe('modules/manager/ansible/extract', () => { describe('extractPackageFile()', () => { it('returns null for empty', () => { - expect(extractPackageFile('nothing here')).toBeNull(); + expect(extractPackageFile('nothing here', '', {})).toBeNull(); }); it('extracts multiple image lines from docker_container', () => { - const res = extractPackageFile(Fixtures.get('main1.yaml')); + const res = extractPackageFile(Fixtures.get('main1.yaml'), '', {}); expect(res?.deps).toMatchSnapshot(); expect(res?.deps).toHaveLength(9); }); it('extracts multiple image lines from docker_service', () => { - const res = extractPackageFile(Fixtures.get('main2.yaml')); + const res = extractPackageFile(Fixtures.get('main2.yaml'), '', {}); expect(res?.deps).toMatchSnapshot(); expect(res?.deps).toHaveLength(4); }); + + it('extracts image and replaces registry', () => { + const res = extractPackageFile( + `--- + - name: Re-create a redis container + docker_container: + name: myredis + image: quay.io/redis:0.0.1`, + '', + { + registryAliases: { + 'quay.io': 'my-quay-mirror.registry.com', + }, + } + ); + expect(res).toEqual({ + deps: [ + { + autoReplaceStringTemplate: + 'quay.io/redis:{{#if newValue}}{{newValue}}{{/if}}{{#if newDigest}}@{{newDigest}}{{/if}}', + currentDigest: undefined, + currentValue: '0.0.1', + datasource: 'docker', + depName: 'my-quay-mirror.registry.com/redis', + replaceString: 'quay.io/redis:0.0.1', + versioning: 'docker', + }, + ], + }); + }); + + it('extracts image but no replacement', () => { + const res = extractPackageFile( + `--- + - name: Re-create a redis container + docker_container: + name: myredis + image: quay.io/redis:0.0.1`, + '', + { + registryAliases: { + 'index.docker.io': 'my-docker-mirror.registry.com', + }, + } + ); + expect(res).toEqual({ + deps: [ + { + autoReplaceStringTemplate: + '{{depName}}{{#if newValue}}:{{newValue}}{{/if}}{{#if newDigest}}@{{newDigest}}{{/if}}', + currentDigest: undefined, + currentValue: '0.0.1', + datasource: 'docker', + depName: 'quay.io/redis', + replaceString: 'quay.io/redis:0.0.1', + versioning: 'docker', + }, + ], + }); + }); + + it('extracts image and no double replacement', () => { + const res = extractPackageFile( + `--- + - name: Re-create a redis container + docker_container: + name: myredis + image: quay.io/redis:0.0.1`, + '', + { + registryAliases: { + 'quay.io': 'my-quay-mirror.registry.com', + 'my-quay-mirror.registry.com': 'quay.io', + }, + } + ); + expect(res).toEqual({ + deps: [ + { + autoReplaceStringTemplate: + 'quay.io/redis:{{#if newValue}}{{newValue}}{{/if}}{{#if newDigest}}@{{newDigest}}{{/if}}', + currentDigest: undefined, + currentValue: '0.0.1', + datasource: 'docker', + depName: 'my-quay-mirror.registry.com/redis', + replaceString: 'quay.io/redis:0.0.1', + versioning: 'docker', + }, + ], + }); + }); }); }); diff --git a/lib/modules/manager/ansible/extract.ts b/lib/modules/manager/ansible/extract.ts index c0167e1107f33d6de30d13a4444a18f46ebe6c2c..cc87b949c01902c3d0842353481a7dc716a9fca2 100644 --- a/lib/modules/manager/ansible/extract.ts +++ b/lib/modules/manager/ansible/extract.ts @@ -2,9 +2,13 @@ import { logger } from '../../../logger'; import { newlineRegex, regEx } from '../../../util/regex'; import * as dockerVersioning from '../../versioning/docker'; import { getDep } from '../dockerfile/extract'; -import type { PackageDependency, PackageFile } from '../types'; +import type { ExtractConfig, PackageDependency, PackageFile } from '../types'; -export function extractPackageFile(content: string): PackageFile | null { +export function extractPackageFile( + content: string, + _filename: string, + config: ExtractConfig +): PackageFile | null { logger.trace('ansible.extractPackageFile()'); let deps: PackageDependency[] = []; const re = regEx(/^\s*image:\s*'?"?([^\s'"]+)'?"?\s*$/); @@ -12,7 +16,7 @@ export function extractPackageFile(content: string): PackageFile | null { const match = re.exec(line); if (match) { const currentFrom = match[1]; - const dep = getDep(currentFrom); + const dep = getDep(currentFrom, true, config.registryAliases); logger.debug( { depName: dep.depName, diff --git a/lib/modules/manager/docker-compose/extract.spec.ts b/lib/modules/manager/docker-compose/extract.spec.ts index 01d5cbbb8faf0596617075ac691cd92a1bc1b02d..b84f0b169d79be7b9185fefbf6a16b082d27032e 100644 --- a/lib/modules/manager/docker-compose/extract.spec.ts +++ b/lib/modules/manager/docker-compose/extract.spec.ts @@ -9,37 +9,37 @@ const yamlFile3DefaultValue = Fixtures.get('docker-compose.3-default-val.yml'); describe('modules/manager/docker-compose/extract', () => { describe('extractPackageFile()', () => { it('returns null for empty', () => { - expect(extractPackageFile('')).toBeNull(); + expect(extractPackageFile('', '', {})).toBeNull(); }); it('returns null for non-object YAML', () => { - expect(extractPackageFile('nothing here')).toBeNull(); + expect(extractPackageFile('nothing here', '', {})).toBeNull(); }); it('returns null for malformed YAML', () => { - expect(extractPackageFile('nothing here\n:::::::')).toBeNull(); + expect(extractPackageFile('nothing here\n:::::::', '', {})).toBeNull(); }); it('extracts multiple image lines for version 1', () => { - const res = extractPackageFile(yamlFile1); + const res = extractPackageFile(yamlFile1, '', {}); expect(res?.deps).toMatchSnapshot(); expect(res?.deps).toHaveLength(8); }); it('extracts multiple image lines for version 3', () => { - const res = extractPackageFile(yamlFile3); + const res = extractPackageFile(yamlFile3, '', {}); expect(res?.deps).toMatchSnapshot(); expect(res?.deps).toHaveLength(8); }); it('extracts multiple image lines for version 3 without set version key', () => { - const res = extractPackageFile(yamlFile3NoVersion); + const res = extractPackageFile(yamlFile3NoVersion, '', {}); expect(res?.deps).toMatchSnapshot(); expect(res?.deps).toHaveLength(8); }); it('extracts default variable values for version 3', () => { - const res = extractPackageFile(yamlFile3DefaultValue); + const res = extractPackageFile(yamlFile3DefaultValue, '', {}); expect(res?.deps).toMatchInlineSnapshot(` [ { @@ -54,5 +54,96 @@ describe('modules/manager/docker-compose/extract', () => { `); expect(res?.deps).toHaveLength(1); }); + + it('extracts image and replaces registry', () => { + const res = extractPackageFile( + ` + version: "3" + services: + nginx: + image: quay.io/nginx:0.0.1 + `, + '', + { + registryAliases: { + 'quay.io': 'my-quay-mirror.registry.com', + }, + } + ); + expect(res).toEqual({ + deps: [ + { + autoReplaceStringTemplate: + 'quay.io/nginx:{{#if newValue}}{{newValue}}{{/if}}{{#if newDigest}}@{{newDigest}}{{/if}}', + currentDigest: undefined, + currentValue: '0.0.1', + datasource: 'docker', + depName: 'my-quay-mirror.registry.com/nginx', + replaceString: 'quay.io/nginx:0.0.1', + }, + ], + }); + }); + + it('extracts image but no replacement', () => { + const res = extractPackageFile( + ` + version: "3" + services: + nginx: + image: quay.io/nginx:0.0.1 + `, + '', + { + registryAliases: { + 'index.docker.io': 'my-docker-mirror.registry.com', + }, + } + ); + expect(res).toEqual({ + deps: [ + { + autoReplaceStringTemplate: + '{{depName}}{{#if newValue}}:{{newValue}}{{/if}}{{#if newDigest}}@{{newDigest}}{{/if}}', + currentDigest: undefined, + currentValue: '0.0.1', + datasource: 'docker', + depName: 'quay.io/nginx', + replaceString: 'quay.io/nginx:0.0.1', + }, + ], + }); + }); + + it('extracts image and no double replacement', () => { + const res = extractPackageFile( + ` + version: "3" + services: + nginx: + image: quay.io/nginx:0.0.1 + `, + '', + { + registryAliases: { + 'quay.io': 'my-quay-mirror.registry.com', + 'my-quay-mirror.registry.com': 'quay.io', + }, + } + ); + expect(res).toEqual({ + deps: [ + { + autoReplaceStringTemplate: + 'quay.io/nginx:{{#if newValue}}{{newValue}}{{/if}}{{#if newDigest}}@{{newDigest}}{{/if}}', + currentDigest: undefined, + currentValue: '0.0.1', + datasource: 'docker', + depName: 'my-quay-mirror.registry.com/nginx', + replaceString: 'quay.io/nginx:0.0.1', + }, + ], + }); + }); }); }); diff --git a/lib/modules/manager/docker-compose/extract.ts b/lib/modules/manager/docker-compose/extract.ts index 0e8bfddb50abe2cc8d5a1dc411f34ab51aa08612..ba716a50940a44bdba2b74825aa9bdeb8f608fdb 100644 --- a/lib/modules/manager/docker-compose/extract.ts +++ b/lib/modules/manager/docker-compose/extract.ts @@ -3,7 +3,7 @@ import { load } from 'js-yaml'; import { logger } from '../../../logger'; import { newlineRegex, regEx } from '../../../util/regex'; import { getDep } from '../dockerfile/extract'; -import type { PackageFile } from '../types'; +import type { ExtractConfig, PackageFile } from '../types'; import type { DockerComposeConfig } from './types'; class LineMapper { @@ -30,7 +30,8 @@ class LineMapper { export function extractPackageFile( content: string, - fileName?: string + fileName: string, + extractConfig: ExtractConfig ): PackageFile | null { logger.debug('docker-compose.extractPackageFile()'); let config: DockerComposeConfig; @@ -71,7 +72,7 @@ export function extractPackageFile( const deps = Object.values(services || {}) .filter((service) => is.string(service?.image) && !service?.build) .map((service) => { - const dep = getDep(service.image); + const dep = getDep(service.image, true, extractConfig.registryAliases); const lineNumber = lineMapper.pluckLineNumber(service.image); // istanbul ignore if if (!lineNumber) { diff --git a/lib/modules/manager/dockerfile/extract.spec.ts b/lib/modules/manager/dockerfile/extract.spec.ts index de7c37cb0163dbf411c1b3ee4850ed61ec9bd1f4..8951876ea3826970ecd7d5beee9fe215163adbae 100644 --- a/lib/modules/manager/dockerfile/extract.spec.ts +++ b/lib/modules/manager/dockerfile/extract.spec.ts @@ -11,12 +11,12 @@ const d4 = Fixtures.get('4.Dockerfile'); describe('modules/manager/dockerfile/extract', () => { describe('extractPackageFile()', () => { it('handles no FROM', () => { - const res = extractPackageFile('no from!'); + const res = extractPackageFile('no from!', '', {}); expect(res).toBeNull(); }); it('handles naked dep', () => { - const res = extractPackageFile('FROM node\n')?.deps; + const res = extractPackageFile('FROM node\n', '', {})?.deps; expect(res).toMatchInlineSnapshot(` [ { @@ -33,7 +33,7 @@ describe('modules/manager/dockerfile/extract', () => { }); it('is case insensitive', () => { - const res = extractPackageFile('From node\n')?.deps; + const res = extractPackageFile('From node\n', '', {})?.deps; expect(res).toMatchInlineSnapshot(` [ { @@ -50,7 +50,7 @@ describe('modules/manager/dockerfile/extract', () => { }); it('handles tag', () => { - const res = extractPackageFile('FROM node:8.9.0-alpine\n')?.deps; + const res = extractPackageFile('FROM node:8.9.0-alpine\n', '', {})?.deps; expect(res).toMatchInlineSnapshot(` [ { @@ -68,7 +68,9 @@ describe('modules/manager/dockerfile/extract', () => { it('handles digest', () => { const res = extractPackageFile( - 'FROM node@sha256:eb85fc5b1198f5e1ec025ea07586bdbbf397e7d82df66c90d7511f533517e063\n' + 'FROM node@sha256:eb85fc5b1198f5e1ec025ea07586bdbbf397e7d82df66c90d7511f533517e063\n', + '', + {} )?.deps; expect(res).toMatchInlineSnapshot(` [ @@ -87,7 +89,9 @@ describe('modules/manager/dockerfile/extract', () => { it('handles tag and digest', () => { const res = extractPackageFile( - 'FROM node:8.9.0@sha256:eb85fc5b1198f5e1ec025ea07586bdbbf397e7d82df66c90d7511f533517e063\n' + 'FROM node:8.9.0@sha256:eb85fc5b1198f5e1ec025ea07586bdbbf397e7d82df66c90d7511f533517e063\n', + '', + {} )?.deps; expect(res).toMatchInlineSnapshot(` [ @@ -105,7 +109,11 @@ describe('modules/manager/dockerfile/extract', () => { }); it('handles from as', () => { - const res = extractPackageFile('FROM node:8.9.0-alpine as base\n')?.deps; + const res = extractPackageFile( + 'FROM node:8.9.0-alpine as base\n', + '', + {} + )?.deps; expect(res).toMatchInlineSnapshot(` [ { @@ -123,7 +131,9 @@ describe('modules/manager/dockerfile/extract', () => { it('handles comments', () => { const res = extractPackageFile( - '# some comment\n# another\n\nFROM node\n' + '# some comment\n# another\n\nFROM node\n', + '', + {} )?.deps; expect(res).toMatchInlineSnapshot(` [ @@ -142,7 +152,9 @@ describe('modules/manager/dockerfile/extract', () => { it('handles custom hosts', () => { const res = extractPackageFile( - 'FROM registry2.something.info/node:8\n' + 'FROM registry2.something.info/node:8\n', + '', + {} )?.deps; expect(res).toMatchInlineSnapshot(` [ @@ -161,7 +173,9 @@ describe('modules/manager/dockerfile/extract', () => { it('handles custom hosts and suffix', () => { const res = extractPackageFile( - 'FROM registry2.something.info/node:8-alpine\n' + 'FROM registry2.something.info/node:8-alpine\n', + '', + {} )?.deps; expect(res).toMatchInlineSnapshot(` [ @@ -180,7 +194,9 @@ describe('modules/manager/dockerfile/extract', () => { it('handles custom hosts with port', () => { const res = extractPackageFile( - 'FROM registry2.something.info:5005/node:8\n' + 'FROM registry2.something.info:5005/node:8\n', + '', + {} )?.deps; expect(res).toMatchInlineSnapshot(` [ @@ -201,7 +217,9 @@ describe('modules/manager/dockerfile/extract', () => { it('handles custom hosts with port without tag', () => { const res = extractPackageFile( - 'FROM registry2.something.info:5005/node\n' + 'FROM registry2.something.info:5005/node\n', + '', + {} )?.deps; expect(res).toMatchInlineSnapshot(` [ @@ -220,7 +238,7 @@ describe('modules/manager/dockerfile/extract', () => { }); it('handles quay hosts with port', () => { - const res = extractPackageFile('FROM quay.io:1234/node\n')?.deps; + const res = extractPackageFile('FROM quay.io:1234/node\n', '', {})?.deps; expect(res?.[0]).toMatchInlineSnapshot(` { "autoReplaceStringTemplate": "{{packageName}}{{#if newValue}}:{{newValue}}{{/if}}{{#if newDigest}}@{{newDigest}}{{/if}}", @@ -236,7 +254,7 @@ describe('modules/manager/dockerfile/extract', () => { }); it('handles namespaced images', () => { - const res = extractPackageFile('FROM mynamespace/node:8\n')?.deps; + const res = extractPackageFile('FROM mynamespace/node:8\n', '', {})?.deps; expect(res).toMatchInlineSnapshot(` [ { @@ -254,7 +272,9 @@ describe('modules/manager/dockerfile/extract', () => { it('handles custom hosts with namespace', () => { const res = extractPackageFile( - 'FROM registry2.something.info/someaccount/node:8\n' + 'FROM registry2.something.info/someaccount/node:8\n', + '', + {} )?.deps; expect(res).toMatchInlineSnapshot(` [ @@ -273,7 +293,9 @@ describe('modules/manager/dockerfile/extract', () => { it('handles abnormal spacing', () => { const res = extractPackageFile( - 'FROM registry.allmine.info:5005/node:8.7.0\n\n' + 'FROM registry.allmine.info:5005/node:8.7.0\n\n', + '', + {} )?.deps; expect(res).toMatchInlineSnapshot(` [ @@ -292,7 +314,9 @@ describe('modules/manager/dockerfile/extract', () => { it('extracts multiple FROM tags', () => { const res = extractPackageFile( - 'FROM node:6.12.3 as frontend\n\n# comment\nENV foo=bar\nFROM python:3.6-slim\n' + 'FROM node:6.12.3 as frontend\n\n# comment\nENV foo=bar\nFROM python:3.6-slim\n', + '', + {} )?.deps; expect(res).toMatchInlineSnapshot(` [ @@ -320,13 +344,15 @@ describe('modules/manager/dockerfile/extract', () => { }); it('skips scratches', () => { - const res = extractPackageFile('FROM scratch\nADD foo\n'); + const res = extractPackageFile('FROM scratch\nADD foo\n', '', {}); expect(res).toBeNull(); }); it('skips named multistage FROM tags', () => { const res = extractPackageFile( - 'FROM node:6.12.3 as frontend\n\n# comment\nENV foo=bar\nFROM frontend\n' + 'FROM node:6.12.3 as frontend\n\n# comment\nENV foo=bar\nFROM frontend\n', + '', + {} )?.deps; expect(res).toMatchInlineSnapshot(` [ @@ -346,7 +372,9 @@ describe('modules/manager/dockerfile/extract', () => { it('handles COPY --from', () => { const res = extractPackageFile( - 'FROM scratch\nCOPY --from=gcr.io/k8s-skaffold/skaffold:v0.11.0 /usr/bin/skaffold /usr/bin/skaffold\n' + 'FROM scratch\nCOPY --from=gcr.io/k8s-skaffold/skaffold:v0.11.0 /usr/bin/skaffold /usr/bin/skaffold\n', + '', + {} )?.deps; expect(res).toMatchInlineSnapshot(` [ @@ -365,7 +393,9 @@ describe('modules/manager/dockerfile/extract', () => { it('skips named multistage COPY --from tags', () => { const res = extractPackageFile( - 'FROM node:6.12.3 as frontend\n\n# comment\nENV foo=bar\nCOPY --from=frontend /usr/bin/node /usr/bin/node\n' + 'FROM node:6.12.3 as frontend\n\n# comment\nENV foo=bar\nCOPY --from=frontend /usr/bin/node /usr/bin/node\n', + '', + {} )?.deps; expect(res).toMatchInlineSnapshot(` [ @@ -385,7 +415,9 @@ describe('modules/manager/dockerfile/extract', () => { it('skips index reference COPY --from tags', () => { const res = extractPackageFile( - 'FROM node:6.12.3 as frontend\n\n# comment\nENV foo=bar\nCOPY --from=0 /usr/bin/node /usr/bin/node\n' + 'FROM node:6.12.3 as frontend\n\n# comment\nENV foo=bar\nCOPY --from=0 /usr/bin/node /usr/bin/node\n', + '', + {} )?.deps; expect(res).toMatchInlineSnapshot(` [ @@ -405,7 +437,9 @@ describe('modules/manager/dockerfile/extract', () => { it('detects ["stage"] and ["final"] deps of docker multi-stage build.', () => { const res = extractPackageFile( - 'FROM node:8.15.1-alpine as skippedfrom\nFROM golang:1.7.3 as builder\n\n# comment\nWORKDIR /go/src/github.com/alexellis/href-counter/\nRUN go get -d -v golang.org/x/net/html \nCOPY app.go .\nRUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o app .\n\nFROM alpine:latest \nRUN apk --no-cache add ca-certificates\nWORKDIR /root/\nCOPY --from=builder /go/src/github.com/alexellis/href-counter/app .\nCMD ["./app"]\n' + 'FROM node:8.15.1-alpine as skippedfrom\nFROM golang:1.7.3 as builder\n\n# comment\nWORKDIR /go/src/github.com/alexellis/href-counter/\nRUN go get -d -v golang.org/x/net/html \nCOPY app.go .\nRUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o app .\n\nFROM alpine:latest \nRUN apk --no-cache add ca-certificates\nWORKDIR /root/\nCOPY --from=builder /go/src/github.com/alexellis/href-counter/app .\nCMD ["./app"]\n', + '', + {} )?.deps; expect(res).toMatchInlineSnapshot(` [ @@ -447,7 +481,7 @@ describe('modules/manager/dockerfile/extract', () => { }); it('extracts images on adjacent lines', () => { - const res = extractPackageFile(d1)?.deps; + const res = extractPackageFile(d1, '', {})?.deps; expect(res).toMatchInlineSnapshot(` [ { @@ -474,7 +508,7 @@ describe('modules/manager/dockerfile/extract', () => { }); it('extracts images from all sorts of (maybe multiline) FROM and COPY --from statements', () => { - const res = extractPackageFile(d2)?.deps; + const res = extractPackageFile(d2, '', {})?.deps; expect(res).toMatchInlineSnapshot(` [ { @@ -564,7 +598,7 @@ describe('modules/manager/dockerfile/extract', () => { }); it('handles calico/node', () => { - const res = extractPackageFile('FROM calico/node\n')?.deps; + const res = extractPackageFile('FROM calico/node\n', '', {})?.deps; expect(res).toMatchInlineSnapshot(` [ { @@ -581,7 +615,7 @@ describe('modules/manager/dockerfile/extract', () => { }); it('handles ubuntu', () => { - const res = extractPackageFile('FROM ubuntu:18.04\n')?.deps; + const res = extractPackageFile('FROM ubuntu:18.04\n', '', {})?.deps; expect(res).toMatchInlineSnapshot(` [ { @@ -599,7 +633,7 @@ describe('modules/manager/dockerfile/extract', () => { }); it('handles debian with codename', () => { - const res = extractPackageFile('FROM debian:buster\n')?.deps; + const res = extractPackageFile('FROM debian:buster\n', '', {})?.deps; expect(res).toEqual([ { autoReplaceStringTemplate: @@ -616,7 +650,7 @@ describe('modules/manager/dockerfile/extract', () => { }); it('handles debian with prefixes', () => { - const res = extractPackageFile('FROM amd64/debian:10\n')?.deps; + const res = extractPackageFile('FROM amd64/debian:10\n', '', {})?.deps; expect(res).toEqual([ { autoReplaceStringTemplate: @@ -634,7 +668,7 @@ describe('modules/manager/dockerfile/extract', () => { }); it('handles prefixes', () => { - const res = extractPackageFile('FROM amd64/ubuntu:18.04\n')?.deps; + const res = extractPackageFile('FROM amd64/ubuntu:18.04\n', '', {})?.deps; expect(res).toMatchInlineSnapshot(` [ { @@ -654,7 +688,9 @@ describe('modules/manager/dockerfile/extract', () => { it('handles implausible line continuation', () => { const res = extractPackageFile( - 'FROM alpine:3.5\n\nRUN something \\' + 'FROM alpine:3.5\n\nRUN something \\', + '', + {} )?.deps; expect(res).toMatchInlineSnapshot(` [ @@ -672,7 +708,7 @@ describe('modules/manager/dockerfile/extract', () => { }); it('handles multi-line FROM with space after escape character', () => { - const res = extractPackageFile('FROM \\ \nnginx:1.20\n')?.deps; + const res = extractPackageFile('FROM \\ \nnginx:1.20\n', '', {})?.deps; expect(res).toMatchInlineSnapshot(` [ { @@ -689,7 +725,11 @@ describe('modules/manager/dockerfile/extract', () => { }); it('handles FROM without ARG default value', () => { - const res = extractPackageFile('ARG img_base\nFROM $img_base\n')?.deps; + const res = extractPackageFile( + 'ARG img_base\nFROM $img_base\n', + '', + {} + )?.deps; expect(res).toMatchInlineSnapshot(` [ { @@ -705,7 +745,9 @@ describe('modules/manager/dockerfile/extract', () => { it('handles FROM with empty ARG default value', () => { const res = extractPackageFile( - 'ARG patch1=""\nARG patch2=\nFROM nginx:1.20${patch1}$patch2\n' + 'ARG patch1=""\nARG patch2=\nFROM nginx:1.20${patch1}$patch2\n', + '', + {} )?.deps; expect(res).toMatchInlineSnapshot(` [ @@ -724,7 +766,9 @@ describe('modules/manager/dockerfile/extract', () => { it('handles FROM with version in ARG value', () => { const res = extractPackageFile( - 'ARG\tVARIANT="1.60.0-bullseye"\nFROM\trust:${VARIANT}\n' + 'ARG\tVARIANT="1.60.0-bullseye"\nFROM\trust:${VARIANT}\n', + '', + {} )?.deps; expect(res).toMatchInlineSnapshot(` [ @@ -743,7 +787,9 @@ describe('modules/manager/dockerfile/extract', () => { it('handles FROM with version in ARG default value', () => { const res = extractPackageFile( - 'ARG IMAGE_VERSION=${IMAGE_VERSION:-ubuntu:xenial}\nfrom ${IMAGE_VERSION} as base\n' + 'ARG IMAGE_VERSION=${IMAGE_VERSION:-ubuntu:xenial}\nfrom ${IMAGE_VERSION} as base\n', + '', + {} )?.deps; expect(res).toMatchInlineSnapshot(` [ @@ -763,7 +809,9 @@ describe('modules/manager/dockerfile/extract', () => { it('handles FROM with digest in ARG default value', () => { const res = extractPackageFile( 'ARG sha_digest=sha256:ab37242e81cbc031b2600eef4440fe87055a05c14b40686df85078cc5086c98f\n' + - ' FROM gcr.io/distroless/java17@$sha_digest' + ' FROM gcr.io/distroless/java17@$sha_digest', + '', + {} )?.deps; expect(res).toMatchInlineSnapshot(` [ @@ -782,7 +830,9 @@ describe('modules/manager/dockerfile/extract', () => { it('handles FROM with overwritten ARG value', () => { const res = extractPackageFile( - 'ARG base=nginx:1.19\nFROM $base as stage1\nARG base=nginx:1.20\nFROM --platform=amd64 $base as stage2\n' + 'ARG base=nginx:1.19\nFROM $base as stage1\nARG base=nginx:1.20\nFROM --platform=amd64 $base as stage2\n', + '', + {} )?.deps; expect(res).toMatchInlineSnapshot(` [ @@ -810,7 +860,9 @@ describe('modules/manager/dockerfile/extract', () => { it('handles FROM with multiple ARG values', () => { const res = extractPackageFile( - 'ARG CUDA=9.2\nARG LINUX_VERSION ubuntu16.04\nFROM nvidia/cuda:${CUDA}-devel-${LINUX_VERSION}\n' + 'ARG CUDA=9.2\nARG LINUX_VERSION ubuntu16.04\nFROM nvidia/cuda:${CUDA}-devel-${LINUX_VERSION}\n', + '', + {} )?.deps; expect(res).toMatchInlineSnapshot(` [ @@ -828,12 +880,16 @@ describe('modules/manager/dockerfile/extract', () => { }); it('skips scratch if provided in ARG value', () => { - const res = extractPackageFile('ARG img="scratch"\nFROM $img as base\n'); + const res = extractPackageFile( + 'ARG img="scratch"\nFROM $img as base\n', + '', + {} + ); expect(res).toBeNull(); }); it('extracts images from multi-line ARG statements', () => { - const res = extractPackageFile(d3)?.deps; + const res = extractPackageFile(d3, '', {})?.deps; expect(res).toEqual([ { autoReplaceStringTemplate: @@ -875,7 +931,9 @@ describe('modules/manager/dockerfile/extract', () => { it('ignores parser directives in wrong order', () => { const res = extractPackageFile( - '# dummy\n# escape = `\n\nFROM\\\nnginx:1.20' + '# dummy\n# escape = `\n\nFROM\\\nnginx:1.20', + '', + {} )?.deps; expect(res).toMatchInlineSnapshot(` [ @@ -893,7 +951,7 @@ describe('modules/manager/dockerfile/extract', () => { }); it('handles an alternative escape character', () => { - const res = extractPackageFile(d4)?.deps; + const res = extractPackageFile(d4, '', {})?.deps; expect(res).toEqual([ { autoReplaceStringTemplate: @@ -954,7 +1012,9 @@ describe('modules/manager/dockerfile/extract', () => { it('handles FROM with version in ARG default value and quotes', () => { const res = extractPackageFile( - 'ARG REF_NAME=${REF_NAME:-"gcr.io/distroless/static-debian11:nonroot@sha256:abc"}\nfrom ${REF_NAME}' + 'ARG REF_NAME=${REF_NAME:-"gcr.io/distroless/static-debian11:nonroot@sha256:abc"}\nfrom ${REF_NAME}', + '', + {} )?.deps; expect(res).toMatchInlineSnapshot(` [ @@ -973,7 +1033,9 @@ describe('modules/manager/dockerfile/extract', () => { it('handles version in ARG and digest in FROM with CRLF linefeed', () => { const res = extractPackageFile( - 'ARG IMAGE_TAG=14.04\r\n#something unrelated\r\nFROM ubuntu:$IMAGE_TAG@sha256:abc\r\n' + 'ARG IMAGE_TAG=14.04\r\n#something unrelated\r\nFROM ubuntu:$IMAGE_TAG@sha256:abc\r\n', + '', + {} )?.deps; expect(res).toEqual([ { @@ -999,7 +1061,9 @@ describe('modules/manager/dockerfile/extract', () => { 'ARG NODE_IMAGE_NAME=node\n' + 'ARG NODE_IMAGE_TAG="16.14.2-alpine3.14"\n' + 'ARG DUMMY_PREFIX=\n' + - 'FROM ${DUMMY_PREFIX}${NODE_IMAGE_HOST}${NODE_IMAGE_NAME}:${NODE_IMAGE_TAG}${NODE_IMAGE_HASH} as yarn\n' + 'FROM ${DUMMY_PREFIX}${NODE_IMAGE_HOST}${NODE_IMAGE_NAME}:${NODE_IMAGE_TAG}${NODE_IMAGE_HASH} as yarn\n', + '', + {} )?.deps; expect(res).toEqual([ { @@ -1024,6 +1088,82 @@ describe('modules/manager/dockerfile/extract', () => { }); }); + it('handles empty optional parameters', () => { + const res = extractPackageFile( + 'FROM quay.io/myName/myPackage:0.6.2\n', + '', + {} + ); + expect(res).toEqual({ + deps: [ + { + autoReplaceStringTemplate: + '{{depName}}{{#if newValue}}:{{newValue}}{{/if}}{{#if newDigest}}@{{newDigest}}{{/if}}', + currentDigest: undefined, + currentValue: '0.6.2', + datasource: 'docker', + depName: 'quay.io/myName/myPackage', + depType: 'final', + replaceString: 'quay.io/myName/myPackage:0.6.2', + }, + ], + }); + }); + + it('handles registry alias', () => { + const res = extractPackageFile( + 'FROM quay.io/myName/myPackage:0.6.2\n', + 'Dockerfile', + { + registryAliases: { + 'quay.io': 'my-quay-mirror.registry.com', + 'index.docker.io': 'my-docker-mirror.registry.com', + }, + } + ); + expect(res).toEqual({ + deps: [ + { + autoReplaceStringTemplate: + 'quay.io/myName/myPackage:{{#if newValue}}{{newValue}}{{/if}}{{#if newDigest}}@{{newDigest}}{{/if}}', + currentDigest: undefined, + currentValue: '0.6.2', + datasource: 'docker', + depName: 'my-quay-mirror.registry.com/myName/myPackage', + depType: 'final', + replaceString: 'quay.io/myName/myPackage:0.6.2', + }, + ], + }); + }); + + it('handles empty registry', () => { + const res = extractPackageFile( + 'FROM myName/myPackage:0.6.2\n', + 'Dockerfile', + { + registryAliases: { + 'quay.io': 'my-quay-mirror.registry.com', + 'index.docker.io': 'my-docker-mirror.registry.com', + }, + } + ); + expect(res).toEqual({ + deps: [ + { + autoReplaceStringTemplate: + '{{depName}}{{#if newValue}}:{{newValue}}{{/if}}{{#if newDigest}}@{{newDigest}}{{/if}}', + currentDigest: undefined, + currentValue: '0.6.2', + datasource: 'docker', + depName: 'myName/myPackage', + depType: 'final', + replaceString: 'myName/myPackage:0.6.2', + }, + ], + }); + }); + describe('getDep()', () => { it('rejects null', () => { expect(getDep(null)).toEqual({ skipReason: 'invalid-value' }); diff --git a/lib/modules/manager/dockerfile/extract.ts b/lib/modules/manager/dockerfile/extract.ts index 9433aeab41ea62ee2fc7fae427e067d10d0ef05d..d3a1df9d1bb81f71cc3ce390fe724083812a5312 100644 --- a/lib/modules/manager/dockerfile/extract.ts +++ b/lib/modules/manager/dockerfile/extract.ts @@ -4,7 +4,7 @@ import { escapeRegExp, newlineRegex, regEx } from '../../../util/regex'; import { DockerDatasource } from '../../datasource/docker'; import * as debianVersioning from '../../versioning/debian'; import * as ubuntuVersioning from '../../versioning/ubuntu'; -import type { PackageDependency, PackageFile } from '../types'; +import type { ExtractConfig, PackageDependency, PackageFile } from '../types'; const variableMarker = '$'; @@ -226,7 +226,11 @@ export function getDep( return dep; } -export function extractPackageFile(content: string): PackageFile | null { +export function extractPackageFile( + content: string, + _filename: string, + config: ExtractConfig +): PackageFile | null { const deps: PackageDependency[] = []; const stageNames: string[] = []; const args: Record<string, string> = {}; @@ -322,7 +326,7 @@ export function extractPackageFile(content: string): PackageFile | null { } else if (fromImage && stageNames.includes(fromImage)) { logger.debug({ image: fromImage }, 'Skipping alias FROM'); } else { - const dep = getDep(fromImage); + const dep = getDep(fromImage, true, config.registryAliases); processDepForAutoReplace(dep, lineNumberRanges, lines, lineFeed); logger.trace( { @@ -350,7 +354,11 @@ export function extractPackageFile(content: string): PackageFile | null { 'Skipping alias COPY --from' ); } else if (Number.isNaN(Number(copyFromMatch.groups.image))) { - const dep = getDep(copyFromMatch.groups.image); + const dep = getDep( + copyFromMatch.groups.image, + true, + config.registryAliases + ); const lineNumberRanges: number[][] = [ [lineNumberInstrStart, lineNumber], ]; diff --git a/lib/modules/manager/droneci/__fixtures__/.drone2.yml b/lib/modules/manager/droneci/__fixtures__/.drone2.yml new file mode 100644 index 0000000000000000000000000000000000000000..c88a7f7d984930f81687be120c035b9e320a0fbb --- /dev/null +++ b/lib/modules/manager/droneci/__fixtures__/.drone2.yml @@ -0,0 +1,8 @@ +kind: pipeline +name: Test + +steps: + - name: mix + image: quay.io/elixir:1.8.1-alpine + environment: + DB_HOST: mysql diff --git a/lib/modules/manager/droneci/extract.spec.ts b/lib/modules/manager/droneci/extract.spec.ts index 97e902236c4e2040d01ef68278e32ed95e3fc75a..f2dc05ea53ad584a42470b8126796548500e71d1 100644 --- a/lib/modules/manager/droneci/extract.spec.ts +++ b/lib/modules/manager/droneci/extract.spec.ts @@ -2,16 +2,85 @@ import { Fixtures } from '../../../../test/fixtures'; import { extractPackageFile } from '.'; +const droneciRegistryAlias = Fixtures.get('.drone2.yml'); + describe('modules/manager/droneci/extract', () => { describe('extractPackageFile()', () => { it('returns null for empty', () => { - expect(extractPackageFile('nothing here')).toBeNull(); + expect(extractPackageFile('nothing here', '', {})).toBeNull(); }); it('extracts multiple image lines', () => { - const res = extractPackageFile(Fixtures.get('.drone.yml')); + const res = extractPackageFile(Fixtures.get('.drone.yml'), '', {}); expect(res?.deps).toMatchSnapshot(); expect(res?.deps).toHaveLength(6); }); }); + + it('extracts image and replaces registry', () => { + const res = extractPackageFile(droneciRegistryAlias, '', { + registryAliases: { + 'quay.io': 'my-quay-mirror.registry.com', + }, + }); + expect(res).toEqual({ + deps: [ + { + autoReplaceStringTemplate: + 'quay.io/elixir:{{#if newValue}}{{newValue}}{{/if}}{{#if newDigest}}@{{newDigest}}{{/if}}', + currentDigest: undefined, + currentValue: '1.8.1-alpine', + datasource: 'docker', + depName: 'my-quay-mirror.registry.com/elixir', + replaceString: 'quay.io/elixir:1.8.1-alpine', + depType: 'docker', + }, + ], + }); + }); + + it('extracts image but no replacement', () => { + const res = extractPackageFile(droneciRegistryAlias, '', { + registryAliases: { + 'index.docker.io': 'my-docker-mirror.registry.com', + }, + }); + expect(res).toEqual({ + deps: [ + { + autoReplaceStringTemplate: + '{{depName}}{{#if newValue}}:{{newValue}}{{/if}}{{#if newDigest}}@{{newDigest}}{{/if}}', + currentDigest: undefined, + currentValue: '1.8.1-alpine', + datasource: 'docker', + depName: 'quay.io/elixir', + replaceString: 'quay.io/elixir:1.8.1-alpine', + depType: 'docker', + }, + ], + }); + }); + + it('extracts image and no double replacement', () => { + const res = extractPackageFile(droneciRegistryAlias, '', { + registryAliases: { + 'quay.io': 'my-quay-mirror.registry.com', + 'my-quay-mirror.registry.com': 'quay.io', + }, + }); + expect(res).toEqual({ + deps: [ + { + autoReplaceStringTemplate: + 'quay.io/elixir:{{#if newValue}}{{newValue}}{{/if}}{{#if newDigest}}@{{newDigest}}{{/if}}', + currentDigest: undefined, + currentValue: '1.8.1-alpine', + datasource: 'docker', + depName: 'my-quay-mirror.registry.com/elixir', + replaceString: 'quay.io/elixir:1.8.1-alpine', + depType: 'docker', + }, + ], + }); + }); }); diff --git a/lib/modules/manager/droneci/extract.ts b/lib/modules/manager/droneci/extract.ts index c0fdcfa1ab858b81d05c3bf4c4ae9f74777c9a46..1b4fde40d811be4841bf1eb1fcd1a9d7e52820a3 100644 --- a/lib/modules/manager/droneci/extract.ts +++ b/lib/modules/manager/droneci/extract.ts @@ -1,9 +1,13 @@ import { logger } from '../../../logger'; import { newlineRegex, regEx } from '../../../util/regex'; import { getDep } from '../dockerfile/extract'; -import type { PackageDependency, PackageFile } from '../types'; +import type { ExtractConfig, PackageDependency, PackageFile } from '../types'; -export function extractPackageFile(content: string): PackageFile | null { +export function extractPackageFile( + content: string, + _filename: string, + config: ExtractConfig +): PackageFile | null { const deps: PackageDependency[] = []; try { const lines = content.split(newlineRegex); @@ -34,7 +38,7 @@ export function extractPackageFile(content: string): PackageFile | null { currentFrom += finalLineMatch.groups.currentFrom; replaceString += '\n' + finalLineMatch.groups.replaceString; - const dep = getDep(currentFrom); + const dep = getDep(currentFrom, true, config.registryAliases); dep.depType = 'docker'; dep.replaceString = replaceString; if (dep.autoReplaceStringTemplate) { @@ -54,7 +58,11 @@ export function extractPackageFile(content: string): PackageFile | null { /^\s* image:\s*'?"?(?<currentFrom>[^\s'"]+)'?"?\s*$/ ).exec(line); if (match?.groups) { - const dep = getDep(match.groups.currentFrom); + const dep = getDep( + match.groups.currentFrom, + true, + config.registryAliases + ); dep.depType = 'docker'; deps.push(dep); } diff --git a/lib/modules/manager/kubernetes/__fixtures__/kubernetes.registry-alias.yaml b/lib/modules/manager/kubernetes/__fixtures__/kubernetes.registry-alias.yaml new file mode 100644 index 0000000000000000000000000000000000000000..7ab092bffe6ee2f3154732dfec5ed639ae1bc760 --- /dev/null +++ b/lib/modules/manager/kubernetes/__fixtures__/kubernetes.registry-alias.yaml @@ -0,0 +1,12 @@ +apiVersion: v1 +kind: Pod +metadata: + name: node-pod + labels: + app: node +spec: + containers: + - name: node + image: quay.io/node:0.0.1 + ports: + - containerPort: 80 diff --git a/lib/modules/manager/kubernetes/extract.spec.ts b/lib/modules/manager/kubernetes/extract.spec.ts index 678031fd0b83feb3360e69867c003851959f0716..897e8dab55ab1154a977386e40525d40b63f1948 100644 --- a/lib/modules/manager/kubernetes/extract.spec.ts +++ b/lib/modules/manager/kubernetes/extract.spec.ts @@ -4,16 +4,17 @@ import { extractPackageFile } from '.'; const kubernetesImagesFile = Fixtures.get('kubernetes.yaml'); const kubernetesConfigMapFile = Fixtures.get('configmap.yaml'); const kubernetesArraySyntaxFile = Fixtures.get('array-syntax.yaml'); +const kubernetesRegistryAlias = Fixtures.get('kubernetes.registry-alias.yaml'); const otherYamlFile = Fixtures.get('gitlab-ci.yaml'); describe('modules/manager/kubernetes/extract', () => { describe('extractPackageFile()', () => { it('returns null for empty', () => { - expect(extractPackageFile('', 'file.yaml')).toBeNull(); + expect(extractPackageFile('', 'file.yaml', {})).toBeNull(); }); it('returns only API version', () => { - const res = extractPackageFile(kubernetesConfigMapFile, 'file.yaml'); + const res = extractPackageFile(kubernetesConfigMapFile, 'file.yaml', {}); expect(res?.deps).toStrictEqual([ { currentValue: 'v1', @@ -23,7 +24,7 @@ describe('modules/manager/kubernetes/extract', () => { }); it('extracts multiple Kubernetes configurations', () => { - const res = extractPackageFile(kubernetesImagesFile, 'file.yaml'); + const res = extractPackageFile(kubernetesImagesFile, 'file.yaml', {}); expect(res?.deps).toStrictEqual([ { autoReplaceStringTemplate: @@ -55,7 +56,11 @@ describe('modules/manager/kubernetes/extract', () => { }); it('extracts image line in a YAML array', () => { - const res = extractPackageFile(kubernetesArraySyntaxFile, 'file.yaml'); + const res = extractPackageFile( + kubernetesArraySyntaxFile, + 'file.yaml', + {} + ); expect(res?.deps).toStrictEqual([ { autoReplaceStringTemplate: @@ -75,7 +80,7 @@ describe('modules/manager/kubernetes/extract', () => { }); it('ignores non-Kubernetes YAML files', () => { - expect(extractPackageFile(otherYamlFile, 'file.yaml')).toBeNull(); + expect(extractPackageFile(otherYamlFile, 'file.yaml', {})).toBeNull(); }); it('handles invalid YAML files', () => { @@ -83,7 +88,71 @@ describe('modules/manager/kubernetes/extract', () => { kind: ConfigMap < `; - expect(extractPackageFile(invalidYaml, 'file.yaml')).toBeNull(); + expect(extractPackageFile(invalidYaml, 'file.yaml', {})).toBeNull(); + }); + + it('extracts images and replaces registries', () => { + const res = extractPackageFile(kubernetesRegistryAlias, 'file.yaml', { + registryAliases: { + 'quay.io': 'my-quay-mirror.registry.com', + }, + }); + expect(res).toEqual({ + deps: [ + { + autoReplaceStringTemplate: + 'quay.io/node:{{#if newValue}}{{newValue}}{{/if}}{{#if newDigest}}@{{newDigest}}{{/if}}', + currentDigest: undefined, + currentValue: '0.0.1', + datasource: 'docker', + depName: 'my-quay-mirror.registry.com/node', + replaceString: 'quay.io/node:0.0.1', + }, + ], + }); + }); + + it('extracts images but does no replacement', () => { + const res = extractPackageFile(kubernetesRegistryAlias, 'file.yaml', { + registryAliases: { + 'index.docker.io': 'my-docker-mirror.registry.com', + }, + }); + expect(res).toEqual({ + deps: [ + { + autoReplaceStringTemplate: + '{{depName}}{{#if newValue}}:{{newValue}}{{/if}}{{#if newDigest}}@{{newDigest}}{{/if}}', + currentDigest: undefined, + currentValue: '0.0.1', + datasource: 'docker', + depName: 'quay.io/node', + replaceString: 'quay.io/node:0.0.1', + }, + ], + }); + }); + + it('extracts images and does no double replacements', () => { + const res = extractPackageFile(kubernetesRegistryAlias, 'file.yaml', { + registryAliases: { + 'quay.io': 'my-quay-mirror.registry.com', + 'my-quay-mirror.registry.com': 'quay.io', + }, + }); + expect(res).toEqual({ + deps: [ + { + autoReplaceStringTemplate: + 'quay.io/node:{{#if newValue}}{{newValue}}{{/if}}{{#if newDigest}}@{{newDigest}}{{/if}}', + currentDigest: undefined, + currentValue: '0.0.1', + datasource: 'docker', + depName: 'my-quay-mirror.registry.com/node', + replaceString: 'quay.io/node:0.0.1', + }, + ], + }); }); }); }); diff --git a/lib/modules/manager/kubernetes/extract.ts b/lib/modules/manager/kubernetes/extract.ts index c16c42141c52f25c596a0e146aa3bcfb937194bb..4c98462e26253fdbb8ef9232ac1bda49cb0317b3 100644 --- a/lib/modules/manager/kubernetes/extract.ts +++ b/lib/modules/manager/kubernetes/extract.ts @@ -3,12 +3,13 @@ import { loadAll } from 'js-yaml'; import { logger } from '../../../logger'; import { newlineRegex, regEx } from '../../../util/regex'; import { getDep } from '../dockerfile/extract'; -import type { PackageDependency, PackageFile } from '../types'; +import type { ExtractConfig, PackageDependency, PackageFile } from '../types'; import type { KubernetesConfiguration } from './types'; export function extractPackageFile( content: string, - fileName: string + fileName: string, + config: ExtractConfig ): PackageFile | null { logger.trace('kubernetes.extractPackageFile()'); @@ -20,21 +21,24 @@ export function extractPackageFile( } const deps: PackageDependency[] = [ - ...extractImages(content), + ...extractImages(content, config), ...extractApis(content, fileName), ]; return deps.length ? { deps } : null; } -function extractImages(content: string): PackageDependency[] { +function extractImages( + content: string, + config: ExtractConfig +): PackageDependency[] { const deps: PackageDependency[] = []; for (const line of content.split(newlineRegex)) { const match = regEx(/^\s*-?\s*image:\s*'?"?([^\s'"]+)'?"?\s*$/).exec(line); if (match) { const currentFrom = match[1]; - const dep = getDep(currentFrom); + const dep = getDep(currentFrom, true, config.registryAliases); logger.debug( { depName: dep.depName,