Skip to content

Commit 3815d7a

Browse files
marko-bekhtadreab8
authored andcommitted
HHH-19341 Add automated release to 5.6
1 parent d7e8a69 commit 3815d7a

File tree

7 files changed

+304
-37
lines changed

7 files changed

+304
-37
lines changed

.release/.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# The folder into which we checkout our release scripts into
2+
*
3+
!.gitignore

build.gradle

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -21,18 +21,12 @@ buildscript {
2121

2222
plugins {
2323
id 'me.champeau.buildscan-recipes' version '0.2.3'
24-
id 'io.github.gradle-nexus.publish-plugin' version '1.1.0'
2524
id 'nu.studer.credentials' version '2.2'
2625
id 'org.hibernate.build.xjc' version '2.0.1' apply false
2726
id 'org.hibernate.build.maven-repo-auth' version '3.0.3' apply false
2827
id 'biz.aQute.bnd' version '5.1.1' apply false
2928
}
3029

31-
ext {
32-
sonatypeOssrhUser = project.findProperty( 'SONATYPE_OSSRH_USER' )
33-
sonatypeOssrhPassword = project.findProperty( 'SONATYPE_OSSRH_PASSWORD' )
34-
}
35-
3630
File versionFile = file( "${rootProject.projectDir}/gradle/version.properties" )
3731

3832
ext {
@@ -51,15 +45,6 @@ ext {
5145
group = 'org.hibernate'
5246
version = project.ormVersion.fullName
5347

54-
nexusPublishing {
55-
repositories {
56-
sonatype {
57-
username = project.sonatypeOssrhUser
58-
password = project.sonatypeOssrhPassword
59-
}
60-
}
61-
}
62-
6348
allprojects {
6449
repositories {
6550
mavenCentral()

ci/release/Jenkinsfile

Lines changed: 275 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,275 @@
1+
#! /usr/bin/groovy
2+
/*
3+
* See https://github.com/hibernate/hibernate-jenkins-pipeline-helpers
4+
*/
5+
@Library('hibernate-jenkins-pipeline-helpers') _
6+
7+
import org.hibernate.jenkins.pipeline.helpers.version.Version
8+
9+
// --------------------------------------------
10+
// Global build configuration
11+
env.PROJECT = "orm"
12+
env.JIRA_KEY = "HHH"
13+
def RELEASE_ON_SCHEDULE = false // Set to `true` *only* on branches where you want a scheduled release.
14+
15+
print "INFO: env.PROJECT = ${env.PROJECT}"
16+
print "INFO: env.JIRA_KEY = ${env.JIRA_KEY}"
17+
18+
// --------------------------------------------
19+
// Build conditions
20+
21+
// Avoid running the pipeline on branch indexing
22+
if (currentBuild.getBuildCauses().toString().contains('BranchIndexingCause')) {
23+
print "INFO: Build skipped due to trigger being Branch Indexing"
24+
currentBuild.result = 'NOT_BUILT'
25+
return
26+
}
27+
28+
def manualRelease = currentBuild.getBuildCauses().toString().contains( 'UserIdCause' )
29+
def cronRelease = currentBuild.getBuildCauses().toString().contains( 'TimerTriggerCause' )
30+
31+
// Only do automatic release on branches where we opted in
32+
if ( !manualRelease && !cronRelease ) {
33+
print "INFO: Build skipped because automated releases on push are disabled on this branch."
34+
currentBuild.result = 'NOT_BUILT'
35+
return
36+
}
37+
38+
if ( !manualRelease && cronRelease && !RELEASE_ON_SCHEDULE ) {
39+
print "INFO: Build skipped because automated releases are disabled on this branch. See constant RELEASE_ON_SCHEDULE in ci/release/Jenkinsfile"
40+
currentBuild.result = 'NOT_BUILT'
41+
return
42+
}
43+
44+
// --------------------------------------------
45+
// Reusable methods
46+
47+
def checkoutReleaseScripts() {
48+
dir('.release/scripts') {
49+
checkout scmGit(branches: [[name: '*/main']], extensions: [],
50+
userRemoteConfigs: [[credentialsId: 'ed25519.Hibernate-CI.github.com',
51+
url: 'https://github.com/hibernate/hibernate-release-scripts.git']])
52+
}
53+
}
54+
55+
56+
// --------------------------------------------
57+
// Pipeline
58+
59+
pipeline {
60+
agent {
61+
label 'Release'
62+
}
63+
triggers {
64+
// Run every week Sunday midnight
65+
cron('0 0 * * 0')
66+
}
67+
tools {
68+
jdk 'OpenJDK 8 Latest'
69+
}
70+
options {
71+
buildDiscarder logRotator(daysToKeepStr: '30', numToKeepStr: '10')
72+
disableConcurrentBuilds(abortPrevious: false)
73+
preserveStashes()
74+
}
75+
parameters {
76+
string(
77+
name: 'RELEASE_VERSION',
78+
defaultValue: '',
79+
description: 'The version to be released, e.g. 6.2.1.Final. Mandatory for manual releases, to prevent mistakes.',
80+
trim: true
81+
)
82+
string(
83+
name: 'DEVELOPMENT_VERSION',
84+
defaultValue: '',
85+
description: 'The next version to be used after the release, e.g. 6.2.2-SNAPSHOT. If not set, determined automatically from the release version.',
86+
trim: true
87+
)
88+
booleanParam(
89+
name: 'RELEASE_DRY_RUN',
90+
defaultValue: false,
91+
description: 'If true, just simulate the release, without pushing any commits or tags, and without uploading any artifacts or documentation.'
92+
)
93+
}
94+
stages {
95+
stage('Release check') {
96+
steps {
97+
script {
98+
print "INFO: params.RELEASE_VERSION = ${params.RELEASE_VERSION}"
99+
print "INFO: params.DEVELOPMENT_VERSION = ${params.DEVELOPMENT_VERSION}"
100+
print "INFO: params.RELEASE_DRY_RUN? = ${params.RELEASE_DRY_RUN}"
101+
102+
checkoutReleaseScripts()
103+
104+
def currentVersion = Version.parseDevelopmentVersion( sh(
105+
script: ".release/scripts/determine-current-version.sh ${env.PROJECT}",
106+
returnStdout: true
107+
).trim() )
108+
echo "Workspace version: ${currentVersion}"
109+
110+
def releaseVersion
111+
def developmentVersion
112+
113+
def lastCommitter = sh(script: 'git show -s --format=\'%an\'', returnStdout: true).trim()
114+
def secondLastCommitter = sh(script: 'git show -s --format=\'%an\' HEAD~1', returnStdout: true).trim()
115+
def isCiLastCommiter = lastCommitter == 'Hibernate-CI' && secondLastCommitter == 'Hibernate-CI'
116+
117+
echo "Last two commits were performed by '${lastCommitter}'/'${secondLastCommitter}'."
118+
echo "Is 'Hibernate-CI' the last commiter: '${isCiLastCommiter}'."
119+
120+
if ( manualRelease ) {
121+
echo "Release was requested manually"
122+
123+
if ( !params.RELEASE_VERSION ) {
124+
throw new IllegalArgumentException(
125+
'Missing value for parameter RELEASE_VERSION. This parameter must be set explicitly to prevent mistakes.'
126+
)
127+
}
128+
releaseVersion = Version.parseReleaseVersion( params.RELEASE_VERSION )
129+
130+
if ( !releaseVersion.toString().startsWith( currentVersion.family + '.' ) ) {
131+
throw new IllegalArgumentException( "RELEASE_VERSION = $releaseVersion, which is different from the family of CURRENT_VERSION = $currentVersion. Did you make a mistake?" )
132+
}
133+
}
134+
else {
135+
echo "Release was triggered automatically"
136+
137+
// Avoid doing an automatic release for commits from a release
138+
139+
if (isCiLastCommiter) {
140+
print "INFO: Automatic release skipped because last commits were for the previous release"
141+
currentBuild.getRawBuild().getExecutor().interrupt(Result.NOT_BUILT)
142+
sleep(1) // Interrupt is not blocking and does not take effect immediately.
143+
return
144+
}
145+
146+
releaseVersion = Version.parseReleaseVersion( sh(
147+
script: ".release/scripts/determine-release-version.sh ${currentVersion}",
148+
returnStdout: true
149+
).trim() )
150+
}
151+
echo "Release version: ${releaseVersion}"
152+
153+
if ( !params.DEVELOPMENT_VERSION ) {
154+
developmentVersion = Version.parseDevelopmentVersion( sh(
155+
script: ".release/scripts/determine-development-version.sh ${releaseVersion}",
156+
returnStdout: true
157+
).trim() )
158+
}
159+
else {
160+
developmentVersion = Version.parseDevelopmentVersion( params.DEVELOPMENT_VERSION )
161+
}
162+
echo "Development version: ${developmentVersion}"
163+
164+
env.RELEASE_VERSION = releaseVersion.toString()
165+
env.DEVELOPMENT_VERSION = developmentVersion.toString()
166+
env.SCRIPT_OPTIONS = params.RELEASE_DRY_RUN ? "-d" : ""
167+
env.JRELEASER_DRY_RUN = params.RELEASE_DRY_RUN
168+
169+
// Determine version id to check if Jira version exists
170+
sh ".release/scripts/determine-jira-version-id.sh ${env.JIRA_KEY} ${releaseVersion.withoutFinalQualifier}"
171+
}
172+
}
173+
}
174+
stage('Release prepare') {
175+
steps {
176+
script {
177+
checkoutReleaseScripts()
178+
179+
configFileProvider([
180+
configFile(fileId: 'release.config.ssh', targetLocation: "${env.HOME}/.ssh/config"),
181+
configFile(fileId: 'release.config.ssh.knownhosts', targetLocation: "${env.HOME}/.ssh/known_hosts")
182+
]) {
183+
sshagent(['ed25519.Hibernate-CI.github.com', 'hibernate.filemgmt.jboss.org', 'hibernate-ci.frs.sourceforge.net']) {
184+
// set release version
185+
// update changelog from JIRA
186+
// tags the version
187+
// changes the version to the provided development version
188+
withEnv([
189+
"DISABLE_REMOTE_GRADLE_CACHE=true",
190+
// Increase the amount of memory for this part since asciidoctor doc rendering consumes a lot of metaspace
191+
"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'"
192+
]) {
193+
sh ".release/scripts/prepare-release.sh -j -b ${env.GIT_BRANCH} -v ${env.DEVELOPMENT_VERSION} ${env.PROJECT} ${env.RELEASE_VERSION}"
194+
}
195+
}
196+
}
197+
}
198+
}
199+
}
200+
stage('Publish release') {
201+
steps {
202+
script {
203+
checkoutReleaseScripts()
204+
205+
configFileProvider([
206+
configFile(fileId: 'release.config.ssh', targetLocation: "${env.HOME}/.ssh/config"),
207+
configFile(fileId: 'release.config.ssh.knownhosts', targetLocation: "${env.HOME}/.ssh/known_hosts")
208+
]) {
209+
withCredentials([
210+
// https://github.com/gradle-nexus/publish-plugin#publishing-to-maven-central-via-sonatype-ossrh
211+
// TODO: HHH-19309:
212+
// Once we switch to maven-central publishing (from nexus2) we need to add a new credentials
213+
// to use the following env variable names to set the user/password:
214+
// - JRELEASER_MAVENCENTRAL_USERNAME
215+
// - JRELEASER_MAVENCENTRAL_TOKEN
216+
// Also use the new `credentialsId` for Maven Central, e.g.:
217+
// usernamePassword(credentialsId: '???????', passwordVariable: 'JRELEASER_MAVENCENTRAL_TOKEN', usernameVariable: 'JRELEASER_MAVENCENTRAL_USERNAME'),
218+
usernamePassword(credentialsId: 'ossrh.sonatype.org', passwordVariable: 'JRELEASER_NEXUS2_PASSWORD', usernameVariable: 'JRELEASER_NEXUS2_USERNAME'),
219+
// https://docs.gradle.org/current/userguide/publishing_gradle_plugins.html#account_setup
220+
usernamePassword(credentialsId: 'gradle-plugin-portal-api-key', passwordVariable: 'GRADLE_PUBLISH_SECRET', usernameVariable: 'GRADLE_PUBLISH_KEY'),
221+
gitUsernamePassword(credentialsId: 'username-and-token.Hibernate-CI.github.com', gitToolName: 'Default'),
222+
file(credentialsId: 'release.gpg.private-key', variable: 'RELEASE_GPG_PRIVATE_KEY_PATH'),
223+
string(credentialsId: 'release.gpg.passphrase', variable: 'JRELEASER_GPG_PASSPHRASE'),
224+
string(credentialsId: 'Hibernate-CI.github.com', variable: 'JRELEASER_GITHUB_TOKEN')
225+
]) {
226+
sshagent(['ed25519.Hibernate-CI.github.com', 'hibernate.filemgmt.jboss.org', 'hibernate-ci.frs.sourceforge.net']) {
227+
// performs documentation upload and Sonatype release
228+
// push to github
229+
withEnv([
230+
"DISABLE_REMOTE_GRADLE_CACHE=true"
231+
]) {
232+
sh ".release/scripts/publish.sh -j ${env.SCRIPT_OPTIONS} ${env.PROJECT} ${env.RELEASE_VERSION} ${env.DEVELOPMENT_VERSION} ${env.GIT_BRANCH}"
233+
}
234+
}
235+
}
236+
}
237+
}
238+
}
239+
}
240+
stage('Website release') {
241+
steps {
242+
script {
243+
checkoutReleaseScripts()
244+
245+
configFileProvider([
246+
configFile(fileId: 'release.config.ssh', targetLocation: "${env.HOME}/.ssh/config"),
247+
configFile(fileId: 'release.config.ssh.knownhosts', targetLocation: "${env.HOME}/.ssh/known_hosts")
248+
]) {
249+
withCredentials([
250+
gitUsernamePassword(credentialsId: 'username-and-token.Hibernate-CI.github.com', gitToolName: 'Default')
251+
]) {
252+
sshagent( ['ed25519.Hibernate-CI.github.com', 'hibernate.filemgmt.jboss.org', 'hibernate-ci.frs.sourceforge.net'] ) {
253+
dir( '.release/hibernate.org' ) {
254+
checkout scmGit(
255+
branches: [[name: '*/production']],
256+
extensions: [],
257+
userRemoteConfigs: [[credentialsId: 'ed25519.Hibernate-CI.github.com', url: 'https://github.com/hibernate/hibernate.org.git']]
258+
)
259+
sh "../scripts/website-release.sh ${env.SCRIPT_OPTIONS} ${env.PROJECT} ${env.RELEASE_VERSION}"
260+
}
261+
}
262+
}
263+
}
264+
}
265+
}
266+
}
267+
}
268+
post {
269+
always {
270+
configFileProvider([configFile(fileId: 'job-configuration.yaml', variable: 'JOB_CONFIGURATION_FILE')]) {
271+
notifyBuildResult maintainers: (String) readYaml(file: env.JOB_CONFIGURATION_FILE).notification?.email?.recipients
272+
}
273+
}
274+
}
275+
}

gradle/published-java-module.gradle

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,5 @@ publishing {
165165

166166
task ciBuild( dependsOn: [test, publish] )
167167

168-
task release( dependsOn: [test, publishToSonatype] )
169-
publishToSonatype.mustRunAfter test
168+
task release( dependsOn: [test] )
170169

gradle/publishing-repos.gradle

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,17 @@ publishing {
1414
publications {
1515
publishedArtifacts( MavenPublication )
1616
}
17-
1817
repositories {
1918
maven {
20-
name 'jboss-snapshots-repository'
21-
url 'https://repository.jboss.org/nexus/content/repositories/snapshots'
19+
name = "staging"
20+
url = rootProject.layout.buildDirectory.dir("staging-deploy${File.separator}maven")
21+
}
22+
maven {
23+
name = 'snapshots'
24+
url = "https://oss.sonatype.org/content/repositories/snapshots/"
25+
// So that Gradle uses the `ORG_GRADLE_PROJECT_snapshotsPassword` / `ORG_GRADLE_PROJECT_snapshotsUsername`
26+
// env variables to read the username/password for the `snapshots` repository publishing:
27+
credentials(PasswordCredentials)
2228
}
2329
}
2430
}

hibernate-infinispan/hibernate-infinispan.gradle

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,5 +30,3 @@ publishing {
3030
}
3131
}
3232
}
33-
34-
task release( dependsOn: publishToSonatype )

0 commit comments

Comments
 (0)