Skip to content

Commit ce1af1a

Browse files
committed
Add manual mode to skip publishing when artifact already exists
1 parent d566c68 commit ce1af1a

File tree

6 files changed

+131
-15
lines changed

6 files changed

+131
-15
lines changed

build.gradle.kts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ gradlePlugin {
3232
id = "dev.poolside.gradle.semantic-version"
3333
group = "dev.poolside.gradle.semanticversion"
3434
implementationClass = "dev.poolside.gradle.semanticversion.SemanticVersionPlugin"
35-
version = "0.1.2"
35+
version = "0.1.3"
3636
displayName = "Poolside Semantic Version Plugin"
3737
}
3838
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package dev.poolside.gradle.semanticversion
2+
3+
open class SemanticVersionExtension {
4+
var manual = false
5+
}

src/main/kotlin/dev/poolside/gradle/semanticversion/SemanticVersionPlugin.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,11 @@ import org.gradle.kotlin.dsl.withType
88

99
class SemanticVersionPlugin : Plugin<Project> {
1010
override fun apply(project: Project) {
11+
val extension = project.extensions.create("semanticVersion", SemanticVersionExtension::class.java)
1112
project.tasks.register("semanticVersion", SemanticVersionTask::class.java) {
1213
this.description = "Determines and sets the semantic version"
1314
this.group = "publishing"
15+
this.manual = extension.manual
1416
}
1517
project.tasks.withType<JavaCompile> {
1618
this.dependsOn("semanticVersion")

src/main/kotlin/dev/poolside/gradle/semanticversion/SemanticVersionTask.kt

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import org.gradle.api.DefaultTask
44
import org.gradle.api.internal.artifacts.repositories.ResolutionAwareRepository
55
import org.gradle.api.publish.PublishingExtension
66
import org.gradle.api.publish.maven.MavenPublication
7+
import org.gradle.api.publish.maven.tasks.PublishToMavenRepository
8+
import org.gradle.api.tasks.Input
79
import org.gradle.api.tasks.TaskAction
810
import org.w3c.dom.Element
911

@@ -12,8 +14,19 @@ abstract class SemanticVersionTask : DefaultTask() {
1214
private val versionRegex = "^\\d+\\.\\d+\$".toRegex()
1315
private val versions = mutableMapOf<String, String>()
1416

17+
@Input
18+
var manual: Boolean = false
19+
1520
@TaskAction
1621
fun setVersion() {
22+
if (manual) {
23+
manual()
24+
} else {
25+
automatic()
26+
}
27+
}
28+
29+
private fun automatic() {
1730
project.allprojects.forEach { p ->
1831
val extension = p.extensions.getByType(PublishingExtension::class.java)
1932
extension.repositories.forEach {
@@ -35,6 +48,29 @@ abstract class SemanticVersionTask : DefaultTask() {
3548
}
3649
}
3750

51+
private fun manual() {
52+
project.allprojects.forEach { p ->
53+
val extension = p.extensions.getByType(PublishingExtension::class.java)
54+
extension.repositories.forEach {
55+
if (it is ResolutionAwareRepository) {
56+
val resolver = it.createResolver()
57+
extension.publications.forEach { publication ->
58+
val pub = publication as MavenPublication
59+
val exists = VersionFinder.versionExists(logger, project, resolver, pub)
60+
project.tasks.withType(PublishToMavenRepository::class.java).configureEach {
61+
onlyIf {
62+
if (exists) {
63+
logger.lifecycle("Resolved published version of '${publication.groupId}:${publication.artifactId}:${publication.version}' already exists")
64+
}
65+
!exists
66+
}
67+
}
68+
}
69+
}
70+
}
71+
}
72+
}
73+
3874
private fun checkVersion(version: String) {
3975
if (!versionRegex.matches(version)) {
4076
throw IllegalArgumentException("Invalid version, must be in format $versionRegex")

src/main/kotlin/dev/poolside/gradle/semanticversion/VersionFinder.kt

Lines changed: 24 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -19,21 +19,9 @@ object VersionFinder {
1919
private val versionComparator = DefaultVersionComparator().asVersionComparator()
2020

2121
fun findVersion(logger: Logger, project: Project, resolver: ConfiguredModuleComponentRepository, publication: MavenPublication): Pair<String, String> {
22-
val remote = resolver.remoteAccess
23-
val local = resolver.localAccess
24-
25-
val dep = project.dependencies.create(group = publication.groupId, name = publication.artifactId, version = "${publication.version}+")
26-
val selector = DefaultModuleComponentSelector.newSelector(dep.module, dep.versionConstraint)
27-
val metadata = GradleDependencyMetadata(selector, Collections.emptyList(), false, false, null, false, null)
28-
29-
val result = DefaultBuildableModuleVersionListingResolveResult()
30-
remote.listModuleVersions(metadata, result)
31-
local.listModuleVersions(metadata, result)
32-
33-
logger.debug("Resolved versions ${result.versions}")
34-
22+
val versions = listVersions(logger, project, resolver, publication, "${publication.version}+")
3523
var latestVersion: Version? = null
36-
result.versions.map { version -> versionParser.transform(version) }.forEach { version ->
24+
versions.map { version -> versionParser.transform(version) }.forEach { version ->
3725
if (latestVersion == null || versionComparator.compare(version, latestVersion) > 0) {
3826
latestVersion = version
3927
}
@@ -51,6 +39,28 @@ object VersionFinder {
5139
return "${publication.groupId}:${publication.artifactId}" to version
5240
}
5341

42+
fun versionExists(logger: Logger, project: Project, resolver: ConfiguredModuleComponentRepository, publication: MavenPublication): Boolean {
43+
val versions = listVersions(logger, project, resolver, publication, publication.version)
44+
return versions.contains(publication.version)
45+
}
46+
47+
private fun listVersions(logger: Logger, project: Project, resolver: ConfiguredModuleComponentRepository, publication: MavenPublication, versionSearch: String): Set<String> {
48+
val remote = resolver.remoteAccess
49+
val local = resolver.localAccess
50+
51+
val dep = project.dependencies.create(group = publication.groupId, name = publication.artifactId, version = versionSearch)
52+
val selector = DefaultModuleComponentSelector.newSelector(dep.module, dep.versionConstraint)
53+
val metadata = GradleDependencyMetadata(selector, Collections.emptyList(), false, false, null, false, null)
54+
55+
val result = DefaultBuildableModuleVersionListingResolveResult()
56+
remote.listModuleVersions(metadata, result)
57+
local.listModuleVersions(metadata, result)
58+
59+
logger.debug("Resolved versions ${result.versions}")
60+
61+
return result.versions
62+
}
63+
5464
private fun incrementVersion(version: Version): String {
5565
val parts = version.numericParts.filterNotNull()
5666
val last = parts.last() + 1

src/test/kotlin/dev/poolside/gradle/semanticversion/SemanticVersionPluginTest.kt

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,11 @@ import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.strategy.DefaultV
44
import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.strategy.Version
55
import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.strategy.VersionParser
66
import org.gradle.testkit.runner.GradleRunner
7+
import org.gradle.testkit.runner.TaskOutcome
78
import org.gradle.testkit.runner.TaskOutcome.FAILED
89
import org.gradle.testkit.runner.UnexpectedBuildFailure
910
import org.junit.jupiter.api.Assertions.assertEquals
11+
import org.junit.jupiter.api.Assertions.assertFalse
1012
import org.junit.jupiter.api.Assertions.assertTrue
1113
import org.junit.jupiter.api.Assertions.fail
1214
import org.junit.jupiter.api.Test
@@ -343,4 +345,65 @@ class SemanticVersionPluginTest {
343345
}
344346
assertEquals("0.1.2", latestVersion.toString())
345347
}
348+
349+
@Test
350+
fun `manual versioning`() {
351+
val build = """
352+
plugins {
353+
java
354+
`maven-publish`
355+
id("dev.poolside.gradle.semantic-version")
356+
}
357+
repositories {
358+
maven { url = uri("${mavenRepo.absolutePath}") }
359+
}
360+
group = "dev.poolside.test"
361+
version = "0.1.0"
362+
semanticVersion {
363+
manual = true
364+
}
365+
publishing {
366+
repositories {
367+
maven { url = uri("${mavenRepo.absolutePath}") }
368+
}
369+
publications {
370+
create<MavenPublication>("mavenJava") {
371+
artifactId = "my-library"
372+
from(components["java"])
373+
}
374+
}
375+
}
376+
""".trimIndent()
377+
val settings = """rootProject.name = "testing""""
378+
File(testProjectDir, "build.gradle.kts").writeText(build)
379+
File(testProjectDir, "settings.gradle.kts").writeText(settings)
380+
GradleRunner.create()
381+
.withPluginClasspath()
382+
.withProjectDir(testProjectDir)
383+
.withArguments("publish")
384+
// .withDebug(true)
385+
.build()
386+
var pomFile = testProjectDir.walk().filter { it.name.startsWith("pom") }.first()
387+
var pom = PomParser.parse(pomFile.absolutePath)
388+
assertEquals("0.1.0", pom.version)
389+
var jarFile = mavenRepo.walk().filter { it.name.endsWith("jar") }.first()
390+
assertTrue(jarFile.absolutePath.endsWith("/dev/poolside/test/my-library/0.1.0/my-library-0.1.0.jar"))
391+
val publishedPom = mavenRepo.walk().filter { it.name.equals("my-library-0.1.0.pom") }.first()
392+
pom = PomParser.parse(publishedPom.absolutePath)
393+
assertEquals("0.1.0", pom.version)
394+
395+
// should skip
396+
val result = GradleRunner.create()
397+
.withPluginClasspath()
398+
.withProjectDir(testProjectDir)
399+
.withArguments("publish")
400+
// .withDebug(true)
401+
.build()
402+
assertEquals(1, result.taskPaths(TaskOutcome.SKIPPED).size)
403+
pomFile = testProjectDir.walk().filter { it.name.startsWith("pom") }.last()
404+
pom = PomParser.parse(pomFile.absolutePath)
405+
assertEquals("0.1.0", pom.version)
406+
jarFile = mavenRepo.walk().filter { it.name.endsWith("jar") }.last()
407+
assertFalse(jarFile.absolutePath.endsWith("/dev/poolside/test/my-library/0.1.1/my-library-0.1.1.jar"))
408+
}
346409
}

0 commit comments

Comments
 (0)