diff --git a/docs/usage/configuration-options.md b/docs/usage/configuration-options.md index de9f0a94591a75c593faadadb6cddcbd72219e3d..689a999d3efcf40f36f0bfc3931a3707f8ddf569 100644 --- a/docs/usage/configuration-options.md +++ b/docs/usage/configuration-options.md @@ -483,6 +483,19 @@ Note: you shouldn't usually need to configure this unless you really care about Renovate supports updating Helm Chart references within `requirements.yaml` files. If your Helm charts make use of Aliases then you will need to configure an `aliases` object in your config to tell Renovate where to look for them. +## helm-values + +Renovate supports updating of Docker dependencies within Helm Chart `values.yaml` files or other YAML +files that use the same format (via `fileMatch` configuration). Updates are performed if the files +follow the conventional format used in most of the `stable` Helm charts: + +```yaml +image: + repository: 'some-docker/dependency' + tag: v1.0.0 + registry: registry.example.com # optional key, will default to "docker.io" +``` + ## helmfile ## homebrew diff --git a/lib/config/definitions.ts b/lib/config/definitions.ts index b46650e7fe58b25c00d528588d70e5f51cb75034..9f2622cb13c59a3ff501123cc78849a9a7fd5b8a 100644 --- a/lib/config/definitions.ts +++ b/lib/config/definitions.ts @@ -1753,6 +1753,18 @@ const options: RenovateOptions[] = [ mergeable: true, cli: false, }, + { + name: 'helm-values', + description: 'Configuration object for helm values.yaml files.', + stage: 'package', + type: 'object', + default: { + commitMessageTopic: 'helm values {{depName}}', + fileMatch: ['(^|/)values.yaml$'], + }, + mergeable: true, + cli: false, + }, { name: 'helmfile', description: 'Configuration object for helmfile helmfile.yaml files.', diff --git a/lib/manager/common.ts b/lib/manager/common.ts index 2a18a1a927aa24b6585d9223ee2bd88be885c4c4..7733e47fdb556a1b4e7b68af6149a1d08f4361ad 100644 --- a/lib/manager/common.ts +++ b/lib/manager/common.ts @@ -148,6 +148,7 @@ export interface Upgrade<T = Record<string, any>> checksumUrl?: string; currentVersion?: string; depGroup?: string; + dockerRepository?: string; downloadUrl?: string; localDir?: string; name?: string; diff --git a/lib/manager/helm-values/extract.ts b/lib/manager/helm-values/extract.ts new file mode 100644 index 0000000000000000000000000000000000000000..84bd266d4f69dd7887a1b96c952ef875f6164fcf --- /dev/null +++ b/lib/manager/helm-values/extract.ts @@ -0,0 +1,60 @@ +import yaml from 'js-yaml'; +import { logger } from '../../logger'; +import { getDep } from '../dockerfile/extract'; + +import { PackageFile, PackageDependency } from '../common'; +import { + matchesHelmValuesDockerHeuristic, + HelmDockerImageDependency, +} from './util'; + +/** + * Recursively find all supported dependencies in the yaml object. + * + * @param parsedContent + */ +function findDependencies( + parsedContent: object | HelmDockerImageDependency, + packageDependencies: Array<PackageDependency> +): Array<PackageDependency> { + if (!parsedContent || typeof parsedContent !== 'object') { + return packageDependencies; + } + + Object.keys(parsedContent).forEach(key => { + if (matchesHelmValuesDockerHeuristic(key, parsedContent[key])) { + const currentItem = parsedContent[key]; + + const registry = currentItem.registry ? `${currentItem.registry}/` : ''; + packageDependencies.push( + getDep(`${registry}${currentItem.repository}:${currentItem.tag}`) + ); + } else { + findDependencies(parsedContent[key], packageDependencies); + } + }); + return packageDependencies; +} + +export function extractPackageFile(content: string): PackageFile { + try { + // a parser that allows extracting line numbers would be preferable, with + // the current approach we need to match anything we find again during the update + const parsedContent = yaml.safeLoad(content); + + logger.debug( + { parsedContent }, + 'Trying to find dependencies in helm-values' + ); + const deps = findDependencies(parsedContent, []); + + if (deps.length) { + logger.debug({ deps }, 'Found dependencies in helm-values'); + return { deps }; + } + } catch (err) { + logger.error({ err }, 'Failed to parse helm-values file'); + } + + return null; +} diff --git a/lib/manager/helm-values/index.ts b/lib/manager/helm-values/index.ts new file mode 100644 index 0000000000000000000000000000000000000000..730b5b60ba42a35b24b351e0793557e86f185454 --- /dev/null +++ b/lib/manager/helm-values/index.ts @@ -0,0 +1,2 @@ +export { extractPackageFile } from './extract'; +export { updateDependency } from './update'; diff --git a/lib/manager/helm-values/update.ts b/lib/manager/helm-values/update.ts new file mode 100644 index 0000000000000000000000000000000000000000..324253136fd76cb77c02485deb285f0d0aba1871 --- /dev/null +++ b/lib/manager/helm-values/update.ts @@ -0,0 +1,122 @@ +import YAWN from 'yawn-yaml/cjs'; +import { logger } from '../../logger'; +import { Upgrade } from '../common'; +import { + matchesHelmValuesDockerHeuristic, + HelmDockerImageDependency, +} from './util'; + +function shouldUpdate( + parentKey: string, + data: unknown | HelmDockerImageDependency, + dockerRepository: string, + currentValue: string, + originalRegistryValue: string +): boolean { + return ( + matchesHelmValuesDockerHeuristic(parentKey, data) && + data.repository === dockerRepository && + data.tag === currentValue && + ((!data.registry && !originalRegistryValue) || + data.registry === originalRegistryValue) + ); +} + +/** + * Extract the originally set registry value if it is included in the depName. + */ +function getOriginalRegistryValue( + depName: string, + dockerRepository: string +): string { + if (depName.length > dockerRepository.length) { + return depName.substring(0, depName.lastIndexOf(dockerRepository) - 1); + } + return ''; +} + +/** + * Recursive function that walks the yaml strucuture + * and updates the first match of an 'image' key it finds, + * if it adheres to the supported structure. + * + * @param parsedContent The part of the yaml tree we should look at. + * @param dockerRepository The docker repository that should be updated. + * @param currentValue The current version that should be updated. + * @param newValue The update version that should be set instead of currentValue. + * @returns True if the parsedContent was updated, false otherwise. + */ +function updateDoc( + parsedContent: object | HelmDockerImageDependency, + dockerRepository: string, + currentValue: string, + newValue: string, + originalRegistryValue: string +): boolean { + for (const key of Object.keys(parsedContent)) { + if ( + shouldUpdate( + key, + parsedContent[key], + dockerRepository, + currentValue, + originalRegistryValue + ) + ) { + // the next statement intentionally updates the passed in parameter + // with the updated dependency value + // eslint-disable-next-line no-param-reassign + parsedContent[key].tag = newValue; + + return true; + } + + if (typeof parsedContent[key] === 'object') { + const foundMatch = updateDoc( + parsedContent[key], + dockerRepository, + currentValue, + newValue, + originalRegistryValue + ); + if (foundMatch) { + return true; + } + } + } + return false; +} + +export function updateDependency( + fileContent: string, + upgrade: Upgrade +): string | null { + if ( + !upgrade || + !upgrade.depName || + !upgrade.newValue || + !upgrade.currentValue || + !upgrade.dockerRepository + ) { + logger.debug('Failed to update dependency, invalid upgrade'); + return fileContent; + } + + const yawn = new YAWN(fileContent); + const doc = yawn.json; + + const originalRegistryValue = getOriginalRegistryValue( + upgrade.depName, + upgrade.dockerRepository + ); + updateDoc( + doc, + upgrade.dockerRepository, + upgrade.currentValue, + upgrade.newValue, + originalRegistryValue + ); + yawn.json = doc; + + return yawn.yaml; +} diff --git a/lib/manager/helm-values/util.ts b/lib/manager/helm-values/util.ts new file mode 100644 index 0000000000000000000000000000000000000000..abbebbaa24a6533f392379b6480858e1c8b3884f --- /dev/null +++ b/lib/manager/helm-values/util.ts @@ -0,0 +1,41 @@ +export type HelmDockerImageDependency = { + registry?: string; + repository: string; + tag: string; +}; + +/** + * This is a workaround helper to allow the usage of 'unknown' in + * a type-guard function while checking that keys exist. + * + * @see https://github.com/microsoft/TypeScript/issues/21732 + * @see https://stackoverflow.com/a/58630274 + */ +function hasKey<K extends string>(k: K, o: {}): o is { [_ in K]: {} } { + return typeof o === 'object' && k in o; +} + +/** + * Type guard to determine whether a given partial Helm values.yaml object potentially + * defines a Helm Docker dependency. + * + * There is no exact standard of how Docker dependencies are defined in Helm + * values.yaml files (as of January 1st 2020), this function defines a + * heuristic based on the most commonly used format in the stable Helm charts: + * + * image: + * repository: 'something' + * tag: v1.0.0 + */ +export function matchesHelmValuesDockerHeuristic( + parentKey: string, + data: unknown +): data is HelmDockerImageDependency { + return ( + parentKey === 'image' && + data && + typeof data === 'object' && + hasKey('repository', data) && + hasKey('tag', data) + ); +} diff --git a/renovate-schema.json b/renovate-schema.json index 1bb82903a1ea7476b7a17da093e772d1d61d31f0..b3f795b5a91693835f5f122b37cbeaf22b3e8630 100644 --- a/renovate-schema.json +++ b/renovate-schema.json @@ -1165,6 +1165,15 @@ }, "$ref": "#" }, + "helm-values": { + "description": "Configuration object for helm values.yaml files.", + "type": "object", + "default": { + "commitMessageTopic": "helm values {{depName}}", + "fileMatch": ["(^|/)values.yaml$"] + }, + "$ref": "#" + }, "helmfile": { "description": "Configuration object for helmfile helmfile.yaml files.", "type": "object", diff --git a/test/manager/helm-requirements/__snapshots__/extract.spec.ts.snap b/test/manager/helm-requirements/__snapshots__/extract.spec.ts.snap index 07b0173fb45f58cb2999c5c9858e809e9f36feeb..d0924ea3f875596cb5e007bcf9a169c36c520a6c 100644 --- a/test/manager/helm-requirements/__snapshots__/extract.spec.ts.snap +++ b/test/manager/helm-requirements/__snapshots__/extract.spec.ts.snap @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`lib/manager/helm/extract extractPackageFile() parses simple requirements.yaml correctly 1`] = ` +exports[`lib/manager/helm-requirements/extract extractPackageFile() parses simple requirements.yaml correctly 1`] = ` Object { "datasource": "helm", "deps": Array [ @@ -22,7 +22,7 @@ Object { } `; -exports[`lib/manager/helm/extract extractPackageFile() resolves aliased registry urls 1`] = ` +exports[`lib/manager/helm-requirements/extract extractPackageFile() resolves aliased registry urls 1`] = ` Object { "datasource": "helm", "deps": Array [ @@ -37,7 +37,7 @@ Object { } `; -exports[`lib/manager/helm/extract extractPackageFile() skips invalid registry urls 1`] = ` +exports[`lib/manager/helm-requirements/extract extractPackageFile() skips invalid registry urls 1`] = ` Object { "datasource": "helm", "deps": Array [ @@ -66,7 +66,7 @@ Object { } `; -exports[`lib/manager/helm/extract extractPackageFile() skips local dependencies 1`] = ` +exports[`lib/manager/helm-requirements/extract extractPackageFile() skips local dependencies 1`] = ` Object { "datasource": "helm", "deps": Array [ diff --git a/test/manager/helm-requirements/__snapshots__/update.spec.ts.snap b/test/manager/helm-requirements/__snapshots__/update.spec.ts.snap index dd97ba5f416e80b7317bf4ed46d463676b33b55f..77cbbdef6e445a6c7bd9c0b9c046eb7090a86535 100644 --- a/test/manager/helm-requirements/__snapshots__/update.spec.ts.snap +++ b/test/manager/helm-requirements/__snapshots__/update.spec.ts.snap @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`lib/manager/helm/extract updateDependency() upgrades dependency if newValue version value is repeated 1`] = ` +exports[`lib/manager/helm-requirements/update updateDependency() upgrades dependency if newValue version value is repeated 1`] = ` " dependencies: - version: 0.9.0 @@ -12,7 +12,7 @@ exports[`lib/manager/helm/extract updateDependency() upgrades dependency if newV " `; -exports[`lib/manager/helm/extract updateDependency() upgrades dependency if valid upgrade 1`] = ` +exports[`lib/manager/helm-requirements/update updateDependency() upgrades dependency if valid upgrade 1`] = ` " dependencies: - name: redis @@ -24,7 +24,7 @@ exports[`lib/manager/helm/extract updateDependency() upgrades dependency if vali " `; -exports[`lib/manager/helm/extract updateDependency() upgrades dependency if version field comes before name field 1`] = ` +exports[`lib/manager/helm-requirements/update updateDependency() upgrades dependency if version field comes before name field 1`] = ` " dependencies: - version: 0.11.0 diff --git a/test/manager/helm-requirements/extract.spec.ts b/test/manager/helm-requirements/extract.spec.ts index df1ec9f0e9e88bfd68020d218574ce09887b6c1d..4de42579ae282d5edd46502ef44a60d3c9d92530 100644 --- a/test/manager/helm-requirements/extract.spec.ts +++ b/test/manager/helm-requirements/extract.spec.ts @@ -3,7 +3,7 @@ import { platform as _platform } from '../../../lib/platform'; const platform: any = _platform; -describe('lib/manager/helm/extract', () => { +describe('lib/manager/helm-requirements/extract', () => { describe('extractPackageFile()', () => { beforeEach(() => { jest.resetAllMocks(); diff --git a/test/manager/helm-requirements/update.spec.ts b/test/manager/helm-requirements/update.spec.ts index 81c8139f4295cc0cfc3548a5e25d49cd42cf3d4b..86d27adda77d0b2cc85b7d5041b6873ee07c9208 100644 --- a/test/manager/helm-requirements/update.spec.ts +++ b/test/manager/helm-requirements/update.spec.ts @@ -1,6 +1,6 @@ import { updateDependency } from '../../../lib/manager/helm-requirements/update'; -describe('lib/manager/helm/extract', () => { +describe('lib/manager/helm-requirements/update', () => { describe('updateDependency()', () => { it('returns the same fileContent for undefined upgrade', () => { const content = ` diff --git a/test/manager/helm-values/__snapshots__/extract.spec.ts.snap b/test/manager/helm-values/__snapshots__/extract.spec.ts.snap new file mode 100644 index 0000000000000000000000000000000000000000..639a6cd8a38bfad7663a019c99b9558697d1c0c0 --- /dev/null +++ b/test/manager/helm-values/__snapshots__/extract.spec.ts.snap @@ -0,0 +1,39 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`lib/manager/helm-values/extract extractPackageFile() extracts from complex values file correctly" 1`] = ` +Object { + "deps": Array [ + Object { + "currentDigest": undefined, + "currentValue": "11.6.0-debian-9-r0", + "datasource": "docker", + "depName": "bitnami/postgresql", + }, + Object { + "currentDigest": undefined, + "currentValue": "0.7.0-debian-9-r12", + "datasource": "docker", + "depName": "docker.io/bitnami/postgres-exporter", + }, + Object { + "currentDigest": undefined, + "currentValue": "11.5.0-debian-9-r0", + "datasource": "docker", + "depName": "docker.io/bitnami/postgresql", + }, + ], +} +`; + +exports[`lib/manager/helm-values/extract extractPackageFile() extracts from values.yaml correctly with same structure as "helm create" 1`] = ` +Object { + "deps": Array [ + Object { + "currentDigest": undefined, + "currentValue": "1.16.1", + "datasource": "docker", + "depName": "nginx", + }, + ], +} +`; diff --git a/test/manager/helm-values/__snapshots__/update.spec.ts.snap b/test/manager/helm-values/__snapshots__/update.spec.ts.snap new file mode 100644 index 0000000000000000000000000000000000000000..f142d094d42a2f4bf8619d7436960e05a41cdc79 --- /dev/null +++ b/test/manager/helm-values/__snapshots__/update.spec.ts.snap @@ -0,0 +1,44 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`lib/manager/helm-values/update updateDependency() upgrades correct dependency if registry included 1`] = ` +" + db: + image: + image: + repository: bitnami/postgresql + tag: 11.6.0-debian-9-r0 + some-non-image-related-key: 'with-some-value' + warehouse: + image: + registry: docker.io + repository: bitnami/postgresql + tag: 12.5.0 + some-non-image-related-key: 'with-some-value' +" +`; + +exports[`lib/manager/helm-values/update updateDependency() upgrades dependency if newValue version value is repeated 1`] = ` +" + db: + image: + image: + registry: docker.io + repository: bitnami/postgresql + tag: 12.5.0 + some-non-image-related-key: 'with-some-value' + warehouse: + image: + registry: docker.io + repository: bitnami/postgresql + tag: 11.6.0-debian-9-r0 + some-non-image-related-key: 'with-some-value' +" +`; + +exports[`lib/manager/helm-values/update updateDependency() upgrades dependency if valid upgrade 1`] = ` +" + image: + repository: bitnami/postgres-exporter + tag: 0.8.0 +" +`; diff --git a/test/manager/helm-values/_fixtures/default_chart_init_values.yaml b/test/manager/helm-values/_fixtures/default_chart_init_values.yaml new file mode 100644 index 0000000000000000000000000000000000000000..ea8ebe72dc7b7f676f050038353b0631b502bca0 --- /dev/null +++ b/test/manager/helm-values/_fixtures/default_chart_init_values.yaml @@ -0,0 +1,68 @@ +# Default values for test-chart. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +replicaCount: 1 + +image: + repository: nginx + tag: 1.16.1 + pullPolicy: IfNotPresent + +imagePullSecrets: [] +nameOverride: "" +fullnameOverride: "" + +serviceAccount: + # Specifies whether a service account should be created + create: true + # The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template + name: + +podSecurityContext: {} + # fsGroup: 2000 + +securityContext: {} + # capabilities: + # drop: + # - ALL + # readOnlyRootFilesystem: true + # runAsNonRoot: true + # runAsUser: 1000 + +service: + type: ClusterIP + port: 80 + +ingress: + enabled: false + annotations: {} + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: "true" + hosts: + - host: chart-example.local + paths: [] + + tls: [] + # - secretName: chart-example-tls + # hosts: + # - chart-example.local + +resources: {} + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + # limits: + # cpu: 100m + # memory: 128Mi + # requests: + # cpu: 100m + # memory: 128Mi + +nodeSelector: {} + +tolerations: [] + +affinity: {} diff --git a/test/manager/helm-values/_fixtures/multi_and_nested_image_values.yaml b/test/manager/helm-values/_fixtures/multi_and_nested_image_values.yaml new file mode 100644 index 0000000000000000000000000000000000000000..ca3582c5b3656afcf0659e0dea7e66237cd67bb0 --- /dev/null +++ b/test/manager/helm-values/_fixtures/multi_and_nested_image_values.yaml @@ -0,0 +1,21 @@ +--- +api: + image: + image: + repository: bitnami/postgresql + tag: 11.6.0-debian-9-r0 + some-non-image-related-key: 'with-some-value' + # https://github.com/helm/charts/blob/c5838636973a5546196db6e48ae46f99a55900c4/stable/postgresql/values.yaml#L426 + metrics: + image: + registry: docker.io + repository: bitnami/postgres-exporter + tag: 0.7.0-debian-9-r12 + pullPolicy: IfNotPresent + +someOtherKey: + - image: + registry: docker.io + repository: bitnami/postgresql + tag: 11.5.0-debian-9-r0 + some-non-image-related-key: 'with-some-value' diff --git a/test/manager/helm-values/extract.spec.ts b/test/manager/helm-values/extract.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..22a56e767e0bef2718d56fcc201cf2a6c51fdaf6 --- /dev/null +++ b/test/manager/helm-values/extract.spec.ts @@ -0,0 +1,41 @@ +import { readFileSync } from 'fs'; + +import { extractPackageFile } from '../../../lib/manager/helm-values/extract'; + +const helmDefaultChartInitValues = readFileSync( + 'test/manager/helm-values/_fixtures/default_chart_init_values.yaml', + 'utf8' +); + +const helmMultiAndNestedImageValues = readFileSync( + 'test/manager/helm-values/_fixtures/multi_and_nested_image_values.yaml', + 'utf8' +); + +describe('lib/manager/helm-values/extract', () => { + describe('extractPackageFile()', () => { + beforeEach(() => { + jest.resetAllMocks(); + }); + it('returns null for invalid yaml file content', () => { + const result = extractPackageFile('nothing here: ['); + expect(result).toBeNull(); + }); + it('returns null for empty yaml file content', () => { + const result = extractPackageFile(''); + expect(result).toBeNull(); + }); + it('returns null for no file content', () => { + const result = extractPackageFile(null); + expect(result).toBeNull(); + }); + it('extracts from values.yaml correctly with same structure as "helm create"', () => { + const result = extractPackageFile(helmDefaultChartInitValues); + expect(result).toMatchSnapshot(); + }); + it('extracts from complex values file correctly"', () => { + const result = extractPackageFile(helmMultiAndNestedImageValues); + expect(result).toMatchSnapshot(); + }); + }); +}); diff --git a/test/manager/helm-values/update.spec.ts b/test/manager/helm-values/update.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..dfba5419234fe9f272155cfd03c76dc7ace61273 --- /dev/null +++ b/test/manager/helm-values/update.spec.ts @@ -0,0 +1,100 @@ +import { updateDependency } from '../../../lib/manager/helm-values/update'; + +describe('lib/manager/helm-values/update', () => { + describe('updateDependency()', () => { + it('returns the same fileContent for undefined upgrade', () => { + const content = 'someKey: "someValue"'; + const upgrade = undefined; + + expect(updateDependency(content, upgrade)).toBe(content); + }); + it('returns the same fileContent for invalid values.yaml file', () => { + const content = ` + Invalid values.yaml content. + `; + const upgrade = { + depName: 'bitnami/postgres-exporter', + currentValue: '0.7.0-debian-9-r12', + datasource: 'docker', + newValue: '0.8.0', + dockerRepository: 'bitnami/postgres-exporter', + }; + expect(updateDependency(content, upgrade)).toBe(content); + }); + it('returns the same fileContent for empty upgrade', () => { + const content = 'someKey: "someValue"'; + const upgrade = {}; + expect(updateDependency(content, upgrade)).toBe(content); + }); + it('returns the same fileContent for null content', () => { + const content = null; + const upgrade = {}; + expect(updateDependency(content, upgrade)).toBe(content); + }); + it('upgrades dependency if valid upgrade', () => { + const content = ` + image: + repository: bitnami/postgres-exporter + tag: 0.7.0-debian-9-r12 + `; + const upgrade = { + depName: 'bitnami/postgres-exporter', + currentValue: '0.7.0-debian-9-r12', + newValue: '0.8.0', + dockerRepository: 'bitnami/postgres-exporter', + }; + expect(updateDependency(content, upgrade)).not.toBe(content); + expect(updateDependency(content, upgrade)).toMatchSnapshot(); + }); + it('upgrades dependency if newValue version value is repeated', () => { + const content = ` + db: + image: + image: + registry: docker.io + repository: bitnami/postgresql + tag: 11.6.0-debian-9-r0 + some-non-image-related-key: 'with-some-value' + warehouse: + image: + registry: docker.io + repository: bitnami/postgresql + tag: 11.6.0-debian-9-r0 + some-non-image-related-key: 'with-some-value' + `; + const upgrade = { + depName: 'docker.io/bitnami/postgresql', + currentValue: '11.6.0-debian-9-r0', + newValue: '12.5.0', + dockerRepository: 'bitnami/postgresql', + }; + expect(updateDependency(content, upgrade)).not.toBe(content); + expect(updateDependency(content, upgrade)).toMatchSnapshot(); + }); + it('upgrades correct dependency if registry included', () => { + const content = ` + db: + image: + image: + repository: bitnami/postgresql + tag: 11.6.0-debian-9-r0 + some-non-image-related-key: 'with-some-value' + warehouse: + image: + registry: docker.io + repository: bitnami/postgresql + tag: 11.6.0-debian-9-r0 + some-non-image-related-key: 'with-some-value' + `; + const upgrade = { + depName: 'docker.io/bitnami/postgresql', + currentValue: '11.6.0-debian-9-r0', + newValue: '12.5.0', + dockerRepository: 'bitnami/postgresql', + }; + + expect(updateDependency(content, upgrade)).not.toBe(content); + expect(updateDependency(content, upgrade)).toMatchSnapshot(); + }); + }); +});