Skip to content
Snippets Groups Projects
Select Git revision
  • 8b761f5a6df0da81a4a110fcc1f79808e6a85798
  • master default
2 results

index.js

Blame
  • user avatar
    Rhys Arkins authored
    8b761f5a
    History
    index.js 5.77 KiB
    const { exec } = require('child-process-promise');
    const fs = require('fs-extra');
    const path = require('path');
    
    const gradle = require('./build-gradle');
    
    const GRADLE_DEPENDENCY_REPORT_COMMAND =
      'gradle --init-script init.gradle dependencyUpdates -Drevision=release';
    const GRADLE_DEPENDENCY_REPORT_FILENAME = 'build/dependencyUpdates/report.json';
    const TIMEOUT_CODE = 143;
    
    async function extractAllPackageFiles(config, packageFiles) {
      if (!packageFiles.some(packageFile => packageFile === 'build.gradle')) {
        logger.warn('No root build.gradle found - skipping');
        return null;
      }
      logger.info('Extracting dependencies from all gradle files');
      // Gradle needs all files to be written to disk before we parse any as some files may reference others
      // But if we're using gitFs then it's not necessary because they're already there
      if (!config.gitFs) {
        for (const packageFile of packageFiles) {
          const localFileName = path.join(config.localDir, packageFile);
          const content = await platform.getFile(packageFile);
          await fs.outputFile(localFileName, content);
        }
      }
    
      await configureUseLatestVersionPlugin(config.localDir);
      await executeGradle(config);
    
      gradle.init();
      const gradleFiles = [];
      for (const packageFile of packageFiles) {
        const content = await platform.getFile(packageFile);
        if (content) {
          const deps = await extractPackageFile(content, packageFile, config);
          if (deps) {
            gradleFiles.push({
              packageFile,
              manager: 'gradle',
              ...deps,
            });
          }
        } else {
          logger.info({ packageFile }, 'packageFile has no content');
        }
      }
      return gradleFiles;
    }
    
    async function extractPackageFile(content, fileName, config) {
      logger.debug(`gradle.extractPackageFile(filename=${fileName})`);
      const gradleFile = path.join(config.localDir, fileName);
      const baseDir = path.dirname(gradleFile);
    
      const deps = await extractDependenciesFromUpdatesReport(baseDir);
      gradle.collectVersionVariables(deps, content);
      return deps.length > 0 ? { deps } : null;
    }
    
    function getPackageUpdates(config) {
      logger.debug(`gradle.getPackageUpdates(depName=${config.depName})`);
    
      if (config.available) {
        return [
          {
            depName: config.depName,
            newValue: config.available.release,
          },
        ];
      }
      return [];
    }
    
    function updateDependency(fileContent, upgrade) {
      // prettier-ignore
      logger.debug(`gradle.updateDependency(): packageFile:${upgrade.packageFile} depName:${upgrade.depName}, version:${upgrade.version} ==> ${upgrade.newValue}`);
    
      const newFileContent = gradle.updateGradleVersion(
        fileContent,
        buildGradleDependency(upgrade),
        upgrade.available.release
      );
      return newFileContent;
    }
    
    async function configureUseLatestVersionPlugin(localDir) {
      const content = `
    gradle.projectsLoaded {
        rootProject.allprojects {
            buildscript {
                repositories {
                    maven {
                     url "https://plugins.gradle.org/m2/"
                    }
                }
               dependencies {
                classpath "gradle.plugin.se.patrikerdes:gradle-use-latest-versions-plugin:0.2.3"
                classpath 'com.github.ben-manes:gradle-versions-plugin:0.17.0'
              }
            }
            afterEvaluate { project ->
              project.apply plugin: 'com.github.ben-manes.versions'
              project.apply plugin: 'se.patrikerdes.use-latest-versions'
            }
        }
    }
      `;
      const gradleInitFile = path.join(localDir, 'init.gradle');
      logger.debug('Creating init.gradle file');
      await fs.writeFile(gradleInitFile, content);
    }
    
    function buildGradleDependency(config) {
      return { group: config.depGroup, name: config.name, version: config.version };
    }
    
    async function extractDependenciesFromUpdatesReport(localDir) {
      const filename = path.join(localDir, GRADLE_DEPENDENCY_REPORT_FILENAME);
      if (!(await fs.exists(filename))) {
        return [];
      }
    
      const contents = await fs.readFile(
        path.join(localDir, GRADLE_DEPENDENCY_REPORT_FILENAME),
        'utf8'
      );
      const dependencies = JSON.parse(contents);
      const combinedGradleDeps = dependencies.current.dependencies.concat(
        dependencies.exceeded.dependencies,
        dependencies.outdated.dependencies,
        dependencies.unresolved.dependencies
      );
      return combinedGradleDeps.map(gradleModule => {
        const dependency = { ...gradleModule };
        delete dependency.group;
        dependency.depGroup = gradleModule.group;
        dependency.depName = `${gradleModule.group}:${gradleModule.name}`;
        dependency.currentValue = gradleModule.version;
        return dependency;
      });
    }
    
    async function executeGradle(config) {
      let stdout;
      let stderr;
      const gradleTimeout =
        config.gradle && config.gradle.timeout
          ? config.gradle.timeout * 1000
          : undefined;
      let cmd;
      if (config.binarySource === 'docker') {
        cmd = getDockerRenovateGradleCommandLine(config.localDir);
      } else {
        cmd = GRADLE_DEPENDENCY_REPORT_COMMAND;
      }
      try {
        logger.debug({ cmd }, 'Start gradle command');
        ({ stdout, stderr } = await exec(cmd, {
          cwd: config.localDir,
          timeout: gradleTimeout,
          shell: true,
        }));
      } catch (err) {
        const errorStr = `Gradle command ${cmd} failed. Exit code: ${err.code}.`;
        // istanbul ignore if
        if (err.code === TIMEOUT_CODE) {
          logger.error(' Process killed. Possibly gradle timed out.');
        }
        logger.warn({ err }, errorStr);
        logger.info('Aborting Renovate due to Gradle lookup errors');
        throw new Error('registry-failure');
      }
      logger.debug(stdout + stderr);
      logger.info('Gradle report complete');
    }
    
    function getDockerRenovateGradleCommandLine(localDir) {
      return `docker run --rm -v ${localDir}:${localDir} -w ${localDir} renovate/gradle ${GRADLE_DEPENDENCY_REPORT_COMMAND}`;
    }
    
    module.exports = {
      extractAllPackageFiles,
      getPackageUpdates,
      updateDependency,
      language: 'java',
    };