Skip to content

Commit

Permalink
patch: switch to task form
Browse files Browse the repository at this point in the history
* A custom class has been added for the task management
* Added dependsOn to test
* Added optional annotations
  • Loading branch information
Im-Fran committed Jan 31, 2024
1 parent 8c59521 commit c18efa4
Show file tree
Hide file tree
Showing 6 changed files with 166 additions and 97 deletions.
2 changes: 1 addition & 1 deletion SonatypeCentralUpload/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ plugins {
id("com.gradle.plugin-publish") version "1.2.1"
}

version = "1.0.0"
version = "1.0.1"
group = "cl.franciscosolis"

// Set up the publishing plugin
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ class SonatypeCentralUploadPluginFunctionalTest {
rootProject.name = "SonatypeCentralUploadTest"
""".trimIndent())
buildFile.writeText("""
import cl.franciscosolis.sonatypecentralupload.SonatypeCentralUploadTask
plugins {
id("cl.franciscosolis.gradledotenv") version "1.0.1"
id("cl.franciscosolis.sonatype-central-upload")
Expand All @@ -55,17 +57,26 @@ class SonatypeCentralUploadPluginFunctionalTest {
group = "cl.franciscosolis"
version = "$version"
sonatypeCentralUpload {
username = env["SONATYPE_USERNAME"] ?: ""
password = env["SONATYPE_PASSWORD"] ?: ""
signingKey = env["SIGNING_KEY"] ?: ""
signingKeyPassphrase = env["SIGNING_PASSWORD"] ?: ""
publicKey = env["PUBLIC_KEY"] ?: ""
archives = files("${mockJar.absolutePath}", "${mockSourcesJar.absolutePath}", "${mockJavadocJar.absolutePath}")
tasks {
register("randomTask") {
doLast {
println("Random task")
}
}
pom = file("${mockPom.absolutePath}")
named<SonatypeCentralUploadTask>("sonatypeCentralUpload") {
dependsOn(named("randomTask"))
username = env["SONATYPE_USERNAME"] ?: ""
password = env["SONATYPE_PASSWORD"] ?: ""
signingKey = env["SIGNING_KEY"] ?: ""
signingKeyPassphrase = env["SIGNING_PASSWORD"] ?: ""
publicKey = env["PUBLIC_KEY"] ?: ""
archives = files("${mockJar.absolutePath}", "${mockSourcesJar.absolutePath}", "${mockJavadocJar.absolutePath}")
pom = file("${mockPom.absolutePath}")
}
}
""".trimIndent())

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package cl.franciscosolis.sonatypecentralupload
import org.gradle.api.file.FileCollection
import org.gradle.api.provider.Property
import org.gradle.api.tasks.Input
import org.gradle.api.tasks.Optional
import java.io.File

abstract class SonatypeCentralUploadExtension {
Expand All @@ -13,12 +14,15 @@ abstract class SonatypeCentralUploadExtension {
abstract val password: Property<String>

@get:Input
@get:Optional
abstract val signingKey: Property<String>

@get:Input
@get:Optional
abstract val signingKeyPassphrase: Property<String>

@get:Input
@get:Optional
abstract val publicKey: Property<String>

@get:Input
Expand Down
Original file line number Diff line number Diff line change
@@ -1,94 +1,19 @@
package cl.franciscosolis.sonatypecentralupload

import cl.franciscosolis.sonatypecentralupload.utils.*
import org.gradle.api.Plugin
import org.gradle.api.Project
import java.io.File
import java.nio.file.Files

class SonatypeCentralUploadPlugin: Plugin<Project> {
override fun apply(project: Project) {
project.extensions.create("sonatypeCentralUpload", SonatypeCentralUploadExtension::class.java)
project.tasks.register("sonatypeCentralUpload") { task ->
val extension = project.extensions.getByType(SonatypeCentralUploadExtension::class.java)
val groupFolder = "${project.group}".replace('.', '/').lowercase()
val sonatypeCentralUploadDir = project.file(project.layout.buildDirectory.dir("sonatype-central-upload"))
val uploadDir = project.file(project.layout.buildDirectory.dir("${sonatypeCentralUploadDir.path}/$groupFolder/${project.name.lowercase()}/${project.version}"))
if (extension.username.orNull?.isBlank() == true) {
throw IllegalStateException("'username' is empty. A username is required.")
}

if (extension.password.orNull?.isBlank() == true) {
throw IllegalStateException("'password' is empty. A password is required.")
}

if (extension.signingKey.orNull?.isBlank() == true) {
throw IllegalStateException("'signingKey' is empty. A signing key is required.")
}

if (!extension.archives.isPresent || extension.archives.orNull?.isEmpty == true) {
throw IllegalStateException("'archives' is empty. Archives to upload are required.")
}

if (!extension.pom.isPresent || extension.pom.orNull == null) {
throw IllegalStateException("'pom' is empty. A pom file is required.")
}

task.doLast {
// Create upload dir
if(!uploadDir.exists()) {
uploadDir.mkdirs()
}

// Get all artifacts
val artifacts = extension.archives.orNull ?: emptyList()

// Copy artifacts to upload dir
for(artifact in artifacts) {
if(!artifact.nameWithoutExtension.startsWith("${project.name.lowercase()}-${project.version}")) {
throw IllegalStateException("Artifact name '${artifact.name}' does not match or does not start with project name '${project.name.lowercase()}-${project.version}'.")
}
val artifactFile = artifact.toPath()
val uploadFile = uploadDir.toPath().resolve(artifactFile.fileName)
Files.copy(artifactFile, uploadFile)
}

val pomFile = extension.pom.orNull ?: throw NullPointerException("Pom file is null.")
Files.copy(pomFile.toPath(), uploadDir.toPath().resolve("${project.name.lowercase()}-${project.version}.pom"))

if (extension.publicKey.orNull?.isNotBlank() == true) {
val publicKey = extension.publicKey.orNull ?: ""
val pkToDistribute = if(publicKey.startsWith("-----BEGIN PGP PUBLIC KEY BLOCK-----")) {
publicKey.replace("\\n", "\n")
} else if (File(publicKey).exists()) {
File(uploadDir, "public.key").readText().replace("\\n", "\n")
} else {
throw IllegalStateException("'publicKey' is not a file or a key block.")
}

sendKeyToServer(pkToDistribute)
}

// Generate signatures for all files
for(file in uploadDir.listFiles() ?: emptyArray()) {
signFile(
file = file,
signingKey = extension.signingKey.orNull ?: "",
signingPassword = extension.signingKeyPassphrase.orNull ?: ""
)
}

// Generate checksums for all files (filter out .asc files)
for (file in (uploadDir.listFiles() ?: emptyArray()).filter { it.extension != "asc" }) {
generateChecksums(file)
}

// Now we need to zip all the contents of 'sonatype-central-upload'
val zipFile = File(sonatypeCentralUploadDir, "${project.name.lowercase()}-${project.version}.zip")
zipFolder(File(sonatypeCentralUploadDir, groupFolder.split('/').first()), zipFile)

initPublishingProcess(zipFile, extension.username.orNull ?: "", extension.password.orNull ?: "")
}
val extension: SonatypeCentralUploadExtension = project.extensions.create("sonatypeCentralUpload", SonatypeCentralUploadExtension::class.java)
project.tasks.register("sonatypeCentralUpload", SonatypeCentralUploadTask::class.java) { task ->
task.username.set(extension.username)
task.password.set(extension.password)
task.signingKey.set(extension.signingKey)
task.signingKeyPassphrase.set(extension.signingKeyPassphrase)
task.publicKey.set(extension.publicKey)
task.archives.set(extension.archives)
task.pom.set(extension.pom)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
package cl.franciscosolis.sonatypecentralupload

import cl.franciscosolis.sonatypecentralupload.utils.*
import org.gradle.api.DefaultTask
import org.gradle.api.file.FileCollection
import org.gradle.api.provider.Property
import org.gradle.api.tasks.Input
import org.gradle.api.tasks.Optional
import org.gradle.api.tasks.TaskAction
import java.io.File
import java.nio.file.Files


abstract class SonatypeCentralUploadTask: DefaultTask() {

@get:Input
abstract val username: Property<String>

@get:Input
abstract val password: Property<String>

@get:Input
@get:Optional
abstract val signingKey: Property<String>

@get:Input
@get:Optional
abstract val signingKeyPassphrase: Property<String>

@get:Input
@get:Optional
abstract val publicKey: Property<String>

@get:Input
abstract val archives: Property<FileCollection>

@get:Input
abstract val pom: Property<File>

@TaskAction
fun run() {
val groupFolder = "${project.group}".replace('.', '/').lowercase()
val sonatypeCentralUploadDir = project.file(project.layout.buildDirectory.dir("sonatype-central-upload"))
val uploadDir = project.file(project.layout.buildDirectory.dir("${sonatypeCentralUploadDir.path}/$groupFolder/${project.name.lowercase()}/${project.version}"))
if (username.orNull?.isBlank() == true) {
throw IllegalStateException("'username' is empty. A username is required.")
}

if (password.orNull?.isBlank() == true) {
throw IllegalStateException("'password' is empty. A password is required.")
}

if (signingKey.orNull?.isBlank() == true) {
throw IllegalStateException("'signingKey' is empty. A signing key is required.")
}

if (!archives.isPresent || archives.orNull?.isEmpty == true) {
throw IllegalStateException("'archives' is empty. Archives to upload are required.")
}

if (!pom.isPresent || pom.orNull == null) {
throw IllegalStateException("'pom' is empty. A pom file is required.")
}

// Create upload dir
if(!uploadDir.exists()) {
uploadDir.mkdirs()
}

// Get all artifacts
val artifacts = archives.orNull ?: emptyList()

// Copy artifacts to upload dir
for(artifact in artifacts) {
if(!artifact.nameWithoutExtension.startsWith("${project.name.lowercase()}-${project.version}")) {
throw IllegalStateException("Artifact name '${artifact.name}' does not match or does not start with project name '${project.name.lowercase()}-${project.version}'.")
}
val artifactFile = artifact.toPath()
val uploadFile = uploadDir.toPath().resolve(artifactFile.fileName)
Files.copy(artifactFile, uploadFile)
}

val pomFile = pom.orNull ?: throw NullPointerException("Pom file is null.")
Files.copy(pomFile.toPath(), uploadDir.toPath().resolve("${project.name.lowercase()}-${project.version}.pom"))

if (publicKey.orNull?.isNotBlank() == true) {
val publicKey = publicKey.orNull ?: ""
val pkToDistribute = if(publicKey.startsWith("-----BEGIN PGP") && publicKey.contains("KEY BLOCK-----")) {
publicKey.replace("\\n", "\n")
} else if (File(publicKey).exists()) {
File(uploadDir, "public.key").readText().replace("\\n", "\n")
} else {
throw IllegalStateException("'publicKey' is not a file or a key block.")
}

sendKeyToServer(pkToDistribute)
}

// Generate signatures for all files
for(file in uploadDir.listFiles() ?: emptyArray()) {
signFile(
file = file,
signingKey = signingKey.orNull ?: "",
signingPassword = signingKeyPassphrase.orNull ?: ""
)
}

// Generate checksums for all files (filter out .asc files)
for (file in (uploadDir.listFiles() ?: emptyArray()).filter { it.extension != "asc" }) {
generateChecksums(file)
}

// Now we need to zip all the contents of 'sonatype-central-upload'
val zipFile = File(sonatypeCentralUploadDir, "${project.name.lowercase()}-${project.version}.zip")
zipFolder(File(sonatypeCentralUploadDir, groupFolder.split('/').first()), zipFile)

initPublishingProcess(zipFile, username.orNull ?: "", password.orNull ?: "")
}



}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import javax.net.ssl.HttpsURLConnection
*/
fun signFile(file: File, signingKey: String, signingPassword: String): File? = try {
val signedFile = File(file.parentFile, "${file.name}.asc")
val keyBytes = if(signingKey.contains("PGP PRIVATE KEY BLOCK")) {
val keyBytes = if(signingKey.startsWith("-----BEGIN PGP") && signingKey.contains("KEY BLOCK-----")) {
signingKey.replace("\\n", "\n")
.toByteArray()
} else if (File(signingKey).exists()) {
Expand Down Expand Up @@ -49,7 +49,7 @@ fun signFile(file: File, signingKey: String, signingPassword: String): File? = t
* Sends the given public key to the key server.
* @param key The public key to send.
*/
fun sendKeyToServer(key: String) {
fun sendKeyToServer(key: String) = try {
val url = URL("https://keyserver.ubuntu.com/pks/add")
val connection = url.openConnection() as HttpsURLConnection
connection.requestMethod = "POST"
Expand All @@ -68,4 +68,11 @@ fun sendKeyToServer(key: String) {
println("Response message: ${connection.responseMessage}")
println("Response body: ${connection.inputStream.bufferedReader().readText()}")
}

connection.disconnect()
} catch (e: Exception) {
if(System.getenv("SONATYPECENTRALUPLOAD_DEBUG") != null) {
e.printStackTrace()
}
System.err.println("Failed to send key to server.")
}

0 comments on commit c18efa4

Please sign in to comment.