Externilization of Maven repo credentials

buildscript is special form in Gradle DSL. You can’t write plugin that provides a structure for Maven repo settings there.

For this reason I have very first lines:

buildscript {
    ext.injectMavenRepos = {
        if (project.hasProperty("myUseJcenter") && project.getProperty("myUseJcenter") == "true") {
            it.jcenter()
        }
        project.getProperties()
                .findAll { key, value -> key.startsWith("myMavenUrl") && value instanceof String && value }
                .each { key, value ->
                    def suffix = key - ~/^myMavenUrl/
                    it.maven {
                        url value
                        def userProp = "myMavenUser" + suffix
                        def passProp = "myMavenPass" + suffix
                        def user = project.hasProperty(userProp) ? project.getProperty(userProp) : null
                        def pass = project.hasProperty(passProp) ? project.getProperty(passProp) : null
                        if (user instanceof String && pass instanceof String && user && pass) {
                            credentials { username user; password pass }
                        }
                    }
                }
    }

    injectMavenRepos(repositories)

    dependencies {
        classpath "org.jfrog.buildinfo:build-info-extractor-gradle:4.14.1"
    }
}

subprojects {
    injectMavenRepos(repositories)

    dependencies {
        compileOnly "org.projectlombok:lombok:${projLombokVersion}"
        annotationProcessor "org.projectlombok:lombok:${projLombokVersion}"
    }
}

I have to use ext. to avoid duplication of same code inside regular repositories.

I pass myUseJcenter or myMavenUrl via -P (in CI) or via ~/.gradle/gradle.properties (local dev host) or via env var following convention ORG_GRADLE_PROJECT_prop=somevalue.

I can define several sources (following prefix agreement):

myMavenUrl_1 = http://localhost:8081/artifactory
myMavenUser_1 = ...
myMavenPass_1 = ...
myMavenUrl_2 = https://evil.corp.com/artifactory

Maven on other hand makes this easier with ~/.m2/settings.xml in a standard way. No need to clutter build scripts with repository definitions.

You can define repos in an init.gradle script (equivalent of settings.xml for Maven)

allprojects {
  repositories {
    maven {
      url "${url}"
      credentials {
        username = 'joe'
        password = 'secret'
    }
  }
}

Similarly, you can also programmatically configure that through a plugin, which sounds like what you’re trying to do.

https://docs.gradle.org/current/userguide/init_scripts.html#sec:init_script_plugins

apply plugin: EnterpriseRepositoryPlugin

class EnterpriseRepositoryPlugin implements Plugin<Gradle> {

    private static String ENTERPRISE_REPOSITORY_URL = "https://repo.gradle.org/gradle/repo"

    void apply(Gradle gradle) {
        // ONLY USE ENTERPRISE REPO FOR DEPENDENCIES
        gradle.allprojects { project ->
            project.repositories {

                // Remove all repositories not pointing to the enterprise repository url
                all { ArtifactRepository repo ->
                    if (!(repo instanceof MavenArtifactRepository) ||
                          repo.url.toString() != ENTERPRISE_REPOSITORY_URL) {
                        project.logger.lifecycle "Repository ${repo.url} removed. Only $ENTERPRISE_REPOSITORY_URL is allowed"
                        remove repo
                    }
                }

                // add the enterprise repository
                maven {
                    name "STANDARD_ENTERPRISE_REPO"
                    url ENTERPRISE_REPOSITORY_URL
                }
            }
        }
    }
}
1 Like

The point is that you can’t do it for buildscript block. It’s a Gradle design limitation.

There is nothing in ~/.gradle/init.d/ that helps you with buildscript block. If it is no a requirement - you provided the sufficient solution.