Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
root = true

[*]
charset = utf-8
indent_size = 2
indent_style = space
insert_final_newline = true
trim_trailing_whitespace = true

[*.{kt,kts}]
ij_kotlin_imports_layout = *
ij_kotlin_allow_trailing_comma = true
ij_kotlin_allow_trailing_comma_on_call_site = true
ij_kotlin_line_break_after_multiline_when_entry = false
ij_kotlin_name_count_to_use_star_import = 999
ij_kotlin_name_count_to_use_star_import_for_members = 999
ij_kotlin_packages_to_use_import_on_demand = unset
indent_size = 4
ktlint_code_style = intellij_idea
ktlint_standard_function-expression-body = disabled

[*.md]
trim_trailing_whitespace = false
27 changes: 20 additions & 7 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import java.net.URI

plugins {
alias(libs.plugins.kgp)
alias(libs.plugins.spotless)
id("java-gradle-plugin")
id("maven-publish")
id("signing")
Expand Down Expand Up @@ -39,12 +40,16 @@ publishing {
publications.configureEach {
this as MavenPublication
if (name == "pluginMaven") {
artifact(tasks.register("emptySources", Jar::class.java) {
archiveClassifier = "sources"
})
artifact(tasks.register("emptyDocs", Jar::class.java) {
archiveClassifier = "javadoc"
})
artifact(
tasks.register("emptySources", Jar::class.java) {
archiveClassifier = "sources"
},
)
artifact(
tasks.register("emptyDocs", Jar::class.java) {
archiveClassifier = "javadoc"
},
)

groupId = project.rootProject.group.toString()
version = project.rootProject.version.toString()
Expand Down Expand Up @@ -85,6 +90,14 @@ signing {
useInMemoryPgpKeys(System.getenv("GPG_KEY"), System.getenv("GPG_KEY_PASSWORD"))
}

spotless {
kotlin {
ktlint(libs.ktlint.get().version)
}
kotlinGradle {
ktlint(libs.ktlint.get().version)
}
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is that going to fail the build everytime there is a code style violation?

As much as I welcome .editorconfig (and even better, .idea/codeStyle), I have very mixed feelings about adding more friction to development. This blog post explains why

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, check depends on spotlessCheck.
.editorconfig would be enough, it's honored by IDEA, VSC, and others.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM 👍 Can you keep .editorconfig but remove spotless?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can. But some rules break the rules, e.g.

ij_kotlin_imports_layout = *

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure I'm following. Do you mean that some of the existing code breaks the rule? This is fine, we can reformat as we go. Or just commit the reformat alongside .editorconfig

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.


dependencies {
implementation(libs.json)
Expand All @@ -100,4 +113,4 @@ tasks.withType<AbstractPublishToMaven>().configureEach {

tasks.withType(Sign::class.java).configureEach {
isEnabled = System.getenv("GPG_KEY").isNullOrBlank().not()
}
}
5 changes: 4 additions & 1 deletion gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,8 @@ okio = "com.squareup.okio:okio:3.8.0"
okhttp = "com.squareup.okhttp3:okhttp:4.12.0"
okhttp-logging-interceptor = "com.squareup.okhttp3:logging-interceptor:4.12.0"
mockwebserver = "com.squareup.okhttp3:mockwebserver:4.12.0"
# Dummy to get renovate updates, the version is used in rootProject build.gradle with spotless.
ktlint = "com.pinterest.ktlint:ktlint-cli:1.5.0"
[plugins]
kgp = { id = "org.jetbrains.kotlin.jvm", version.ref = "kgp" }
kgp = { id = "org.jetbrains.kotlin.jvm", version.ref = "kgp" }
spotless = "com.diffplug.spotless:7.0.3"
11 changes: 6 additions & 5 deletions settings.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
pluginManagement {
listOf(repositories, dependencyResolutionManagement.repositories).forEach {
it.apply {
mavenCentral()
listOf(repositories, dependencyResolutionManagement.repositories).forEach {
it.apply {
mavenCentral()
gradlePluginPortal()
}
}
}
}
}
10 changes: 5 additions & 5 deletions src/main/kotlin/nmcp/NmcpAggregation.kt
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
package nmcp

import java.time.Duration
import javax.inject.Inject
import org.gradle.api.Project
import org.gradle.api.artifacts.Configuration
import org.gradle.api.provider.Property
import java.time.Duration
import javax.inject.Inject

abstract class NmcpAggregation @Inject constructor(
private val configuration: Configuration,
private val project: Project,
) {
) {
/**
* The central portal username
*/
Expand Down Expand Up @@ -57,6 +57,6 @@ abstract class NmcpAggregation @Inject constructor(
abstract val verificationTimeout: Property<Duration>

fun project(path: String) {
project.dependencies.add(configuration.name, project.dependencies.project(mapOf("path" to path)))
project.dependencies.add(configuration.name, project.dependencies.project(mapOf("path" to path)))
}
}
}
29 changes: 15 additions & 14 deletions src/main/kotlin/nmcp/NmcpExtension.kt
Original file line number Diff line number Diff line change
Expand Up @@ -66,11 +66,10 @@ open class NmcpExtension(private val project: Project) {
it.archiveFileName.set("publication$capitalized.zip")
}


val publishTaskProvider = project.tasks.register("publish${capitalized}PublicationToCentralPortal", NmcpPublishTask::class.java) {
it.inputFile.set(zipTaskProvider.flatMap { it.archiveFile })
it.username.set(spec.username.orElse(project.provider { error("Nmcp: username must not be empty")}))
it.password.set(spec.password.orElse(project.provider { error("Nmcp: password must not be empty")}))
it.username.set(spec.username.orElse(project.provider { error("Nmcp: username must not be empty") }))
it.password.set(spec.password.orElse(project.provider { error("Nmcp: password must not be empty") }))
it.publicationType.set(spec.publicationType)
it.publicationName.set(spec.publicationName.orElse("${project.name}-${project.version}.zip"))
it.endpoint.set(spec.endpoint)
Expand Down Expand Up @@ -140,23 +139,25 @@ open class NmcpExtension(private val project: Project) {
action.execute(aggregation)

val zipTaskProvider = project.tasks.register("zipAggregationPublication", Zip::class.java) {
it.from(configuration.elements.map {
check (it.isNotEmpty()) {
"nmcp: no aggregate dependencies found, please apply the 'com.gradleup.nmcp' in your submodules"
}
it.map {
project.zipTree(it)
}
})
it.from(
configuration.elements.map {
check(it.isNotEmpty()) {
"nmcp: no aggregate dependencies found, please apply the 'com.gradleup.nmcp' in your submodules"
}
it.map {
project.zipTree(it)
}
},
)

it.destinationDirectory.set(project.layout.buildDirectory.dir("nmcp/zip"))
it.archiveFileName.set("publicationAggregated.zip")
}

project.tasks.register("publishAggregatedPublicationToCentralPortal", NmcpPublishTask::class.java) {
it.inputFile.set(zipTaskProvider.flatMap { it.archiveFile })
it.username.set(aggregation.username.orElse(project.provider { error("Nmcp: username must not be empty")}))
it.password.set(aggregation.password.orElse(project.provider { error("Nmcp: password must not be empty")}))
it.username.set(aggregation.username.orElse(project.provider { error("Nmcp: username must not be empty") }))
it.password.set(aggregation.password.orElse(project.provider { error("Nmcp: password must not be empty") }))
it.publicationType.set(aggregation.publicationType)
it.publicationName.set(aggregation.publicationName.orElse("${project.name}-${project.version}.zip"))
it.endpoint.set(aggregation.endpoint)
Expand Down Expand Up @@ -199,4 +200,4 @@ open class NmcpExtension(private val project: Project) {
}
}
}
}
}
4 changes: 2 additions & 2 deletions src/main/kotlin/nmcp/NmcpPlugin.kt
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ internal fun HasConfigurableAttributes<*>.configureAttributes(project: Project)
}
}

class NmcpPlugin: Plugin<Project> {
class NmcpPlugin : Plugin<Project> {
override fun apply(target: Project) {
target.configurations.create(configurationName) {
it.isCanBeConsumed = true
Expand All @@ -32,4 +32,4 @@ class NmcpPlugin: Plugin<Project> {
}
target.extensions.create("nmcp", NmcpExtension::class.java, target)
}
}
}
40 changes: 23 additions & 17 deletions src/main/kotlin/nmcp/NmcpPublishTask.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
package nmcp

import java.time.Duration
import kotlin.time.Duration.Companion.minutes
import kotlin.time.TimeSource.Monotonic.markNow
import kotlin.time.toJavaDuration
import kotlin.time.toKotlinDuration
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonObject
import kotlinx.serialization.json.JsonPrimitive
Expand All @@ -14,15 +19,13 @@ import okio.ByteString
import org.gradle.api.DefaultTask
import org.gradle.api.file.RegularFileProperty
import org.gradle.api.provider.Property
import org.gradle.api.tasks.*
import org.gradle.api.tasks.Input
import org.gradle.api.tasks.InputFile
import org.gradle.api.tasks.Optional
import org.gradle.api.tasks.PathSensitive
import org.gradle.api.tasks.PathSensitivity
import org.gradle.api.tasks.TaskAction
import org.gradle.work.DisableCachingByDefault
import java.time.Duration
import kotlin.time.Duration.Companion.minutes
import kotlin.time.Duration.Companion.seconds
import kotlin.time.TimeSource.Monotonic.markNow
import kotlin.time.toJavaDuration
import kotlin.time.toKotlinDuration


@DisableCachingByDefault
abstract class NmcpPublishTask : DefaultTask() {
Expand Down Expand Up @@ -75,7 +78,7 @@ abstract class NmcpPublishTask : DefaultTask() {
.addFormDataPart(
"bundle",
publicationName.get(),
inputFile.get().asFile.asRequestBody("application/zip".toMediaType())
inputFile.get().asFile.asRequestBody("application/zip".toMediaType()),
)
.build()

Expand Down Expand Up @@ -105,17 +108,20 @@ abstract class NmcpPublishTask : DefaultTask() {
val timeout = verificationTimeout.orElse(10.minutes.toJavaDuration()).get()
val mark = markNow()
while (true) {
check (mark.elapsedNow() < timeout.toKotlinDuration()) {
check(mark.elapsedNow() < timeout.toKotlinDuration()) {
"Nmcp: timeout while verifying deployment status."
}
when (val status = verifyStatus(
deploymentId = deploymentId,
endpoint = endpoint,
token = token,
)) {
when (
val status = verifyStatus(
deploymentId = deploymentId,
endpoint = endpoint,
token = token,
)
) {
PENDING,
VALIDATING,
PUBLISHING -> {
PUBLISHING,
-> {
// Come back later
Thread.sleep(2000)
}
Expand Down Expand Up @@ -201,4 +207,4 @@ private fun verifyStatus(
else -> error("Nmcp: unexpected status: $state")
}
}
}
}
4 changes: 2 additions & 2 deletions src/main/kotlin/nmcp/NmcpSpec.kt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package nmcp

import org.gradle.api.provider.Property
import java.time.Duration
import org.gradle.api.provider.Property

abstract class NmcpSpec {
/**
Expand Down Expand Up @@ -49,4 +49,4 @@ abstract class NmcpSpec {
* Default: 600 (10 minutes).
*/
abstract val verificationTimeout: Property<Duration>
}
}