import upath from 'upath' ; import * as datasourceSbtPackage from '../../../datasource/sbt-package' ; import { logger } from '../../../logger' ; import { localPathExists , readLocalFile , writeLocalFile , } from '../../../util/fs' ; import { regEx } from '../../../util/regex' ; import type { BuildDependency , GradleDependencyWithRepos , GradleProject , } from './types' ; export const GRADLE_DEPENDENCY_REPORT_FILENAME = 'gradle-renovate-report.json' ; export async function createRenovateGradlePlugin ( gradleRoot = '.' ) { const content = `
import groovy.json.JsonOutput
import org.gradle.api.internal.artifacts.dependencies.DefaultExternalModuleDependency
import java.util.concurrent.ConcurrentLinkedQueue

def output = new ConcurrentLinkedQueue<>();

allprojects {
  tasks.register("renovate") {
    doLast {
      def project = ['project': project.name]
      output << project

      def repos = (repositories + buildscript.repositories + settings.pluginManagement.repositories)
        .findAll { it instanceof MavenArtifactRepository && it.url.scheme ==~ /https?/ }
        .collect { "$it.url" }
        .unique()
      project.repositories = repos

      def deps = (buildscript.configurations + configurations + settings.buildscript.configurations)
        .collect { it.dependencies + it.dependencyConstraints }
        .flatten()
        .findAll { it instanceof DefaultExternalModuleDependency || it instanceof DependencyConstraint }
        .findAll { 'Pinned to the embedded Kotlin' != it.reason } // Embedded Kotlin dependencies
        .collect { ['name':it.name, 'group':it.group, 'version':it.version] }
      project.dependencies = deps
    }
  }
}
gradle.buildFinished {
   def outputFile = new File('${ GRADLE_DEPENDENCY_REPORT_FILENAME }')
   def json = JsonOutput.toJson(output)
   outputFile.write json
}` ; const gradleInitFile = upath . join ( gradleRoot , 'renovate-plugin.gradle' ) ; logger . debug ( 'Creating renovate-plugin.gradle file with renovate gradle plugin' ) ; await writeLocalFile ( gradleInitFile , content ) ; } async function readGradleReport ( localDir ) { const renovateReportFilename = upath . join ( localDir , GRADLE_DEPENDENCY_REPORT_FILENAME ) ; if ( ! ( await localPathExists ( renovateReportFilename ) ) ) { return [ ] ; } const contents = await readLocalFile ( renovateReportFilename , 'utf8' ) ; try { return JSON . parse ( contents ) ; } catch ( err ) { logger . error ( { err } , 'Invalid Gradle extract JSON' ) ; return [ ] ; } } function mergeDependenciesWithRepositories ( project ) { if ( ! project . dependencies ) { return [ ] ; } return project . dependencies . map ( ( dep ) => ( { ... dep , repos : [ ... project . repositories ] , } ) ) ; } function flattenDependencies ( accumulator , currentValue ) { accumulator . push ( ... currentValue ) ; return accumulator ; } function combineReposOnDuplicatedDependencies ( accumulator , currentValue ) { const existingDependency = accumulator . find ( ( dep ) => dep . name === currentValue . name && dep . group === currentValue . group ) ; if ( existingDependency ) { const nonExistingRepos = currentValue . repos . filter ( ( repo ) => ! existingDependency . repos . includes ( repo ) ) ; existingDependency . repos . push ( ... nonExistingRepos ) ; } else { accumulator . push ( currentValue ) ; } return accumulator ; } function buildDependency ( gradleModule ) { return { name : gradleModule . name , depGroup : gradleModule . group , depName : `${ gradleModule . group }:${ gradleModule . name }` , currentValue : gradleModule . version , registryUrls : gradleModule . repos , } ; } export async function extractDependenciesFromUpdatesReport ( localDir ) { const gradleProjectConfigurations = await readGradleReport ( localDir ) ; const dependencies = gradleProjectConfigurations . map ( mergeDependenciesWithRepositories , [ ] ) . reduce ( flattenDependencies , [ ] ) . reduce ( combineReposOnDuplicatedDependencies , [ ] ) ; return dependencies . map ( ( gradleModule ) => buildDependency ( gradleModule ) ) . map ( ( dep ) => { const { depName , currentValue } = dep ; if ( depName . endsWith ( '_%%' ) ) { return { ... dep , depName : depName . replace ( regEx ( /_%%/ ) , '' ) , datasource : datasourceSbtPackage . id , } ; } if ( regEx ( /^%.*%$/ ) . test ( currentValue ) ) { return { ... dep , skipReason : 'version-placeholder' } ; } return dep ; } ) ; }