From aa4b04744803b06b39914bb0acd98f44f803b8d5 Mon Sep 17 00:00:00 2001
From: Marc Philipp <mail@marcphilipp.de>
Date: Sun, 31 May 2020 15:06:00 +0200
Subject: [PATCH 1/3] Customize User-Agent

---
 build.gradle.kts                                            | 6 ++++++
 .../gradlenexus/publishplugin/NexusPublishPluginTests.kt    | 2 ++
 .../gradlenexus/publishplugin/internal/NexusClient.kt       | 6 ++++++
 3 files changed, 14 insertions(+)

diff --git a/build.gradle.kts b/build.gradle.kts
index 56603b58..e44a3793 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -152,6 +152,9 @@ tasks {
         dependsOn(relocateShadowJar)
         configurations = listOf(shadowed)
         exclude("META-INF/maven/**", "META-INF/proguard/**", "META-INF/*.kotlin_module")
+        manifest {
+            attributes["Implementation-Version"] = project.version
+        }
     }
     jar {
         enabled = false
@@ -186,6 +189,9 @@ tasks {
         useJUnitPlatform()
         maxParallelForks = 8
     }
+    withType<Test>().matching { it.name.startsWith("compatTest") }.configureEach {
+        systemProperty("plugin.version", project.version)
+    }
     dokka {
         configuration {
             outputFormat = "javadoc"
diff --git a/src/compatTest/kotlin/io/github/gradlenexus/publishplugin/NexusPublishPluginTests.kt b/src/compatTest/kotlin/io/github/gradlenexus/publishplugin/NexusPublishPluginTests.kt
index f403f3c2..12a430ef 100644
--- a/src/compatTest/kotlin/io/github/gradlenexus/publishplugin/NexusPublishPluginTests.kt
+++ b/src/compatTest/kotlin/io/github/gradlenexus/publishplugin/NexusPublishPluginTests.kt
@@ -20,6 +20,7 @@ import com.github.tomakehurst.wiremock.WireMockServer
 import com.github.tomakehurst.wiremock.client.WireMock.aResponse
 import com.github.tomakehurst.wiremock.client.WireMock.anyUrl
 import com.github.tomakehurst.wiremock.client.WireMock.containing
+import com.github.tomakehurst.wiremock.client.WireMock.equalTo
 import com.github.tomakehurst.wiremock.client.WireMock.get
 import com.github.tomakehurst.wiremock.client.WireMock.getRequestedFor
 import com.github.tomakehurst.wiremock.client.WireMock.matchingJsonPath
@@ -696,6 +697,7 @@ class NexusPublishPluginTests {
     @SafeVarargs
     private fun stubStagingProfileRequest(url: String, vararg stagingProfiles: Map<String, String>) {
         server.stubFor(get(urlEqualTo(url))
+                .withHeader("User-Agent", equalTo("gradle-nexus-publish-plugin/${System.getProperty("plugin.version")}"))
                 .willReturn(aResponse().withBody(gson.toJson(mapOf("data" to listOf(*stagingProfiles))))))
     }
 
diff --git a/src/main/kotlin/io/github/gradlenexus/publishplugin/internal/NexusClient.kt b/src/main/kotlin/io/github/gradlenexus/publishplugin/internal/NexusClient.kt
index 24ba685d..8c02b629 100644
--- a/src/main/kotlin/io/github/gradlenexus/publishplugin/internal/NexusClient.kt
+++ b/src/main/kotlin/io/github/gradlenexus/publishplugin/internal/NexusClient.kt
@@ -54,6 +54,12 @@ open class NexusClient(private val baseUrl: URI, username: String?, password: St
                                 .build())
                     }
         }
+        httpClientBuilder.addInterceptor { chain ->
+            val version = javaClass.`package`.implementationVersion
+            chain.proceed(chain.request().newBuilder()
+                    .header("User-Agent", "gradle-nexus-publish-plugin/$version")
+                    .build())
+        }
         val retrofit = Retrofit.Builder()
                 .baseUrl(baseUrl.toString())
                 .client(httpClientBuilder.build())

From 601a78abe6682063e54930973f1c5c3d005e2a9d Mon Sep 17 00:00:00 2001
From: Marc Philipp <mail@marcphilipp.de>
Date: Sun, 31 May 2020 15:29:12 +0200
Subject: [PATCH 2/3] Make staging repo description configurable

The description can now be customized on the extension or individual
tasks and now defaults to the GAV of the root project.

Resolves #31.
---
 .../publishplugin/NexusPublishPluginTests.kt        |  2 +-
 .../AbstractNexusStagingRepositoryTask.kt           |  6 ++++++
 .../publishplugin/CloseNexusStagingRepository.kt    |  2 +-
 .../InitializeNexusStagingRepository.kt             |  2 +-
 .../publishplugin/NexusPublishExtension.kt          |  4 ++++
 .../publishplugin/ReleaseNexusStagingRepository.kt  |  2 +-
 .../publishplugin/internal/NexusClient.kt           | 12 ++++++------
 .../internal/StagingRepositoryTransitioner.kt       |  8 ++++----
 .../internal/StagingRepositoryTransitionerTest.kt   | 13 +++++++------
 9 files changed, 31 insertions(+), 20 deletions(-)

diff --git a/src/compatTest/kotlin/io/github/gradlenexus/publishplugin/NexusPublishPluginTests.kt b/src/compatTest/kotlin/io/github/gradlenexus/publishplugin/NexusPublishPluginTests.kt
index 12a430ef..94fb8e71 100644
--- a/src/compatTest/kotlin/io/github/gradlenexus/publishplugin/NexusPublishPluginTests.kt
+++ b/src/compatTest/kotlin/io/github/gradlenexus/publishplugin/NexusPublishPluginTests.kt
@@ -200,7 +200,7 @@ class NexusPublishPluginTests {
         assertThat(result.output).containsOnlyOnce("Created staging repository '$STAGED_REPOSITORY_ID' at ${server.baseUrl()}/repositories/$STAGED_REPOSITORY_ID/content/")
         assertNotConsidered(result, ":initializeSomeOtherNexusStagingRepository")
         server.verify(postRequestedFor(urlEqualTo("/staging/profiles/$STAGING_PROFILE_ID/start"))
-                .withRequestBody(matchingJsonPath("\$.data[?(@.description == 'Created by io.github.gradle-nexus.publish-plugin Gradle plugin')]")))
+                .withRequestBody(matchingJsonPath("\$.data[?(@.description == 'org.example:sample:0.0.1')]")))
         assertUploadedToStagingRepo("/org/example/sample/0.0.1/sample-0.0.1.pom")
         assertUploadedToStagingRepo("/org/example/sample/0.0.1/sample-0.0.1.jar")
     }
diff --git a/src/main/kotlin/io/github/gradlenexus/publishplugin/AbstractNexusStagingRepositoryTask.kt b/src/main/kotlin/io/github/gradlenexus/publishplugin/AbstractNexusStagingRepositoryTask.kt
index c1927cf4..632aeadc 100644
--- a/src/main/kotlin/io/github/gradlenexus/publishplugin/AbstractNexusStagingRepositoryTask.kt
+++ b/src/main/kotlin/io/github/gradlenexus/publishplugin/AbstractNexusStagingRepositoryTask.kt
@@ -18,6 +18,7 @@ package io.github.gradlenexus.publishplugin
 
 import org.gradle.api.DefaultTask
 import org.gradle.api.model.ObjectFactory
+import org.gradle.api.tasks.Input
 import org.gradle.api.tasks.Internal
 import org.gradle.api.tasks.Nested
 import org.gradle.kotlin.dsl.property
@@ -44,6 +45,11 @@ constructor(objects: ObjectFactory, extension: NexusPublishExtension, repository
         set(repository)
     }
 
+    @Input
+    val description = objects.property<String>().apply {
+        set(extension.description)
+    }
+
     init {
         this.onlyIf { extension.useStaging.getOrElse(false) }
     }
diff --git a/src/main/kotlin/io/github/gradlenexus/publishplugin/CloseNexusStagingRepository.kt b/src/main/kotlin/io/github/gradlenexus/publishplugin/CloseNexusStagingRepository.kt
index 9dc05832..9bc07a26 100644
--- a/src/main/kotlin/io/github/gradlenexus/publishplugin/CloseNexusStagingRepository.kt
+++ b/src/main/kotlin/io/github/gradlenexus/publishplugin/CloseNexusStagingRepository.kt
@@ -50,7 +50,7 @@ constructor(objects: ObjectFactory, extension: NexusPublishExtension, repository
         val client = NexusClient(repository.get().nexusUrl.get(), repository.get().username.orNull, repository.get().password.orNull, clientTimeout.orNull, connectTimeout.orNull)
         val repositoryTransitioner = StagingRepositoryTransitioner(client, BasicActionRetrier.retryUntilRepoTransitionIsCompletedRetrier(repository.get().retrying.get()))
         logger.info("Closing staging repository with id '{}'", stagingRepositoryId.get())
-        repositoryTransitioner.effectivelyClose(stagingRepositoryId.get())
+        repositoryTransitioner.effectivelyClose(stagingRepositoryId.get(), description.get())
         logger.info("Repository with id '{}' effectively closed", stagingRepositoryId.get())
     }
 }
diff --git a/src/main/kotlin/io/github/gradlenexus/publishplugin/InitializeNexusStagingRepository.kt b/src/main/kotlin/io/github/gradlenexus/publishplugin/InitializeNexusStagingRepository.kt
index 4b5e57ba..b59019ef 100644
--- a/src/main/kotlin/io/github/gradlenexus/publishplugin/InitializeNexusStagingRepository.kt
+++ b/src/main/kotlin/io/github/gradlenexus/publishplugin/InitializeNexusStagingRepository.kt
@@ -49,7 +49,7 @@ open class InitializeNexusStagingRepository @Inject constructor(
         val client = NexusClient(serverUrl, repository.username.orNull, repository.password.orNull, clientTimeout.orNull, connectTimeout.orNull)
         val stagingProfileId = determineStagingProfileId(repository, client)
         logger.info("Creating staging repository for {} at {}, stagingProfileId '{}'", repository.name, serverUrl, stagingProfileId)
-        val descriptor = client.createStagingRepository(stagingProfileId)
+        val descriptor = client.createStagingRepository(stagingProfileId, description.get())
         val consumerUrl = HttpUrl.get(serverUrl)!!.newBuilder().addEncodedPathSegments("repositories/${descriptor.stagingRepositoryId}/content/").build()
         logger.lifecycle("Created staging repository '{}' at {}", descriptor.stagingRepositoryId, consumerUrl)
         registry.get()[repository.name] = descriptor
diff --git a/src/main/kotlin/io/github/gradlenexus/publishplugin/NexusPublishExtension.kt b/src/main/kotlin/io/github/gradlenexus/publishplugin/NexusPublishExtension.kt
index 2820fbc9..7a7b670a 100644
--- a/src/main/kotlin/io/github/gradlenexus/publishplugin/NexusPublishExtension.kt
+++ b/src/main/kotlin/io/github/gradlenexus/publishplugin/NexusPublishExtension.kt
@@ -38,6 +38,10 @@ open class NexusPublishExtension(project: Project) {
         set(project.provider { project.group.toString() })
     }
 
+    val description = project.objects.property<String>().apply {
+        set(project.provider { project.run { "$group:$name:$version" } })
+    }
+
     val clientTimeout = project.objects.property<Duration>().apply {
         set(Duration.ofMinutes(1))
     }
diff --git a/src/main/kotlin/io/github/gradlenexus/publishplugin/ReleaseNexusStagingRepository.kt b/src/main/kotlin/io/github/gradlenexus/publishplugin/ReleaseNexusStagingRepository.kt
index 6ea957ba..3c317df4 100644
--- a/src/main/kotlin/io/github/gradlenexus/publishplugin/ReleaseNexusStagingRepository.kt
+++ b/src/main/kotlin/io/github/gradlenexus/publishplugin/ReleaseNexusStagingRepository.kt
@@ -49,7 +49,7 @@ constructor(objects: ObjectFactory, extension: NexusPublishExtension, repository
         val client = NexusClient(repository.get().nexusUrl.get(), repository.get().username.orNull, repository.get().password.orNull, clientTimeout.orNull, connectTimeout.orNull)
         val repositoryTransitioner = StagingRepositoryTransitioner(client, BasicActionRetrier.retryUntilRepoTransitionIsCompletedRetrier(repository.get().retrying.get()))
         logger.info("Releasing staging repository with id '{}'", stagingRepositoryId.get())
-        repositoryTransitioner.effectivelyRelease(stagingRepositoryId.get())
+        repositoryTransitioner.effectivelyRelease(stagingRepositoryId.get(), description.get())
         logger.info("Repository with id '{}' effectively released", stagingRepositoryId.get())
     }
 }
diff --git a/src/main/kotlin/io/github/gradlenexus/publishplugin/internal/NexusClient.kt b/src/main/kotlin/io/github/gradlenexus/publishplugin/internal/NexusClient.kt
index 8c02b629..e74c93f4 100644
--- a/src/main/kotlin/io/github/gradlenexus/publishplugin/internal/NexusClient.kt
+++ b/src/main/kotlin/io/github/gradlenexus/publishplugin/internal/NexusClient.kt
@@ -86,8 +86,8 @@ open class NexusClient(private val baseUrl: URI, username: String?, password: St
                 ?.id
     }
 
-    fun createStagingRepository(stagingProfileId: String): StagingRepositoryDescriptor {
-        val response = api.startStagingRepo(stagingProfileId, Dto(Description("Created by io.github.gradle-nexus.publish-plugin Gradle plugin"))).execute()
+    fun createStagingRepository(stagingProfileId: String, description: String): StagingRepositoryDescriptor {
+        val response = api.startStagingRepo(stagingProfileId, Dto(Description(description))).execute()
         if (!response.isSuccessful) {
             throw failure("create staging repository", response)
         }
@@ -95,15 +95,15 @@ open class NexusClient(private val baseUrl: URI, username: String?, password: St
         return StagingRepositoryDescriptor(baseUrl, stagingRepositoryId)
     }
 
-    open fun closeStagingRepository(stagingRepositoryId: String) {
-        val response = api.closeStagingRepo(Dto(StagingRepositoryToTransit(listOf(stagingRepositoryId), "Closed by io.github.gradle-nexus.publish-plugin Gradle plugin"))).execute()
+    open fun closeStagingRepository(stagingRepositoryId: String, description: String) {
+        val response = api.closeStagingRepo(Dto(StagingRepositoryToTransit(listOf(stagingRepositoryId), description))).execute()
         if (!response.isSuccessful) {
             throw failure("close staging repository", response)
         }
     }
 
-    open fun releaseStagingRepository(stagingRepositoryId: String) {
-        val response = api.releaseStagingRepo(Dto(StagingRepositoryToTransit(listOf(stagingRepositoryId), "Release by io.github.gradle-nexus.publish-plugin Gradle plugin"))).execute()
+    open fun releaseStagingRepository(stagingRepositoryId: String, description: String) {
+        val response = api.releaseStagingRepo(Dto(StagingRepositoryToTransit(listOf(stagingRepositoryId), description))).execute()
         if (!response.isSuccessful) {
             throw failure("release staging repository", response)
         }
diff --git a/src/main/kotlin/io/github/gradlenexus/publishplugin/internal/StagingRepositoryTransitioner.kt b/src/main/kotlin/io/github/gradlenexus/publishplugin/internal/StagingRepositoryTransitioner.kt
index 08127e3b..96e4811f 100644
--- a/src/main/kotlin/io/github/gradlenexus/publishplugin/internal/StagingRepositoryTransitioner.kt
+++ b/src/main/kotlin/io/github/gradlenexus/publishplugin/internal/StagingRepositoryTransitioner.kt
@@ -26,13 +26,13 @@ class StagingRepositoryTransitioner(val nexusClient: NexusClient, val retrier: A
         private val log: Logger = LoggerFactory.getLogger(StagingRepositoryTransitioner::class.java.simpleName)
     }
 
-    fun effectivelyClose(repoId: String) {
-        effectivelyChangeState(repoId, StagingRepository.State.CLOSED, nexusClient::closeStagingRepository)
+    fun effectivelyClose(repoId: String, description: String) {
+        effectivelyChangeState(repoId, StagingRepository.State.CLOSED) { nexusClient.closeStagingRepository(it, description) }
     }
 
     //TODO: Add support for autoDrop=false
-    fun effectivelyRelease(repoId: String) {
-        effectivelyChangeState(repoId, StagingRepository.State.NOT_FOUND, nexusClient::releaseStagingRepository)
+    fun effectivelyRelease(repoId: String, description: String) {
+        effectivelyChangeState(repoId, StagingRepository.State.NOT_FOUND) { nexusClient.releaseStagingRepository(it, description) }
     }
 
     private fun effectivelyChangeState(repoId: String, desiredState: StagingRepository.State, transitionClientRequest: (String) -> Unit) {
diff --git a/src/test/kotlin/io/github/gradlenexus/publishplugin/internal/StagingRepositoryTransitionerTest.kt b/src/test/kotlin/io/github/gradlenexus/publishplugin/internal/StagingRepositoryTransitionerTest.kt
index 1ebb8937..37861d54 100644
--- a/src/test/kotlin/io/github/gradlenexus/publishplugin/internal/StagingRepositoryTransitionerTest.kt
+++ b/src/test/kotlin/io/github/gradlenexus/publishplugin/internal/StagingRepositoryTransitionerTest.kt
@@ -33,6 +33,7 @@ internal class StagingRepositoryTransitionerTest {
 
     companion object {
         private const val TEST_STAGING_REPO_ID = "orgexample-42"
+        private const val DESCRIPTION = "some description"
     }
 
     @Mock
@@ -53,10 +54,10 @@ internal class StagingRepositoryTransitionerTest {
                 .willReturn(StagingRepository(TEST_STAGING_REPO_ID, StagingRepository.State.CLOSED, false))
         given(retrier.execute(anyOrNull())).willAnswer(executeFunctionPassedAsFirstArgument())
 
-        transitioner.effectivelyClose(TEST_STAGING_REPO_ID)
+        transitioner.effectivelyClose(TEST_STAGING_REPO_ID, DESCRIPTION)
 
         val inOrder = inOrder(nexusClient, retrier)
-        inOrder.verify(nexusClient).closeStagingRepository(TEST_STAGING_REPO_ID)
+        inOrder.verify(nexusClient).closeStagingRepository(TEST_STAGING_REPO_ID, DESCRIPTION)
         inOrder.verify(nexusClient).getStagingRepositoryStateById(TEST_STAGING_REPO_ID)
     }
 
@@ -66,10 +67,10 @@ internal class StagingRepositoryTransitionerTest {
                 .willReturn(StagingRepository(TEST_STAGING_REPO_ID, StagingRepository.State.NOT_FOUND, false))
         given(retrier.execute(anyOrNull())).willAnswer(executeFunctionPassedAsFirstArgument())
 
-        transitioner.effectivelyRelease(TEST_STAGING_REPO_ID)
+        transitioner.effectivelyRelease(TEST_STAGING_REPO_ID, DESCRIPTION)
 
         val inOrder = inOrder(nexusClient, retrier)
-        inOrder.verify(nexusClient).releaseStagingRepository(TEST_STAGING_REPO_ID)
+        inOrder.verify(nexusClient).releaseStagingRepository(TEST_STAGING_REPO_ID, DESCRIPTION)
         inOrder.verify(nexusClient).getStagingRepositoryStateById(TEST_STAGING_REPO_ID)
     }
 
@@ -80,7 +81,7 @@ internal class StagingRepositoryTransitionerTest {
         given(retrier.execute(anyOrNull())).willAnswer(executeFunctionPassedAsFirstArgument())
 
         assertThatExceptionOfType(RepositoryTransitionException::class.java)
-                .isThrownBy { transitioner.effectivelyClose(TEST_STAGING_REPO_ID) }
+                .isThrownBy { transitioner.effectivelyClose(TEST_STAGING_REPO_ID, DESCRIPTION) }
                 .withMessageContainingAll(TEST_STAGING_REPO_ID, "transitioning=true")
     }
 
@@ -91,7 +92,7 @@ internal class StagingRepositoryTransitionerTest {
         given(retrier.execute(anyOrNull())).willAnswer(executeFunctionPassedAsFirstArgument())
 
         assertThatExceptionOfType(RepositoryTransitionException::class.java)
-                .isThrownBy { transitioner.effectivelyClose(TEST_STAGING_REPO_ID) }
+                .isThrownBy { transitioner.effectivelyClose(TEST_STAGING_REPO_ID, DESCRIPTION) }
                 .withMessageContainingAll(TEST_STAGING_REPO_ID, StagingRepository.State.OPEN.toString(), StagingRepository.State.CLOSED.toString())
     }
 

From 14512e4eeee1e1ca73ffa437def1e73501e49e9c Mon Sep 17 00:00:00 2001
From: Marc Philipp <mail@marcphilipp.de>
Date: Sun, 31 May 2020 20:38:57 +0200
Subject: [PATCH 3/3] Make test work when run via IntelliJ IDEA

---
 .../gradlenexus/publishplugin/NexusPublishPluginTests.kt  | 8 ++++----
 .../gradlenexus/publishplugin/internal/NexusClient.kt     | 2 +-
 2 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/src/compatTest/kotlin/io/github/gradlenexus/publishplugin/NexusPublishPluginTests.kt b/src/compatTest/kotlin/io/github/gradlenexus/publishplugin/NexusPublishPluginTests.kt
index 94fb8e71..cced52b8 100644
--- a/src/compatTest/kotlin/io/github/gradlenexus/publishplugin/NexusPublishPluginTests.kt
+++ b/src/compatTest/kotlin/io/github/gradlenexus/publishplugin/NexusPublishPluginTests.kt
@@ -20,9 +20,9 @@ import com.github.tomakehurst.wiremock.WireMockServer
 import com.github.tomakehurst.wiremock.client.WireMock.aResponse
 import com.github.tomakehurst.wiremock.client.WireMock.anyUrl
 import com.github.tomakehurst.wiremock.client.WireMock.containing
-import com.github.tomakehurst.wiremock.client.WireMock.equalTo
 import com.github.tomakehurst.wiremock.client.WireMock.get
 import com.github.tomakehurst.wiremock.client.WireMock.getRequestedFor
+import com.github.tomakehurst.wiremock.client.WireMock.matching
 import com.github.tomakehurst.wiremock.client.WireMock.matchingJsonPath
 import com.github.tomakehurst.wiremock.client.WireMock.post
 import com.github.tomakehurst.wiremock.client.WireMock.postRequestedFor
@@ -33,8 +33,6 @@ import com.github.tomakehurst.wiremock.client.WireMock.urlMatching
 import com.github.tomakehurst.wiremock.stubbing.Scenario
 import com.google.gson.Gson
 import io.github.gradlenexus.publishplugin.internal.StagingRepository
-import java.nio.file.Files
-import java.nio.file.Path
 import org.assertj.core.api.Assertions.assertThat
 import org.gradle.testkit.runner.BuildResult
 import org.gradle.testkit.runner.GradleRunner
@@ -52,6 +50,8 @@ import org.junit.jupiter.api.extension.ExtendWith
 import org.junit.jupiter.api.io.TempDir
 import ru.lanwen.wiremock.ext.WiremockResolver
 import ru.lanwen.wiremock.ext.WiremockResolver.Wiremock
+import java.nio.file.Files
+import java.nio.file.Path
 
 @Suppress("FunctionName") // TODO: How to suppress "kotlin:S100" from SonarLint?
 @ExtendWith(WiremockResolver::class)
@@ -697,7 +697,7 @@ class NexusPublishPluginTests {
     @SafeVarargs
     private fun stubStagingProfileRequest(url: String, vararg stagingProfiles: Map<String, String>) {
         server.stubFor(get(urlEqualTo(url))
-                .withHeader("User-Agent", equalTo("gradle-nexus-publish-plugin/${System.getProperty("plugin.version")}"))
+                .withHeader("User-Agent", matching("gradle-nexus-publish-plugin/.*"))
                 .willReturn(aResponse().withBody(gson.toJson(mapOf("data" to listOf(*stagingProfiles))))))
     }
 
diff --git a/src/main/kotlin/io/github/gradlenexus/publishplugin/internal/NexusClient.kt b/src/main/kotlin/io/github/gradlenexus/publishplugin/internal/NexusClient.kt
index e74c93f4..eb26e0d3 100644
--- a/src/main/kotlin/io/github/gradlenexus/publishplugin/internal/NexusClient.kt
+++ b/src/main/kotlin/io/github/gradlenexus/publishplugin/internal/NexusClient.kt
@@ -55,7 +55,7 @@ open class NexusClient(private val baseUrl: URI, username: String?, password: St
                     }
         }
         httpClientBuilder.addInterceptor { chain ->
-            val version = javaClass.`package`.implementationVersion
+            val version = javaClass.`package`.implementationVersion ?: "dev"
             chain.proceed(chain.request().newBuilder()
                     .header("User-Agent", "gradle-nexus-publish-plugin/$version")
                     .build())