Skip to content

Commit 8b6bb88

Browse files
committed
Fail ignition build when the same jar with multiple versions found in the module build result
Fixes: IGN-10168
1 parent 4fd236a commit 8b6bb88

File tree

4 files changed

+93
-2
lines changed

4 files changed

+93
-2
lines changed

gradle-module-plugin/build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ dependencies {
6161
implementation(libs.kotlinXmlBuilder)
6262
api(libs.moduleSigner)
6363
testImplementation(libs.kotlinTestJunit)
64+
testImplementation(libs.junit.jupiter.api)
6465
testImplementation("io.ia.sdk.tools.module.gen:generator-core")
6566
}
6667

gradle-module-plugin/gradle/libs.versions.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
[versions]
22
kotlin = "1.7.10"
33
moshi = "1.9.3"
4+
junit-jupiter = "5.11.4"
45

56
[libraries]
67
# Dependencies referencable in buildscripts. Note that dashes are replaced by periods in the buildscript reference.
78
guava = { module = "com.google.guava:guava", version = "30.1.1-jre" }
89
kotlinTest = { module = "org.jetbrains.kotlin:kotlin-test", version.ref = "kotlin" }
910
kotlinTestJunit = { module = "org.jetbrains.kotlin:kotlin-test-junit", version.ref = "kotlin" }
1011
kotlinXmlBuilder = { module = "org.redundent:kotlin-xml-builder", version = "1.7.2" }
12+
junit-jupiter-api = { module = "org.junit.jupiter:junit-jupiter-api", version.ref = "junit-jupiter" }
1113
moshi = { module = "com.squareup.moshi:moshi-kotlin", version.ref = "moshi" }
1214
moshiCodegen = { module = "com.squareup.moshi:moshi-kotlin-codegen", version.ref = "moshi" }
1315
moduleSigner = { module = "com.inductiveautomation.ignitionsdk:module-signer", version = "0.0.1.ia" }

gradle-module-plugin/src/functionalTest/kotlin/io/ia/sdk/gradle/modl/task/ZipModuleTests.kt

Lines changed: 53 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,62 @@ package io.ia.sdk.gradle.modl.task
33
import io.ia.ignition.module.generator.ModuleGenerator
44
import io.ia.sdk.gradle.modl.BaseTest
55
import io.ia.sdk.gradle.modl.util.unsignedModuleName
6-
import org.junit.Test
7-
import kotlin.test.assertTrue
6+
import org.gradle.api.Project
7+
import org.gradle.api.internal.project.DefaultProject
8+
import org.gradle.api.tasks.TaskExecutionException
9+
import org.gradle.testfixtures.ProjectBuilder
10+
import org.junit.jupiter.api.Assertions.assertThrows
11+
import org.junit.jupiter.api.Assertions.assertTrue
12+
import org.junit.jupiter.api.BeforeEach
13+
import org.junit.jupiter.api.Test
14+
import org.junit.jupiter.api.io.TempDir
15+
import java.io.File
816

917
class ZipModuleTests : BaseTest() {
1018

19+
@TempDir
20+
lateinit var testProjectDir: File
21+
private lateinit var project: Project
22+
private lateinit var task: ZipModule
23+
24+
@BeforeEach
25+
fun setup() {
26+
project = ProjectBuilder.builder().withProjectDir(testProjectDir).build() as DefaultProject
27+
task = project.tasks.create("testTask", ZipModule::class.java)
28+
29+
// Set up the task properties with the test directory
30+
task.content.set(project.objects.directoryProperty().fileValue(File(testProjectDir, "content")))
31+
task.unsignedModule.set(project.objects.fileProperty().fileValue(File(testProjectDir, "output.modl")))
32+
}
33+
34+
@Test
35+
fun `task succeeds when no duplicate jars exist`() {
36+
// Arrange
37+
val contentDir = File(testProjectDir, "content").apply { mkdirs() }
38+
File(contentDir, "my-lib-1.0.jar").createNewFile()
39+
File(contentDir, "another-lib-2.0.jar").createNewFile()
40+
41+
// Act & Assert: The task should not throw an exception
42+
task.execute()
43+
}
44+
45+
@Test
46+
fun `task fails when duplicate jars with different versions exist`() {
47+
// Arrange
48+
val contentDir = File(testProjectDir, "content").apply { mkdirs() }
49+
File(contentDir, "my-lib-1.0.jar").createNewFile()
50+
File(contentDir, "my-lib-2.0.jar").createNewFile() // This is the duplicate
51+
52+
// Act & Assert: The task should throw a TaskExecutionException
53+
val exception = assertThrows(TaskExecutionException::class.java) {
54+
task.execute()
55+
}
56+
57+
// Verify the exception message
58+
val expectedMessage = "Jar with 'my-lib' has multiple versions presented"
59+
assertTrue(exception.message!!.contains(expectedMessage))
60+
}
61+
1162
@Test
1263
fun `unsigned module is built and has appropriate name`() {
1364
val name = "Some Thing"

gradle-module-plugin/src/main/kotlin/io/ia/sdk/gradle/modl/task/ZipModule.kt

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ import org.gradle.api.tasks.OutputFile
1313
import org.gradle.api.tasks.PathSensitive
1414
import org.gradle.api.tasks.PathSensitivity
1515
import org.gradle.api.tasks.TaskAction
16+
import org.gradle.api.tasks.TaskExecutionException
17+
import java.io.File
1618
import javax.inject.Inject
1719

1820
/**
@@ -46,10 +48,45 @@ open class ZipModule @Inject constructor(objects: ObjectFactory) : DefaultTask()
4648
val unsignedFile = unsignedModule.get()
4749
val contentDir = content.get().asFile
4850

51+
checkDuplicateJars(contentDir)
52+
4953
project.logger.info("Zipping '${contentDir.absolutePath}' into ' ${unsignedFile.asFile.absolutePath}'")
5054
project.ant.invokeMethod(
5155
"zip",
5256
mapOf("basedir" to contentDir, "destfile" to unsignedFile)
5357
)
5458
}
59+
60+
/**
61+
* Try to detect jars in contentDir with the same name but have multiple
62+
* versions existed. Fail the build when it's found.
63+
**/
64+
fun checkDuplicateJars(contentDir: File) {
65+
project.logger.info("Parsing file name in: ${contentDir.absolutePath}")
66+
67+
val fileMap = mutableMapOf<String, String>()
68+
val regex = "^(.+?)-(\\d+.*)(?:\\.jar)".toRegex()
69+
70+
contentDir.walk().filter { it.isFile }.forEach { file ->
71+
val matchResult = regex.find(file.name) // Match all the jar files
72+
73+
if (matchResult != null) {
74+
val name = matchResult.groupValues[1]
75+
val version = matchResult.groupValues[2]
76+
77+
if (fileMap.containsKey(name)) {
78+
throw TaskExecutionException(
79+
this,
80+
IllegalArgumentException(
81+
"""Jar with '$name' has multiple versions presented in ${contentDir.absolutePath}
82+
Please ensure only one version exist (preferably the highest) and update lib.version.toml file if needed.
83+
""".trimIndent()
84+
)
85+
)
86+
} else {
87+
fileMap[name] = version
88+
}
89+
}
90+
}
91+
}
5592
}

0 commit comments

Comments
 (0)