HIBERNATE-213: fix release publishing for the multi-module build - #196
Conversation
Three defects, each of which on its own prevents a release.
publish.sh expanded the Gradle task list as "${TASK}", making the two
release task names a single argv element, so Gradle looked for one task
named "publishArchives closeAndReleaseSonatypeStagingRepository". A bash
array expanded with "${TASKS[@]}" passes them separately. Snapshot
publishing was unaffected because publishSnapshots is a single word,
which is why this went unnoticed until the first release attempt.
SYSTEM_PROPERTIES becomes an array for the same reason, and RELEASE now
uses ${RELEASE:-false}, the default-value expansion it was reaching for.
publishArchives and publishSnapshots declared dependsOn(tasks.named(...)),
which resolves to the root project's tasks alone, so the publications of
the Spring Boot modules were never uploaded and the build still passed.
Both lifecycle tasks now depend on the equivalent task in every project
that applies mongo-hibernate-publish.
The starter module applies plain java-library rather than the Java
conventions, so it published neither a sources nor a javadoc jar; Maven
Central requires both, and the staging repository would have failed to
close. Producing the two jars moves from mongo-hibernate-java to
mongo-hibernate-publish, since the requirement follows from publishing a
module rather than from how the module is compiled.
| ############################################ | ||
| source java-config.sh | ||
|
|
||
| RELEASE=${RELEASE:false} |
There was a problem hiding this comment.
should I create a follow up for java driver ? (maybe spark and kafka too) as java driver has the same issue
https://github.com/mongodb/mongo-java-driver/blob/main/.evergreen/publish.sh#L13
On the other hand, I checked that RELEASE variable is always set in pipeline so this fix should not have blocked us during the release
There was a problem hiding this comment.
Its worth it, if you do a PR feel free to assign to me
| SYSTEM_PROPERTIES=(-Dorg.gradle.internal.publish.checksums.insecure=true) | ||
|
|
||
| ./gradlew -version | ||
| ./gradlew ${SYSTEM_PROPERTIES} --stacktrace --info "${TASK}" |
There was a problem hiding this comment.
I believe the problem is is quotes " , java driver has the same pattern but doesn't use quotes instead of introducing the array , why do you think having array is better ?
There was a problem hiding this comment.
I agree - just don't quote when calling ./gradlew - follows the java driver convention
Claude seems to think the array approach is safer because if quotes were added in the future it would still work. 🤷
There was a problem hiding this comment.
Yes, and this is exactly how it broke in the first place: quotes were added around TASKS as a drive-by change, probably in response to a warning in the IDE.
| TASKS=(publishSnapshots) | ||
| fi | ||
|
|
||
| SYSTEM_PROPERTIES="-Dorg.gradle.internal.publish.checksums.insecure=true" |
There was a problem hiding this comment.
| // A plain `tasks.named(name)` below would resolve to the root project's task alone, leaving the | ||
| // publications of the subprojects unpublished. The Callable defers looking at the projects until the task | ||
| // graph is built, by which point the subprojects have been evaluated and their plugins are visible. | ||
| fun publishingTaskInEveryProject(name: String) = Callable { |
There was a problem hiding this comment.
how about adding 1 validation layer
fun publishingTaskInEveryProject(name: String) = Callable {
val publishing = allprojects.filter { it.pluginManager.hasPlugin("mongo-hibernate-publish") }
val withPublications = allprojects.filter {
it.extensions.findByType<PublishingExtension>()?.publications?.isNotEmpty() == true
}
require((withPublications - publishing.toSet()).isEmpty()) {
"Projects declare publications but don't apply mongo-hibernate-publish: ${withPublications - publishing.toSet()}"
}
publishing.map { it.tasks.named(name) }
}
This way we check that every project that want to be published must declare mongo-hibernate-publish
I am still debating if it will be useful, for example if I were to introduce a new module like Quarkus starter I would just copy paste the Spring boot starter
There was a problem hiding this comment.
Great idea. Tested, and applied.
| source java-config.sh | ||
|
|
||
| RELEASE=${RELEASE:false} | ||
| RELEASE=${RELEASE:-false} |
rozza
left a comment
There was a problem hiding this comment.
Just one nit (optional).
I wondered why not just register the task inside the convention - but this seems to be the better approach as there is one single publish (archives/snapshot) task registered - rather than one per sub project.
FYI - buildSrc is not under spotless - something you may want to add in the future.
Fixes three defects in the release process.
publish.sh expanded the Gradle task list as
"${TASK}", making the two release task names a single argv element, so Gradle looked for one task named"publishArchives closeAndReleaseSonatypeStagingRepository". A bash array expanded with"${TASKS[@]}"passes them separately. Snapshot publishing was unaffected becausepublishSnapshotsis a single word, which is why this went unnoticed until the first release attempt.SYSTEM_PROPERTIESbecomes an array for the same reason, and RELEASE now uses${RELEASE:-false}.publishArchivesandpublishSnapshotsdeclareddependsOn(tasks.named(...)), which resolves to the root project's tasks alone, so the publications of the Spring Boot modules were never uploaded and the build still passed. Both lifecycle tasks now depend on the equivalent task in every project that appliesmongo-hibernate-publish.The starter module applies plain
java-libraryrather than the Java conventions, so it published neither a sources nor a javadoc jar; Maven Central requires both, and the staging repository would have failed to close. Producing the two jars moves frommongo-hibernate-javatomongo-hibernate-publish, since the requirement follows from publishing a module rather than from how the module is compiled.