diff --git a/.ci/jenkins/Jenkinsfile.deploy b/.ci/jenkins/Jenkinsfile.deploy index 4e30c0c3d5c..771331d5692 100644 --- a/.ci/jenkins/Jenkinsfile.deploy +++ b/.ci/jenkins/Jenkinsfile.deploy @@ -35,7 +35,7 @@ imageUtils = null pipeline { agent { - docker { + docker { image env.AGENT_DOCKER_BUILDER_IMAGE args env.AGENT_DOCKER_BUILDER_ARGS label util.avoidFaultyNodes() @@ -52,7 +52,6 @@ pipeline { OPTAPLANNER_CI_EMAIL_TO = credentials("${JENKINS_EMAIL_CREDS_ID}") PR_BRANCH_HASH = "${util.generateHash(10)}" - } stages { @@ -103,7 +102,7 @@ pipeline { stage('Prepare for PR') { when { - expression { return isRelease() || isCreatePr() } + expression { return isCreatePr() } } steps { script { @@ -144,19 +143,15 @@ pipeline { .withProperty('maven.test.failure.ignore', true) .withProperty('operator.image.build') .skipTests(params.SKIP_TESTS) - def Closure mavenRunClosure = { - configFileProvider([configFile(fileId: env.MAVEN_SETTINGS_CONFIG_FILE_ID, variable: 'MAVEN_SETTINGS_FILE')]) { - mavenCommand.withSettingsXmlFile(MAVEN_SETTINGS_FILE).run("clean $installOrDeploy") - } - } + if (isRelease()) { release.gpgImportKeyFromStringWithoutPassword(getReleaseGpgSignKeyCredsId()) mavenCommand.withProfiles(['apache-release']) - mavenRunClosure() - } else { - mavenRunClosure() } + configFileProvider([configFile(fileId: env.MAVEN_SETTINGS_CONFIG_FILE_ID, variable: 'MAVEN_SETTINGS_FILE')]) { + mavenCommand.withSettingsXmlFile(MAVEN_SETTINGS_FILE).run("clean $installOrDeploy") + } } if (isRelease()) { updateAntoraYaml(optaplannerFolder) @@ -176,7 +171,7 @@ pipeline { stage('Build Quickstarts') { steps { script { - configFileProvider([configFile(fileId: env.MAVEN_SETTINGS_CONFIG_FILE_ID, variable: 'MAVEN_SETTINGS_FILE')]){ + configFileProvider([configFile(fileId: env.MAVEN_SETTINGS_CONFIG_FILE_ID, variable: 'MAVEN_SETTINGS_FILE')]) { getOptaplannerQuickstartsMavenCommand() .withProperty('maven.test.failure.ignore', true) .skipTests(params.SKIP_TESTS) @@ -197,7 +192,7 @@ pipeline { stage('Create PRs') { when { - expression { return isRelease() || isCreatePr() } + expression { return isCreatePr() } } steps { script { @@ -217,6 +212,18 @@ pipeline { } } + stage('Commit and Create Tag') { + when { + expression { return isRelease() } + } + steps { + script { + commitAndCreateTag(optaplannerFolder, getBuildBranch()) + commitAndCreateTag(quickstartsFolder, getQuickStartsBranch()) + } + } + } + stage('Push a temporary operator image to a registry') { when { expression { return isRelease() } @@ -255,7 +262,7 @@ pipeline { void sendErrorNotification() { if (params.SEND_NOTIFICATION) { String additionalInfo = "**[${getBuildBranch()}] Optaplanner - Deploy**" - mailer.sendMarkdownTestSummaryNotification("CI failures", [env.OPTAPLANNER_CI_EMAIL_TO], additionalInfo) + mailer.sendMarkdownTestSummaryNotification('CI failures', [env.OPTAPLANNER_CI_EMAIL_TO], additionalInfo) } else { echo 'No notification sent per configuration' } @@ -335,6 +342,20 @@ void prepareForPR(String folder) { } } +void commitAndCreateTag(String folder, String buildBranch) { + dir(folder) { + def commitMsg = "[${buildBranch}] Update project version to ${getProjectVersion()}" + githubscm.setUserConfigFromCreds(getGitAuthorPushCredsId()) + githubscm.commitChanges(commitMsg, { + githubscm.findAndStageNotIgnoredFiles('pom.xml') + githubscm.findAndStageNotIgnoredFiles('build.gradle') + githubscm.findAndStageNotIgnoredFiles('antora.yml') + }) + githubscm.tagRepository(getGitTagName()) + githubscm.pushRemoteTag('origin', getGitTagName(), getGitAuthorPushCredsId()) + } +} + void commitAndCreatePR(String folder, String repo, String buildBranch) { dir(folder) { def commitMsg = "[${buildBranch}] Update project version to ${getProjectVersion()}" @@ -385,7 +406,7 @@ MavenCommand getOptaplannerQuickstartsMavenCommand() { * Builds the parent modules and the BOM so that project depending on these artifacts can resolve. */ void mavenCleanInstallOptaPlannerParents() { - configFileProvider([configFile(fileId: env.MAVEN_SETTINGS_CONFIG_FILE_ID, variable: 'MAVEN_SETTINGS_FILE')]){ + configFileProvider([configFile(fileId: env.MAVEN_SETTINGS_CONFIG_FILE_ID, variable: 'MAVEN_SETTINGS_FILE')]) { getOptaplannerMavenCommand() .skipTests(true) .withOptions(['-U', '-pl org.optaplanner:optaplanner-build-parent,org.optaplanner:optaplanner-bom', '-am']) @@ -403,7 +424,7 @@ void runMavenDeploy(MavenCommand mvnCmd, String localDeploymentId = '') { mvnCmd.withDeployRepository(env.MAVEN_DEPLOY_REPOSITORY) } - configFileProvider([configFile(fileId: env.MAVEN_SETTINGS_CONFIG_FILE_ID, variable: 'MAVEN_SETTINGS_FILE')]){ + configFileProvider([configFile(fileId: env.MAVEN_SETTINGS_CONFIG_FILE_ID, variable: 'MAVEN_SETTINGS_FILE')]) { mvnCmd .withSettingsXmlFile(MAVEN_SETTINGS_FILE) .skipTests(true) @@ -532,4 +553,8 @@ String getReleaseGpgSignKeyCredsId() { String getReleaseGpgSignPassphraseCredsId() { return env.RELEASE_GPG_SIGN_PASSPHRASE_CREDS_ID -} \ No newline at end of file +} + +String getGitTagName() { + return params.GIT_TAG_NAME +} diff --git a/.ci/jenkins/dsl/jobs.groovy b/.ci/jenkins/dsl/jobs.groovy index 64a62c5919f..d189091f687 100644 --- a/.ci/jenkins/dsl/jobs.groovy +++ b/.ci/jenkins/dsl/jobs.groovy @@ -149,19 +149,14 @@ void setupProjectReleaseJob() { GIT_BRANCH_NAME: "${GIT_BRANCH}", GIT_AUTHOR: "${GIT_AUTHOR_NAME}", - - DEFAULT_STAGING_REPOSITORY: "${MAVEN_NEXUS_STAGING_PROFILE_URL}", - ARTIFACTS_REPOSITORY: "${MAVEN_ARTIFACTS_REPOSITORY}", - OPTAPLANNER_LATEST_STREAM: "${GIT_MAIN_BRANCH}" ]) KogitoJobTemplate.createPipelineJob(this, jobParams)?.with { parameters { stringParam('RESTORE_FROM_PREVIOUS_JOB', '', 'URL to a previous stopped release job which needs to be continued') - stringParam('OPTAPLANNER_VERSION', '', 'Project version of OptaPlanner and its examples to release as Major.minor.micro') - stringParam('OPTAPLANNER_RELEASE_BRANCH', '', '(optional) Use to override the release branch name deduced from the OPTAPLANNER_VERSION') + stringParam('RELEASE_VERSION', '', 'Project version of OptaPlanner and its examples to release as Major.minor.micro') - stringParam('DROOLS_VERSION', '', '(optional) Drools version to be set to the project before releasing the artifacts.') + stringParam('GIT_TAG_NAME', '', 'Git tag to create. i.e.: 10.0.0-rc1') booleanParam('SKIP_TESTS', false, 'Skip all tests') } @@ -370,6 +365,8 @@ void setupDeployJob(JobType jobType, String envName = '') { stringParam('OPERATOR_IMAGE_REGISTRY_TOKEN_CREDENTIALS_ID', "${CLOUD_IMAGE_REGISTRY_TOKEN_CREDENTIALS_ID}", 'Image registry token credentials id.') stringParam('OPERATOR_IMAGE_NAMESPACE', "${CLOUD_IMAGE_NAMESPACE}", 'Operator image namespace to use to deploy image.') stringParam('OPERATOR_IMAGE_TAG', '', 'Image tag to use to deploy the operator image. OptaPlanner project version if not set.') + + stringParam('GIT_TAG_NAME', '', 'Optional if not RELEASE. Tag to be created in the repository') } } } diff --git a/.ci/jenkins/project/Jenkinsfile.release b/.ci/jenkins/project/Jenkinsfile.release index b52329f201d..61fcf539d45 100644 --- a/.ci/jenkins/project/Jenkinsfile.release +++ b/.ci/jenkins/project/Jenkinsfile.release @@ -22,10 +22,8 @@ import org.jenkinsci.plugins.workflow.libs.Library @Library('jenkins-pipeline-shared-libraries')_ OPTAPLANNER_DEPLOY = 'optaplanner-deploy' -OPTAPLANNER_PROMOTE = 'optaplanner-promote' ARTIFACTS_STAGING_STAGE = 'stage.artifacts.staging' -ARTIFACTS_RELEASE_STAGE = 'stage.artifacts.release' JOB_PROPERTY_PREFIX = 'build' JOB_RESULT_PROPERTY_KEY = 'result' @@ -54,24 +52,17 @@ pipeline { echo "Release properties imported from previous job: ${releaseProperties}" } - assert getOptaPlannerVersion() + assert getReleaseVersion() currentBuild.displayName = getDisplayName() - sendNotification("Release Pipeline has started...\nOptaplanner version = ${getOptaPlannerVersion()}\n=> ${env.BUILD_URL}") - - // Safety measure to not publish to main JBoss - if (getGitAuthor() != 'apache' && !getArtifactsRepositoryParam()) { - sendNotification("Git Author is different from `apache` and no `ARTIFACTS_REPOSITORY` parameter has been provided. Are you sure you want to continue ? => ${env.BUILD_URL}input") - input message: 'Should the pipeline continue with no `ARTIFACTS_REPOSITORY` defined ?', ok: 'Yes' - } + sendNotification("Release Pipeline has started...\nOptaplanner version = ${getReleaseVersion()}\n=> ${env.BUILD_URL}") } } post { always { - setReleasePropertyIfneeded('optaplanner.version', getOptaPlannerVersion()) - setReleasePropertyIfneeded('optaplanner.branch', getOptaPlannerReleaseBranch()) - setReleasePropertyIfneeded('drools.version', getDroolsVersion()) + setReleasePropertyIfneeded('release.version', getReleaseVersion()) + setReleasePropertyIfneeded('git.tag.name', getGitTagName()) } } } @@ -82,7 +73,6 @@ pipeline { def buildParams = getDefaultBuildParams() addSkipTestsParam(buildParams) addSkipIntegrationTestsParam(buildParams) - addStringParam(buildParams, 'QUICKSTARTS_BUILD_BRANCH_NAME', getOptaPlannerReleaseBranch()) buildJob(OPTAPLANNER_DEPLOY, buildParams) } } @@ -92,54 +82,12 @@ pipeline { steps { script { if (!areArtifactsStaged()) { - sendNotification("All artifacts have been staged. You can find them here: ${getStagingRepository()}") + sendNotification('All artifacts have been staged.') } setArtifactsStaged() } } } - - stage('Are staged artifacts released?') { - when { - // Execute only if artifacts repository was not given, which means the staging repository has been created - expression { return !getArtifactsRepositoryParam() && !areArtifactsReleased() } - } - steps { - script { - String body = "${getOptaPlannerVersion()} artifacts are ready for release.\n" + - "Please release the staging repositories and then confirm here: ${env.BUILD_URL}input" - sendNotification(body) - input message: 'Has the staging repository been released ?', ok: 'Yes' - - sendNotification('Artifacts have been released. Finalizing now the release ...') - setArtifactsReleased() - } - } - } - - stage('Promote OptaPlanner') { - when { - expression { return isJobConsideredOk(OPTAPLANNER_DEPLOY) } - } - steps { - script { - def buildParams = getDefaultBuildParams() - addDeployBuildUrlParam(buildParams, OPTAPLANNER_DEPLOY) - - buildJob(OPTAPLANNER_PROMOTE, buildParams) - } - } - } - - stage('Setup next snapshot version') { - steps { - script { - def buildParams = [] - addStringParam(buildParams, 'OPTAPLANNER_VERSION', util.getNextVersion(getOptaPlannerVersion(), 'micro')) - build(job: '../setup-branch/0-setup-branch', wait: false, parameters: buildParams, propagate: false) - } - } - } } post { always { @@ -301,9 +249,10 @@ def readPropertiesFromUrl(String url, String propsFilename) { List getDefaultBuildParams() { List buildParams = [] - addDisplayNameParam(buildParams, getDisplayName(getOptaPlannerVersion())) - addStringParam(buildParams, 'PROJECT_VERSION', getOptaPlannerVersion()) - addStringParam(buildParams, 'DROOLS_VERSION', getDroolsVersion()) + addDisplayNameParam(buildParams, getDisplayName(getReleaseVersion())) + addStringParam(buildParams, 'PROJECT_VERSION', getReleaseVersion()) + addStringParam(buildParams, 'DROOLS_VERSION', getReleaseVersion()) + addStringParam(buildParams, 'GIT_TAG_NAME', getGitTagName()) return buildParams } @@ -350,30 +299,14 @@ String getDisplayName(version = '') { return "Release ${version}" } -String getOptaPlannerVersion() { - return params.OPTAPLANNER_VERSION ?: getReleaseProperty('optaplanner.version') -} - -String getDroolsVersion() { - return params.DROOLS_VERSION ?: getReleaseProperty('drools.version') +String getReleaseVersion() { + return params.RELEASE_VERSION ?: getReleaseProperty('release.version') } String getGitAuthor() { return env.GIT_AUTHOR } -String getArtifactsRepositoryParam() { - return env['ARTIFACTS_REPOSITORY'] ?: '' -} - -String getOptaPlannerReleaseBranch() { - return params.OPTAPLANNER_RELEASE_BRANCH ?: (getReleaseProperty('optaplanner.branch') ?: util.getReleaseBranchFromVersion(getOptaPlannerVersion())) -} - -String getStagingRepository() { - return getArtifactsRepositoryParam() ?: env.DEFAULT_STAGING_REPOSITORY -} - void setReleasePropertyIfneeded(String key, def value) { if (value) { releaseProperties[key] = value @@ -402,10 +335,6 @@ void setArtifactsStaged() { setReleasePropertyIfneeded(ARTIFACTS_STAGING_STAGE, true) } -boolean areArtifactsReleased() { - return hasReleaseProperty(ARTIFACTS_RELEASE_STAGE) -} - -void setArtifactsReleased() { - setReleasePropertyIfneeded(ARTIFACTS_RELEASE_STAGE, true) +String getGitTagName() { + return params.GIT_TAG_NAME ?: getReleaseProperty('git.tag.name') }