diff --git a/lib/config/definitions.js b/lib/config/definitions.js index 23434682b9b61c182e387de7cb3dd0b3d0fa70e2..ea6e421b5eab9cd8221d50505dc966725ee77548 100644 --- a/lib/config/definitions.js +++ b/lib/config/definitions.js @@ -872,6 +872,16 @@ const options = [ mergeable: true, cli: false, }, + { + name: 'docker-compose', + description: + 'Configuration object for Docker Compose renovation. Also inherits settings from `docker` object.', + stage: 'repository', + type: 'json', + default: { + enabled: false, + }, + }, ]; function getOptions() { diff --git a/lib/manager/docker-compose/extract.js b/lib/manager/docker-compose/extract.js new file mode 100644 index 0000000000000000000000000000000000000000..acb47c0f5e55a8a187830bbe4c9fc970e28089cd --- /dev/null +++ b/lib/manager/docker-compose/extract.js @@ -0,0 +1,42 @@ +const { splitImageParts } = require('../docker/extract'); + +module.exports = { + extractDependencies, +}; + +function extractDependencies(content) { + logger.debug('docker-compose.extractDependencies()'); + const deps = []; + let lineNumber = 0; + for (const line of content.split('\n')) { + const match = line.match(/^\s*image:\s*([^\s]+)\s*$/); + if (match) { + const currentFrom = match[1]; + const { + dockerRegistry, + depName, + currentTag, + currentDigest, + currentDepTagDigest, + currentDepTag, + } = splitImageParts(currentFrom); + logger.info( + { dockerRegistry, depName, currentTag, currentDigest }, + 'Docker Compose image' + ); + deps.push({ + depType: 'Docker Compose', + lineNumber, + currentFrom, + currentDepTagDigest, + dockerRegistry, + currentDepTag, + currentDigest, + depName, + currentTag, + }); + } + lineNumber += 1; + } + return deps; +} diff --git a/lib/manager/docker-compose/index.js b/lib/manager/docker-compose/index.js new file mode 100644 index 0000000000000000000000000000000000000000..a87d498c2014a23daf1a9b6a1cb8364098f209ba --- /dev/null +++ b/lib/manager/docker-compose/index.js @@ -0,0 +1,16 @@ +const { extractDependencies } = require('./extract'); +const { getPackageUpdates } = require('../docker/package'); +const { resolvePackageFile } = require('./resolve'); +const { setNewValue } = require('./update'); + +const filePattern = new RegExp('(^|/)docker-compose[^/]*\\.ya?ml$'); +const contentPattern = new RegExp('(^|\\n)\\s*image:'); + +module.exports = { + contentPattern, + extractDependencies, + filePattern, + getPackageUpdates, + resolvePackageFile, + setNewValue, +}; diff --git a/lib/manager/docker-compose/resolve.js b/lib/manager/docker-compose/resolve.js new file mode 100644 index 0000000000000000000000000000000000000000..04d77824c1fd87dfd5f9e5e6bc36cbf2f184f360 --- /dev/null +++ b/lib/manager/docker-compose/resolve.js @@ -0,0 +1,22 @@ +const { mergeChildConfig } = require('../../config'); + +module.exports = { + resolvePackageFile, +}; + +async function resolvePackageFile(config, inputFile) { + const composeConfig = mergeChildConfig( + config.docker, + config['docker-compose'] + ); + const packageFile = mergeChildConfig(composeConfig, inputFile); + logger.debug( + `Resolving packageFile ${JSON.stringify(packageFile.packageFile)}` + ); + packageFile.content = await platform.getFile(packageFile.packageFile); + if (!packageFile.content) { + logger.debug('No packageFile content'); + return null; + } + return packageFile; +} diff --git a/lib/manager/docker-compose/update.js b/lib/manager/docker-compose/update.js new file mode 100644 index 0000000000000000000000000000000000000000..811dbee90df62d2dbc8064b78baeba17cd5867b3 --- /dev/null +++ b/lib/manager/docker-compose/update.js @@ -0,0 +1,26 @@ +module.exports = { + setNewValue, +}; + +function setNewValue(currentFileContent, upgrade) { + try { + logger.debug(`setNewValue: ${upgrade.newFrom}`); + const lines = currentFileContent.split('\n'); + const lineToChange = lines[upgrade.lineNumber]; + const imageLine = new RegExp(/^(\s*image:\s*)[^\s]+(\s*)$/); + if (!lineToChange.match(imageLine)) { + logger.debug('No image line found'); + return null; + } + const newLine = lineToChange.replace(imageLine, `$1${upgrade.newFrom}$2`); + if (newLine === lineToChange) { + logger.debug('No changes necessary'); + return currentFileContent; + } + lines[upgrade.lineNumber] = newLine; + return lines.join('\n'); + } catch (err) { + logger.info({ err }, 'Error setting new Dockerfile value'); + return null; + } +} diff --git a/lib/manager/docker/extract.js b/lib/manager/docker/extract.js index 5da249d5a2033cbd7ef65f13d92149d87d1a21f2..5ddc932c7a90fcde3ba971db478fa1c692a0e252 100644 --- a/lib/manager/docker/extract.js +++ b/lib/manager/docker/extract.js @@ -1,4 +1,5 @@ module.exports = { + splitImageParts, extractDependencies, }; @@ -12,6 +13,26 @@ function groupedRegex(string, pattern) { ); } +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 = []; @@ -30,15 +51,14 @@ function extractDependencies(content) { stageNames.push(fromRest[1]); } const fromSuffix = fromRest.join(' '); - 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(':'); + const { + dockerRegistry, + depName, + currentTag, + currentDigest, + currentDepTagDigest, + currentDepTag, + } = splitImageParts(currentFrom); logger.info({ depName, currentTag, currentDigest }, 'Dockerfile FROM'); if (currentFrom === 'scratch') { logger.debug('Skipping scratch'); diff --git a/lib/manager/index.js b/lib/manager/index.js index ec6e6b3db0ca0b2de5e02a2011a1c508bca0f1cb..d267a30881bed6fbfa3971da2aeaf34337985e82 100644 --- a/lib/manager/index.js +++ b/lib/manager/index.js @@ -3,7 +3,15 @@ const { mergeChildConfig } = require('../config'); const { checkMonorepos } = require('../manager/npm/monorepos'); const managers = {}; -const managerList = ['bazel', 'docker', 'meteor', 'npm', 'nvm', 'travis']; +const managerList = [ + 'bazel', + 'docker', + 'docker-compose', + 'meteor', + 'npm', + 'nvm', + 'travis', +]; for (const manager of managerList) { // eslint-disable-next-line global-require,import/no-dynamic-require managers[manager] = require(`./${manager}`); diff --git a/test/_fixtures/docker-compose/docker-compose.1.yml b/test/_fixtures/docker-compose/docker-compose.1.yml new file mode 100644 index 0000000000000000000000000000000000000000..c4622f4d8cef14b643b4c28255c680e680d84151 --- /dev/null +++ b/test/_fixtures/docker-compose/docker-compose.1.yml @@ -0,0 +1,92 @@ +version: "3" +services: + + redis: + image: quay.io/something/redis:alpine + ports: + - "6379" + networks: + - frontend + deploy: + replicas: 2 + update_config: + parallelism: 2 + delay: 10s + restart_policy: + condition: on-failure + + db: + image: postgres:9.4.0 + volumes: + - db-data:/var/lib/postgresql/data + networks: + - backend + deploy: + placement: + constraints: [node.role == manager] + + vote: + image: dockersamples/examplevotingapp_vote:before + ports: + - 5000:80 + networks: + - frontend + depends_on: + - redis + deploy: + replicas: 2 + update_config: + parallelism: 2 + restart_policy: + condition: on-failure + + result: + image: dockersamples/examplevotingapp_result:before + ports: + - 5001:80 + networks: + - backend + depends_on: + - db + deploy: + replicas: 1 + update_config: + parallelism: 2 + delay: 10s + restart_policy: + condition: on-failure + + worker: + image: dockersamples/examplevotingapp_worker + networks: + - frontend + - backend + deploy: + mode: replicated + replicas: 1 + labels: [APP=VOTING] + restart_policy: + condition: on-failure + delay: 10s + max_attempts: 3 + window: 120s + placement: + constraints: [node.role == manager] + + visualizer: + image: dockersamples/visualizer:stable + ports: + - "8080:8080" + stop_grace_period: 1m30s + volumes: + - "/var/run/docker.sock:/var/run/docker.sock" + deploy: + placement: + constraints: [node.role == manager] + +networks: + frontend: + backend: + +volumes: + db-data: diff --git a/test/manager/__snapshots__/resolve.spec.js.snap b/test/manager/__snapshots__/resolve.spec.js.snap index e7598cdcc7dfcc204ca54922cebcd93936372a7a..505450279d2aee91cf4f5b41c600d34d6b70ded6 100644 --- a/test/manager/__snapshots__/resolve.spec.js.snap +++ b/test/manager/__snapshots__/resolve.spec.js.snap @@ -43,239 +43,6 @@ Array [ ] `; -exports[`manager/resolve resolvePackageFiles() detects meteor and docker and travis and bazel and nvm 1`] = ` -Array [ - Object { - "content": "{}", - "enabled": true, - "manager": "meteor", - "packageFile": "package.js", - }, - Object { - "branchName": "{{{branchPrefix}}}docker-{{{depNameSanitized}}}-{{{newVersionMajor}}}.x", - "commitMessage": "Update {{{depName}}} to tag {{{newTag}}}", - "content": "# comment -FROM node:8 -", - "currentFrom": "node:8", - "digest": Object { - "branchName": "{{{branchPrefix}}}docker-{{{depNameSanitized}}}-{{{currentTag}}}", - "commitMessage": "Update {{{depName}}}:{{{currentTag}}} digest", - "prBody": "This Pull Request updates Docker base image \`{{{depName}}}:{{{currentTag}}}\` to the latest digest (\`{{{newDigest}}}\`). For details on Renovate's Docker support, please visit https://renovateapp.com/docs/language-support/docker - -{{#if schedule}} -**Note**: This PR was created on a configured schedule (\\"{{{schedule}}}\\"{{#if timezone}} in timezone \`{{{timezone}}}\`{{/if}}) and will not receive updates outside those times. -{{/if}} - -{{#if hasErrors}} - ---- - -# Errors - -Renovate encountered some errors when processing your repository, so you are being notified here even if they do not directly apply to this PR. - -{{#each errors as |error|}} -- \`{{error.depName}}\`: {{error.message}} -{{/each}} -{{/if}} - -{{#if hasWarnings}} - ---- - -# Warnings - -Please make sure the following warnings are safe to ignore: - -{{#each warnings as |warning|}} -- \`{{warning.depName}}\`: {{warning.message}} -{{/each}} -{{/if}}", - "prTitle": "Update Dockerfile {{{depName}}} image {{{currentTag}}} digest ({{{newDigestShort}}})", - }, - "enabled": true, - "group": Object { - "prBody": "This Pull Request updates Dockerfiles to use image digests. - -{{#if schedule}} -**Note**: This PR was created on a configured schedule (\\"{{{schedule}}}\\"{{#if timezone}} in timezone \`{{{timezone}}}\`{{/if}}) and will not receive updates outside those times. -{{/if}} - -{{#each upgrades as |upgrade|}} -- {{#if repositoryUrl}}[{{upgrade.depName}}]({{upgrade.repositoryUrl}}){{else}}\`{{{depName}}}\`{{/if}}: \`{{upgrade.newDigest}}\` -{{/each}} - -{{#if hasErrors}} - ---- - -# Errors - -Renovate encountered some errors when processing your repository, so you are being notified here even if they do not directly apply to this PR. - -{{#each errors as |error|}} -- \`{{error.depName}}\`: {{error.message}} -{{/each}} -{{/if}} - -{{#if hasWarnings}} - ---- - -# Warnings - -Please make sure the following warnings are safe to ignore: - -{{#each warnings as |warning|}} -- \`{{warning.depName}}\`: {{warning.message}} -{{/each}} -{{/if}}", - "prTitle": "Update Docker {{{groupName}}} digests", - }, - "major": Object { - "enabled": false, - }, - "manager": "docker", - "packageFile": "Dockerfile", - "pin": Object { - "branchName": "{{{branchPrefix}}}docker-pin-{{{depNameSanitized}}}-{{{currentTag}}}", - "group": Object { - "prBody": "This Pull Request pins Dockerfiles to use image digests. For details on Renovate's Docker support, please visit https://renovateapp.com/docs/language-support/docker - -{{#if schedule}} -**Note**: This PR was created on a configured schedule (\\"{{{schedule}}}\\"{{#if timezone}} in timezone \`{{{timezone}}}\`{{/if}}) and will not receive updates outside those times. -{{/if}} - -{{#each upgrades as |upgrade|}} -- {{#if repositoryUrl}}[{{upgrade.depName}}]({{upgrade.repositoryUrl}}){{else}}\`{{{depName}}}\`{{/if}}: \`{{upgrade.newDigest}}\` -{{/each}} - -**Important**: Renovate will wait until you have merged this Pin request before creating PRs for any *upgrades*. If you do not wish to pin anything, please update your config accordingly instead of leaving this PR open. - -{{#if hasErrors}} - ---- - -# Errors - -Renovate encountered some errors when processing your repository, so you are being notified here even if they do not directly apply to this PR. - -{{#each errors as |error|}} -- \`{{error.depName}}\`: {{error.message}} -{{/each}} -{{/if}} - -{{#if hasWarnings}} - ---- - -# Warnings - -Please make sure the following warnings are safe to ignore: - -{{#each warnings as |warning|}} -- \`{{warning.depName}}\`: {{warning.message}} -{{/each}} -{{/if}}", - "prTitle": "Pin Docker digests", - }, - "groupName": "Pin Docker Digests", - "prBody": "This Pull Request pins Docker base image \`{{{depName}}}:{{{currentTag}}}\` to use a digest (\`{{{newDigest}}}\`). -This digest will then be kept updated via Pull Requests whenever the image is updated on the Docker registry. For details on Renovate's Docker support, please visit https://renovateapp.com/docs/language-support/docker - -{{#if schedule}} -**Note**: This PR was created on a configured schedule (\\"{{{schedule}}}\\"{{#if timezone}} in timezone \`{{{timezone}}}\`{{/if}}) and will not receive updates outside those times. -{{/if}} - -**Important**: Renovate will wait until you have merged this Pin request before creating PRs for any *upgrades*. If you do not wish to pin anything, please update your config accordingly instead of leaving this PR open. - -{{#if hasErrors}} - ---- - -# Errors - -Renovate encountered some errors when processing your repository, so you are being notified here even if they do not directly apply to this PR. - -{{#each errors as |error|}} -- \`{{error.depName}}\`: {{error.message}} -{{/each}} -{{/if}} - -{{#if hasWarnings}} - ---- - -# Warnings - -Please make sure the following warnings are safe to ignore: - -{{#each warnings as |warning|}} -- \`{{warning.depName}}\`: {{warning.message}} -{{/each}} -{{/if}}", - "prTitle": "Pin Dockerfile {{{depName}}}:{{{currentTag}}} image digest", - }, - "prBody": "This Pull Request updates Docker base image \`{{{depName}}}\` from tag \`{{{currentTag}}}\` to new tag \`{{{newTag}}}\`. For details on Renovate's Docker support, please visit https://renovateapp.com/docs/language-support/docker - -{{#if schedule}} -**Note**: This PR was created on a configured schedule (\\"{{{schedule}}}\\"{{#if timezone}} in timezone \`{{{timezone}}}\`{{/if}}) and will not receive updates outside those times. -{{/if}} - -{{#if hasErrors}} - ---- - -# Errors - -Renovate encountered some errors when processing your repository, so you are being notified here even if they do not directly apply to this PR. - -{{#each errors as |error|}} -- \`{{error.depName}}\`: {{error.message}} -{{/each}} -{{/if}} - -{{#if hasWarnings}} - ---- - -# Warnings - -Please make sure the following warnings are safe to ignore: - -{{#each warnings as |warning|}} -- \`{{warning.depName}}\`: {{warning.message}} -{{/each}} -{{/if}}", - "prTitle": "Update {{{depName}}} Dockerfile tag to {{#if isMajor}}v{{{newVersionMajor}}}{{else}}v{{{newTag}}}{{/if}}", - }, - Object { - "content": "# travis", - "enabled": false, - "groupName": "Node.js", - "lazyGrouping": false, - "manager": "travis", - "packageFile": ".travis.yml", - }, - Object { - "content": "# WORKSPACE", - "enabled": true, - "manager": "bazel", - "packageFile": "WORKSPACE", - }, - Object { - "content": "8.9 -", - "enabled": true, - "groupName": "Node.js", - "lazyGrouping": false, - "manager": "nvm", - "packageFile": ".nvmrc", - }, -] -`; - exports[`manager/resolve resolvePackageFiles() skips if no content or no match 1`] = `Array []`; exports[`manager/resolve resolvePackageFiles() strips npmrc with NPM_TOKEN 1`] = ` diff --git a/test/manager/docker-compose/__snapshots__/extract.spec.js.snap b/test/manager/docker-compose/__snapshots__/extract.spec.js.snap new file mode 100644 index 0000000000000000000000000000000000000000..37e53650f76101bc8fc697052c63238ff9262386 --- /dev/null +++ b/test/manager/docker-compose/__snapshots__/extract.spec.js.snap @@ -0,0 +1,72 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`lib/manager/docker-compose/extract extractDependencies() extracts multiple image lines 1`] = ` +Array [ + Object { + "currentDepTag": "something/redis:alpine", + "currentDepTagDigest": "something/redis:alpine", + "currentDigest": undefined, + "currentFrom": "quay.io/something/redis:alpine", + "currentTag": "alpine", + "depName": "something/redis", + "depType": "Docker Compose", + "dockerRegistry": "quay.io", + "lineNumber": 4, + }, + Object { + "currentDepTag": "postgres:9.4.0", + "currentDepTagDigest": "postgres:9.4.0", + "currentDigest": undefined, + "currentFrom": "postgres:9.4.0", + "currentTag": "9.4.0", + "depName": "postgres", + "depType": "Docker Compose", + "dockerRegistry": undefined, + "lineNumber": 18, + }, + Object { + "currentDepTag": "dockersamples/examplevotingapp_vote:before", + "currentDepTagDigest": "dockersamples/examplevotingapp_vote:before", + "currentDigest": undefined, + "currentFrom": "dockersamples/examplevotingapp_vote:before", + "currentTag": "before", + "depName": "dockersamples/examplevotingapp_vote", + "depType": "Docker Compose", + "dockerRegistry": undefined, + "lineNumber": 28, + }, + Object { + "currentDepTag": "dockersamples/examplevotingapp_result:before", + "currentDepTagDigest": "dockersamples/examplevotingapp_result:before", + "currentDigest": undefined, + "currentFrom": "dockersamples/examplevotingapp_result:before", + "currentTag": "before", + "depName": "dockersamples/examplevotingapp_result", + "depType": "Docker Compose", + "dockerRegistry": undefined, + "lineNumber": 43, + }, + Object { + "currentDepTag": "dockersamples/examplevotingapp_worker", + "currentDepTagDigest": "dockersamples/examplevotingapp_worker", + "currentDigest": undefined, + "currentFrom": "dockersamples/examplevotingapp_worker", + "currentTag": undefined, + "depName": "dockersamples/examplevotingapp_worker", + "depType": "Docker Compose", + "dockerRegistry": undefined, + "lineNumber": 59, + }, + Object { + "currentDepTag": "dockersamples/visualizer:stable", + "currentDepTagDigest": "dockersamples/visualizer:stable", + "currentDigest": undefined, + "currentFrom": "dockersamples/visualizer:stable", + "currentTag": "stable", + "depName": "dockersamples/visualizer", + "depType": "Docker Compose", + "dockerRegistry": undefined, + "lineNumber": 76, + }, +] +`; diff --git a/test/manager/docker-compose/extract.spec.js b/test/manager/docker-compose/extract.spec.js new file mode 100644 index 0000000000000000000000000000000000000000..c2062d48eb3a3a39ffc3d63a964b87a2c37d2332 --- /dev/null +++ b/test/manager/docker-compose/extract.spec.js @@ -0,0 +1,23 @@ +const fs = require('fs'); +const { + extractDependencies, +} = require('../../../lib/manager/docker-compose/extract'); + +const yamlFile = fs.readFileSync( + 'test/_fixtures/docker-compose/docker-compose.1.yml', + 'utf8' +); + +describe('lib/manager/docker-compose/extract', () => { + describe('extractDependencies()', () => { + let config; + beforeEach(() => { + config = {}; + }); + it('extracts multiple image lines', () => { + const res = extractDependencies(yamlFile, config); + expect(res).toMatchSnapshot(); + expect(res).toHaveLength(6); + }); + }); +}); diff --git a/test/manager/docker-compose/update.spec.js b/test/manager/docker-compose/update.spec.js new file mode 100644 index 0000000000000000000000000000000000000000..1ba3bd84593884a4060ff5e2e2405d666f630f95 --- /dev/null +++ b/test/manager/docker-compose/update.spec.js @@ -0,0 +1,41 @@ +const fs = require('fs'); +const dcUpdate = require('../../../lib/manager/docker-compose/update'); + +const yamlFile = fs.readFileSync( + 'test/_fixtures/docker-compose/docker-compose.1.yml', + 'utf8' +); + +describe('manager/docker-compose/update', () => { + describe('setNewValue', () => { + it('replaces existing value', () => { + const upgrade = { + lineNumber: 18, + newFrom: 'postgres:9.6.8@sha256:abcdefghijklmnop', + }; + const res = dcUpdate.setNewValue(yamlFile, upgrade); + expect(res).not.toEqual(yamlFile); + expect(res.includes(upgrade.newFrom)).toBe(true); + }); + it('returns same', () => { + const upgrade = { + lineNumber: 4, + newFrom: 'quay.io/something/redis:alpine', + }; + const res = dcUpdate.setNewValue(yamlFile, upgrade); + expect(res).toEqual(yamlFile); + }); + it('returns null if mismatch', () => { + const upgrade = { + lineNumber: 17, + newFrom: 'postgres:9.6.8@sha256:abcdefghijklmnop', + }; + const res = dcUpdate.setNewValue(yamlFile, upgrade); + expect(res).toBe(null); + }); + it('returns null if error', () => { + const res = dcUpdate.setNewValue(null, null); + expect(res).toBe(null); + }); + }); +}); diff --git a/test/manager/resolve.spec.js b/test/manager/resolve.spec.js index a945e81fb5efa081ebcbcb2a545c42902d5946ac..12f91ad93d62b47cb48fe4e6c505b1d900e326c9 100644 --- a/test/manager/resolve.spec.js +++ b/test/manager/resolve.spec.js @@ -99,22 +99,25 @@ describe('manager/resolve', () => { config.packageFiles = [ 'package.js', 'Dockerfile', + 'docker-compose.yml', '.travis.yml', 'WORKSPACE', '.nvmrc', ]; platform.getFile.mockReturnValueOnce('{}'); // package.js platform.getFile.mockReturnValueOnce('# comment\nFROM node:8\n'); // Dockerfile + platform.getFile.mockReturnValueOnce('image: node:8\n'); // Docker Compose platform.getFile.mockReturnValueOnce('# travis'); // .travis.yml platform.getFile.mockReturnValueOnce('# WORKSPACE'); // Dockerfile platform.getFile.mockReturnValueOnce('8.9\n'); // Dockerfile const res = await resolvePackageFiles(config); - expect(res.packageFiles).toMatchSnapshot(); + expect(res.packageFiles).toHaveLength(6); }); it('skips if no content or no match', async () => { config.packageFiles = [ 'Dockerfile', 'other/Dockerfile', + 'docker-compose.yml', '.travis.yml', 'WORKSPACE', 'package.js', diff --git a/website/docs/_posts/2017-10-05-configuration-options.md b/website/docs/_posts/2017-10-05-configuration-options.md index db3699e31faf997f05f48238721ea03649f2f43c..2025e5943df5cc2b43b77c0fada1c6a718452422 100644 --- a/website/docs/_posts/2017-10-05-configuration-options.md +++ b/website/docs/_posts/2017-10-05-configuration-options.md @@ -238,6 +238,15 @@ Configuration specific for Dockerfile updates. | type | object | | default | { enabled: true, major: { enabled: false }, } | +## docker-compose + +Configuration object for Docker Compose yaml file renovation. Also inherits settings from `docker` object. + +| name | value | +| ------- | ------------------ | +| type | object | +| default | { enabled: false } | + ## enabled Enable or disable Renovate.