Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

HHH-18912 - ORM release process #9423

Merged
merged 5 commits into from
Dec 19, 2024
Merged
Show file tree
Hide file tree
Changes from all 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
53 changes: 6 additions & 47 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -42,77 +42,36 @@ apply from: file( 'gradle/module.gradle' )
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Release Task

task release {
tasks.register('release') {
description = "The task performed when we are performing a release build. Relies on " +
"the fact that subprojects will appropriately define a release task " +
"themselves if they have any release-related activities to perform"

doFirst {
def javaVersionsInUse = jdkVersions.allVersions
if ( javaVersionsInUse != [JavaLanguageVersion.of( 11 )].toSet() ) {
throw new IllegalStateException( "Please use JDK 11 to perform the release. Currently using: ${javaVersionsInUse}" )
if (javaVersionsInUse != [JavaLanguageVersion.of(11)].toSet()) {
throw new IllegalStateException("Please use JDK 11 to perform the release. Currently using: ${javaVersionsInUse}")
}
}
}

task publish {
tasks.register('publish') {
description = "The task performed when we want to just publish maven artifacts. Relies on " +
"the fact that subprojects will appropriately define a release task " +
"themselves if they have any publish-related activities to perform"
}

ext {
if ( project.hasProperty( 'hibernatePublishUsername' ) ) {
if ( ! project.hasProperty( 'hibernatePublishPassword' ) ) {
throw new GradleException( "Should specify both `hibernatePublishUsername` and `hibernatePublishPassword` as project properties" );
}
}
}

nexusPublishing {
repositories {
sonatype {
username = project.hasProperty( 'hibernatePublishUsername' ) ? project.property( 'hibernatePublishUsername' ) : null
password = project.hasProperty( 'hibernatePublishPassword' ) ? project.property( 'hibernatePublishPassword' ) : null
}
sonatype()
}
}

gradle.taskGraph.addTaskExecutionGraphListener(
new TaskExecutionGraphListener() {
@Override
void graphPopulated(TaskExecutionGraph graph) {
String[] tasksToLookFor = [
'publish',
'publishToSonatype',
'publishAllPublicationsToSonatype',
'publishPublishedArtifactsPublicationToSonatypeRepository',
'publishRelocationArtifactsPublicationToSonatypeRepository',
]

for ( String taskToLookFor : tasksToLookFor ) {
if ( graph.hasTask( taskToLookFor ) ) {
// trying to publish - make sure the needed credentials are available

if ( project.property( 'hibernatePublishUsername' ) == null ) {
throw new RuntimeException( "`-PhibernatePublishUsername=...` not found" )
}
if ( project.property( 'hibernatePublishPassword' ) == null ) {
throw new RuntimeException( "`-PhibernatePublishPassword=...` not found" )
}

break;
}
}
}
}
)


// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// CI Build Task

task ciBuild {
tasks.register('ciBuild') {
description = "The task performed when one of the 'main' jobs are triggered on the " +
"CI server. Just as above, relies on the fact that subprojects will " +
"appropriately define a release task themselves if they have any tasks " +
Expand Down
46 changes: 23 additions & 23 deletions ci/release/Jenkinsfile
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,10 @@ pipeline {
stage('Release check') {
steps {
script {
print "INFO: params.RELEASE_VERSION = ${params.RELEASE_VERSION}"
print "INFO: params.DEVELOPMENT_VERSION = ${params.DEVELOPMENT_VERSION}"
print "INFO: params.RELEASE_DRY_RUN? = ${params.RELEASE_DRY_RUN}"

checkoutReleaseScripts()

def currentVersion = Version.parseDevelopmentVersion( sh(
Expand Down Expand Up @@ -163,24 +167,18 @@ pipeline {
configFile(fileId: 'release.config.ssh', targetLocation: "${env.HOME}/.ssh/config"),
configFile(fileId: 'release.config.ssh.knownhosts', targetLocation: "${env.HOME}/.ssh/known_hosts")
]) {
withCredentials([
usernamePassword(credentialsId: 'ossrh.sonatype.org', passwordVariable: 'OSSRH_PASSWORD', usernameVariable: 'OSSRH_USER'),
usernamePassword(credentialsId: 'gradle-plugin-portal-api-key', passwordVariable: 'PLUGIN_PORTAL_PASSWORD', usernameVariable: 'PLUGIN_PORTAL_USERNAME'),
file(credentialsId: 'release.gpg.private-key', variable: 'RELEASE_GPG_PRIVATE_KEY_PATH'),
string(credentialsId: 'release.gpg.passphrase', variable: 'RELEASE_GPG_PASSPHRASE')
]) {
sshagent(['ed25519.Hibernate-CI.github.com', 'hibernate.filemgmt.jboss.org', 'hibernate-ci.frs.sourceforge.net']) {
// set release version
// update changelog from JIRA
// tags the version
// changes the version to the provided development version
withEnv([
"BRANCH=${env.GIT_BRANCH}",
// Increase the amount of memory for this part since asciidoctor doc rendering consumes a lot of metaspace
"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'"
]) {
sh ".release/scripts/prepare-release.sh ${env.PROJECT} ${env.RELEASE_VERSION} ${env.DEVELOPMENT_VERSION}"
}
sshagent(['ed25519.Hibernate-CI.github.com', 'hibernate.filemgmt.jboss.org', 'hibernate-ci.frs.sourceforge.net']) {
// set release version
// update changelog from JIRA
// tags the version
// changes the version to the provided development version
withEnv([
"BRANCH=${env.GIT_BRANCH}",
"DISABLE_REMOTE_GRADLE_CACHE=true",
// Increase the amount of memory for this part since asciidoctor doc rendering consumes a lot of metaspace
"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'"
]) {
sh ".release/scripts/prepare-release.sh ${env.PROJECT} ${env.RELEASE_VERSION} ${env.DEVELOPMENT_VERSION}"
}
}
}
Expand All @@ -197,11 +195,13 @@ pipeline {
configFile(fileId: 'release.config.ssh.knownhosts', targetLocation: "${env.HOME}/.ssh/known_hosts")
]) {
withCredentials([
usernamePassword(credentialsId: 'ossrh.sonatype.org', passwordVariable: 'OSSRH_PASSWORD', usernameVariable: 'OSSRH_USER'),
usernamePassword(credentialsId: 'gradle-plugin-portal-api-key', passwordVariable: 'PLUGIN_PORTAL_PASSWORD', usernameVariable: 'PLUGIN_PORTAL_USERNAME'),
file(credentialsId: 'release.gpg.private-key', variable: 'RELEASE_GPG_PRIVATE_KEY_PATH'),
string(credentialsId: 'release.gpg.passphrase', variable: 'RELEASE_GPG_PASSPHRASE'),
gitUsernamePassword(credentialsId: 'username-and-token.Hibernate-CI.github.com', gitToolName: 'Default')
// https://github.com/gradle-nexus/publish-plugin#publishing-to-maven-central-via-sonatype-ossrh
usernamePassword(credentialsId: 'ossrh.sonatype.org', passwordVariable: 'ORG_GRADLE_PROJECT_sonatypePassword', usernameVariable: 'ORG_GRADLE_PROJECT_sonatypeUsername'),
// https://docs.gradle.org/current/userguide/publishing_gradle_plugins.html#account_setup
usernamePassword(credentialsId: 'gradle-plugin-portal-api-key', passwordVariable: 'GRADLE_PUBLISH_SECRET', usernameVariable: 'GRADLE_PUBLISH_KEY'),
file(credentialsId: 'release.gpg.private-key', variable: 'SIGNING_GPG_PRIVATE_KEY_PATH'),
string(credentialsId: 'release.gpg.passphrase', variable: 'SIGNING_GPG_PASSPHRASE'),
gitUsernamePassword(credentialsId: 'username-and-token.Hibernate-CI.github.com', gitToolName: 'Default')
]) {
sshagent(['ed25519.Hibernate-CI.github.com', 'hibernate.filemgmt.jboss.org', 'hibernate-ci.frs.sourceforge.net']) {
// performs documentation upload and Sonatype release
Expand Down
30 changes: 14 additions & 16 deletions ci/snapshot-publish.Jenkinsfile
Original file line number Diff line number Diff line change
Expand Up @@ -30,22 +30,20 @@ pipeline {
}
stage('Publish') {
steps {
withCredentials([
usernamePassword(credentialsId: 'ossrh.sonatype.org', usernameVariable: 'hibernatePublishUsername', passwordVariable: 'hibernatePublishPassword'),
usernamePassword(credentialsId: 'plugins.gradle.org', usernameVariable: 'hibernatePluginPortalUsername', passwordVariable: 'hibernatePluginPortalPassword'),
string(credentialsId: 'ge.hibernate.org-access-key', variable: 'GRADLE_ENTERPRISE_ACCESS_KEY'),
string(credentialsId: 'release.gpg.passphrase', variable: 'SIGNING_PASS'),
file(credentialsId: 'release.gpg.private-key', variable: 'SIGNING_KEYRING')
]) {
sh '''./gradlew clean publish \
-PhibernatePublishUsername=$hibernatePublishUsername \
-PhibernatePublishPassword=$hibernatePublishPassword \
-Pgradle.publish.key=$hibernatePluginPortalUsername \
-Pgradle.publish.secret=$hibernatePluginPortalPassword \
--no-scan \
-DsigningPassword=$SIGNING_PASS \
-DsigningKeyFile=$SIGNING_KEYRING \
'''
withCredentials([
// https://github.com/gradle-nexus/publish-plugin#publishing-to-maven-central-via-sonatype-ossrh
usernamePassword(credentialsId: 'ossrh.sonatype.org', passwordVariable: 'ORG_GRADLE_PROJECT_sonatypePassword', usernameVariable: 'ORG_GRADLE_PROJECT_sonatypeUsername'),
// https://docs.gradle.org/current/userguide/publishing_gradle_plugins.html#account_setup
usernamePassword(credentialsId: 'gradle-plugin-portal-api-key', passwordVariable: 'GRADLE_PUBLISH_SECRET', usernameVariable: 'GRADLE_PUBLISH_KEY'),
file(credentialsId: 'release.gpg.private-key', variable: 'SIGNING_GPG_PRIVATE_KEY_PATH'),
string(credentialsId: 'release.gpg.passphrase', variable: 'SIGNING_GPG_PASSPHRASE')
gitUsernamePassword(credentialsId: 'username-and-token.Hibernate-CI.github.com', gitToolName: 'Default')
]) {
withEnv([
"DISABLE_REMOTE_GRADLE_CACHE=true"
]) {
sh './gradlew clean publish -x test --no-scan --no-daemon --no-build-cache --stacktrace'
}
}
}
}
Expand Down
163 changes: 61 additions & 102 deletions gradle/published-java-module.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ dependencies {
// Publishing

java {
// Configure the Java "software component" to include javadoc and sources jars in addition to the classes jar.
// Ultimately, this component is what makes up the publication for this project.
withJavadocJar()
withSourcesJar()
}
Expand All @@ -37,6 +39,7 @@ publishing {
publications {
// main publication
publishedArtifacts {
// including sources and javadoc jars, per above
from components.java
}

Expand Down Expand Up @@ -98,130 +101,86 @@ publishing {
}


var signingKey = resolveSigningKey()
var signingPassword = findSigningProperty( "signingPassword" )
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Signing

signing {
useInMemoryPgpKeys( signingKey, signingPassword )
def signPublicationsTask = tasks.register('signPublications') {
description "Grouping task which executes all Sign tasks"

sign publishing.publications.publishedArtifacts
dependsOn tasks.withType( Sign )
}

String resolveSigningKey() {
var key = findSigningProperty( "signingKey" )
if ( key != null ) {
return key
}

var keyFile = findSigningProperty( "signingKeyFile" )
if ( keyFile != null ) {
return new File( keyFile ).text
}

return null
tasks.named( "publishPublishedArtifactsPublicationToSonatypeRepository" ) {
// publishing depends on signing
dependsOn signPublicationsTask
}

String findSigningProperty(String propName) {
if ( System.getProperty( propName ) != null ) {
logger.debug "Found `{}` as a system property", propName
return System.getProperty(propName )
}
else if ( System.getenv().get( propName ) != null ) {
logger.debug "Found `{}` as an env-var property", propName
return System.getenv().get( propName )
}
else if ( project.hasProperty( propName ) ) {
logger.debug "Found `{}` as a project property", propName
return project.hasProperty( propName )
}
else {
logger.debug "Did not find `{}`", propName
return null
}
tasks.register('sign') {
description "Pseudonym for :signPublications"
dependsOn signPublicationsTask
}


var signingTask = project.tasks.getByName( "signPublishedArtifactsPublication" ) as Sign
var signingExtension = project.getExtensions().getByType(SigningExtension) as SigningExtension
signingExtension.sign publishing.publications.publishedArtifacts

task sign {
dependsOn "signPublications"
}
gradle.taskGraph.whenReady { TaskExecutionGraph graph ->
boolean wasSigningRequested = false
boolean wasPublishingRequested = false

graph.allTasks.each {task ->
if ( task instanceof Sign ) {
wasSigningRequested = true
}
else if ( task instanceof PublishToMavenRepository ) {
wasPublishingRequested = true
}
}

task signPublications { t ->
tasks.withType( Sign ).all { s ->
t.dependsOn s
if ( wasPublishingRequested ) {
def ossrhUser = System.getenv().get( "ORG_GRADLE_PROJECT_sonatypeUsername" )
def ossrhPass = System.getenv().get( "ORG_GRADLE_PROJECT_sonatypePassword" )
if ( ossrhUser == null || ossrhPass == null ) {
throw new RuntimeException( "Cannot perform publishing to OSSRH without credentials." )
}
logger.lifecycle "Publishing {} : {} : {}", project.group, project.name, project.version
}
}

signingTask.doFirst {
if ( signingKey == null || signingPassword == null ) {
throw new GradleException(
"Cannot perform signing without GPG details. Please set the `signingKey` and `signingKeyFile` properties"
)
if ( wasSigningRequested || wasPublishingRequested ) {
// signing was explicitly requested and/or we are publishing to Sonatype OSSRH
// - we need the signing to happen
signingExtension.required = true

var signingKey = resolveSigningKey()
var signingPassword = resolveSigningPassphrase()
signingExtension.useInMemoryPgpKeys( signingKey, signingPassword )
}
else {
// signing was not explicitly requested and we are not publishing to OSSRH,
// - disable all Sign tasks
tasks.withType( Sign ).each { t-> t.enabled = false }
}
}


boolean wasSigningExplicitlyRequested() {
// check whether signing task was explicitly requested when running the build
//
// NOTE: due to https://discuss.gradle.org/t/how-to-tell-if-a-task-was-explicitly-asked-for-on-the-command-line/42853/3
// we cannot definitively know whether the task was requested. Gradle really just does not expose this information.
// so we make a convention - we check the "start parameters" object to see which task-names were requested;
// the problem is that these are the raw names directly from the command line. e.g. it is perfectly legal to
// say `gradlew signPubArtPub` in place of `gradlew signPublishedArtifactsPublication` - Gradle will simply
// "expand" the name it finds. However, it does not make that available.
//
// so the convention is that we will check for the following task names
//
// for each of:
// 1. `sign`
// 2. `signPublications`
// 3. `signPublishedArtifactsPublication`
//
// and we check both forms:
// 1. "${taskName}"
// 2. project.path + ":${taskName}"
//
// we need to check both again because of the "start parameters" discussion

def signingTaskNames = ["sign", "signPublications", "signPublishedArtifactsPublication"]

for ( String taskName : signingTaskNames ) {
if ( gradle.startParameter.taskNames.contains( taskName )
|| gradle.startParameter.taskNames.contains( "${project.path}:${taskName}" ) ) {
return true
}
static String resolveSigningKey() {
var key = System.getenv().get( "SIGNING_GPG_PRIVATE_KEY" )
if ( key != null ) {
return key
}

return false
}
var keyFile = System.getenv().get( "SIGNING_GPG_PRIVATE_KEY_PATH" )
if ( keyFile != null ) {
return new File( keyFile ).text
}

if ( wasSigningExplicitlyRequested() ) {
// signing was explicitly requested
signingExtension.required = true
throw new RuntimeException( "Cannot perform signing without GPG details." )
}
else {
gradle.taskGraph.whenReady { graph ->
if ( graph.hasTask( signingTask ) ) {
// signing is scheduled to happen.
//
// we know, from above if-check, that it was not explicitly requested -
// so it is triggered via task dependency. make sure we want it to happen
var publishingTask = project.tasks.getByName( "publishPublishedArtifactsPublicationToSonatypeRepository" ) as PublishToMavenRepository
if ( graph.hasTask( publishingTask ) ) {
// we are publishing to Sonatype OSSRH - we need the signing to happen
signingExtension.required = true
}
else {
// signing was not explicitly requested and we are not publishing to OSSRH,
// so do not sign.
signingTask.enabled = false
}
}

static String resolveSigningPassphrase() {
var passphrase = System.getenv().get( "SIGNING_GPG_PASSPHRASE" )
if ( passphrase == null ) {
throw new RuntimeException( "Cannot perform signing without GPG details." )
}
return passphrase
}


Expand Down
Loading
Loading