|
| 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 | +} |
0 commit comments