diff --git a/lib/manager/gradle/build-gradle.js b/lib/manager/gradle/build-gradle.js
index 962dcbd96c0d9b6adefc150188418b0dda644c1d..d9ab74bbce7cbf03943511acc1d825cefdccf383 100644
--- a/lib/manager/gradle/build-gradle.js
+++ b/lib/manager/gradle/build-gradle.js
@@ -3,6 +3,8 @@
  * gradle-use-latest-versions-plugin is licensed under MIT and Copyright (c) 2018 Patrik Erdes
  */
 
+let variables = {};
+
 function updateGradleVersion(buildGradleContent, dependency, newVersion) {
   if (dependency) {
     const updateFunctions = [
@@ -11,6 +13,8 @@ function updateGradleVersion(buildGradleContent, dependency, newVersion) {
       updateVersionMapVariableFormat,
       updateVersionStringVariableFormat,
       updateVersionExpressionVariableFormat,
+      updateGlobalVariables,
+      updatePropertyFileGlobalVariables,
     ];
 
     // eslint-disable-next-line guard-for-in
@@ -29,6 +33,31 @@ function updateGradleVersion(buildGradleContent, dependency, newVersion) {
   return buildGradleContent;
 }
 
+function collectVersionVariables(dependencies, buildGradleContent) {
+  for (const dep of dependencies) {
+    const dependency = {
+      ...dep,
+      group: dep.depGroup,
+    };
+    const regexes = [
+      moduleStringVariableExpressionVersionFormatMatch(dependency),
+      moduleStringVariableInterpolationVersionFormatMatch(dependency),
+      moduleMapVariableVersionFormatMatch(dependency),
+    ];
+
+    for (const regex of regexes) {
+      const match = buildGradleContent.match(regex);
+      if (match) {
+        variables[`${dependency.group}:${dependency.name}`] = match[1];
+      }
+    }
+  }
+}
+
+function init() {
+  variables = {};
+}
+
 function updateVersionStringFormat(dependency, buildGradleContent, newVersion) {
   const regex = moduleStringVersionFormatMatch(dependency);
   if (buildGradleContent.match(regex)) {
@@ -93,6 +122,37 @@ function updateVersionExpressionVariableFormat(
   return null;
 }
 
+function updateGlobalVariables(dependency, buildGradleContent, newVersion) {
+  const variable = variables[`${dependency.group}:${dependency.name}`];
+  if (variable) {
+    const regex = variableDefinitionFormatMatch(variable);
+    const match = buildGradleContent.match(regex);
+    if (match) {
+      return buildGradleContent.replace(
+        variableDefinitionFormatMatch(variable),
+        `$1${newVersion}$3`
+      );
+    }
+  }
+  return null;
+}
+
+function updatePropertyFileGlobalVariables(
+  dependency,
+  buildGradleContent,
+  newVersion
+) {
+  const variable = variables[`${dependency.group}:${dependency.name}`];
+  if (variable) {
+    const regex = new RegExp(`(${variable}\\s*=\\s*)(.*)`);
+    const match = buildGradleContent.match(regex);
+    if (match) {
+      return buildGradleContent.replace(regex, `$1${newVersion}`);
+    }
+  }
+  return null;
+}
+
 function moduleStringVersionFormatMatch(dependency) {
   return new RegExp(
     `(["']${dependency.group}:${dependency.name}:)[^$].*?(["'])`
@@ -130,9 +190,11 @@ function moduleStringVariableExpressionVersionFormatMatch(dependency) {
 }
 
 function variableDefinitionFormatMatch(variable) {
-  return new RegExp(`(${variable}\\s+=\\s*?["'])(.*)(["'])`);
+  return new RegExp(`(${variable}\\s*=\\s*?["'])(.*)(["'])`);
 }
 
 module.exports = {
   updateGradleVersion,
+  collectVersionVariables,
+  init,
 };
diff --git a/lib/manager/gradle/index.js b/lib/manager/gradle/index.js
index 77eacbf687ba55fbb88c37d342ec726ec04e67be..af316d61de6549261944d2f76a7d074cea84c3c5 100644
--- a/lib/manager/gradle/index.js
+++ b/lib/manager/gradle/index.js
@@ -24,6 +24,14 @@ async function extractAllPackageFiles(config, packageFiles) {
       await fs.outputFile(localFileName, content);
     }
   }
+
+  await configureUseLatestVersionPlugin(config.localDir);
+  const gradleSuccess = await executeGradle(config);
+  if (!gradleSuccess) {
+    return null;
+  }
+
+  gradle.init();
   const gradleFiles = [];
   for (const packageFile of packageFiles) {
     const content = await platform.getFile(packageFile);
@@ -48,15 +56,8 @@ async function extractPackageFile(content, fileName, config) {
   const gradleFile = path.join(config.localDir, fileName);
   const baseDir = path.dirname(gradleFile);
 
-  if (isProjectRootGradle(fileName)) {
-    await configureUseLatestVersionPlugin(baseDir);
-    const gradleSuccess = await executeGradle(config);
-    if (!gradleSuccess) {
-      return null;
-    }
-  }
-
   const deps = await extractDependenciesFromUpdatesReport(baseDir);
+  gradle.collectVersionVariables(deps, content);
   return deps.length > 0 ? { deps } : null;
 }
 
@@ -177,17 +178,12 @@ async function executeGradle(config) {
   return true;
 }
 
-function isProjectRootGradle(fileName) {
-  return fileName === 'build.gradle';
-}
-
 function getDockerRenovateGradleCommandLine(localDir) {
   return `docker run --rm -v ${localDir}:${localDir} -w ${localDir} renovate/gradle ${GRADLE_DEPENDENCY_REPORT_COMMAND}`;
 }
 
 module.exports = {
   extractAllPackageFiles,
-  extractPackageFile,
   getPackageUpdates,
   updateDependency,
   language: 'java',
diff --git a/test/manager/gradle/__snapshots__/index.spec.js.snap b/test/manager/gradle/__snapshots__/index.spec.js.snap
index f1b545b4b942dad1ca73933710607e8726f78b1d..53ed5f5d7117383bc727939400e9b9321abae18e 100644
--- a/test/manager/gradle/__snapshots__/index.spec.js.snap
+++ b/test/manager/gradle/__snapshots__/index.spec.js.snap
@@ -1,77 +1,81 @@
 // Jest Snapshot v1, https://goo.gl/fbAQLP
 
 exports[`manager/gradle extractPackageFile should return gradle dependencies 1`] = `
-Object {
-  "deps": Array [
-    Object {
-      "currentValue": "0.1",
-      "depGroup": "com.fkorotkov",
-      "depName": "com.fkorotkov:gradle-libraries-plugin",
-      "name": "gradle-libraries-plugin",
-      "version": "0.1",
-    },
-    Object {
-      "currentValue": "0.2.3",
-      "depGroup": "gradle.plugin.se.patrikerdes",
-      "depName": "gradle.plugin.se.patrikerdes:gradle-use-latest-versions-plugin",
-      "name": "gradle-use-latest-versions-plugin",
-      "version": "0.2.3",
-    },
-    Object {
-      "currentValue": "1.3",
-      "depGroup": "org.hamcrest",
-      "depName": "org.hamcrest:hamcrest-core",
-      "name": "hamcrest-core",
-      "version": "1.3",
-    },
-    Object {
-      "available": Object {
-        "integration": null,
-        "milestone": null,
-        "release": "3.2.8",
+Array [
+  Object {
+    "deps": Array [
+      Object {
+        "currentValue": "0.1",
+        "depGroup": "com.fkorotkov",
+        "depName": "com.fkorotkov:gradle-libraries-plugin",
+        "name": "gradle-libraries-plugin",
+        "version": "0.1",
       },
-      "currentValue": "3.1",
-      "depGroup": "cglib",
-      "depName": "cglib:cglib-nodep",
-      "name": "cglib-nodep",
-      "version": "3.1",
-    },
-    Object {
-      "available": Object {
-        "integration": null,
-        "milestone": null,
-        "release": "6.1.10.RELEASE",
+      Object {
+        "currentValue": "0.2.3",
+        "depGroup": "gradle.plugin.se.patrikerdes",
+        "depName": "gradle.plugin.se.patrikerdes:gradle-use-latest-versions-plugin",
+        "name": "gradle-use-latest-versions-plugin",
+        "version": "0.2.3",
       },
-      "currentValue": "6.0.9.RELEASE",
-      "depGroup": "org.grails",
-      "depName": "org.grails:gorm-hibernate5-spring-boot",
-      "name": "gorm-hibernate5-spring-boot",
-      "version": "6.0.9.RELEASE",
-    },
-    Object {
-      "available": Object {
-        "integration": null,
-        "milestone": null,
-        "release": "8.0.12",
+      Object {
+        "currentValue": "1.3",
+        "depGroup": "org.hamcrest",
+        "depName": "org.hamcrest:hamcrest-core",
+        "name": "hamcrest-core",
+        "version": "1.3",
       },
-      "currentValue": "5.1.41",
-      "depGroup": "mysql",
-      "depName": "mysql:mysql-connector-java",
-      "name": "mysql-connector-java",
-      "version": "5.1.41",
-    },
-    Object {
-      "available": Object {
-        "integration": null,
-        "milestone": null,
-        "release": "2.0.5.RELEASE",
+      Object {
+        "available": Object {
+          "integration": null,
+          "milestone": null,
+          "release": "3.2.8",
+        },
+        "currentValue": "3.1",
+        "depGroup": "cglib",
+        "depName": "cglib:cglib-nodep",
+        "name": "cglib-nodep",
+        "version": "3.1",
       },
-      "currentValue": "1.5.2.RELEASE",
-      "depGroup": "org.springframework.boot",
-      "depName": "org.springframework.boot:spring-boot-starter-test",
-      "name": "spring-boot-starter-test",
-      "version": "1.5.2.RELEASE",
-    },
-  ],
-}
+      Object {
+        "available": Object {
+          "integration": null,
+          "milestone": null,
+          "release": "6.1.10.RELEASE",
+        },
+        "currentValue": "6.0.9.RELEASE",
+        "depGroup": "org.grails",
+        "depName": "org.grails:gorm-hibernate5-spring-boot",
+        "name": "gorm-hibernate5-spring-boot",
+        "version": "6.0.9.RELEASE",
+      },
+      Object {
+        "available": Object {
+          "integration": null,
+          "milestone": null,
+          "release": "8.0.12",
+        },
+        "currentValue": "5.1.41",
+        "depGroup": "mysql",
+        "depName": "mysql:mysql-connector-java",
+        "name": "mysql-connector-java",
+        "version": "5.1.41",
+      },
+      Object {
+        "available": Object {
+          "integration": null,
+          "milestone": null,
+          "release": "2.0.5.RELEASE",
+        },
+        "currentValue": "1.5.2.RELEASE",
+        "depGroup": "org.springframework.boot",
+        "depName": "org.springframework.boot:spring-boot-starter-test",
+        "name": "spring-boot-starter-test",
+        "version": "1.5.2.RELEASE",
+      },
+    ],
+    "manager": "gradle",
+    "packageFile": "build.gradle",
+  },
+]
 `;
diff --git a/test/manager/gradle/build-gradle.spec.js b/test/manager/gradle/build-gradle.spec.js
index 8ddd97cb9b00c9058d77dc5d44f3e5b0c9070bf4..1726b5e41fd7db5d7668a81d4228500f5dd27c29 100644
--- a/test/manager/gradle/build-gradle.spec.js
+++ b/test/manager/gradle/build-gradle.spec.js
@@ -1,6 +1,10 @@
 const gradle = require('../../../lib/manager/gradle/build-gradle');
 
 describe('lib/manager/gradle/updateGradleVersion', () => {
+  beforeEach(() => {
+    gradle.init();
+  });
+
   it('returns the same file if dependency is null', () => {
     const gradleFile = "runtime('mysql:mysql-connector-java:6.0.5')";
     const updatedGradleFile = gradle.updateGradleVersion(
@@ -34,8 +38,8 @@ describe('lib/manager/gradle/updateGradleVersion', () => {
   });
 
   it('returns a file updated if the version defined as map is found', () => {
-    const gradleFile = `compile group  : 'mysql'               , 
-               name   : 'mysql-connector-java', 
+    const gradleFile = `compile group  : 'mysql'               ,
+               name   : 'mysql-connector-java',
                version: '6.0.5'`;
     const updatedGradleFile = gradle.updateGradleVersion(
       gradleFile,
@@ -43,29 +47,29 @@ describe('lib/manager/gradle/updateGradleVersion', () => {
       '7.0.0'
     );
     expect(updatedGradleFile).toEqual(
-      `compile group  : 'mysql'               , 
-               name   : 'mysql-connector-java', 
+      `compile group  : 'mysql'               ,
+               name   : 'mysql-connector-java',
                version: '7.0.0'`
     );
   });
 
   it('should returns a file updated if the version defined in a variable as a string is found', () => {
-    const gradleFile = `String mysqlVersion = "6.0.5"
-    runtime (  'mysql:mysql-connector-java:$mysqlVersion'  )
+    const gradleFile = `String mysqlVersion= "6.0.5"
+    runtime (  "mysql:mysql-connector-java:$mysqlVersion"  )
     `;
     const updatedGradleFile = gradle.updateGradleVersion(
       gradleFile,
       { group: 'mysql', name: 'mysql-connector-java', version: '6.0.5' },
       '7.0.0'
     );
-    expect(updatedGradleFile).toEqual(`String mysqlVersion = "7.0.0"
-    runtime (  'mysql:mysql-connector-java:$mysqlVersion'  )
+    expect(updatedGradleFile).toEqual(`String mysqlVersion= "7.0.0"
+    runtime (  "mysql:mysql-connector-java:$mysqlVersion"  )
     `);
   });
 
   it('should returns a file updated if the version defined in a expression as a string is found', () => {
     const gradleFile = `String mysqlVersion = "6.0.5"
-    runtime (  'mysql:mysql-connector-java:\${mysqlVersion}'  )
+    runtime (  "mysql:mysql-connector-java:\${mysqlVersion}"  )
     `;
     const updatedGradleFile = gradle.updateGradleVersion(
       gradleFile,
@@ -73,14 +77,14 @@ describe('lib/manager/gradle/updateGradleVersion', () => {
       '7.0.0'
     );
     expect(updatedGradleFile).toEqual(`String mysqlVersion = "7.0.0"
-    runtime (  'mysql:mysql-connector-java:\${mysqlVersion}'  )
+    runtime (  "mysql:mysql-connector-java:\${mysqlVersion}"  )
     `);
   });
 
   it('should returns a file updated if the version defined in a variable as a map is found', () => {
     const gradleFile = `String mysqlVersion = "6.0.5"
-               compile group  : 'mysql'               , 
-               name           : 'mysql-connector-java', 
+               compile group  : 'mysql'               ,
+               name           : 'mysql-connector-java',
                version        : mysqlVersion
                `;
     const updatedGradleFile = gradle.updateGradleVersion(
@@ -90,10 +94,92 @@ describe('lib/manager/gradle/updateGradleVersion', () => {
     );
     expect(updatedGradleFile).toEqual(
       `String mysqlVersion = "7.0.0"
-               compile group  : 'mysql'               , 
-               name           : 'mysql-connector-java', 
+               compile group  : 'mysql'               ,
+               name           : 'mysql-connector-java',
                version        : mysqlVersion
                `
     );
   });
+
+  it('should replace a external groovy variable assigned to a specific dependency', () => {
+    const gradleFile =
+      'runtime (  "mysql:mysql-connector-java:${mysqlVersion}"  )'; // eslint-disable-line no-template-curly-in-string
+    const mysqlDependency = {
+      group: 'mysql',
+      depGroup: 'mysql',
+      name: 'mysql-connector-java',
+      version: '6.0.5',
+    };
+    gradle.collectVersionVariables([mysqlDependency], gradleFile);
+
+    const gradleWithVersionFile = 'String mysqlVersion = "6.0.5"';
+    const updatedGradleFile = gradle.updateGradleVersion(
+      gradleWithVersionFile,
+      mysqlDependency,
+      '7.0.0'
+    );
+    expect(updatedGradleFile).toEqual('String mysqlVersion = "7.0.0"');
+  });
+
+  it('should replace a external property variable assigned to a specific dependency', () => {
+    const gradleFile =
+      'runtime (  "mysql:mysql-connector-java:${mysqlVersion}"  )'; // eslint-disable-line no-template-curly-in-string
+    const mysqlDependency = {
+      group: 'mysql',
+      depGroup: 'mysql',
+      name: 'mysql-connector-java',
+      version: '6.0.5',
+    };
+    gradle.collectVersionVariables([mysqlDependency], gradleFile);
+
+    const propertyFile = 'mysqlVersion=6.0.5';
+    const updatedGradleFile = gradle.updateGradleVersion(
+      propertyFile,
+      mysqlDependency,
+      '7.0.0'
+    );
+    expect(updatedGradleFile).toEqual('mysqlVersion=7.0.0');
+  });
+
+  it('should replace a external variable assigned to a map dependency', () => {
+    const gradleFile = `compile group  : 'mysql'               ,
+               name           : 'mysql-connector-java',
+               version        : mysqlVersion
+               `;
+    const mysqlDependency = {
+      group: 'mysql',
+      depGroup: 'mysql',
+      name: 'mysql-connector-java',
+      version: '6.0.5',
+    };
+    gradle.collectVersionVariables([mysqlDependency], gradleFile);
+
+    const gradleWithVersionFile = 'String mysqlVersion = "6.0.5"';
+    const updatedGradleFile = gradle.updateGradleVersion(
+      gradleWithVersionFile,
+      mysqlDependency,
+      '7.0.0'
+    );
+    expect(updatedGradleFile).toEqual('String mysqlVersion = "7.0.0"');
+  });
+
+  it('should replace a external variable assigned to a interpolated dependency', () => {
+    const gradleFile =
+      'runtime (  "mysql:mysql-connector-java:$mysqlVersion"  )';
+    const mysqlDependency = {
+      group: 'mysql',
+      depGroup: 'mysql',
+      name: 'mysql-connector-java',
+      version: '6.0.5',
+    };
+    gradle.collectVersionVariables([mysqlDependency], gradleFile);
+
+    const gradleWithVersionFile = 'String mysqlVersion = "6.0.5"';
+    const updatedGradleFile = gradle.updateGradleVersion(
+      gradleWithVersionFile,
+      mysqlDependency,
+      '7.0.0'
+    );
+    expect(updatedGradleFile).toEqual('String mysqlVersion = "7.0.0"');
+  });
 });
diff --git a/test/manager/gradle/index.spec.js b/test/manager/gradle/index.spec.js
index 1d6716fa9106202ae88160bded771b0f2c1d8d21..4351bdc866eaa1f039141e9940ed5fafa0a9e118 100644
--- a/test/manager/gradle/index.spec.js
+++ b/test/manager/gradle/index.spec.js
@@ -27,33 +27,29 @@ describe('manager/gradle', () => {
     fs.mkdir.mockReturnValue(true);
     fs.exists.mockReturnValue(true);
     exec.mockReturnValue({ stdout: 'gradle output', stderr: '' });
+    platform.getFile.mockReturnValue('some content');
   });
 
   describe('extractPackageFile', () => {
     it('should return gradle dependencies', async () => {
-      const dependencies = await manager.extractPackageFile(
-        'content',
+      const dependencies = await manager.extractAllPackageFiles(config, [
         'build.gradle',
-        config
-      );
-
+      ]);
       expect(dependencies).toMatchSnapshot();
     });
 
-    it('should return null if there are no dependencies', async () => {
+    it('should return empty if there are no dependencies', async () => {
       fs.readFile.mockReturnValue(
         fsReal.readFileSync(
           'test/_fixtures/gradle/updatesReportEmpty.json',
           'utf8'
         )
       );
-      const dependencies = await manager.extractPackageFile(
-        'content',
+      const dependencies = await manager.extractAllPackageFiles(config, [
         'build.gradle',
-        config
-      );
+      ]);
 
-      expect(dependencies).toEqual(null);
+      expect(dependencies).toEqual([]);
     });
 
     it('should return null if gradle execution fails', async () => {
@@ -61,32 +57,23 @@ describe('manager/gradle', () => {
         throw new Error();
       });
 
-      const dependencies = await manager.extractPackageFile(
-        'content',
+      const dependencies = await manager.extractAllPackageFiles(config, [
         'build.gradle',
-        config
-      );
-
+      ]);
       expect(dependencies).toEqual(null);
     });
 
     it('should return empty if there is no dependency report', async () => {
-      fs.readFile.mockImplementation(() => {
-        throw new Error();
-      });
       fs.exists.mockReturnValue(false);
-
-      const dependencies = await manager.extractPackageFile(
-        'content',
+      const dependencies = await manager.extractAllPackageFiles(config, [
         'build.gradle',
-        config
-      );
+      ]);
 
-      expect(dependencies).toEqual(null);
+      expect(dependencies).toEqual([]);
     });
 
     it('should execute gradle with the proper parameters', async () => {
-      await manager.extractPackageFile('content', 'build.gradle', config);
+      await manager.extractAllPackageFiles(config, ['build.gradle']);
 
       expect(exec.mock.calls[0][0]).toBe(
         'gradle --init-script init.gradle dependencyUpdates -Drevision=release'
@@ -97,28 +84,49 @@ describe('manager/gradle', () => {
       });
     });
 
-    it('should return null if no build.gradle', async () => {
+    it('should return null and gradle should not be executed if no build.gradle', async () => {
       const packageFiles = ['foo/build.gradle'];
       expect(
         await manager.extractAllPackageFiles(config, packageFiles)
       ).toBeNull();
+
+      expect(exec.mock.calls.length).toBe(0);
     });
 
     it('should return empty if not content', async () => {
-      const packageFiles = ['build.gradle'];
-      const res = await manager.extractAllPackageFiles(config, packageFiles);
+      platform.getFile.mockReturnValue(null);
+      const res = await manager.extractAllPackageFiles(config, [
+        'build.gradle',
+      ]);
       expect(res).toEqual([]);
     });
 
     it('should write files before extracting', async () => {
-      const packageFiles = ['build.gradle'];
-      platform.getFile.mockReturnValue('some content');
-      const res = await manager.extractAllPackageFiles(config, packageFiles);
-      expect(res).not.toBeNull();
+      const packageFiles = ['build.gradle', 'foo/build.gradle'];
+      await manager.extractAllPackageFiles(config, packageFiles);
+
+      expect(toUnix(fs.outputFile.mock.calls[0][0])).toBe(
+        'localDir/build.gradle'
+      );
+      expect(toUnix(fs.outputFile.mock.calls[1][0])).toBe(
+        'localDir/foo/build.gradle'
+      );
+    });
+
+    it('should not write files if gitFs is enabled', async () => {
+      const configWithgitFs = {
+        gitFs: true,
+        ...config,
+      };
+
+      const packageFiles = ['build.gradle', 'foo/build.gradle'];
+      await manager.extractAllPackageFiles(configWithgitFs, packageFiles);
+
+      expect(fs.outputFile.mock.calls.length).toBe(0);
     });
 
     it('should configure the useLatestVersion plugin', async () => {
-      await manager.extractPackageFile('content', 'build.gradle', config);
+      await manager.extractAllPackageFiles(config, ['build.gradle']);
 
       expect(toUnix(fs.writeFile.mock.calls[0][0])).toBe(
         'localDir/init.gradle'
@@ -130,11 +138,7 @@ describe('manager/gradle', () => {
         binarySource: 'docker',
         ...config,
       };
-      await manager.extractPackageFile(
-        'content',
-        'build.gradle',
-        configWithDocker
-      );
+      await manager.extractAllPackageFiles(configWithDocker, ['build.gradle']);
 
       expect(exec.mock.calls[0][0]).toBe(
         'docker run --rm -v localDir:localDir -w localDir renovate/gradle gradle --init-script init.gradle dependencyUpdates -Drevision=release'