Skip to content

Commit cab91bf

Browse files
committed
1 parent 62f3ee2 commit cab91bf

File tree

3 files changed

+115
-154
lines changed

3 files changed

+115
-154
lines changed

ci/release/Jenkinsfile

Lines changed: 24 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,10 @@ pipeline {
9292
stage('Release check') {
9393
steps {
9494
script {
95+
print "INFO: params.RELEASE_VERSION = ${params.RELEASE_VERSION}"
96+
print "INFO: params.DEVELOPMENT_VERSION = ${params.DEVELOPMENT_VERSION}"
97+
print "INFO: params.RELEASE_DRY_RUN? = ${params.RELEASE_DRY_RUN}"
98+
9599
checkoutReleaseScripts()
96100

97101
def currentVersion = Version.parseDevelopmentVersion( sh(
@@ -163,26 +167,19 @@ pipeline {
163167
configFile(fileId: 'release.config.ssh', targetLocation: "${env.HOME}/.ssh/config"),
164168
configFile(fileId: 'release.config.ssh.knownhosts', targetLocation: "${env.HOME}/.ssh/known_hosts")
165169
]) {
166-
withCredentials([
167-
usernamePassword(credentialsId: 'ossrh.sonatype.org', passwordVariable: 'OSSRH_PASSWORD', usernameVariable: 'OSSRH_USER'),
168-
usernamePassword(credentialsId: 'gradle-plugin-portal-api-key', passwordVariable: 'PLUGIN_PORTAL_PASSWORD', usernameVariable: 'PLUGIN_PORTAL_USERNAME'),
169-
file(credentialsId: 'release.gpg.private-key', variable: 'RELEASE_GPG_PRIVATE_KEY_PATH'),
170-
string(credentialsId: 'release.gpg.passphrase', variable: 'RELEASE_GPG_PASSPHRASE')
171-
]) {
172-
sshagent(['ed25519.Hibernate-CI.github.com', 'hibernate.filemgmt.jboss.org', 'hibernate-ci.frs.sourceforge.net']) {
173-
// set release version
174-
// update changelog from JIRA
175-
// tags the version
176-
// changes the version to the provided development version
177-
withEnv([
178-
"BRANCH=${env.GIT_BRANCH}",
179-
// Increase the amount of memory for this part since asciidoctor doc rendering consumes a lot of metaspace
180-
"GRADLE_OPTS=-Dorg.gradle.jvmargs='-Dlog4j2.disableJmx -Xmx4g -XX:MaxMetaspaceSize=768m -XX:+HeapDumpOnOutOfMemoryError -Duser.language=en -Duser.country=US -Duser.timezone=UTC -Dfile.encoding=UTF-8'"
181-
]) {
182-
sh ".release/scripts/prepare-release.sh ${env.PROJECT} ${env.RELEASE_VERSION} ${env.DEVELOPMENT_VERSION}"
183-
}
184-
}
185-
}
170+
sshagent(['ed25519.Hibernate-CI.github.com', 'hibernate.filemgmt.jboss.org', 'hibernate-ci.frs.sourceforge.net']) {
171+
// set release version
172+
// update changelog from JIRA
173+
// tags the version
174+
// changes the version to the provided development version
175+
withEnv([
176+
"BRANCH=${env.GIT_BRANCH}",
177+
// Increase the amount of memory for this part since asciidoctor doc rendering consumes a lot of metaspace
178+
"GRADLE_OPTS=-Dorg.gradle.jvmargs='-Dlog4j2.disableJmx -Xmx4g -XX:MaxMetaspaceSize=768m -XX:+HeapDumpOnOutOfMemoryError -Duser.language=en -Duser.country=US -Duser.timezone=UTC -Dfile.encoding=UTF-8'"
179+
]) {
180+
sh ".release/scripts/prepare-release.sh ${env.PROJECT} ${env.RELEASE_VERSION} ${env.DEVELOPMENT_VERSION}"
181+
}
182+
}
186183
}
187184
}
188185
}
@@ -197,11 +194,13 @@ pipeline {
197194
configFile(fileId: 'release.config.ssh.knownhosts', targetLocation: "${env.HOME}/.ssh/known_hosts")
198195
]) {
199196
withCredentials([
200-
usernamePassword(credentialsId: 'ossrh.sonatype.org', passwordVariable: 'OSSRH_PASSWORD', usernameVariable: 'OSSRH_USER'),
201-
usernamePassword(credentialsId: 'gradle-plugin-portal-api-key', passwordVariable: 'PLUGIN_PORTAL_PASSWORD', usernameVariable: 'PLUGIN_PORTAL_USERNAME'),
202-
file(credentialsId: 'release.gpg.private-key', variable: 'RELEASE_GPG_PRIVATE_KEY_PATH'),
203-
string(credentialsId: 'release.gpg.passphrase', variable: 'RELEASE_GPG_PASSPHRASE'),
204-
gitUsernamePassword(credentialsId: 'username-and-token.Hibernate-CI.github.com', gitToolName: 'Default')
197+
// https://github.com/gradle-nexus/publish-plugin#publishing-to-maven-central-via-sonatype-ossrh
198+
usernamePassword(credentialsId: 'ossrh.sonatype.org', passwordVariable: 'ORG_GRADLE_PROJECT_sonatypePassword', usernameVariable: 'ORG_GRADLE_PROJECT_sonatypeUsername'),
199+
// https://docs.gradle.org/current/userguide/publishing_gradle_plugins.html#account_setup
200+
usernamePassword(credentialsId: 'gradle-plugin-portal-api-key', passwordVariable: 'GRADLE_PUBLISH_SECRET', usernameVariable: 'GRADLE_PUBLISH_KEY'),
201+
file(credentialsId: 'release.gpg.private-key', variable: 'SIGNING_GPG_PRIVATE_KEY_PATH'),
202+
string(credentialsId: 'release.gpg.passphrase', variable: 'SIGNING_GPG_PASSPHRASE')
203+
gitUsernamePassword(credentialsId: 'username-and-token.Hibernate-CI.github.com', gitToolName: 'Default')
205204
]) {
206205
sshagent(['ed25519.Hibernate-CI.github.com', 'hibernate.filemgmt.jboss.org', 'hibernate-ci.frs.sourceforge.net']) {
207206
// performs documentation upload and Sonatype release

gradle/published-java-module.gradle

Lines changed: 61 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ dependencies {
2929
// Publishing
3030

3131
java {
32+
// Configure the Java "software component" to include javadoc and sources jars in addition to the classes jar.
33+
// Ultimately, this component is what makes up the publication for this project.
3234
withJavadocJar()
3335
withSourcesJar()
3436
}
@@ -37,6 +39,7 @@ publishing {
3739
publications {
3840
// main publication
3941
publishedArtifacts {
42+
// including sources and javadoc jars, per above
4043
from components.java
4144
}
4245

@@ -98,130 +101,86 @@ publishing {
98101
}
99102

100103

101-
var signingKey = resolveSigningKey()
102-
var signingPassword = findSigningProperty( "signingPassword" )
104+
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
105+
// Signing
103106

104-
signing {
105-
useInMemoryPgpKeys( signingKey, signingPassword )
107+
def signPublicationsTask = tasks.register('signPublications') {
108+
description "Grouping task which executes all Sign tasks"
106109

107-
sign publishing.publications.publishedArtifacts
110+
dependsOn tasks.withType( Sign )
108111
}
109112

110-
String resolveSigningKey() {
111-
var key = findSigningProperty( "signingKey" )
112-
if ( key != null ) {
113-
return key
114-
}
115-
116-
var keyFile = findSigningProperty( "signingKeyFile" )
117-
if ( keyFile != null ) {
118-
return new File( keyFile ).text
119-
}
120-
121-
return null
113+
tasks.named( "publishPublishedArtifactsPublicationToSonatypeRepository" ) {
114+
// publishing depends on signing
115+
dependsOn signPublicationsTask
122116
}
123117

124-
String findSigningProperty(String propName) {
125-
if ( System.getProperty( propName ) != null ) {
126-
logger.debug "Found `{}` as a system property", propName
127-
return System.getProperty(propName )
128-
}
129-
else if ( System.getenv().get( propName ) != null ) {
130-
logger.debug "Found `{}` as an env-var property", propName
131-
return System.getenv().get( propName )
132-
}
133-
else if ( project.hasProperty( propName ) ) {
134-
logger.debug "Found `{}` as a project property", propName
135-
return project.hasProperty( propName )
136-
}
137-
else {
138-
logger.debug "Did not find `{}`", propName
139-
return null
140-
}
118+
tasks.register('sign') {
119+
description "Pseudonym for :signPublications"
120+
dependsOn signPublicationsTask
141121
}
142122

143-
144-
var signingTask = project.tasks.getByName( "signPublishedArtifactsPublication" ) as Sign
145123
var signingExtension = project.getExtensions().getByType(SigningExtension) as SigningExtension
146124

147-
task sign {
148-
dependsOn "signPublications"
149-
}
125+
gradle.taskGraph.whenReady { TaskExecutionGraph graph ->
126+
boolean wasSigningRequested = false
127+
boolean wasPublishingRequested = false
128+
129+
graph.allTasks.each {task ->
130+
if ( task instanceof Sign ) {
131+
wasSigningRequested = true
132+
}
133+
else if ( task instanceof PublishToMavenRepository ) {
134+
wasPublishingRequested = true
135+
}
136+
}
150137

151-
task signPublications { t ->
152-
tasks.withType( Sign ).all { s ->
153-
t.dependsOn s
138+
if ( wasPublishingRequested ) {
139+
def ossrhUser = System.getenv().get( "ORG_GRADLE_PROJECT_sonatypeUsername" )
140+
def ossrhPass = System.getenv().get( "ORG_GRADLE_PROJECT_sonatypePassword" )
141+
if ( ossrhUser == null || ossrhPass == null ) {
142+
throw new RuntimeException( "Cannot perform publishing to OSSRH without credentials." )
143+
}
144+
logger.lifecycle "Publishing groupId: '" + project.group + "', version: '" + project.version + "'"
154145
}
155-
}
156146

157-
signingTask.doFirst {
158-
if ( signingKey == null || signingPassword == null ) {
159-
throw new GradleException(
160-
"Cannot perform signing without GPG details. Please set the `signingKey` and `signingKeyFile` properties"
161-
)
147+
if ( wasSigningRequested || wasPublishingRequested ) {
148+
// signing was explicitly requested and/or we are publishing to Sonatype OSSRH
149+
// - we need the signing to happen
150+
signingExtension.required = true
151+
152+
var signingKey = resolveSigningKey()
153+
var signingPassword = resolveSigningPassphrase()
154+
signingExtension.useInMemoryPgpKeys( signingKey, signingPassword )
155+
signingExtension.sign publishing.publications.publishedArtifacts
156+
}
157+
else {
158+
// signing was not explicitly requested and we are not publishing to OSSRH,
159+
// - disable all Sign tasks
160+
tasks.withType( Sign ).each { enabled = false }
162161
}
163162
}
164163

165-
166-
boolean wasSigningExplicitlyRequested() {
167-
// check whether signing task was explicitly requested when running the build
168-
//
169-
// NOTE: due to https://discuss.gradle.org/t/how-to-tell-if-a-task-was-explicitly-asked-for-on-the-command-line/42853/3
170-
// we cannot definitively know whether the task was requested. Gradle really just does not expose this information.
171-
// so we make a convention - we check the "start parameters" object to see which task-names were requested;
172-
// the problem is that these are the raw names directly from the command line. e.g. it is perfectly legal to
173-
// say `gradlew signPubArtPub` in place of `gradlew signPublishedArtifactsPublication` - Gradle will simply
174-
// "expand" the name it finds. However, it does not make that available.
175-
//
176-
// so the convention is that we will check for the following task names
177-
//
178-
// for each of:
179-
// 1. `sign`
180-
// 2. `signPublications`
181-
// 3. `signPublishedArtifactsPublication`
182-
//
183-
// and we check both forms:
184-
// 1. "${taskName}"
185-
// 2. project.path + ":${taskName}"
186-
//
187-
// we need to check both again because of the "start parameters" discussion
188-
189-
def signingTaskNames = ["sign", "signPublications", "signPublishedArtifactsPublication"]
190-
191-
for ( String taskName : signingTaskNames ) {
192-
if ( gradle.startParameter.taskNames.contains( taskName )
193-
|| gradle.startParameter.taskNames.contains( "${project.path}:${taskName}" ) ) {
194-
return true
195-
}
164+
static String resolveSigningKey() {
165+
var key = System.getenv().get( "SIGNING_GPG_PRIVATE_KEY" )
166+
if ( key != null ) {
167+
return key
196168
}
197169

198-
return false
199-
}
170+
var keyFile = System.getenv().get( "SIGNING_GPG_PRIVATE_KEY_PATH" )
171+
if ( keyFile != null ) {
172+
return new File( keyFile ).text
173+
}
200174

201-
if ( wasSigningExplicitlyRequested() ) {
202-
// signing was explicitly requested
203-
signingExtension.required = true
175+
throw new RuntimeException( "Cannot perform signing without GPG details." )
204176
}
205-
else {
206-
gradle.taskGraph.whenReady { graph ->
207-
if ( graph.hasTask( signingTask ) ) {
208-
// signing is scheduled to happen.
209-
//
210-
// we know, from above if-check, that it was not explicitly requested -
211-
// so it is triggered via task dependency. make sure we want it to happen
212-
var publishingTask = project.tasks.getByName( "publishPublishedArtifactsPublicationToSonatypeRepository" ) as PublishToMavenRepository
213-
if ( graph.hasTask( publishingTask ) ) {
214-
// we are publishing to Sonatype OSSRH - we need the signing to happen
215-
signingExtension.required = true
216-
}
217-
else {
218-
// signing was not explicitly requested and we are not publishing to OSSRH,
219-
// so do not sign.
220-
signingTask.enabled = false
221-
}
222-
}
223177

178+
static String resolveSigningPassphrase() {
179+
var passphrase = System.getenv().get( "SIGNING_GPG_PASSPHRASE" )
180+
if ( passphrase == null ) {
181+
throw new RuntimeException( "Cannot perform signing without GPG details." )
224182
}
183+
return passphrase
225184
}
226185

227186

tooling/hibernate-gradle-plugin/hibernate-gradle-plugin.gradle

Lines changed: 30 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -100,21 +100,6 @@ publishing {
100100
}
101101
}
102102

103-
// local publishing (SNAPSHOT testing), cont.
104-
// - https://github.com/gradle-nexus/publish-plugin/issues/143
105-
// - https://github.com/gradle-nexus/publish-plugin/pull/144
106-
gradle.taskGraph.whenReady {
107-
tasks.withType(PublishToMavenRepository) { PublishToMavenRepository t ->
108-
if ( t.repository == null ) {
109-
logger.info( "Task `{}` had null repository", t.path )
110-
}
111-
else if ( t.repository.name == "sonatype" ) {
112-
logger.debug( "Disabling task `{}` because it publishes to Sonatype", t.path )
113-
t.enabled = false
114-
}
115-
}
116-
}
117-
118103
processResources {
119104
inputs.property( "orm-version", getVersion() )
120105
description = description + " (injected with Hibernate version)"
@@ -153,20 +138,38 @@ tasks.publish.enabled !project.ormVersion.isSnapshot
153138
tasks.publishPlugins.enabled !project.ormVersion.isSnapshot
154139

155140
gradle.taskGraph.whenReady { tg ->
156-
if ( tg.hasTask( project.tasks.publishPlugins ) && project.tasks.publishPlugins.enabled ) {
157-
// look for sys-prop or env-var overrides of the tokens used for publishing
158-
if ( project.properties.containsKey( 'gradle.publish.key' )
159-
|| project.properties.containsKey( 'gradle.publish.secret' ) ) {
160-
// nothing to do - already explicitly set
161-
}
162-
else {
163-
// use the values from the credentials provider, if any
164-
if ( project.property( 'gradle.publish.key' ) == null ) {
165-
throw new RuntimeException( "`-Pgradle.publish.key=...` not found" )
141+
// verify credentials for publishing the plugin up front to avoid any work (only if we are publishing)
142+
if ( tg.hasTask( ":publishPlugins" ) && project.tasks.publishPlugins.enabled ) {
143+
// we are publishing the plugin - make sure there is a credentials pair
144+
//
145+
// first, check the `GRADLE_PUBLISH_KEY` / `GRADLE_PUBLISH_SECRET` combo (env vars)
146+
// and then the `gradle.publish.key` / `gradle.publish.secret` combo (project prop)
147+
// - see https://docs.gradle.org/current/userguide/publishing_gradle_plugins.html#account_setup
148+
if ( System.getenv().get("GRADLE_PUBLISH_KEY") != null ) {
149+
if ( System.getenv().get("GRADLE_PUBLISH_SECRET") != null ) {
150+
throw new RuntimeException( "`GRADLE_PUBLISH_KEY` specified, but not `GRADLE_PUBLISH_SECRET` for publishing Gradle plugin" )
166151
}
167-
if ( project.property( 'gradle.publish.secret' ) == null ) {
168-
throw new RuntimeException( "`-Pgradle.publish.secret=...` not found" )
152+
}
153+
else if ( project.findProperty( 'gradle.publish.key' ) != null ) {
154+
if ( project.findProperty( 'gradle.publish.secret' ) != null ) {
155+
throw new RuntimeException( "`gradle.publish.key` specified, but not `gradle.publish.secret` for publishing Gradle plugin" )
169156
}
170157
}
158+
else {
159+
throw new RuntimeException( "No credentials specified for publishing Gradle plugin" )
160+
}
161+
}
162+
163+
// local publishing (SNAPSHOT testing), cont.
164+
// - https://github.com/gradle-nexus/publish-plugin/issues/143
165+
// - https://github.com/gradle-nexus/publish-plugin/pull/144
166+
tasks.withType(PublishToMavenRepository) { PublishToMavenRepository t ->
167+
if ( t.repository == null ) {
168+
logger.info( "Task `{}` had null repository", t.path )
169+
}
170+
else if ( t.repository.name == "sonatype" ) {
171+
logger.debug( "Disabling task `{}` because it publishes to Sonatype", t.path )
172+
t.enabled = false
173+
}
171174
}
172175
}

0 commit comments

Comments
 (0)