diff --git a/gradle-plugin/src/functionalTest/kotlin/io/spine/embedcode/gradle/EmbedCodePluginSpec.kt b/gradle-plugin/src/functionalTest/kotlin/io/spine/embedcode/gradle/EmbedCodePluginSpec.kt index 2788e4c..b3c95a6 100644 --- a/gradle-plugin/src/functionalTest/kotlin/io/spine/embedcode/gradle/EmbedCodePluginSpec.kt +++ b/gradle-plugin/src/functionalTest/kotlin/io/spine/embedcode/gradle/EmbedCodePluginSpec.kt @@ -125,6 +125,42 @@ internal class EmbedCodePluginSpec { result.output shouldContain "Downloading Embed Code $TEST_RELEASE_TAG" } + @Test + fun `install the Linux ZIP release asset`() { + val releaseTag = "v1.2.5" + val asset = releaseDirectory.resolve( + "download/$releaseTag/embed-code-linux.zip", + ) + Files.createDirectories(asset.parent) + ZipOutputStream(Files.newOutputStream(asset)).use { zip -> + zip.putNextEntry(ZipEntry("embed-code-linux")) + zip.write("Linux executable".toByteArray()) + zip.closeEntry() + } + writeBuildFile(version = releaseTag, sha256 = sha256(asset)) + selectLinuxReleaseAsset() + + val result = runner(":installEmbedCode").build() + + result.task(":installEmbedCode")?.outcome shouldBe TaskOutcome.SUCCESS + Files.readString(installedExecutable(releaseTag)) shouldBe "Linux executable" + } + + @Test + fun `install a bare Linux asset from a release published before ZIP packaging`() { + val asset = releaseDirectory.resolve( + "download/$TEST_RELEASE_TAG/embed-code-linux", + ) + Files.writeString(asset, "Legacy Linux executable") + writeBuildFile(sha256 = sha256(asset)) + selectLinuxReleaseAsset() + + val result = runner(":installEmbedCode").build() + + result.task(":installEmbedCode")?.outcome shouldBe TaskOutcome.SUCCESS + Files.readString(installedExecutable()) shouldBe "Legacy Linux executable" + } + @Test fun `reuse the verified default executable without another download`() { val downloads = AtomicInteger() @@ -340,6 +376,7 @@ internal class EmbedCodePluginSpec { val platform = EmbedCodePlatform.detect( System.getProperty("os.name"), System.getProperty("os.arch"), + TEST_RELEASE_TAG, ) val taskTemporaryDirectory = projectDirectory.resolve("build/tmp/installEmbedCode") Files.createDirectories(taskTemporaryDirectory) @@ -757,6 +794,7 @@ internal class EmbedCodePluginSpec { val platform = EmbedCodePlatform.detect( System.getProperty("os.name"), System.getProperty("os.arch"), + TEST_RELEASE_TAG, ) val source = "$baseUrl/download/$TEST_RELEASE_TAG/${platform.assetName}" result.task(":installEmbedCode")?.outcome shouldBe TaskOutcome.FAILED @@ -1002,6 +1040,23 @@ internal class EmbedCodePluginSpec { ) } + /** + * Overrides the installation task to select the Linux AMD64 release asset. + */ + private fun selectLinuxReleaseAsset() { + Files.writeString( + projectDirectory.resolve("build.gradle.kts"), + """ + + tasks.named("installEmbedCode") { + operatingSystem.set("Linux") + architecture.set("amd64") + } + """.trimIndent(), + StandardOpenOption.APPEND, + ) + } + /** * Returns the cache directory for [releaseTag]. */ @@ -1070,6 +1125,7 @@ internal class EmbedCodePluginSpec { val platform = EmbedCodePlatform.detect( System.getProperty("os.name"), System.getProperty("os.arch"), + tag, ) val versionDirectory = root.resolve("download/$tag") Files.createDirectories(versionDirectory) @@ -1117,6 +1173,7 @@ internal class EmbedCodePluginSpec { val platform = EmbedCodePlatform.detect( System.getProperty("os.name"), System.getProperty("os.arch"), + tag.trim(), ) val asset = root.resolve("download/${tag.trim()}/${platform.assetName}") return sha256(asset) diff --git a/gradle-plugin/src/main/kotlin/io/spine/embedcode/gradle/EmbedCodePlatform.kt b/gradle-plugin/src/main/kotlin/io/spine/embedcode/gradle/EmbedCodePlatform.kt index 818a319..8401e15 100644 --- a/gradle-plugin/src/main/kotlin/io/spine/embedcode/gradle/EmbedCodePlatform.kt +++ b/gradle-plugin/src/main/kotlin/io/spine/embedcode/gradle/EmbedCodePlatform.kt @@ -50,9 +50,13 @@ internal data class EmbedCodePlatform( } /** - * Selects the release asset for [osName] and [architecture]. + * Selects the release asset for [osName], [architecture], and [releaseTag]. */ - fun detect(osName: String, architecture: String): EmbedCodePlatform { + fun detect( + osName: String, + architecture: String, + releaseTag: String, + ): EmbedCodePlatform { val os = osName.lowercase(Locale.ROOT) val arch = architecture.lowercase(Locale.ROOT) val isAmd64 = arch == "amd64" || arch == "x86_64" @@ -70,7 +74,11 @@ internal data class EmbedCodePlatform( ) os.contains("linux") && isAmd64 -> EmbedCodePlatform( - "embed-code-linux", + if (releaseTag in bareLinuxAssetReleases) { + "embed-code-linux" + } else { + "embed-code-linux.zip" + }, "embed-code-linux", ) @@ -85,5 +93,13 @@ internal data class EmbedCodePlatform( ) } } + + /** + * All releases published before Linux ZIP packaging was introduced. + * + * The upstream release workflow defines ZIP packaging for subsequent releases. + * Update this mapping if that workflow changes. + */ + private val bareLinuxAssetReleases = setOf("v1.2.3", "v1.2.4") } } diff --git a/gradle-plugin/src/main/kotlin/io/spine/embedcode/gradle/InstallEmbedCodeTask.kt b/gradle-plugin/src/main/kotlin/io/spine/embedcode/gradle/InstallEmbedCodeTask.kt index b466eb0..f3f1a5f 100644 --- a/gradle-plugin/src/main/kotlin/io/spine/embedcode/gradle/InstallEmbedCodeTask.kt +++ b/gradle-plugin/src/main/kotlin/io/spine/embedcode/gradle/InstallEmbedCodeTask.kt @@ -134,7 +134,11 @@ public abstract class InstallEmbedCodeTask : DefaultTask() { hostOperatingSystem, hostArchitecture, ) - val platform = EmbedCodePlatform.detect(hostOperatingSystem, hostArchitecture) + val platform = EmbedCodePlatform.detect( + hostOperatingSystem, + hostArchitecture, + releaseTag, + ) val asset = platform.assetName val baseUrl = trimTrailingSlashes(downloadBaseUrl.get()) val installationRoot = installationDirectory.get().asFile.toPath() diff --git a/gradle-plugin/src/test/kotlin/io/spine/embedcode/gradle/EmbedCodePlatformSpec.kt b/gradle-plugin/src/test/kotlin/io/spine/embedcode/gradle/EmbedCodePlatformSpec.kt index 80b53a4..9b066f6 100644 --- a/gradle-plugin/src/test/kotlin/io/spine/embedcode/gradle/EmbedCodePlatformSpec.kt +++ b/gradle-plugin/src/test/kotlin/io/spine/embedcode/gradle/EmbedCodePlatformSpec.kt @@ -39,7 +39,7 @@ internal class EmbedCodePlatformSpec { fun `select Apple silicon asset`() { assertEquals( EmbedCodePlatform("embed-code-macos-arm64.zip", "embed-code-macos-arm64"), - EmbedCodePlatform.detect("Mac OS X", "aarch64"), + EmbedCodePlatform.detect("Mac OS X", "aarch64", "v1.2.4"), ) } @@ -47,23 +47,34 @@ internal class EmbedCodePlatformSpec { fun `select Intel macOS asset`() { assertEquals( EmbedCodePlatform("embed-code-macos-x64.zip", "embed-code-macos-x64"), - EmbedCodePlatform.detect("Mac OS X", "x86_64"), + EmbedCodePlatform.detect("Mac OS X", "x86_64", "v1.2.4"), ) } @Test - fun `select Linux asset`() { + fun `select Linux ZIP asset for a new release`() { assertEquals( - EmbedCodePlatform("embed-code-linux", "embed-code-linux"), - EmbedCodePlatform.detect("Linux", "amd64"), + EmbedCodePlatform("embed-code-linux.zip", "embed-code-linux"), + EmbedCodePlatform.detect("Linux", "amd64", "v1.2.5"), ) } + @Test + fun `select bare Linux asset for releases published before ZIP packaging`() { + listOf("v1.2.3", "v1.2.4").forEach { releaseTag -> + assertEquals( + EmbedCodePlatform("embed-code-linux", "embed-code-linux"), + EmbedCodePlatform.detect("Linux", "amd64", releaseTag), + releaseTag, + ) + } + } + @Test fun `select Windows asset`() { assertEquals( EmbedCodePlatform("embed-code-windows.exe", "embed-code-windows.exe"), - EmbedCodePlatform.detect("Windows 11", "amd64"), + EmbedCodePlatform.detect("Windows 11", "amd64", "v1.2.4"), ) } @@ -80,7 +91,7 @@ internal class EmbedCodePlatformSpec { @Test fun `reject platform without release binary`() { val error = assertThrows(GradleException::class.java) { - EmbedCodePlatform.detect("Linux", "aarch64") + EmbedCodePlatform.detect("Linux", "aarch64", "v1.2.4") } assertEquals(