diff --git a/build.gradle b/build.gradle index ae7a4284a399..49b19dffae15 100644 --- a/build.gradle +++ b/build.gradle @@ -42,77 +42,35 @@ 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 " + diff --git a/ci/release/Jenkinsfile b/ci/release/Jenkinsfile index b36cc7afe360..f86c976528ab 100644 --- a/ci/release/Jenkinsfile +++ b/ci/release/Jenkinsfile @@ -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( @@ -164,27 +168,20 @@ 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}", - "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}" - } - } - } + 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}" + } + } } } } @@ -199,10 +196,12 @@ 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'), + // 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']) { diff --git a/gradle/published-java-module.gradle b/gradle/published-java-module.gradle index b9ea71617b22..8c2cf18ddffd 100644 --- a/gradle/published-java-module.gradle +++ b/gradle/published-java-module.gradle @@ -21,6 +21,7 @@ configurations { } dependencies { + // `javadocSources` is a special Configuration which is used as a basis for the aggregated-javadocs we produce javadocSources sourceSets.main.allJava } @@ -29,6 +30,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() } @@ -98,130 +101,90 @@ publishing { } -var signingKey = resolveSigningKey() -var signingPassword = findSigningProperty( "signingPassword" ) -signing { - useInMemoryPgpKeys( signingKey, signingPassword ) - sign publishing.publications.publishedArtifacts -} -String resolveSigningKey() { - var key = findSigningProperty( "signingKey" ) - if ( key != null ) { - return key - } - var keyFile = findSigningProperty( "signingKeyFile" ) - if ( keyFile != null ) { - return new File( keyFile ).text - } +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Signing + +def signPublicationsTask = tasks.register('signPublications') { + description "Grouping task which executes all Sign tasks" - return null + dependsOn tasks.withType( Sign ) } -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.named( "publishPublishedArtifactsPublicationToSonatypeRepository" ) { + // publishing depends on signing + dependsOn signPublicationsTask } +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 -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 groupId: '" + project.group + "', version: '" + 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 ) + signingExtension.sign publishing.publications.publishedArtifacts + } + else { + // signing was not explicitly requested and we are not publishing to OSSRH, + // - disable all Sign tasks + tasks.withType( Sign ).each { 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 } diff --git a/tooling/hibernate-gradle-plugin/hibernate-gradle-plugin.gradle b/tooling/hibernate-gradle-plugin/hibernate-gradle-plugin.gradle index 551820769781..aded4a3e08e6 100644 --- a/tooling/hibernate-gradle-plugin/hibernate-gradle-plugin.gradle +++ b/tooling/hibernate-gradle-plugin/hibernate-gradle-plugin.gradle @@ -23,10 +23,7 @@ apply from: rootProject.file( 'gradle/releasable.gradle' ) description = "Gradle plugin for integrating Hibernate aspects into your build" -ext { - pluginId = 'org.hibernate.orm' - pluginVersion = project.version -} +def pluginId = 'org.hibernate.orm' dependencies { implementation project(':hibernate-core') @@ -50,7 +47,7 @@ dependencies { gradlePlugin { plugins { ormPlugin { - id = project.pluginId + id = pluginId implementationClass = 'org.hibernate.orm.tooling.gradle.HibernateOrmPlugin' } } @@ -70,7 +67,7 @@ pluginBundle { plugins { ormPlugin { - id = project.pluginId + id = pluginId displayName = 'Gradle plugin for Hibernate ORM' description = 'Applies Hibernate aspects into the build' } @@ -100,21 +97,6 @@ publishing { } } -// local publishing (SNAPSHOT testing), cont. -// - https://github.com/gradle-nexus/publish-plugin/issues/143 -// - https://github.com/gradle-nexus/publish-plugin/pull/144 -gradle.taskGraph.whenReady { - tasks.withType(PublishToMavenRepository) { PublishToMavenRepository t -> - if ( t.repository == null ) { - logger.info( "Task `{}` had null repository", t.path ) - } - else if ( t.repository.name == "sonatype" ) { - logger.debug( "Disabling task `{}` because it publishes to Sonatype", t.path ) - t.enabled = false - } - } -} - processResources { inputs.property( "orm-version", getVersion() ) description = description + " (injected with Hibernate version)" @@ -153,20 +135,38 @@ tasks.publish.enabled !project.ormVersion.isSnapshot tasks.publishPlugins.enabled !project.ormVersion.isSnapshot gradle.taskGraph.whenReady { tg -> - if ( tg.hasTask( project.tasks.publishPlugins ) && project.tasks.publishPlugins.enabled ) { - // look for sys-prop or env-var overrides of the tokens used for publishing - if ( project.properties.containsKey( 'gradle.publish.key' ) - || project.properties.containsKey( 'gradle.publish.secret' ) ) { - // nothing to do - already explicitly set - } - else { - // use the values from the credentials provider, if any - if ( project.property( 'gradle.publish.key' ) == null ) { - throw new RuntimeException( "`-Pgradle.publish.key=...` not found" ) + // verify credentials for publishing the plugin up front to avoid any work (only if we are publishing) + if ( tg.hasTask( ":publishPlugins" ) && project.tasks.publishPlugins.enabled ) { + // we are publishing the plugin - make sure there is a credentials pair + // + // first, check the `GRADLE_PUBLISH_KEY` / `GRADLE_PUBLISH_SECRET` combo (env vars) + // and then the `gradle.publish.key` / `gradle.publish.secret` combo (project prop) + // - see https://docs.gradle.org/current/userguide/publishing_gradle_plugins.html#account_setup + if ( System.getenv().get("GRADLE_PUBLISH_KEY") != null ) { + if ( System.getenv().get("GRADLE_PUBLISH_SECRET") != null ) { + throw new RuntimeException( "`GRADLE_PUBLISH_KEY` specified, but not `GRADLE_PUBLISH_SECRET` for publishing Gradle plugin" ) } - if ( project.property( 'gradle.publish.secret' ) == null ) { - throw new RuntimeException( "`-Pgradle.publish.secret=...` not found" ) + } + else if ( project.findProperty( 'gradle.publish.key' ) != null ) { + if ( project.findProperty( 'gradle.publish.secret' ) != null ) { + throw new RuntimeException( "`gradle.publish.key` specified, but not `gradle.publish.secret` for publishing Gradle plugin" ) } } + else { + throw new RuntimeException( "No credentials specified for publishing Gradle plugin" ) + } + } + + // local publishing (SNAPSHOT testing), cont. + // - https://github.com/gradle-nexus/publish-plugin/issues/143 + // - https://github.com/gradle-nexus/publish-plugin/pull/144 + tasks.withType(PublishToMavenRepository) { PublishToMavenRepository t -> + if ( t.repository == null ) { + logger.info( "Task `{}` had null repository", t.path ) + } + else if ( t.repository.name == "sonatype" ) { + logger.debug( "Disabling task `{}` because it publishes to Sonatype", t.path ) + t.enabled = false + } } } \ No newline at end of file