diff --git a/sigstore-gradle/sigstore-gradle-sign-base-plugin/src/main/kotlin/dev/sigstore/sign/SigstoreSignExtension.kt b/sigstore-gradle/sigstore-gradle-sign-base-plugin/src/main/kotlin/dev/sigstore/sign/SigstoreSignExtension.kt index def65036..f2340db7 100644 --- a/sigstore-gradle/sigstore-gradle-sign-base-plugin/src/main/kotlin/dev/sigstore/sign/SigstoreSignExtension.kt +++ b/sigstore-gradle/sigstore-gradle-sign-base-plugin/src/main/kotlin/dev/sigstore/sign/SigstoreSignExtension.kt @@ -26,6 +26,9 @@ import org.gradle.api.provider.Property import org.gradle.api.publish.Publication import org.gradle.api.publish.PublicationArtifact import org.gradle.api.publish.internal.PublicationInternal +import org.gradle.api.publish.maven.MavenArtifact +import org.gradle.api.publish.maven.internal.artifact.AbstractMavenArtifact +import org.gradle.api.publish.maven.internal.artifact.DerivedMavenArtifact import org.gradle.kotlin.dsl.create import org.gradle.kotlin.dsl.named import org.gradle.kotlin.dsl.register @@ -88,28 +91,34 @@ abstract class SigstoreSignExtension(private val project: Project) { val artifacts = mutableMapOf() publication.allPublishableArtifacts { val publishableArtifact = this - if (file.extension !in listOf("asc", SigstoreSignature.EXTENSION)) { + if (!file.name.endsWith(".asc") && !file.name.endsWith(SigstoreSignature.DOT_EXTENSION)) { val signatureLocation = - signatureDirectory.map { it.file(file.name + "." + SigstoreSignature.EXTENSION) } + signatureDirectory.map { it.file(file.name + SigstoreSignature.DOT_EXTENSION) } signTask.configure { sign(publishableArtifact.file, builtBy = publishableArtifact) .outputSignature.set(signatureLocation) } - artifacts[publishableArtifact] = publication.addDerivedArtifact( - publishableArtifact, - DefaultDerivedArtifactFile(project.tasks.named(signTask.name), signatureLocation) - ).apply { builtBy(signTask) } + val dervied = DefaultDerivedArtifactFile(project.tasks.named(signTask.name), signatureLocation) + artifacts[publishableArtifact] = publication.addDerivedArtifact(publishableArtifact, dervied).apply { + builtBy(signTask) + // TODO: workaround for https://github.com/gradle/gradle/issues/28969 + // TODO: Behavior is undefined for non-maven artifacts. + if (publishableArtifact is AbstractMavenArtifact) { + (this as DerivedMavenArtifact).setExtension((publishableArtifact as AbstractMavenArtifact).extension + SigstoreSignature.DOT_EXTENSION) + } + } // Gradle's signing plugin reacts on adding artifacts, and it might add .asc signature - // So we need to remove .sigstore.asc as it is unwanted in most of the cases + // So we need to remove .sigstore.json.asc as it is unwanted in most of the cases if (removeSigstoreAsc) { project.tasks.withType() .matching { it.name.contains(publicationName, ignoreCase = true) } .configureEach { - // Remove .sigstore.asc signature. + // Remove .sigstore.json.asc signature. // Unfortunately, it will scan all the signatures every time, // however, it seems to be the only way to do it since the artifacts can be added // within afterEvaluate block, so we can't use afterEvaluate - // to "remove all .sigstore.asc" at once + // to "remove all .sigstore.json.asc" at once + signatures.removeIf { it.name.endsWith(SigstoreSignature.DOT_EXTENSION + ".asc") } signatures.removeIf { it.name.endsWith(".sigstore.asc") } } } diff --git a/sigstore-gradle/sigstore-gradle-sign-base-plugin/src/main/kotlin/dev/sigstore/sign/SigstoreSignature.kt b/sigstore-gradle/sigstore-gradle-sign-base-plugin/src/main/kotlin/dev/sigstore/sign/SigstoreSignature.kt index 421bde3f..4682c5ff 100644 --- a/sigstore-gradle/sigstore-gradle-sign-base-plugin/src/main/kotlin/dev/sigstore/sign/SigstoreSignature.kt +++ b/sigstore-gradle/sigstore-gradle-sign-base-plugin/src/main/kotlin/dev/sigstore/sign/SigstoreSignature.kt @@ -25,7 +25,8 @@ import javax.inject.Inject abstract class SigstoreSignature @Inject constructor(private val name: String) : Named { companion object { - const val EXTENSION = "sigstore" + const val EXTENSION = "sigstore.json" + const val DOT_EXTENSION = ".$EXTENSION"; } // Gradle 6.8.3: Cannot have abstract method SigstoreSignature.getName @@ -73,7 +74,7 @@ abstract class SigstoreSignature @Inject constructor(private val name: String) : init { outputSignature.convention( - signatureDirectory.map { it.file(file.singleFile.name + ".$EXTENSION") } + signatureDirectory.map { it.file(file.singleFile.name + DOT_EXTENSION) } ) } } diff --git a/sigstore-gradle/sigstore-gradle-sign-base-plugin/src/main/kotlin/dev/sigstore/sign/tasks/SigstoreSignFilesTask.kt b/sigstore-gradle/sigstore-gradle-sign-base-plugin/src/main/kotlin/dev/sigstore/sign/tasks/SigstoreSignFilesTask.kt index 2527191a..11a92b5b 100644 --- a/sigstore-gradle/sigstore-gradle-sign-base-plugin/src/main/kotlin/dev/sigstore/sign/tasks/SigstoreSignFilesTask.kt +++ b/sigstore-gradle/sigstore-gradle-sign-base-plugin/src/main/kotlin/dev/sigstore/sign/tasks/SigstoreSignFilesTask.kt @@ -31,7 +31,6 @@ import org.gradle.api.plugins.JavaPluginExtension import org.gradle.api.provider.Property import org.gradle.api.provider.Provider import org.gradle.api.provider.ProviderFactory -import org.gradle.api.provider.SetProperty import org.gradle.api.tasks.* import org.gradle.jvm.toolchain.JavaLauncher import org.gradle.jvm.toolchain.JavaToolchainService diff --git a/sigstore-gradle/sigstore-gradle-sign-base-plugin/src/test/kotlin/dev/sigstore/gradle/PluginSmokeTest.kt b/sigstore-gradle/sigstore-gradle-sign-base-plugin/src/test/kotlin/dev/sigstore/gradle/PluginSmokeTest.kt index a345efae..6e533ef0 100644 --- a/sigstore-gradle/sigstore-gradle-sign-base-plugin/src/test/kotlin/dev/sigstore/gradle/PluginSmokeTest.kt +++ b/sigstore-gradle/sigstore-gradle-sign-base-plugin/src/test/kotlin/dev/sigstore/gradle/PluginSmokeTest.kt @@ -39,17 +39,17 @@ class PluginSmokeTest : BaseGradleTest() { project { apply(plugin = "dev.sigstore.sign-base") val hello by tasks.registering(WriteProperties::class) { - outputFile = layout.buildDirectory.file("props/$name.properties").get().asFile + destinationFile = layout.buildDirectory.file("props/$name.properties") property("hello", "world") } // It should be eagerly created to access signOutput val signFile by tasks.registering(SigstoreSignFilesTask::class) { - signFile(hello.map { it.outputFile }) + signFile(hello.map { it.destinationFile.asFile.get() }) } Assertions.assertThat(signFile.flatMap { it.singleSignature() }.get().asFile) - .hasFileName("hello.properties.sigstore") + .hasFileName("hello.properties.sigstore.json") } } diff --git a/sigstore-gradle/sigstore-gradle-sign-base-plugin/src/test/kotlin/dev/sigstore/gradle/SigstoreSignTest.kt b/sigstore-gradle/sigstore-gradle-sign-base-plugin/src/test/kotlin/dev/sigstore/gradle/SigstoreSignTest.kt index c99c78c6..77978f96 100644 --- a/sigstore-gradle/sigstore-gradle-sign-base-plugin/src/test/kotlin/dev/sigstore/gradle/SigstoreSignTest.kt +++ b/sigstore-gradle/sigstore-gradle-sign-base-plugin/src/test/kotlin/dev/sigstore/gradle/SigstoreSignTest.kt @@ -45,7 +45,7 @@ class SigstoreSignTest: BaseGradleTest() { } def signFile = tasks.register("signFile", SigstoreSignFilesTask) { signFile(helloProps.map { it.outputFile }) - .outputSignature.set(file("build/helloProps.txt.sigstore")) + .outputSignature.set(file("build/helloProps.txt.sigstore.json")) } """.trimIndent() ) @@ -57,7 +57,7 @@ class SigstoreSignTest: BaseGradleTest() { enableConfigurationCache(case.gradle) prepare(case.gradle.version, "signFile", "-s") .build() - assertThat(projectDir.resolve("build/helloProps.txt.sigstore")) + assertThat(projectDir.resolve("build/helloProps.txt.sigstore.json")) .content() .basicSigstoreStructure() diff --git a/sigstore-gradle/sigstore-gradle-sign-plugin/src/test/kotlin/dev/sigstore/gradle/RemoveSigstoreAscTest.kt b/sigstore-gradle/sigstore-gradle-sign-plugin/src/test/kotlin/dev/sigstore/gradle/RemoveSigstoreAscTest.kt index 3f90500a..06075cbb 100644 --- a/sigstore-gradle/sigstore-gradle-sign-plugin/src/test/kotlin/dev/sigstore/gradle/RemoveSigstoreAscTest.kt +++ b/sigstore-gradle/sigstore-gradle-sign-plugin/src/test/kotlin/dev/sigstore/gradle/RemoveSigstoreAscTest.kt @@ -19,14 +19,11 @@ package dev.sigstore.gradle import dev.sigstore.testkit.BaseGradleTest import dev.sigstore.testkit.TestedGradle import dev.sigstore.testkit.TestedGradleAndSigstoreJava -import dev.sigstore.testkit.TestedSigstoreJava import dev.sigstore.testkit.annotations.EnabledIfOidcExists import org.assertj.core.api.Assertions.assertThat import org.assertj.core.api.SoftAssertions import org.gradle.util.GradleVersion import org.junit.jupiter.params.ParameterizedTest -import org.junit.jupiter.params.provider.Arguments -import org.junit.jupiter.params.provider.Arguments.arguments import org.junit.jupiter.params.provider.MethodSource @EnabledIfOidcExists @@ -89,8 +86,8 @@ class RemoveSigstoreAscTest : BaseGradleTest() { projectDir.resolve("gradle.properties").toFile().appendText( """ - # By default, dev.sigstore.sign asks Gradle to avoid signing .sigstore as .sigstore.asc - # This is an opt-out hatch for those who need .sigstore.asc + # By default, dev.sigstore.sign asks Gradle to avoid signing .sigstore.json as + # .sigstore.json.asc This is an opt-out hatch for those who need .sigstore.json.asc dev.sigstore.sign.remove.sigstore.asc=false """.trimIndent() ) @@ -153,7 +150,7 @@ class RemoveSigstoreAscTest : BaseGradleTest() { } private fun SoftAssertions.assertSignatures(name: String, expectSigstoreAsc: Boolean = false) { - assertThat(projectDir.resolve("build/tmp-repo/dev/sigstore/test/sigstore-test/1.0/$name.sigstore")) + assertThat(projectDir.resolve("build/tmp-repo/dev/sigstore/test/sigstore-test/1.0/$name.sigstore.json")) .describedAs("$name should be signed with Sigstore") .content() .basicSigstoreStructure() @@ -163,14 +160,14 @@ class RemoveSigstoreAscTest : BaseGradleTest() { assertThat(projectDir.resolve("build/tmp-repo/dev/sigstore/test/sigstore-test/1.0/$name.asc.sigstore")) .describedAs("$name.asc should NOT be signed with Sigstore") .doesNotExist() - assertThat(projectDir.resolve("build/tmp-repo/dev/sigstore/test/sigstore-test/1.0/$name.sigstore.asc")) + assertThat(projectDir.resolve("build/tmp-repo/dev/sigstore/test/sigstore-test/1.0/$name.sigstore.json.asc")) .apply { if (expectSigstoreAsc) { - describedAs("$name.sigstore should be signed with PGP") + describedAs("$name.sigstore.json should be signed with PGP") exists() } else { - // We don't want to sign .sigstore files with PGP - describedAs("$name.sigstore should NOT be signed with PGP") + // We don't want to sign .sigstore.json files with PGP + describedAs("$name.sigstore.json should NOT be signed with PGP") doesNotExist() } } diff --git a/sigstore-gradle/sigstore-gradle-sign-plugin/src/test/kotlin/dev/sigstore/gradle/SigstorePublishSignTest.kt b/sigstore-gradle/sigstore-gradle-sign-plugin/src/test/kotlin/dev/sigstore/gradle/SigstorePublishSignTest.kt index 172dc1a0..d6552cb5 100644 --- a/sigstore-gradle/sigstore-gradle-sign-plugin/src/test/kotlin/dev/sigstore/gradle/SigstorePublishSignTest.kt +++ b/sigstore-gradle/sigstore-gradle-sign-plugin/src/test/kotlin/dev/sigstore/gradle/SigstorePublishSignTest.kt @@ -17,9 +17,7 @@ package dev.sigstore.gradle import dev.sigstore.testkit.BaseGradleTest -import dev.sigstore.testkit.TestedGradle import dev.sigstore.testkit.TestedGradleAndSigstoreJava -import dev.sigstore.testkit.TestedSigstoreJava import dev.sigstore.testkit.annotations.EnabledIfOidcExists import org.assertj.core.api.Assertions.assertThat import org.junit.jupiter.params.ParameterizedTest @@ -70,16 +68,16 @@ class SigstorePublishSignTest : BaseGradleTest() { prepare(case.gradle.version, "publishAllPublicationsToTmpRepository", "-s") .build() - assertThat(projectDir.resolve("build/tmp-repo/dev/sigstore/test/sigstore-test/1.0/sigstore-test-1.0.pom.sigstore")) + assertThat(projectDir.resolve("build/tmp-repo/dev/sigstore/test/sigstore-test/1.0/sigstore-test-1.0.pom.sigstore.json")) .content() .basicSigstoreStructure() - assertThat(projectDir.resolve("build/tmp-repo/dev/sigstore/test/sigstore-test/1.0/sigstore-test-1.0.jar.sigstore")) + assertThat(projectDir.resolve("build/tmp-repo/dev/sigstore/test/sigstore-test/1.0/sigstore-test-1.0.jar.sigstore.json")) .content() .basicSigstoreStructure() - assertThat(projectDir.resolve("build/tmp-repo/dev/sigstore/test/sigstore-test/1.0/sigstore-test-1.0-sources.jar.sigstore")) + assertThat(projectDir.resolve("build/tmp-repo/dev/sigstore/test/sigstore-test/1.0/sigstore-test-1.0-sources.jar.sigstore.json")) .content() .basicSigstoreStructure() - assertThat(projectDir.resolve("build/tmp-repo/dev/sigstore/test/sigstore-test/1.0/sigstore-test-1.0.module.sigstore")) + assertThat(projectDir.resolve("build/tmp-repo/dev/sigstore/test/sigstore-test/1.0/sigstore-test-1.0.module.sigstore.json")) .content() .basicSigstoreStructure() diff --git a/sigstore-testkit/src/main/kotlin/dev/sigstore/testkit/BaseGradleTest.kt b/sigstore-testkit/src/main/kotlin/dev/sigstore/testkit/BaseGradleTest.kt index 8f4fc603..21db1c18 100644 --- a/sigstore-testkit/src/main/kotlin/dev/sigstore/testkit/BaseGradleTest.kt +++ b/sigstore-testkit/src/main/kotlin/dev/sigstore/testkit/BaseGradleTest.kt @@ -35,6 +35,7 @@ open class BaseGradleTest { ON, OFF } + // to debug these tests, add .withDebug(true) before running a test in debug mode protected val gradleRunner = GradleRunner.create().withPluginClasspath() companion object {