Search code examples
kotlingradlemaven-publish

How to read Maven repository credentials only when needed?


I have a Gradle Kotlin DSL script that publishes some artifacts to a local Maven repository:

    publishing {
        publications {
            create<MavenPublication>("maven") {
                groupId = "my.company"
                artifactId = project.name
                version = "0.0.1"
                from(components["java"])
            }
        }
        repositories {
            maven {
                url = uri("https://maven.mycompany.com/content/repositories/whatever")
                credentials {
                    username = (read from some file)
                    password = (read from some file)
                }
            }
        }
    }

As you can see, Gradle will always try to read the username and password from file. Even if the publish task isn't going to be executed.

I tried to fix it by moving the credentials to a doFirst block in the publish task, but the code is simply never executed:

publishing {
  doFirst { // this doesn't compile, doFirst doesn't exist here 
  }
}
tasks.getByName("publish").doFirst {
  // this compiles just fine, but it's never executed
}
tasks.named("publish") {
  doFirst {
    // this compiles just fine, but it's never executed
  }
}

How do I set credentials so that it only happens when executing the publish task?


Solution

  • You are always configuring the credentials regardless if they are needed or not. You need to conditionally configure the credentials. This can be accomplished in many ways.

    For example, let's say you never want to publish snapshot versions. Your build could look something like:

    version = "0.0.1-SNAPSHOT"
    
    publishing {
        publications {
            create<MavenPublication>("maven") {
                from(components["java"])
            }
            repositories {
                maven {
                    url = uri("https://maven.mycompany.com/content/repositories/whatever")
                    if (!version.toString().contains("SNAPSHOT")) {
                        credentials {
                            username = property("username") as String
                            password = property("password") as String
                        }
                    }
                }
            }
        }
    }
    

    Notice the conditional. During the configuration phase, Gradle will evaluate that condition and skip credentials { } because the version contains SNAPSHOT.

    As I said, there are a variety of ways you can do the above. However, the best way is to use environment variables:

    publishing {
        publications {
            create<MavenPublication>("maven") {
                from(components["java"])
            }
            repositories {
                maven {
                    url = uri("https://maven.mycompany.com/content/repositories/whatever")
                    credentials {
                        username = System.getenv()["username"]
                        password = System.getenv()["password"]
                    }
                }
            }
        }
    }
    

    No conditions whatsoever. null is an acceptable value for the credentials and doesn't matter during the configuration phase. It only matters when you publish is when you will get a NullPointerException