This is an automated email from the ASF dual-hosted git repository.
yesamer pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/incubator-kie-drools.git
The following commit(s) were added to refs/heads/main by this push:
new 0dd35d13a35 ci: restore Jenkins build configuration to re-enable
snapshots generation (#6736)
0dd35d13a35 is described below
commit 0dd35d13a351dcb4aa45d617722d7b506b7234a1
Author: Yeser Amer <[email protected]>
AuthorDate: Fri Jun 26 09:49:03 2026 +0200
ci: restore Jenkins build configuration to re-enable snapshots generation
(#6736)
* Restored .ci
* Remove enviroments and disable pr check
* Disable PR checks
* Revert
* removing PR check
* Disabling PR Checks
* Remove PR check Jenkinsfile to disable
continuous-integration/jenkins/pr-head
---
.ci/jenkins/Jenkinsfile.deploy | 318 +++++++++++++++++++++
.ci/jenkins/Jenkinsfile.promote | 254 +++++++++++++++++
.ci/jenkins/Jenkinsfile.setup-branch | 169 +++++++++++
.ci/jenkins/Jenkinsfile.weekly.deploy | 241 ++++++++++++++++
.ci/jenkins/config/branch.yaml | 109 +++++++
.ci/jenkins/config/main.yaml | 44 +++
.ci/jenkins/dsl/jobs.groovy | 409 +++++++++++++++++++++++++++
.ci/jenkins/dsl/test.sh | 53 ++++
.ci/jenkins/project/Jenkinsfile.nightly | 190 +++++++++++++
.ci/jenkins/project/Jenkinsfile.post-release | 148 ++++++++++
.ci/jenkins/project/Jenkinsfile.release | 336 ++++++++++++++++++++++
.ci/jenkins/project/Jenkinsfile.setup-branch | 228 +++++++++++++++
.ci/jenkins/project/Jenkinsfile.weekly | 183 ++++++++++++
13 files changed, 2682 insertions(+)
diff --git a/.ci/jenkins/Jenkinsfile.deploy b/.ci/jenkins/Jenkinsfile.deploy
new file mode 100644
index 00000000000..1947593ad41
--- /dev/null
+++ b/.ci/jenkins/Jenkinsfile.deploy
@@ -0,0 +1,318 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import org.jenkinsci.plugins.workflow.libs.Library
+@Library('jenkins-pipeline-shared-libraries')_
+
+import org.kie.jenkins.MavenCommand
+
+deployProperties = [:]
+
+pipeline {
+ agent {
+ docker {
+ image env.AGENT_DOCKER_BUILDER_IMAGE
+ args env.AGENT_DOCKER_BUILDER_ARGS
+ label util.avoidFaultyNodes()
+ }
+ }
+
+ options {
+ timestamps()
+ timeout(time: 180, unit: 'MINUTES')
+ }
+
+ environment {
+ DROOLS_CI_EMAIL_TO = credentials("${JENKINS_EMAIL_CREDS_ID}")
+
+ PR_BRANCH_HASH = "${util.generateHash(10)}"
+ }
+
+ stages {
+ stage('Initialize') {
+ steps {
+ script {
+ cleanWs(disableDeferredWipeout: true)
+
+ if (params.DISPLAY_NAME) {
+ currentBuild.displayName = params.DISPLAY_NAME
+ }
+
+ if (isRelease() || isCreatePr()) {
+ // Verify version is set
+ assert getProjectVersion()
+
+ if (isRelease()) {
+ // Verify if on right release branch
+ assert getBuildBranch() ==
util.getReleaseBranchFromVersion(getProjectVersion())
+ }
+ }
+
+ dir(getRepoName()) {
+ checkoutRepo()
+ }
+ }
+ }
+ post {
+ success {
+ script {
+ setDeployPropertyIfNeeded('git.branch',
getBuildBranch())
+ setDeployPropertyIfNeeded('git.author', getGitAuthor())
+ setDeployPropertyIfNeeded('project.version',
getProjectVersion())
+ setDeployPropertyIfNeeded('release', isRelease())
+ }
+ }
+ }
+ }
+ stage('Prepare for PR') {
+ when {
+ expression { return isCreatePr() }
+ }
+ steps {
+ script {
+ dir(getRepoName()) {
+ if (githubscm.isBranchExist('origin', getPRBranch())) {
+ githubscm.removeRemoteBranch('origin',
getPRBranch(), getGitAuthorPushCredsId())
+ }
+ githubscm.createBranch(getPRBranch())
+ }
+ }
+ }
+ }
+ stage('Update project version') {
+ when {
+ expression { return getProjectVersion() }
+ }
+ steps {
+ script {
+ configFileProvider([configFile(fileId:
env.MAVEN_SETTINGS_CONFIG_FILE_ID, variable: 'MAVEN_SETTINGS_FILE')]) {
+ maven.mvnVersionsSet(
+
getMavenCommand().withSettingsXmlFile(MAVEN_SETTINGS_FILE),
+ getProjectVersion(),
+ !isRelease()
+ )
+ }
+ }
+ }
+ }
+ stage('Deploy drools') {
+ steps {
+ script {
+ withCredentials([usernamePassword(credentialsId:
env.MAVEN_REPO_CREDS_ID, usernameVariable: 'REPOSITORY_USER', passwordVariable:
'REPOSITORY_TOKEN')]) {
+ def installOrDeploy
+ if (shouldDeployToRepository()) {
+ installOrDeploy = "deploy -DdeployAtEnd
-Dapache.repository.username=${REPOSITORY_USER}
-Dapache.repository.password=${REPOSITORY_TOKEN} -DretryFailedDeploymentCount=5"
+ } else {
+ installOrDeploy = 'install'
+ }
+ def mavenCommand = getMavenCommand()
+ .withOptions(env.DROOLS_BUILD_MVN_OPTS ? [
env.DROOLS_BUILD_MVN_OPTS ] : [])
+ .withOptions(env.BUILD_MVN_OPTS_CURRENT ? [
env.BUILD_MVN_OPTS_CURRENT ] : [])
+ .withProperty('maven.test.failure.ignore', true)
+ .skipTests(params.SKIP_TESTS)
+
+ if (isRelease()) {
+
releaseUtils.gpgImportKeyFromStringWithoutPassword(getReleaseGpgSignKeyCredsId())
+ mavenCommand
+ .withProfiles(['apache-release'])
+ .withProperty('only.reproducible')
+ }
+
+ configFileProvider([configFile(fileId:
env.MAVEN_SETTINGS_CONFIG_FILE_ID, variable: 'MAVEN_SETTINGS_FILE')]) {
+
mavenCommand.withSettingsXmlFile(MAVEN_SETTINGS_FILE).run("clean
$installOrDeploy")
+ }
+ }
+ }
+ }
+ post {
+ always {
+ script {
+ saveReports()
+ util.archiveConsoleLog()
+ }
+ }
+ }
+ }
+ stage('Create PR') {
+ when {
+ expression { return isCreatePr() }
+ }
+ steps {
+ script {
+ dir(getRepoName()) {
+ if (githubscm.isThereAnyChanges()) {
+ commitAndCreatePR()
+ } else {
+ println '[WARN] no changes to commit'
+ }
+ }
+ }
+ }
+ post {
+ success {
+ script {
+
setDeployPropertyIfNeeded("${getRepoName()}.pr.source.uri",
"https://github.com/${getGitAuthor()}/${getRepoName()}")
+
setDeployPropertyIfNeeded("${getRepoName()}.pr.source.ref", getPRBranch())
+
setDeployPropertyIfNeeded("${getRepoName()}.pr.target.uri",
"https://github.com/${getGitAuthor()}/${getRepoName()}")
+
setDeployPropertyIfNeeded("${getRepoName()}.pr.target.ref", getBuildBranch())
+ }
+ }
+ }
+ }
+ stage('Commit and Create Tag') {
+ when {
+ expression { return isRelease() }
+ }
+ steps {
+ script {
+ dir(getRepoName()) {
+ if (githubscm.isThereAnyChanges()) {
+ def commitMsg = "[${getBuildBranch()}] Update
version to ${getProjectVersion()}"
+
githubscm.setUserConfigFromCreds(getGitAuthorPushCredsId())
+ githubscm.commitChanges(commitMsg, {
+
githubscm.findAndStageNotIgnoredFiles('pom.xml')
+
githubscm.findAndStageNotIgnoredFiles('antora.yml')
+ })
+ } else {
+ println '[WARN] no changes to commit'
+ }
+ githubscm.tagRepository(getGitTagName())
+ githubscm.pushRemoteTag('origin', getGitTagName(),
getGitAuthorPushCredsId())
+ }
+ }
+ }
+ }
+ }
+ post {
+ always {
+ script {
+ def propertiesStr = deployProperties.collect { entry ->
"${entry.key}=${entry.value}" }.join('\n')
+ writeFile(text: propertiesStr, file: PROPERTIES_FILE_NAME)
+ archiveArtifacts(artifacts: PROPERTIES_FILE_NAME)
+ }
+ }
+ unsuccessful {
+ sendNotification()
+ }
+ cleanup {
+ script {
+ util.cleanNode()
+ }
+ }
+ }
+}
+
+void saveReports() {
+ junit testResults: '**/target/surefire-reports/**/*.xml,
**/target/failsafe-reports/**/*.xml, **/target/invoker-reports/**/TEST-*.xml',
allowEmptyResults: true
+}
+
+void checkoutRepo() {
+ deleteDir()
+ checkout(githubscm.resolveRepository(getRepoName(), getGitAuthor(),
getBuildBranch(), false, getGitAuthorCredsId()))
+ // need to manually checkout branch since on a detached branch after
checkout command
+ sh "git checkout ${getBuildBranch()}"
+}
+
+void commitAndCreatePR() {
+ def commitMsg = "[${getBuildBranch()}] Update version to
${getProjectVersion()}"
+ def prBody = "Generated by build ${BUILD_TAG}: ${BUILD_URL}.\nPlease do
not merge, it should be merged automatically."
+ githubscm.setUserConfigFromCreds(getGitAuthorPushCredsId())
+ githubscm.commitChanges(commitMsg, {
+ githubscm.findAndStageNotIgnoredFiles('pom.xml')
+ githubscm.findAndStageNotIgnoredFiles('antora.yml')
+ })
+ githubscm.pushObject('origin', getPRBranch(), getGitAuthorPushCredsId())
+ deployProperties["${getRepoName()}.pr.link"] =
githubscm.createPRWithLabels(commitMsg, prBody, getBuildBranch(), ['skip-ci']
as String[], getGitAuthorCredsId())
+}
+
+void sendNotification() {
+ if (params.SEND_NOTIFICATION) {
+ mailer.sendMarkdownTestSummaryNotification('Deploy',
"[${getBuildBranch()}] Drools", [env.DROOLS_CI_EMAIL_TO])
+ } else {
+ echo 'No notification sent per configuration'
+ }
+}
+
+boolean shouldDeployToRepository() {
+ return env.MAVEN_DEPLOY_REPOSITORY || getGitAuthor() == 'apache'
+}
+
+boolean isRelease() {
+ return env.RELEASE ? env.RELEASE.toBoolean() : false
+}
+
+boolean isCreatePr() {
+ return params.CREATE_PR
+}
+
+String getRepoName() {
+ return env.REPO_NAME
+}
+
+String getGitAuthor() {
+ // GIT_AUTHOR can be env or param
+ return "${GIT_AUTHOR}"
+}
+
+String getBuildBranch() {
+ return params.BUILD_BRANCH_NAME
+}
+
+String getProjectVersion() {
+ return params.PROJECT_VERSION
+}
+
+String getPRBranch() {
+ return params.DROOLS_PR_BRANCH
+}
+
+String getGitAuthorCredsId() {
+ return env.GIT_AUTHOR_CREDS_ID
+}
+
+String getGitAuthorPushCredsId() {
+ return env.GIT_AUTHOR_PUSH_CREDS_ID
+}
+
+void setDeployPropertyIfNeeded(String key, def value) {
+ if (value) {
+ deployProperties[key] = value
+ }
+}
+
+MavenCommand getMavenCommand(String directory = '') {
+ directory = directory ?: getRepoName()
+ def mvnCmd = new MavenCommand(this, ['-fae', '-ntp'])
+ .withOptions(env.BUILD_MVN_OPTS ? [ env.BUILD_MVN_OPTS ] : [])
+ .inDirectory(directory)
+ .withProperty('full')
+ return mvnCmd
+}
+
+String getReleaseGpgSignKeyCredsId() {
+ return env.RELEASE_GPG_SIGN_KEY_CREDS_ID
+}
+
+String getReleaseGpgSignPassphraseCredsId() {
+ return env.RELEASE_GPG_SIGN_PASSPHRASE_CREDS_ID
+}
+
+String getGitTagName() {
+ return params.GIT_TAG_NAME
+}
\ No newline at end of file
diff --git a/.ci/jenkins/Jenkinsfile.promote b/.ci/jenkins/Jenkinsfile.promote
new file mode 100644
index 00000000000..c1c0ba9d588
--- /dev/null
+++ b/.ci/jenkins/Jenkinsfile.promote
@@ -0,0 +1,254 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import org.jenkinsci.plugins.workflow.libs.Library
+@Library('jenkins-pipeline-shared-libraries')_
+
+import org.kie.jenkins.MavenCommand
+
+deployProperties = [:]
+pipelineProperties = [:]
+
+pipeline {
+ agent {
+ docker {
+ image env.AGENT_DOCKER_BUILDER_IMAGE
+ args env.AGENT_DOCKER_BUILDER_ARGS
+ label util.avoidFaultyNodes()
+ }
+ }
+
+ options {
+ timestamps()
+ timeout(time: 180, unit: 'MINUTES')
+ }
+
+ environment {
+ DROOLS_CI_EMAIL_TO = credentials("${JENKINS_EMAIL_CREDS_ID}")
+ }
+
+ stages {
+ stage('Initialization') {
+ steps {
+ script {
+ cleanWs()
+
+ if (params.DISPLAY_NAME != '') {
+ currentBuild.displayName = params.DISPLAY_NAME
+ }
+
+ readDeployProperties()
+
+ assert getProjectVersion()
+ assert getBuildBranch() ==
util.getReleaseBranchFromVersion(getProjectVersion())
+ }
+ }
+ }
+ stage('Merge deploy PR and tag') {
+ steps {
+ script {
+ dir(getRepoName()) {
+ approveAndMergePR(getDeployPrLink())
+ checkoutRepo()
+ tagLatest()
+ }
+ }
+ }
+ }
+
+ stage('Create release') {
+ steps {
+ script {
+ dir(getRepoName()) {
+ checkoutRepo()
+ if(githubscm.isReleaseExist(getGitTag(),
getGitAuthorCredsId())) {
+ githubscm.deleteRelease(getGitTag(),
getGitAuthorPushCredsId())
+ }
+
githubscm.createReleaseWithGeneratedReleaseNotes(getGitTag(), getBuildBranch(),
githubscm.getPreviousTagFromVersion(getGitTag()), getGitAuthorPushCredsId())
+ githubscm.updateReleaseBody(getGitTag(),
getGitAuthorPushCredsId())
+ }
+ }
+ }
+ }
+
+ stage('Upload drools binaries and documentation') {
+ when {
+ expression { return isMainStream() }
+ }
+ steps {
+ script {
+ configFileProvider([configFile(fileId:
env.MAVEN_SETTINGS_CONFIG_FILE_ID, variable: 'MAVEN_SETTINGS_FILE')]){
+ getMavenCommand()
+ .withOptions(env.DROOLS_BUILD_MVN_OPTS ? [
env.DROOLS_BUILD_MVN_OPTS ] : [])
+ .withOptions(env.BUILD_MVN_OPTS_CURRENT ? [
env.BUILD_MVN_OPTS_CURRENT ] : [])
+ .inDirectory(getRepoName())
+ .skipTests(true)
+ .withProperty('full')
+ .withSettingsXmlFile(MAVEN_SETTINGS_FILE)
+ .run('clean install')
+ }
+ uploadFileMgmt(getRepoName())
+ }
+ }
+ }
+ }
+ post {
+ unsuccessful {
+ sendNotification()
+ }
+ cleanup {
+ script {
+ util.cleanNode()
+ }
+ }
+ }
+}
+
+void sendNotification() {
+ if (params.SEND_NOTIFICATION) {
+ mailer.sendMarkdownTestSummaryNotification('Promote',
"[${getBuildBranch()}] Drools", [env.DROOLS_CI_EMAIL_TO])
+ } else {
+ echo 'No notification sent per configuration'
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// Deployment properties
+//////////////////////////////////////////////////////////////////////////////
+
+void readDeployProperties() {
+ String deployUrl = params.DEPLOY_BUILD_URL
+ if (deployUrl != '') {
+ if (!deployUrl.endsWith('/')) {
+ deployUrl += '/'
+ }
+ sh "wget ${deployUrl}artifact/${PROPERTIES_FILE_NAME} -O
${PROPERTIES_FILE_NAME}"
+ deployProperties = readProperties file: PROPERTIES_FILE_NAME
+ // echo all properties
+ echo deployProperties.collect { entry -> "${entry.key}=${entry.value}"
}.join('\n')
+ }
+}
+
+boolean hasDeployProperty(String key) {
+ return deployProperties[key] != null
+}
+
+String getDeployProperty(String key) {
+ if (hasDeployProperty(key)) {
+ return deployProperties[key]
+ }
+ return ''
+}
+
+String getParamOrDeployProperty(String paramKey, String deployPropertyKey) {
+ if (params[paramKey] != '') {
+ return params[paramKey]
+ }
+ return getDeployProperty(deployPropertyKey)
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// Getter / Setter
+//////////////////////////////////////////////////////////////////////////////
+
+String getRepoName() {
+ return env.REPO_NAME
+}
+
+String getProjectVersion() {
+ return getParamOrDeployProperty('PROJECT_VERSION', 'project.version')
+}
+
+String getGitTag() {
+ return params.GIT_TAG != '' ? params.GIT_TAG : getProjectVersion()
+}
+
+String getBuildBranch() {
+ return params.BUILD_BRANCH_NAME
+}
+
+String getGitAuthor() {
+ return env.GIT_AUTHOR
+}
+
+String getGitAuthorCredsId() {
+ return env.GIT_AUTHOR_CREDS_ID
+}
+
+String getGitAuthorPushCredsId() {
+ return env.GIT_AUTHOR_PUSH_CREDS_ID
+}
+
+String getDeployPrLink() {
+ return getDeployProperty("${getRepoName()}.pr.link")
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// Git
+//////////////////////////////////////////////////////////////////////////////
+
+void checkoutRepo() {
+ deleteDir()
+ checkout(githubscm.resolveRepository(getRepoName(), getGitAuthor(),
getBuildBranch(), false, getGitAuthorCredsId()))
+ // need to manually checkout branch since on a detached branch after
checkout command
+ sh "git checkout ${getBuildBranch()}"
+}
+
+void approveAndMergePR(String prLink) {
+ if (prLink?.trim()) {
+ githubscm.approvePR(prLink, getGitAuthorPushCredsId())
+ githubscm.mergePR(prLink, getGitAuthorPushCredsId())
+ }
+}
+
+void tagLatest() {
+ if (getGitTag()) {
+ githubscm.tagLocalAndRemoteRepository('origin', getGitTag(),
getGitAuthorPushCredsId(), env.BUILD_TAG, true)
+ }
+}
+
+MavenCommand getMavenCommand() {
+ mvnCmd = new MavenCommand(this, ['-fae', '-ntp'])
+ .withOptions(env.BUILD_MVN_OPTS ? [ env.BUILD_MVN_OPTS ] :
[])
+ if (env.MAVEN_DEPENDENCIES_REPOSITORY) {
+ mvnCmd.withDependencyRepositoryInSettings('deps-repo',
env.MAVEN_DEPENDENCIES_REPOSITORY)
+ }
+ return mvnCmd
+}
+
+void uploadFileMgmt(String directory) {
+ if (isNotTestingBuild()) {
+ echo "upload binaries and docs for ${directory}"
+ dir(directory) {
+ sshagent(['drools-filemgmt']) {
+ sh "script/release/upload_filemgmt.sh ${getProjectVersion()}"
+ }
+ }
+ } else {
+ echo 'No uploadFileMgmt due to testing build'
+ }
+}
+
+boolean isNotTestingBuild() {
+ return getGitAuthor() == 'apache'
+}
+
+boolean isMainStream() {
+ return env.DROOLS_STREAM == 'main'
+}
\ No newline at end of file
diff --git a/.ci/jenkins/Jenkinsfile.setup-branch
b/.ci/jenkins/Jenkinsfile.setup-branch
new file mode 100644
index 00000000000..1bc66b50064
--- /dev/null
+++ b/.ci/jenkins/Jenkinsfile.setup-branch
@@ -0,0 +1,169 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import org.jenkinsci.plugins.workflow.libs.Library
+@Library('jenkins-pipeline-shared-libraries')_
+
+import org.kie.jenkins.MavenCommand
+
+pipeline {
+ agent {
+ docker {
+ image env.AGENT_DOCKER_BUILDER_IMAGE
+ args env.AGENT_DOCKER_BUILDER_ARGS
+ label util.avoidFaultyNodes()
+ }
+ }
+
+ options {
+ timestamps()
+ timeout(time: 180, unit: 'MINUTES')
+ }
+
+ environment {
+ DROOLS_CI_EMAIL_TO = credentials("${JENKINS_EMAIL_CREDS_ID}")
+
+ BRANCH_HASH = "${util.generateHash(10)}"
+ }
+
+ stages {
+ stage('Initialize') {
+ steps {
+ script {
+ cleanWs(disableDeferredWipeout: true)
+
+ if (params.DISPLAY_NAME) {
+ currentBuild.displayName = params.DISPLAY_NAME
+ }
+ dir(getRepoName()) {
+ checkoutRepo(getRepoName(), getBuildBranch())
+ }
+ }
+ }
+ }
+ stage('Update project version') {
+ steps {
+ script {
+ dir(getRepoName()) {
+ configFileProvider([configFile(fileId:
env.MAVEN_SETTINGS_CONFIG_FILE_ID, variable: 'MAVEN_SETTINGS_FILE')]){
+ maven.mvnVersionsSet(
+
getMavenCommand().withSettingsXmlFile(MAVEN_SETTINGS_FILE),
+ getDroolsVersion(),
+ true
+ )
+ }
+ }
+ }
+ }
+ }
+ stage('Update branch') {
+ steps {
+ script {
+ dir(getRepoName()) {
+ if (githubscm.isThereAnyChanges()) {
+ def commitMsg = "Update version to
${getDroolsVersion()}"
+
githubscm.setUserConfigFromCreds(getGitAuthorPushCredsId())
+ githubscm.commitChanges(commitMsg, {
+
githubscm.findAndStageNotIgnoredFiles('pom.xml')
+
githubscm.findAndStageNotIgnoredFiles('antora.yml')
+ })
+ githubscm.pushObject('origin', getBuildBranch(),
getGitAuthorPushCredsId())
+ } else {
+ println '[WARN] no changes to commit'
+ }
+ }
+ }
+ }
+ }
+ stage('Update Drools version in kie-benchmarks') {
+ when {
+ expression { isMainStream() && isMainBranch() }
+ }
+ steps {
+ script {
+ build job: '../tools/kie-benchmarks-update-drools',
parameters: [ string(name: 'NEW_VERSION', value: "${getDroolsVersion()}")]
+ }
+ }
+ }
+ }
+ post {
+ unsuccessful {
+ sendNotification()
+ }
+ cleanup {
+ script {
+ util.cleanNode()
+ }
+ }
+ }
+}
+
+void sendNotification() {
+ if (params.SEND_NOTIFICATION) {
+ mailer.sendMarkdownTestSummaryNotification('Setup branch',
"[${getBuildBranch()}] Drools", [env.DROOLS_CI_EMAIL_TO])
+ } else {
+ echo 'No notification sent per configuration'
+ }
+}
+
+void checkoutRepo(String repository, String branch) {
+ checkout(githubscm.resolveRepository(repository, getGitAuthor(), branch,
false, getGitAuthorCredsId()))
+ // need to manually checkout branch since on a detached branch after
checkout command
+ sh "git checkout ${branch}"
+}
+
+String getRepoName() {
+ return env.REPO_NAME
+}
+
+String getGitAuthor() {
+ // GIT_AUTHOR can be env or param
+ return "${GIT_AUTHOR}"
+}
+
+String getBuildBranch() {
+ return params.BUILD_BRANCH_NAME
+}
+
+String getDroolsVersion() {
+ return params.DROOLS_VERSION
+}
+
+String getGitAuthorCredsId() {
+ return env.GIT_AUTHOR_CREDS_ID
+}
+
+String getGitAuthorPushCredsId() {
+ return env.GIT_AUTHOR_PUSH_CREDS_ID
+}
+
+
+MavenCommand getMavenCommand() {
+ return new MavenCommand(this, ['-fae', '-ntp'])
+ .withOptions(env.BUILD_MVN_OPTS ? [ env.BUILD_MVN_OPTS ] : [])
+ .withProperty('full')
+}
+
+boolean isMainBranch() {
+ return env.IS_MAIN_BRANCH ? env.IS_MAIN_BRANCH.toBoolean() : false
+}
+
+boolean isMainStream() {
+ return env.DROOLS_STREAM == 'main'
+}
\ No newline at end of file
diff --git a/.ci/jenkins/Jenkinsfile.weekly.deploy
b/.ci/jenkins/Jenkinsfile.weekly.deploy
new file mode 100644
index 00000000000..318a5215dc0
--- /dev/null
+++ b/.ci/jenkins/Jenkinsfile.weekly.deploy
@@ -0,0 +1,241 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import org.jenkinsci.plugins.workflow.libs.Library
+@Library('jenkins-pipeline-shared-libraries')_
+
+import org.kie.jenkins.MavenCommand
+import org.kie.jenkins.MavenStagingHelper
+
+deployProperties = [:]
+
+pipeline {
+ agent {
+ docker {
+ image env.AGENT_DOCKER_BUILDER_IMAGE
+ args env.AGENT_DOCKER_BUILDER_ARGS
+ label util.avoidFaultyNodes() //force retest
+ }
+ }
+
+ options {
+ timestamps()
+ timeout(time: 180, unit: 'MINUTES')
+ }
+
+ environment {
+ DROOLS_CI_EMAIL_TO = credentials("${JENKINS_EMAIL_CREDS_ID}")
+
+ MAVEN_DEPLOY_LOCAL_DIR = "/tmp/maven_deploy_dir"
+ }
+
+ stages {
+ stage('Initialize') {
+ steps {
+ script {
+ cleanWs(disableDeferredWipeout: true)
+
+ if (params.DISPLAY_NAME) {
+ currentBuild.displayName = params.DISPLAY_NAME
+ }
+
+ dir(getRepoName()) {
+ checkoutRepo()
+ }
+
+ env.PROJECT_VERSION =
maven.mvnGetVersionProperty(getMavenCommand(), 'project.version')
+ }
+ }
+ post {
+ success {
+ script {
+ setDeployPropertyIfNeeded('git.branch',
getBuildBranch())
+ setDeployPropertyIfNeeded('git.author', getGitAuthor())
+ setDeployPropertyIfNeeded('project.version',
getProjectVersion())
+ }
+ }
+ }
+ }
+
+ stage('Update project version') {
+ steps {
+ script {
+ maven.mvnVersionsSet(
+ getMavenCommand(),
+ getProjectVersion(),
+ true
+ )
+ }
+ }
+ }
+
+ stage('Build & Test & Install/Deploy') {
+ steps {
+ script {
+ withCredentials([usernamePassword(credentialsId:
env.MAVEN_REPO_CREDS_ID, usernameVariable: 'REPOSITORY_USER', passwordVariable:
'REPOSITORY_TOKEN')]) {
+ def installOrDeploy
+ if (shouldDeployToRepository()) {
+ installOrDeploy = "deploy -DdeployAtEnd
-Dapache.repository.username=${REPOSITORY_USER}
-Dapache.repository.password=${REPOSITORY_TOKEN}
-DretryFailedDeploymentCount=5" +
+ "
-Daether.connector.basic.parallelPut=false"
+ } else {
+ installOrDeploy = 'install'
+ }
+ configFileProvider([configFile(fileId:
env.MAVEN_SETTINGS_CONFIG_FILE_ID, variable: 'MAVEN_SETTINGS_FILE')]){
+ getMavenCommand()
+ .withOptions(env.DROOLS_BUILD_MVN_OPTS ? [
env.DROOLS_BUILD_MVN_OPTS ] : [])
+ .withOptions(env.BUILD_MVN_OPTS_CURRENT ? [
env.BUILD_MVN_OPTS_CURRENT ] : [])
+ .withProperty('maven.test.failure.ignore',
true)
+ .skipTests(params.SKIP_TESTS)
+ .withSettingsXmlFile(MAVEN_SETTINGS_FILE)
+ .run("clean $installOrDeploy")
+ }
+ }
+ }
+ }
+ }
+
+ stage('Create and push a new tag') {
+ steps {
+ script {
+ projectVersion = getProjectVersion(false)
+ dir(getRepoName()) {
+ if (githubscm.isThereAnyChanges()) {
+ def commitMsg = "[${getBuildBranch()}] Update
version to ${projectVersion}"
+
githubscm.setUserConfigFromCreds(getGitAuthorPushCredsId())
+ githubscm.commitChanges(commitMsg, {
githubscm.findAndStageNotIgnoredFiles('pom.xml') })
+ } else {
+ println '[WARN] no changes to commit'
+ }
+ githubscm.tagRepository(projectVersion)
+ githubscm.pushRemoteTag('origin', projectVersion,
getGitAuthorPushCredsId())
+ }
+ }
+ }
+ }
+ }
+ post {
+ always {
+ script {
+ def propertiesStr = deployProperties.collect { entry ->
"${entry.key}=${entry.value}" }.join('\n')
+ writeFile(text: propertiesStr, file: PROPERTIES_FILE_NAME)
+ archiveArtifacts(artifacts: PROPERTIES_FILE_NAME)
+ }
+ }
+ unsuccessful {
+ sendNotification()
+ }
+ cleanup {
+ script {
+ util.cleanNode()
+ }
+ }
+ }
+}
+
+void saveReports() {
+ junit testResults: '**/target/surefire-reports/**/*.xml,
**/target/failsafe-reports/**/*.xml, **/target/invoker-reports/**/TEST-*.xml',
allowEmptyResults: true
+}
+
+void checkoutRepo() {
+ deleteDir()
+ checkout(githubscm.resolveRepository(getRepoName(), getGitAuthor(),
getBuildBranch(), false, getGitAuthorCredsId()))
+ // need to manually checkout branch since on a detached branch after
checkout command
+ sh "git checkout ${getBuildBranch()}"
+ checkoutDatetime = getCheckoutDatetime()
+ if (checkoutDatetime) {
+ sh "git checkout `git rev-list -n 1 --before=\"${checkoutDatetime}\"
${getBuildBranch()}`"
+ }
+}
+
+void sendNotification() {
+ if (params.SEND_NOTIFICATION) {
+ mailer.sendMarkdownTestSummaryNotification('Weekly Deploy',
"[${getBuildBranch()}] Drools", [env.DROOLS_CI_EMAIL_TO])
+ } else {
+ echo 'No notification sent per configuration'
+ }
+}
+
+boolean shouldDeployToRepository() {
+ return env.MAVEN_DEPLOY_REPOSITORY && env.MAVEN_REPO_CREDS_ID &&
getGitAuthor() == 'apache'
+}
+
+String getRepoName() {
+ return env.REPO_NAME
+}
+
+String getGitAuthor() {
+ // GIT_AUTHOR can be env or param
+ return "${GIT_AUTHOR}"
+}
+
+String getBuildBranch() {
+ return params.BUILD_BRANCH_NAME
+}
+
+String getPRBranch() {
+ return params.DROOLS_PR_BRANCH
+}
+
+String getGitAuthorCredsId() {
+ return env.GIT_AUTHOR_CREDS_ID
+}
+
+String getGitAuthorPushCredsId() {
+ return env.GIT_AUTHOR_PUSH_CREDS_ID
+}
+
+void setDeployPropertyIfNeeded(String key, def value) {
+ if (value) {
+ deployProperties[key] = value
+ }
+}
+
+MavenCommand getMavenCommand(String directory = '') {
+ directory = directory ?: getRepoName()
+ def mvnCmd = new MavenCommand(this, ['-fae', '-ntp'])
+ .withOptions(env.BUILD_MVN_OPTS ? [ env.BUILD_MVN_OPTS ] : [])
+ .inDirectory(directory)
+ if (!isMainStream()) { // Workaround as enforcer rules may not be fixed on
other streams
+ mvnCmd.withProperty('enforcer.skip')
+ } else {
+ mvnCmd.withProperty('full')
+ }
+ return mvnCmd
+}
+
+boolean isMainStream() {
+ return env.DROOLS_STREAM == 'main'
+}
+
+String getCheckoutDatetime() {
+ return params.GIT_CHECKOUT_DATETIME
+}
+
+String getProjectVersionDate() {
+ def projectVersionDate = (getCheckoutDatetime() =~
/(\d{4}-\d{2}-\d{2})/)[0][0]
+ return projectVersionDate.replace('-', '')
+}
+
+String getProjectVersion(boolean keepSnapshotSuffix = true) {
+ def projectVersion = env.PROJECT_VERSION
+ if (keepSnapshotSuffix) {
+ return projectVersion.replace("-SNAPSHOT",
"-${getProjectVersionDate()}-SNAPSHOT")
+ }
+ return projectVersion.replace("-SNAPSHOT", "-${getProjectVersionDate()}")
+}
\ No newline at end of file
diff --git a/.ci/jenkins/config/branch.yaml b/.ci/jenkins/config/branch.yaml
new file mode 100644
index 00000000000..167ec60102c
--- /dev/null
+++ b/.ci/jenkins/config/branch.yaml
@@ -0,0 +1,109 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+generation_config:
+ missing_environment: ignore
+environments:
+ default:
+ env_vars:
+ DROOLS_BUILD_MVN_OPTS: -Dfull
+ native:
+ env_vars:
+ NATIVE: true
+ BUILD_MVN_OPTS_CURRENT: -Dnative -Dquarkus.native.container-build=true
+ DROOLS_BUILD_MVN_OPTS: -Dfull
+ ADDITIONAL_TIMEOUT: 720
+ ids:
+ - native
+ sonarcloud:
+ auto_generation: false
+ env_vars:
+ ENABLE_SONARCLOUD: true
+ DROOLS_BUILD_MVN_OPTS: -Dfull
+ ids:
+ - sonarcloud
+ - coverage
+repositories:
+ - name: incubator-kie-drools
+ job_display_name: drools
+git:
+ author:
+ name: apache
+ credentials_id: 399061d0-5ab5-4142-a186-a52081fef742
+ token_credentials_id: kie-ci3-token
+ push:
+ credentials_id: 84811880-2025-45b6-a44c-2f33bef30ad2
+ token_credentials_id: 41128c14-bb63-4708-9074-d20a318ee630
+ fork_author:
+ name: kie-ci
+ credentials_id: kie-ci
+ push:
+ credentials_id: kie-ci
+ quarkus:
+ author:
+ name: quarkusio
+ credentials_id: kie-ci
+ branch: main
+ jenkins_config_path: .ci/jenkins
+buildchain_config:
+ git:
+ repository: incubator-kie-kogito-pipelines
+ file_path: .ci/pull-request-config.yaml
+ token_credentials_id: kie-ci3-token
+maven:
+ settings:
+ nightly:
+ config_file_id: kie-nightly-settings
+ release:
+ config_file_id: kie-release-settings
+ nexus:
+ release_url: TO_DEFINE
+ release_repository: TO_DEFINE
+ staging_profile_url: TO_DEFINE
+ staging_profile_id: TO_DEFINE
+ build_promotion_profile_id: TO_DEFINE
+ artifacts_repository: ''
+ artifacts_upload_repository:
+ nightly:
+ url: https://repository.apache.org/content/repositories/snapshots
+ creds_id: apache-nexus-kie-deploy-credentials
+ release:
+ url: https://repository.apache.org/service/local/staging/deploy/maven2
+ creds_id: jenkins-deploy-to-nexus-staging
+cloud:
+ image:
+ registry_user_credentials_id: DOCKERHUB_USER
+ registry_token_credentials_id: DOCKERHUB_TOKEN
+ registry: docker.io
+ namespace: apache
+ latest_git_branch: main
+release:
+ gpg:
+ sign:
+ key_credentials_id: GPG_KEY_FILE
+ passphrase_credentials_id: ''
+jenkins:
+ email_creds_id: DROOLS_CI_NOTIFICATION_EMAILS
+ agent:
+ docker:
+ builder:
+ image: docker.io/apache/incubator-kie-kogito-ci-build:main-latest
+ args: --privileged --group-add docker
+ default_tools:
+ jdk: jdk_17_latest
+ maven: maven_3.9.11
+ sonar_jdk: jdk_17_latest
diff --git a/.ci/jenkins/config/main.yaml b/.ci/jenkins/config/main.yaml
new file mode 100644
index 00000000000..992283120b9
--- /dev/null
+++ b/.ci/jenkins/config/main.yaml
@@ -0,0 +1,44 @@
+ecosystem:
+ main_project: drools
+ projects:
+ - name: drools
+ regexs:
+ - drools.*
+ - incubator-kie-drools.*
+ - name: kie-benchmarks
+ ignore_release: true
+ regexs:
+ - kie-benchmarks.*
+ - incubator-kie-benchmarks.*
+git:
+ branches:
+ - name: main
+ main_branch: true
+ - name: 10.0.x
+ seed:
+ branch: seed-drools-10.0.x
+ - name: 10.1.x
+ seed:
+ branch: seed-drools-10.1.x
+ - name: 10.2.x
+ seed:
+ branch: seed-drools-10.2.x
+seed:
+ config_file:
+ git:
+ repository: incubator-kie-drools
+ author:
+ name: apache
+ credentials_id: ASF_Cloudbees_Jenkins_ci-builds
+ push:
+ credentials_id: 84811880-2025-45b6-a44c-2f33bef30ad2
+ branch: main
+ path: .ci/jenkins/config/branch.yaml
+ jenkinsfile: dsl/seed/jenkinsfiles/Jenkinsfile.seed.branch
+jenkins:
+ email_creds_id: DROOLS_CI_NOTIFICATION_EMAILS
+ agent:
+ docker:
+ builder:
+ image: docker.io/apache/incubator-kie-kogito-ci-build:main-latest
+ args: --privileged --group-add docker
diff --git a/.ci/jenkins/dsl/jobs.groovy b/.ci/jenkins/dsl/jobs.groovy
new file mode 100644
index 00000000000..8c49a232cef
--- /dev/null
+++ b/.ci/jenkins/dsl/jobs.groovy
@@ -0,0 +1,409 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+/*
+* This file is describing all the Jenkins jobs in the DSL format (see
https://plugins.jenkins.io/job-dsl/)
+* needed by the Kogito pipelines.
+*
+* The main part of Jenkins job generation is defined into the
https://github.com/apache/incubator-kie-kogito-pipelines repository.
+*
+* This file is making use of shared libraries defined in
+*
https://github.com/apache/incubator-kie-kogito-pipelines/tree/main/dsl/seed/src/main/groovy/org/kie/jenkins/jobdsl.
+*/
+
+import org.kie.jenkins.jobdsl.model.JenkinsFolder
+import org.kie.jenkins.jobdsl.model.JobType
+import org.kie.jenkins.jobdsl.utils.EnvUtils
+import org.kie.jenkins.jobdsl.utils.JobParamsUtils
+import org.kie.jenkins.jobdsl.KogitoJobTemplate
+import org.kie.jenkins.jobdsl.KogitoJobUtils
+import org.kie.jenkins.jobdsl.Utils
+
+jenkins_path = '.ci/jenkins'
+
+boolean isMainStream() {
+ return Utils.getStream(this) == 'main'
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////
+// Whole Drools project jobs
+///////////////////////////////////////////////////////////////////////////////////////////
+
+jenkins_path_project = "${jenkins_path}/project"
+
+// Init branch
+createProjectSetupBranchJob()
+
+// Nightly jobs
+setupProjectNightlyJob()
+
+// Weekly jobs
+setupProjectWeeklyJob()
+
+// Release jobs
+setupProjectReleaseJob()
+setupProjectPostReleaseJob()
+
+// Tools
+KogitoJobUtils.createQuarkusPlatformUpdateToolsJob(this, 'drools')
+KogitoJobUtils.createMainQuarkusUpdateToolsJob(this,
+ [ 'drools' ],
+ [ 'mariofusco', 'danielezonca']
+)
+
+void createProjectSetupBranchJob() {
+ def jobParams = JobParamsUtils.getBasicJobParams(this, '0-setup-branch',
JobType.SETUP_BRANCH, "${jenkins_path_project}/Jenkinsfile.setup-branch",
'Drools Setup Branch')
+ jobParams.env.putAll([
+ JENKINS_EMAIL_CREDS_ID: "${JENKINS_EMAIL_CREDS_ID}",
+
+ GIT_BRANCH_NAME: "${GIT_BRANCH}",
+
+ IS_MAIN_BRANCH: "${Utils.isMainBranch(this)}",
+ DROOLS_STREAM: Utils.getStream(this),
+ ])
+ KogitoJobTemplate.createPipelineJob(this, jobParams)?.with {
+ parameters {
+ stringParam('DROOLS_VERSION', '', 'Drools version')
+ booleanParam('DEPLOY', true, 'Deploy artifacts')
+ }
+ }
+}
+
+void setupProjectNightlyJob() {
+ def jobParams = JobParamsUtils.getBasicJobParams(this, '0-nightly',
JobType.NIGHTLY, "${jenkins_path_project}/Jenkinsfile.nightly", 'Drools
Nightly')
+ jobParams.triggers = [cron : isMainStream() ? '@midnight' : 'H 3 * * *']
+ jobParams.env.putAll([
+ JENKINS_EMAIL_CREDS_ID: "${JENKINS_EMAIL_CREDS_ID}",
+
+ GIT_BRANCH_NAME: "${GIT_BRANCH}",
+
+ DROOLS_STREAM: Utils.getStream(this),
+ ])
+ KogitoJobTemplate.createPipelineJob(this, jobParams)?.with {
+ parameters {
+ booleanParam('SKIP_TESTS', false, 'Skip all tests')
+ }
+ }
+}
+
+void setupProjectWeeklyJob() {
+ def jobParams = JobParamsUtils.getBasicJobParams(this, '0-weekly',
JobType.OTHER, "${jenkins_path_project}/Jenkinsfile.weekly", 'Drools Weekly')
+ jobParams.triggers = [cron : '0 3 * * 0']
+ jobParams.env.putAll([
+ JENKINS_EMAIL_CREDS_ID: "${JENKINS_EMAIL_CREDS_ID}",
+
+ GIT_BRANCH_NAME: "${GIT_BRANCH}",
+
+ DROOLS_STREAM: Utils.getStream(this),
+ ])
+ KogitoJobTemplate.createPipelineJob(this, jobParams)?.with {
+ parameters {
+ booleanParam('SKIP_TESTS', false, 'Skip all tests')
+ }
+ }
+}
+
+void setupProjectReleaseJob() {
+ def jobParams = JobParamsUtils.getBasicJobParams(this, '0-drools-release',
JobType.RELEASE, "${jenkins_path_project}/Jenkinsfile.release", 'Drools/Kogito
Artifacts Release')
+ jobParams.env.putAll([
+ JENKINS_EMAIL_CREDS_ID: "${JENKINS_EMAIL_CREDS_ID}",
+
+ GIT_BRANCH_NAME: "${GIT_BRANCH}",
+ GIT_AUTHOR: "${GIT_AUTHOR_NAME}",
+ ])
+ KogitoJobTemplate.createPipelineJob(this, jobParams)?.with {
+ parameters {
+ stringParam('RESTORE_FROM_PREVIOUS_JOB', '', 'URL to a previous
stopped release job which needs to be continued')
+
+ stringParam('RELEASE_VERSION', '', 'Drools version to release as
Major.minor.micro')
+
+ stringParam('GIT_TAG_NAME', '', 'Git tag to create. i.e.:
10.0.0-rc1')
+
+ booleanParam('SKIP_TESTS', false, 'Skip all tests')
+ }
+ }
+}
+
+void setupProjectPostReleaseJob() {
+ def jobParams = JobParamsUtils.getBasicJobParams(this,
'drools-post-release', JobType.RELEASE,
"${jenkins_path_project}/Jenkinsfile.post-release", 'Drools Post Release')
+ JobParamsUtils.setupJobParamsAgentDockerBuilderImageConfiguration(this,
jobParams)
+ jobParams.env.putAll([
+ JENKINS_EMAIL_CREDS_ID: "${JENKINS_EMAIL_CREDS_ID}",
+
+ GIT_BRANCH_NAME: "${GIT_BRANCH}",
+ GIT_AUTHOR: "${GIT_AUTHOR_NAME}",
+ GIT_AUTHOR_CREDS_ID: "${GIT_AUTHOR_CREDENTIALS_ID}",
+ GIT_AUTHOR_PUSH_CREDS_ID: "${GIT_AUTHOR_PUSH_CREDENTIALS_ID}",
+
+ DROOLS_STREAM: Utils.getStream(this),
+ ])
+ KogitoJobTemplate.createPipelineJob(this, jobParams)?.with {
+ parameters {
+ stringParam('DROOLS_VERSION', '', 'Drools version to release as
Major.minor.micro')
+
+ stringParam('RELEASE_NOTES_NUMBER', '', 'number of JIRA release
notes')
+ }
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////
+// Drools repository only project jobs
+///////////////////////////////////////////////////////////////////////////////////////////
+
+Map getMultijobPRConfig(JenkinsFolder jobFolder) {
+ def jobConfig = [
+ parallel: true,
+ buildchain: true,
+ jobs : [
+ [
+ id: 'drools',
+ primary: true,
+ env : [
+ // Sonarcloud analysis only on main branch
+ // As we have only Community edition
+ ENABLE_SONARCLOUD:
EnvUtils.isDefaultEnvironment(this, jobFolder.getEnvironmentName()) &&
Utils.isMainBranch(this),
+ ]
+ ], [
+ id: 'kogito-runtimes',
+ repository: 'incubator-kie-kogito-runtimes'
+ ], [
+ id: 'kogito-apps',
+ repository: 'incubator-kie-kogito-apps',
+ ], [
+ id: 'kogito-quarkus-examples',
+ repository: 'incubator-kie-kogito-examples',
+ env : [
+ KOGITO_EXAMPLES_SUBFOLDER_POM:
'kogito-quarkus-examples/',
+ ],
+ ], [
+ id: 'kogito-springboot-examples',
+ repository: 'incubator-kie-kogito-examples',
+ env : [
+ KOGITO_EXAMPLES_SUBFOLDER_POM:
'kogito-springboot-examples/',
+ ],
+ ], [
+ id: 'kogito-gradle-examples',
+ repository: 'incubator-kie-kogito-examples',
+ env : [
+ KOGITO_EXAMPLES_SUBFOLDER_POM:
'gradle-examples/',
+ ],
+ ]
+ // Commented as not migrated
+ // ], [
+ // id: 'kie-jpmml-integration',
+ // repository: 'incubator-kie-jpmml-integration'
+ // ]
+ ]
+ ]
+
+ // For Quarkus 3, run only drools PR check... for now
+ if (EnvUtils.hasEnvironmentId(this, jobFolder.getEnvironmentName(),
'quarkus3')) {
+ jobConfig.jobs.retainAll { it.id == 'drools' }
+ }
+
+ return jobConfig
+}
+
+// PR checks
+// DISABLED: Commenting out to disable Jenkins PR check
(continuous-integration/jenkins/pr-head)
+// Utils.isMainBranch(this) &&
KogitoJobTemplate.createPullRequestMultibranchPipelineJob(this,
"${jenkins_path}/Jenkinsfile")
+
+// Init branch
+createSetupBranchJob()
+
+// Nightly jobs
+Closure setup3AMCronTriggerJobParamsGetter = { script ->
+ def jobParams = JobParamsUtils.DEFAULT_PARAMS_GETTER(script)
+ jobParams.triggers = [ cron: 'H 3 * * *' ]
+ return jobParams
+}
+
+Closure setupSonarProjectKeyEnv = { Closure paramsGetter ->
+ return { script ->
+ def jobParams = paramsGetter(script)
+ jobParams.env.put('SONAR_PROJECT_KEY', 'apache_incubator-kie-drools')
+ return jobParams
+ }
+}
+
+Closure nightlyJobParamsGetter = isMainStream() ?
JobParamsUtils.DEFAULT_PARAMS_GETTER : setup3AMCronTriggerJobParamsGetter
+KogitoJobUtils.createNightlyBuildChainBuildAndDeployJobForCurrentRepo(this,
'', true)
+setupSpecificBuildChainNightlyJob('native', nightlyJobParamsGetter)
+setupSpecificBuildChainNightlyJob('sonarcloud',
setupSonarProjectKeyEnv(nightlyJobParamsGetter))
+// Quarkus 3 nightly is exported to Kogito pipelines for easier integration
+
+// Release jobs
+setupDeployJob()
+setupPromoteJob()
+
+// Weekly deploy job
+setupWeeklyDeployJob()
+
+// Tools job
+if (isMainStream()) {
+ KogitoJobUtils.createQuarkusUpdateToolsJob(this, 'drools', [
+ modules: [ 'drools-build-parent' ],
+ compare_deps_remote_poms: [ 'io.quarkus:quarkus-bom' ],
+ properties: [ 'version.io.quarkus' ],
+ ])
+}
+
+/////////////////////////////////////////////////////////////////
+// Methods
+/////////////////////////////////////////////////////////////////
+
+void setupQuarkusIntegrationJob(String envName, Closure defaultJobParamsGetter
= JobParamsUtils.DEFAULT_PARAMS_GETTER) {
+ KogitoJobUtils.createNightlyBuildChainIntegrationJob(this, envName,
Utils.getRepoName(this), true, defaultJobParamsGetter)
+}
+
+void setupSpecificBuildChainNightlyJob(String envName, Closure
defaultJobParamsGetter = JobParamsUtils.DEFAULT_PARAMS_GETTER) {
+ KogitoJobUtils.createNightlyBuildChainBuildAndTestJobForCurrentRepo(this,
envName, true, defaultJobParamsGetter)
+}
+
+void createSetupBranchJob() {
+ def jobParams = JobParamsUtils.getBasicJobParams(this, 'drools',
JobType.SETUP_BRANCH, "${jenkins_path}/Jenkinsfile.setup-branch", 'Drools Setup
branch')
+ JobParamsUtils.setupJobParamsAgentDockerBuilderImageConfiguration(this,
jobParams)
+ jobParams.env.putAll([
+ JENKINS_EMAIL_CREDS_ID: "${JENKINS_EMAIL_CREDS_ID}",
+
+ GIT_AUTHOR: "${GIT_AUTHOR_NAME}",
+ GIT_AUTHOR_CREDS_ID: "${GIT_AUTHOR_CREDENTIALS_ID}",
+ GIT_AUTHOR_PUSH_CREDS_ID: "${GIT_AUTHOR_PUSH_CREDENTIALS_ID}",
+
+ MAVEN_SETTINGS_CONFIG_FILE_ID:
Utils.getMavenSettingsConfigFileId(this, JobType.NIGHTLY.name),
+
+ IS_MAIN_BRANCH: "${Utils.isMainBranch(this)}",
+ DROOLS_STREAM: Utils.getStream(this),
+ ])
+ KogitoJobTemplate.createPipelineJob(this, jobParams)?.with {
+ parameters {
+ stringParam('DISPLAY_NAME', '', 'Setup a specific build display
name')
+
+ stringParam('BUILD_BRANCH_NAME', "${GIT_BRANCH}", 'Set the Git
branch to checkout')
+
+ stringParam('DROOLS_VERSION', '', 'Drools version to set.')
+
+ booleanParam('SEND_NOTIFICATION', false, 'In case you want the
pipeline to send a notification on CI channel for this run.')
+ }
+ }
+}
+
+void setupDeployJob() {
+ def jobParams = JobParamsUtils.getBasicJobParams(this, 'drools-deploy',
JobType.RELEASE, "${jenkins_path}/Jenkinsfile.deploy", 'Drools Deploy')
+ JobParamsUtils.setupJobParamsAgentDockerBuilderImageConfiguration(this,
jobParams)
+ jobParams.env.putAll([
+ PROPERTIES_FILE_NAME: 'deployment.properties',
+ JENKINS_EMAIL_CREDS_ID: "${JENKINS_EMAIL_CREDS_ID}",
+
+ GIT_AUTHOR: "${GIT_AUTHOR_NAME}",
+ GIT_AUTHOR_CREDS_ID: "${GIT_AUTHOR_CREDENTIALS_ID}",
+ GIT_AUTHOR_PUSH_CREDS_ID: "${GIT_AUTHOR_PUSH_CREDENTIALS_ID}",
+
+ MAVEN_SETTINGS_CONFIG_FILE_ID:
Utils.getMavenSettingsConfigFileId(this, JobType.RELEASE.name),
+ MAVEN_DEPENDENCIES_REPOSITORY: "${MAVEN_ARTIFACTS_REPOSITORY}",
+ MAVEN_DEPLOY_REPOSITORY:
Utils.getMavenArtifactsUploadRepositoryUrl(this, JobType.RELEASE.name),
+ MAVEN_REPO_CREDS_ID:
Utils.getMavenArtifactsUploadRepositoryCredentialsId(this,
JobType.RELEASE.name),
+
+ DROOLS_STREAM: Utils.getStream(this),
+
+ RELEASE_GPG_SIGN_KEY_CREDS_ID:
Utils.getReleaseGpgSignKeyCredentialsId(this),
+ RELEASE_GPG_SIGN_PASSPHRASE_CREDS_ID:
Utils.getReleaseGpgSignPassphraseCredentialsId(this)
+ ])
+ KogitoJobTemplate.createPipelineJob(this, jobParams)?.with {
+ parameters {
+ stringParam('DISPLAY_NAME', '', 'Setup a specific build display
name')
+
+ stringParam('BUILD_BRANCH_NAME', "${GIT_BRANCH}", 'Set the Git
branch to checkout')
+
+ booleanParam('SKIP_TESTS', false, 'Skip tests')
+
+ booleanParam('CREATE_PR', false, 'Should we create a PR with the
changes ?')
+ stringParam('PROJECT_VERSION', '', 'Optional if not RELEASE. If
RELEASE, cannot be empty.')
+ stringParam('DROOLS_PR_BRANCH', '', 'PR branch name')
+
+ stringParam('GIT_TAG_NAME', '', 'Optional if not RELEASE. Tag to
be created in the repository')
+
+ booleanParam('SEND_NOTIFICATION', false, 'In case you want the
pipeline to send a notification on CI channel for this run.')
+ }
+ }
+}
+
+void setupPromoteJob() {
+ def jobParams = JobParamsUtils.getBasicJobParams(this, 'drools-promote',
JobType.RELEASE, "${jenkins_path}/Jenkinsfile.promote", 'Drools Promote')
+ JobParamsUtils.setupJobParamsAgentDockerBuilderImageConfiguration(this,
jobParams)
+ jobParams.env.putAll([
+ PROPERTIES_FILE_NAME: 'deployment.properties',
+ JENKINS_EMAIL_CREDS_ID: "${JENKINS_EMAIL_CREDS_ID}",
+
+ GIT_AUTHOR: "${GIT_AUTHOR_NAME}",
+ GIT_AUTHOR_CREDS_ID: "${GIT_AUTHOR_CREDENTIALS_ID}",
+ GIT_AUTHOR_PUSH_CREDS_ID: "${GIT_AUTHOR_PUSH_CREDENTIALS_ID}",
+
+ MAVEN_SETTINGS_CONFIG_FILE_ID:
Utils.getMavenSettingsConfigFileId(this, JobType.RELEASE.name),
+ MAVEN_DEPENDENCIES_REPOSITORY: "${MAVEN_ARTIFACTS_REPOSITORY}",
+ MAVEN_DEPLOY_REPOSITORY: "${MAVEN_ARTIFACTS_REPOSITORY}",
+
+ DROOLS_STREAM: Utils.getStream(this),
+ ])
+ KogitoJobTemplate.createPipelineJob(this, jobParams)?.with {
+ parameters {
+ stringParam('DISPLAY_NAME', '', 'Setup a specific build display
name')
+ stringParam('BUILD_BRANCH_NAME', "${GIT_BRANCH}", 'Set the Git
branch to checkout')
+ // Deploy job url to retrieve deployment.properties
+ stringParam('DEPLOY_BUILD_URL', '', 'URL to jenkins deploy build
to retrieve the `deployment.properties` file. If base parameters are defined,
they will override the `deployment.properties` information')
+ // Release information which can override `deployment.properties`
+ stringParam('PROJECT_VERSION', '', 'Override
`deployment.properties`. Optional if not RELEASE. If RELEASE, cannot be empty.')
+ stringParam('GIT_TAG', '', 'Git tag to set, if different from
PROJECT_VERSION')
+ booleanParam('SEND_NOTIFICATION', false, 'In case you want the
pipeline to send a notification on CI channel for this run.')
+ }
+ }
+}
+
+void setupWeeklyDeployJob() {
+ def jobParams = JobParamsUtils.getBasicJobParams(this,
'drools.weekly-deploy', JobType.OTHER,
"${jenkins_path}/Jenkinsfile.weekly.deploy", 'Drools Weekly Deploy')
+ JobParamsUtils.setupJobParamsAgentDockerBuilderImageConfiguration(this,
jobParams)
+ jobParams.env.putAll([
+ PROPERTIES_FILE_NAME: 'deployment.properties',
+ JENKINS_EMAIL_CREDS_ID: "${JENKINS_EMAIL_CREDS_ID}",
+
+ GIT_AUTHOR: "${GIT_AUTHOR_NAME}",
+ GIT_AUTHOR_CREDS_ID: "${GIT_AUTHOR_CREDENTIALS_ID}",
+ GIT_AUTHOR_PUSH_CREDS_ID: "${GIT_AUTHOR_PUSH_CREDENTIALS_ID}",
+
+ MAVEN_SETTINGS_CONFIG_FILE_ID:
Utils.getMavenSettingsConfigFileId(this, JobType.NIGHTLY.name),
+ MAVEN_DEPENDENCIES_REPOSITORY: "${MAVEN_ARTIFACTS_REPOSITORY}",
+ MAVEN_DEPLOY_REPOSITORY:
Utils.getMavenArtifactsUploadRepositoryUrl(this, JobType.NIGHTLY.name),
+ MAVEN_REPO_CREDS_ID:
Utils.getMavenArtifactsUploadRepositoryCredentialsId(this,
JobType.NIGHTLY.name),
+
+ DROOLS_STREAM: Utils.getStream(this),
+ ])
+ KogitoJobTemplate.createPipelineJob(this, jobParams)?.with {
+ parameters {
+ stringParam('DISPLAY_NAME', '', 'Setup a specific build display
name')
+
+ stringParam('BUILD_BRANCH_NAME', "${GIT_BRANCH}", 'Set the Git
branch to checkout')
+
+ booleanParam('SKIP_TESTS', false, 'Skip tests')
+
+ stringParam('GIT_CHECKOUT_DATETIME', '', 'Git checkout date and
time - (Y-m-d H:i)')
+
+ booleanParam('SEND_NOTIFICATION', false, 'In case you want the
pipeline to send a notification on CI channel for this run.')
+ }
+ }
+}
\ No newline at end of file
diff --git a/.ci/jenkins/dsl/test.sh b/.ci/jenkins/dsl/test.sh
new file mode 100755
index 00000000000..2c830677b44
--- /dev/null
+++ b/.ci/jenkins/dsl/test.sh
@@ -0,0 +1,53 @@
+#!/bin/bash -e
+
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+# Used to retrieve current git author, to set correctly the main config file
repo
+GIT_SERVER='github.com'
+
+git_url=$(git remote -v | grep origin | awk -F' ' '{print $2}' | head -n 1)
+if [ -z "${git_url}" ]; then
+ echo "Script must be executed in a Git repository for this script to run
correctly"
+ exit 1
+fi
+echo "git_url = ${git_url}"
+
+git_server_url=
+if [[ "${git_url}" = https://* ]]; then
+ git_server_url="https://${GIT_SERVER}/"
+elif [[ "${git_url}" = git@* ]]; then
+ git_server_url="git@${GIT_SERVER}:"
+else
+ echo "Unknown protocol for url ${git_url}"
+ exit 1
+fi
+
+git_author="$(echo ${git_url} | awk -F"${git_server_url}" '{print $2}' | awk
-F. '{print $1}' | awk -F/ '{print $1}')"
+
+export DSL_DEFAULT_MAIN_CONFIG_FILE_REPO="${git_author}"/incubator-kie-drools
+export DSL_DEFAULT_FALLBACK_MAIN_CONFIG_FILE_REPO=apache/incubator-kie-drools
+export DSL_DEFAULT_MAIN_CONFIG_FILE_PATH=.ci/jenkins/config/main.yaml
+export DSL_DEFAULT_BRANCH_CONFIG_FILE_REPO="${git_author}"/incubator-kie-drools
+
+file=$(mktemp)
+# For more usage of the script, use ./test.sh -h
+curl -o ${file}
https://raw.githubusercontent.com/apache/incubator-kie-kogito-pipelines/main/dsl/seed/scripts/seed_test.sh
+chmod u+x ${file}
+${file} $@
\ No newline at end of file
diff --git a/.ci/jenkins/project/Jenkinsfile.nightly
b/.ci/jenkins/project/Jenkinsfile.nightly
new file mode 100644
index 00000000000..4391733ce5e
--- /dev/null
+++ b/.ci/jenkins/project/Jenkinsfile.nightly
@@ -0,0 +1,190 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import org.jenkinsci.plugins.workflow.libs.Library
+
+@Library('jenkins-pipeline-shared-libraries')_
+
+// Deploy jobs
+DROOLS_DEPLOY = 'drools.build-and-deploy'
+// KIE_JPMML_INTEGRATION_DEPLOY = 'kie-jpmml-integration.build-and-deploy' //
Commented as not migrated for now
+
+// Map of executed jobs
+// See
https://javadoc.jenkins.io/plugin/workflow-support/org/jenkinsci/plugins/workflow/support/steps/build/RunWrapper.html
+// for more options on built job entity
+JOBS = [:]
+
+FAILED_STAGES = [:]
+UNSTABLE_STAGES = [:]
+
+// Should be multibranch pipeline
+pipeline {
+ agent {
+ label util.avoidFaultyNodes('ubuntu')
+ }
+
+ options {
+ timeout(time: 360, unit: 'MINUTES')
+ }
+
+ environment {
+ DROOLS_CI_EMAIL = credentials("${JENKINS_EMAIL_CREDS_ID}")
+
+ // Use branch name in nightly tag as we may have parallel main and
release branch builds
+ NIGHTLY_TAG = """${getBuildBranch()}-${sh(
+ returnStdout: true,
+ script: 'date -u "+%Y-%m-%d"'
+ ).trim()}"""
+ }
+
+ stages {
+ stage('Initialize') {
+ steps {
+ script {
+ echo "nightly tag is ${env.NIGHTLY_TAG}"
+
+ currentBuild.displayName = env.NIGHTLY_TAG
+ }
+ }
+ }
+ stage('Build & Deploy Drools') {
+ steps {
+ script {
+ def buildParams = getDefaultBuildParams()
+ addSkipTestsParam(buildParams)
+ addSkipIntegrationTestsParam(buildParams)
+
+ buildJob(DROOLS_DEPLOY, buildParams)
+ }
+ }
+ post {
+ failure {
+ addFailedStage(DROOLS_DEPLOY)
+ }
+ }
+ }
+ // stage('Build & Deploy KIE jpmml integration') {
+ // steps {
+ // script {
+ // def buildParams = getDefaultBuildParams()
+ // addSkipTestsParam(buildParams)
+ // addSkipIntegrationTestsParam(buildParams)
+
+ // buildJob(KIE_JPMML_INTEGRATION_DEPLOY, buildParams)
+ // }
+ // }
+ // post {
+ // failure {
+ // addFailedStage(KIE_JPMML_INTEGRATION_DEPLOY)
+ // }
+ // }
+ // }
+ }
+ post {
+ unsuccessful {
+ sendPipelineErrorNotification()
+ }
+ }
+}
+
+def buildJob(String jobName, List buildParams, String jobKey = jobName) {
+ echo "[${jobKey}] Build ${jobName} with params ${buildParams}"
+
+ def job = build(job: "${jobName}", wait: true, parameters: buildParams,
propagate: false)
+ JOBS[jobKey] = job
+
+ // Set Unstable if job did not succeed
+ if (!isJobSucceeded(jobKey)) {
+ addUnstableStage(jobKey)
+ unstable("Job ${jobName} finished with result ${job.result}")
+ }
+ return job
+}
+
+def getJob(String jobKey) {
+ return JOBS[jobKey]
+}
+
+String getJobUrl(String jobKey) {
+ echo "getJobUrl for ${jobKey}"
+ return getJob(jobKey)?.absoluteUrl ?: ''
+}
+
+boolean isJobSucceeded(String jobKey) {
+ return getJob(jobKey)?.result == 'SUCCESS'
+}
+
+void addFailedStage(String jobKey = '') {
+ FAILED_STAGES.put("${env.STAGE_NAME}", jobKey)
+}
+void addUnstableStage(String jobKey = '') {
+ UNSTABLE_STAGES.put("${env.STAGE_NAME}", jobKey)
+}
+
+void sendPipelineErrorNotification() {
+ String bodyMsg = "Kogito nightly job #${env.BUILD_NUMBER} was:
${currentBuild.currentResult}"
+
+ paramsStr = ''
+ if (params.SKIP_TESTS) {
+ paramsStr += '\n- Tests skipped'
+ }
+ bodyMsg += paramsStr ? "\n\nConfiguration:${paramsStr}" : '\n'
+
+ if (FAILED_STAGES.size() > 0) {
+ bodyMsg += '\nFailed stages: \n- '
+ bodyMsg += FAILED_STAGES.collect { "${it.key} =>
${getJobUrl(it.value)}" }.join('\n- ')
+ }
+ bodyMsg += '\n'
+ if (UNSTABLE_STAGES.size() > 0) {
+ bodyMsg += '\nUnstable stages: \n- '
+ bodyMsg += UNSTABLE_STAGES.collect { "${it.key} =>
${getJobUrl(it.value)}" }.join('\n- ')
+ }
+ bodyMsg += '\n'
+ bodyMsg += "\nPlease look here: ${env.BUILD_URL}"
+ emailext body: bodyMsg, subject: "[${getBuildBranch()}][d] Full Pipeline",
+ to: env.DROOLS_CI_EMAIL
+}
+
+List getDefaultBuildParams() {
+ List params = []
+ addStringParam(params, 'DISPLAY_NAME', "${env.NIGHTLY_TAG}")
+ addBooleanParam(params, 'SEND_NOTIFICATION', true)
+
+ return params
+}
+
+void addSkipTestsParam(buildParams) {
+ addBooleanParam(buildParams, 'SKIP_TESTS', params.SKIP_TESTS)
+}
+
+void addSkipIntegrationTestsParam(buildParams) {
+ addBooleanParam(buildParams, 'SKIP_INTEGRATION_TESTS', params.SKIP_TESTS)
+}
+
+void addStringParam(List buildParams, String key, String value) {
+ buildParams.add(string(name: key, value: value))
+}
+
+void addBooleanParam(List buildParams, String key, boolean value) {
+ buildParams.add(booleanParam(name: key, value: value))
+}
+
+String getBuildBranch() {
+ return env.GIT_BRANCH_NAME
+}
\ No newline at end of file
diff --git a/.ci/jenkins/project/Jenkinsfile.post-release
b/.ci/jenkins/project/Jenkinsfile.post-release
new file mode 100644
index 00000000000..4e054a3a6fd
--- /dev/null
+++ b/.ci/jenkins/project/Jenkinsfile.post-release
@@ -0,0 +1,148 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import org.jenkinsci.plugins.workflow.libs.Library
+
+@Library('jenkins-pipeline-shared-libraries')_
+
+import org.kie.jenkins.MavenCommand
+
+
+pipeline {
+ agent {
+ docker {
+ image env.AGENT_DOCKER_BUILDER_IMAGE
+ args env.AGENT_DOCKER_BUILDER_ARGS
+ label util.avoidFaultyNodes()
+ }
+ }
+
+ options {
+ timestamps()
+ timeout(time: 120, unit: 'MINUTES')
+ disableConcurrentBuilds(abortPrevious: true)
+ }
+
+ environment {
+ DROOLS_CI_EMAIL_TO = credentials("${JENKINS_EMAIL_CREDS_ID}")
+
+ PR_BRANCH_HASH = "${util.generateHash(10)}"
+ }
+
+ stages {
+ stage('Initialization') {
+ steps {
+ script {
+ cleanWs(disableDeferredWipeout: true)
+ }
+ }
+ }
+ stage('Update drools version in drools-website') {
+ steps {
+ script {
+ String droolsWebsiteRepository =
'incubator-kie-drools-website'
+ String prLink = null
+ String prBranchName =
"${getProjectVersion().toLowerCase()}-${env.PR_BRANCH_HASH}"
+ dir(droolsWebsiteRepository) {
+ checkoutRepo(droolsWebsiteRepository,
getBuildBranch()) // there is no other branch
+ githubscm.createBranch(prBranchName)
+
+ // Update versions in links on the website and in the
docs.
+ sh "./scripts/update-versions.sh
${getProjectVersion()} ${getNextMinorSnapshotVersion(getProjectVersion())}
${getReleaseNotesNumber()}"
+ // Check if everyting builds
+ sh 'mvn clean generate-resources'
+ // Add changed files, commit, open and merge PR
+ prLink = commitAndCreatePR("Upgrade drools-website
${getProjectVersion()}", prBranchName, getBuildBranch())
+ approveAndMergePR(prLink)
+ }
+ }
+ }
+ }
+ }
+ post {
+ cleanup {
+ cleanWs()
+ }
+ unsuccessful {
+ sendErrorNotification()
+ }
+ }
+}
+
+void sendErrorNotification() {
+ mailer.sendMarkdownTestSummaryNotification('Post-release',
"[${getBuildBranch()}] Drools-website", [env.DROOLS_CI_EMAIL_TO])
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// Getter / Setter
+//////////////////////////////////////////////////////////////////////////////
+
+String getProjectVersion() {
+ return params.DROOLS_VERSION
+}
+
+String getBuildBranch() {
+ return 'main'
+}
+
+String getNextMinorSnapshotVersion(String currentVersion) {
+ return util.getNextVersion(currentVersion, 'minor')
+}
+
+String getGitAuthorCredsId() {
+ return env.GIT_AUTHOR_CREDS_ID
+}
+
+String getGitAuthorPushCredsId() {
+ return env.GIT_AUTHOR_PUSH_CREDS_ID
+}
+
+String getGitAuthor() {
+ return env.GIT_AUTHOR
+}
+
+String getReleaseNotesNumber() {
+ return params.RELEASE_NOTES_NUMBER
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// Git
+//////////////////////////////////////////////////////////////////////////////
+
+void checkoutRepo(String repo, String branch) {
+ deleteDir()
+ checkout(githubscm.resolveRepository(repo, getGitAuthor(), branch, false,
getGitAuthorCredsId()))
+ // need to manually checkout branch since on a detached branch after
checkout command
+ sh "git checkout ${branch}"
+}
+
+void approveAndMergePR(String prLink) {
+ if (prLink?.trim()) {
+ githubscm.approvePR(prLink, getGitAuthorPushCredsId())
+ githubscm.mergePR(prLink, getGitAuthorPushCredsId())
+ }
+}
+
+String commitAndCreatePR(String commitMsg, String localBranch, String
targetBranch) {
+ def prBody = "Generated by build ${BUILD_TAG}: ${BUILD_URL}"
+ githubscm.setUserConfigFromCreds(getGitAuthorPushCredsId())
+ githubscm.commitChanges(commitMsg)
+ githubscm.pushObject('origin', localBranch, getGitAuthorPushCredsId())
+ return githubscm.createPR(commitMsg, prBody, targetBranch,
getGitAuthorCredsId())
+}
\ No newline at end of file
diff --git a/.ci/jenkins/project/Jenkinsfile.release
b/.ci/jenkins/project/Jenkinsfile.release
new file mode 100644
index 00000000000..1287fe191f5
--- /dev/null
+++ b/.ci/jenkins/project/Jenkinsfile.release
@@ -0,0 +1,336 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import org.jenkinsci.plugins.workflow.libs.Library
+
+@Library('jenkins-pipeline-shared-libraries')_
+
+droolsRepo = 'drools'
+// kieJpmmlIntegrationRepo = 'kie-jpmml-integration' // Commented as not
migrated for now
+
+ARTIFACTS_STAGING_STAGE = 'stage.artifacts.staging'
+ARTIFACTS_RELEASE_STAGE = 'stage.artifacts.release'
+
+JOB_PROPERTY_PREFIX = 'build'
+JOB_RESULT_PROPERTY_KEY = 'result'
+JOB_URL_PROPERTY_KEY = 'absoluteUrl'
+JOB_DECISION_PROPERTY_KEY = 'decision'
+JOB_DECISION_MESSAGE_PROPERTY_KEY = 'decisionMessage'
+
+releaseProperties = [:]
+
+pipeline {
+ agent {
+ label util.avoidFaultyNodes('ubuntu')
+ }
+
+ environment {
+ DROOLS_CI_EMAIL = credentials("${JENKINS_EMAIL_CREDS_ID}")
+ }
+
+ stages {
+ stage('Initialize') {
+ steps {
+ script {
+ // Restore config from previous run
+ if (params.RESTORE_FROM_PREVIOUS_JOB) {
+ releaseProperties =
readPropertiesFromUrl(params.RESTORE_FROM_PREVIOUS_JOB, 'release.properties')
+ echo "Release properties imported from previous job:
${releaseProperties}"
+ }
+
+ assert getReleaseVersion()
+
+ currentBuild.displayName = getDisplayName()
+
+ sendNotification("Release Pipeline has started...\nDrools
version = ${getReleaseVersion()}\n=> ${env.BUILD_URL}")
+ }
+ }
+ post {
+ always {
+ setReleasePropertyIfneeded('release.version',
getReleaseVersion())
+ setReleasePropertyIfneeded('git.tag.name', getGitTagName())
+ }
+ }
+ }
+
+ stage('Build & Deploy Drools') {
+ steps {
+ script {
+ def buildParams = getDefaultBuildParams()
+ addSkipTestsParam(buildParams)
+ buildJob(getDeployJobName(droolsRepo), buildParams)
+ }
+ }
+ }
+
+ stage('Artifacts\' staging finalization') {
+ steps {
+ script {
+ if (!areArtifactsStaged()) {
+ sendNotification('All artifacts have been staged.')
+ }
+ setArtifactsStaged()
+ }
+ }
+ }
+ }
+ post {
+ always {
+ script {
+ saveReleaseProperties()
+ }
+ }
+ cleanup {
+ cleanWs()
+ }
+ success {
+ script {
+ sendSuccessfulReleaseNotification()
+ }
+ }
+ unsuccessful {
+ sendErrorNotification()
+ }
+ }
+}
+
+def buildJob(String jobName, List buildParams, boolean shouldWait = true) {
+ if (!hasJob(jobName) || (getJobResult(jobName) != 'SUCCESS' &&
getJobDecision(jobName) == 'retry')) {
+ sendStageNotification()
+ echo "Build ${jobName} with shouldWait=${shouldWait} and params
${buildParams}"
+ def job = build(job: "./${jobName}", wait: shouldWait, parameters:
buildParams, propagate: false)
+ removeJobDecision(jobName)
+ registerJobExecution(jobName, job.result, job.absoluteUrl)
+ } else {
+ echo 'Job was already executed. Retrieving information...'
+ }
+
+ saveReleaseProperties()
+
+ def jobResult = getJobResult(jobName)
+ def jobUrl = getJobUrl(jobName)
+ def jobDecision = getJobDecision(jobName)
+ if (jobResult != 'SUCCESS') {
+ if (jobDecision != 'continue' && jobDecision != 'skip') {
+ echo "Sending a notification about an unsuccessful job build
${jobName}."
+ sendNotification("`${jobName}` finished with status
`${jobResult}`.\nSee: ${jobUrl}\n\nPlease provide which action should be done
(retry ? continue ? skip ? abort ?): ${env.BUILD_URL}input")
+
+ // abort is handled automatically by the pipeline in the input
+ def result = input message: "Job `${jobName}` is in status
${jobResult}. What do you want to do ?\nBeware that skipping a deploy job will
not launch the promote part.", parameters: [choice(name: 'ACTION', choices:
['retry', 'continue', 'skip'].join('\n')), string(name: 'MESSAGE', description:
'If you want to add information to your action...')]
+ def inputDecision = result['ACTION']
+ def inputMessage = result['MESSAGE']
+ registerJobDecision(jobName, inputDecision, inputMessage)
+
+ String resultStr = "`${jobName}` failure => Decision was made to
${inputDecision}."
+ if (inputMessage) {
+ resultStr += "Additional Information: `${inputMessage}`"
+ }
+ sendNotification(resultStr)
+
+ if (inputDecision == 'retry') {
+ // If retry, remove job and build again
+ return buildJob(jobName, buildParams)
+ }
+ } else {
+ echo "Job decision was '${jobDecision}'"
+ }
+ } else {
+ echo 'Job succeeded'
+ }
+}
+
+String getDeployJobName(String repository) {
+ return "${repository}-deploy"
+}
+
+String getJobPropertySuffix(String jobName) {
+ return "${JOB_PROPERTY_PREFIX}.${jobName}"
+}
+
+String getJobPropertyKey(String jobName, String key) {
+ return "${getJobPropertySuffix(jobName)}.${key}"
+}
+
+def registerJobExecution(String jobName, String result, String absoluteUrl) {
+ setReleasePropertyIfneeded(getJobPropertyKey(jobName,
JOB_RESULT_PROPERTY_KEY), result)
+ setReleasePropertyIfneeded(getJobPropertyKey(jobName,
JOB_URL_PROPERTY_KEY), absoluteUrl)
+}
+
+def registerJobDecision(String jobName, String decision, String message = '') {
+ setReleasePropertyIfneeded(getJobPropertyKey(jobName,
JOB_DECISION_PROPERTY_KEY), decision)
+ setReleasePropertyIfneeded(getJobPropertyKey(jobName,
JOB_DECISION_MESSAGE_PROPERTY_KEY), message)
+}
+
+def removeJobDecision(String jobName) {
+ removeReleaseProperty(getJobPropertyKey(jobName,
JOB_DECISION_PROPERTY_KEY))
+ removeReleaseProperty(getJobPropertyKey(jobName,
JOB_DECISION_MESSAGE_PROPERTY_KEY))
+}
+
+List getAllJobNames() {
+ return releaseProperties.findAll { it.key.startsWith(JOB_PROPERTY_PREFIX)
}.collect { it.key.split('\\.')[1] }.unique()
+}
+
+boolean hasJob(String jobName) {
+ return releaseProperties.any {
it.key.startsWith(getJobPropertySuffix(jobName)) }
+}
+
+String getJobUrl(String jobName) {
+ echo "getJobUrl for ${jobName}"
+ return getReleaseProperty(getJobPropertyKey(jobName,
JOB_URL_PROPERTY_KEY)) ?: ''
+}
+
+String getJobResult(String jobName) {
+ echo "getJobResult for ${jobName}"
+ return getReleaseProperty(getJobPropertyKey(jobName,
JOB_RESULT_PROPERTY_KEY)) ?: ''
+}
+
+String getJobDecision(String jobName) {
+ echo "getJobDecision for ${jobName}"
+ return getReleaseProperty(getJobPropertyKey(jobName,
JOB_DECISION_PROPERTY_KEY)) ?: ''
+}
+
+boolean isJobConsideredOk(String jobName) {
+ String result = getJobResult(jobName)
+ String decision = getJobDecision(jobName)
+ return result == 'SUCCESS' || (result == 'UNSTABLE' && decision ==
'continue')
+}
+
+void saveReleaseProperties() {
+ def propertiesStr = releaseProperties.collect { entry ->
"${entry.key}=${entry.value}" }.join('\n')
+ writeFile( file : 'release.properties' , text : propertiesStr)
+ archiveArtifacts artifacts: 'release.properties'
+}
+
+void sendSuccessfulReleaseNotification() {
+ String bodyMsg = 'Release is successful with those jobs:\n'
+ getAllJobNames().findAll { isJobConsideredOk(it) }.each {
+ bodyMsg += "- ${it}\n"
+ }
+ bodyMsg += "\nPlease look here: ${BUILD_URL} for more information"
+ sendNotification(bodyMsg)
+}
+
+void sendErrorNotification() {
+ sendNotification("Kogito release job #${BUILD_NUMBER} was:
${currentBuild.currentResult}\nPlease look here: ${BUILD_URL}")
+}
+
+void sendStageNotification() {
+ sendNotification("${env.STAGE_NAME}")
+}
+
+void sendNotification(String body) {
+ echo 'Send Notification'
+ echo body
+ emailext body: body, subject: "[${env.GIT_BRANCH_NAME}] Release Pipeline",
+ to: env.DROOLS_CI_EMAIL
+}
+
+def readPropertiesFromUrl(String url, String propsFilename) {
+ if (!url.endsWith('/')) {
+ url += '/'
+ }
+ sh "wget ${url}artifact/${propsFilename} -O ${propsFilename}"
+ def props = readProperties file: propsFilename
+ echo props.collect { entry -> "${entry.key}=${entry.value}" }.join('\n')
+ return props
+}
+
+List getDefaultBuildParams() {
+ List buildParams = []
+ addDisplayNameParam(buildParams, getDisplayName(getReleaseVersion()))
+ addStringParam(buildParams, 'PROJECT_VERSION', getReleaseVersion())
+ addStringParam(buildParams, 'DROOLS_PR_BRANCH',
"drools-${getReleaseVersion()}")
+ addStringParam(buildParams, 'GIT_TAG_NAME', getGitTagName())
+ return buildParams
+}
+
+void addDisplayNameParam(buildParams, name = '') {
+ name = name ?: getDisplayName()
+ addStringParam(buildParams, 'DISPLAY_NAME', name)
+}
+
+void addDeployBuildUrlParam(buildParams, jobName) {
+ addDeployBuildUrlParamOrClosure(buildParams, jobName)
+}
+
+void addDeployBuildUrlParamOrClosure(buildParams, jobName, closure = null) {
+ String url = getJobUrl(jobName)
+ if (url) {
+ addStringParam(buildParams, 'DEPLOY_BUILD_URL', getJobUrl(jobName))
+ } else if (closure) {
+ closure()
+ }
+}
+
+void addSkipTestsParam(buildParams) {
+ addBooleanParam(buildParams, 'SKIP_TESTS', params.SKIP_TESTS)
+}
+
+void addStringParam(List buildParams, String key, String value) {
+ buildParams.add(string(name: key, value: value))
+}
+
+void addBooleanParam(List buildParams, String key, boolean value) {
+ buildParams.add(booleanParam(name: key, value: value))
+}
+
+String getDisplayName(version = '') {
+ version = version ?: getReleaseVersion()
+ return "Release ${version}"
+}
+
+String getReleaseVersion() {
+ return params.RELEASE_VERSION ?: getReleaseProperty('release.version')
+}
+
+String getGitAuthor() {
+ return env.GIT_AUTHOR
+}
+
+void setReleasePropertyIfneeded(String key, def value) {
+ if (value) {
+ releaseProperties[key] = value
+ }
+}
+
+void removeReleaseProperty(String key) {
+ if (hasReleaseProperty(key)) {
+ releaseProperties.remove(key)
+ }
+}
+
+boolean hasReleaseProperty(String key) {
+ return releaseProperties.containsKey(key)
+}
+
+def getReleaseProperty(String key) {
+ return hasReleaseProperty(key) ? releaseProperties[key] : ''
+}
+
+boolean areArtifactsStaged() {
+ return hasReleaseProperty(ARTIFACTS_STAGING_STAGE)
+}
+
+void setArtifactsStaged() {
+ setReleasePropertyIfneeded(ARTIFACTS_STAGING_STAGE, true)
+}
+
+String getGitTagName() {
+ return params.GIT_TAG_NAME ?: getReleaseProperty('git.tag.name')
+}
\ No newline at end of file
diff --git a/.ci/jenkins/project/Jenkinsfile.setup-branch
b/.ci/jenkins/project/Jenkinsfile.setup-branch
new file mode 100644
index 00000000000..4a6a18c46bc
--- /dev/null
+++ b/.ci/jenkins/project/Jenkinsfile.setup-branch
@@ -0,0 +1,228 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import org.jenkinsci.plugins.workflow.libs.Library
+
+@Library('jenkins-pipeline-shared-libraries')_
+
+// Map of executed jobs
+// See
https://javadoc.jenkins.io/plugin/workflow-support/org/jenkinsci/plugins/workflow/support/steps/build/RunWrapper.html
+// for more options on built job entity
+JOBS = [:]
+
+FAILED_STAGES = [:]
+UNSTABLE_STAGES = [:]
+
+pipeline {
+ agent {
+ label util.avoidFaultyNodes('ubuntu')
+ }
+
+ options {
+ timeout(time: 360, unit: 'MINUTES')
+ }
+
+ environment {
+ DROOLS_CI_EMAIL = credentials("${JENKINS_EMAIL_CREDS_ID}")
+
+ // Use branch name in nightly tag as we may have parallel main and
release branch builds
+ NIGHTLY_TAG = """${getBuildBranch()}-${sh(
+ returnStdout: true,
+ script: 'date -u "+%Y-%m-%d"'
+ ).trim()}"""
+}
+
+ stages {
+ stage('Initialize') {
+ steps {
+ script {
+ echo "nightly tag is ${env.NIGHTLY_TAG}"
+
+ currentBuild.displayName = env.NIGHTLY_TAG
+ }
+ }
+ }
+
+ stage('Init Drools') {
+ steps {
+ script {
+ def buildParams = getDefaultBuildParams()
+ addDroolsVersionParam(buildParams)
+ buildJob('drools', buildParams)
+ }
+ }
+ post {
+ failure {
+ addFailedStage('drools')
+ }
+ }
+ }
+
+ // Commented as not migrated for now
+ // stage('Init KIE jpmml integration') {
+ // steps {
+ // script {
+ // def buildParams = getDefaultBuildParams()
+ // addDroolsVersionParam(buildParams)
+ // buildJob('kie-jpmml-integration', buildParams)
+ // }
+ // }
+ // post {
+ // failure {
+ // addFailedStage('kie-jpmml-integration')
+ // }
+ // }
+ // }
+
+ // Launch the nightly to deploy all artifacts from the branch
+ stage('Launch the nightly') {
+ when {
+ expression { return params.DEPLOY }
+ }
+ steps {
+ script {
+ def buildParams = getDefaultBuildParams()
+ addBooleanParam(buildParams, 'SKIP_TESTS', true)
+ build(job: '../nightly/0-nightly', wait: false,
parameters: buildParams, propagate: false)
+ }
+ }
+ post {
+ failure {
+ addFailedStage('nightly')
+ }
+ }
+ }
+
+ // Launch the weekly to deploy all artifacts from the branch
+ stage('Launch the weekly') {
+ when {
+ expression { return params.DEPLOY }
+ }
+ steps {
+ script {
+ def buildParams = getDefaultBuildParams()
+ addBooleanParam(buildParams, 'SKIP_TESTS', true)
+ build(job: '../other/0-weekly', wait: false, parameters:
buildParams, propagate: false)
+ }
+ }
+ post {
+ failure {
+ addFailedStage('weekly')
+ }
+ }
+ }
+ }
+ post {
+ unsuccessful {
+ sendPipelineErrorNotification()
+ }
+ }
+}
+
+def buildJob(String jobName, List buildParams, String jobKey = jobName,
boolean waitForJob = true) {
+ echo "[${jobKey}] Build ${jobName} with params ${buildParams}"
+
+ def job = build(job: "${jobName}", wait: waitForJob, parameters:
buildParams, propagate: false)
+ JOBS[jobKey] = job
+
+ // Set Unstable if job did not succeed
+ if (waitForJob && !isJobSucceeded(jobKey)) {
+ addUnstableStage(jobKey)
+ unstable("Job ${jobName} finished with result ${job.result}")
+ }
+ return job
+}
+
+def getJob(String jobKey) {
+ return JOBS[jobKey]
+}
+
+String getJobUrl(String jobKey) {
+ echo "getJobUrl for ${jobKey}"
+ return getJob(jobKey)?.absoluteUrl ?: ''
+}
+
+boolean isJobSucceeded(String jobKey) {
+ return getJob(jobKey)?.result == 'SUCCESS'
+}
+
+void addFailedStage(String jobKey = '') {
+ FAILED_STAGES.put("${STAGE_NAME}", jobKey)
+}
+void addUnstableStage(String jobKey = '') {
+ UNSTABLE_STAGES.put("${STAGE_NAME}", jobKey)
+}
+
+void sendPipelineErrorNotification() {
+ String bodyMsg = "Kogito setup branch job #${BUILD_NUMBER} was:
${currentBuild.currentResult}"
+
+ if (FAILED_STAGES.size()) {
+ bodyMsg += '\nFailed stages: \n- '
+ bodyMsg += FAILED_STAGES.collect { "${it.key} =>
${getJobUrl(it.value)}" }.join('\n- ')
+ }
+ bodyMsg += '\n'
+ if (UNSTABLE_STAGES.size()) {
+ bodyMsg += '\nUnstable stages: \n- '
+ bodyMsg += UNSTABLE_STAGES.collect { "${it.key} =>
${getJobUrl(it.value)}" }.join('\n- ')
+ }
+ bodyMsg += '\n'
+ bodyMsg += "\nPlease look here: ${BUILD_URL}"
+ emailext body: bodyMsg, subject: "[${getBuildBranch()}][d] Setup branch",
+ to: env.DROOLS_CI_EMAIL
+}
+
+List getDefaultBuildParams() {
+ List buildParams = []
+ addStringParam(buildParams, 'DISPLAY_NAME', "${env.NIGHTLY_TAG}")
+ addBooleanParam(buildParams, 'SEND_NOTIFICATION', true)
+
+ return buildParams
+}
+
+void addDroolsVersionParam(buildParams) {
+ addStringParam(buildParams, 'DROOLS_VERSION', getDroolsVersion())
+}
+
+void addStringParam(List params, String key, String value) {
+ params.add(string(name: key, value: value))
+}
+
+void addBooleanParam(List params, String key, boolean value) {
+ params.add(booleanParam(name: key, value: value))
+}
+
+String getBuildBranch() {
+ return env.GIT_BRANCH_NAME
+}
+
+String getDroolsVersion() {
+ return params.DROOLS_VERSION ?:
getVersionFromReleaseBranch(getBuildBranch())
+}
+
+String getVersionFromReleaseBranch(String releaseBranch, int microVersion =
999, String suffix = 'SNAPSHOT') {
+ String [] versionSplit = releaseBranch.split("\\.")
+ if (versionSplit.length == 3
+ && versionSplit[0].isNumber()
+ && versionSplit[1].isNumber()
+ && versionSplit[2] == 'x') {
+ return "${versionSplit[0]}.${versionSplit[1]}.${microVersion}${suffix
? '-' + suffix : ''}"
+ } else {
+ error 'Cannot parse given branch as a release branch, aka [M].[m].x
...'
+ }
+}
\ No newline at end of file
diff --git a/.ci/jenkins/project/Jenkinsfile.weekly
b/.ci/jenkins/project/Jenkinsfile.weekly
new file mode 100644
index 00000000000..2a7e3322bd5
--- /dev/null
+++ b/.ci/jenkins/project/Jenkinsfile.weekly
@@ -0,0 +1,183 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import org.jenkinsci.plugins.workflow.libs.Library
+
+@Library('jenkins-pipeline-shared-libraries')_
+
+// Deploy jobs
+DROOLS_DEPLOY = 'drools.weekly-deploy'
+// KIE_JPMML_INTEGRATION_DEPLOY = 'kie-jpmml-integration.build-and-deploy' //
Commented as not migrated for now
+
+// Map of executed jobs
+// See
https://javadoc.jenkins.io/plugin/workflow-support/org/jenkinsci/plugins/workflow/support/steps/build/RunWrapper.html
+// for more options on built job entity
+JOBS = [:]
+
+FAILED_STAGES = [:]
+UNSTABLE_STAGES = [:]
+
+// Should be multibranch pipeline
+pipeline {
+ agent {
+ label util.avoidFaultyNodes('ubuntu')
+ }
+
+ options {
+ timeout(time: 360, unit: 'MINUTES')
+ }
+
+ environment {
+ DROOLS_CI_EMAIL = credentials("${JENKINS_EMAIL_CREDS_ID}")
+
+ // Use branch name in weekly tag as we may have parallel main and
release branch builds
+ WEEKLY_TAG = """${getBuildBranch()}-${sh(
+ returnStdout: true,
+ script: 'date -u "+%Y-%m-%d"'
+ ).trim()}"""
+ }
+
+ stages {
+ stage('Initialize') {
+ steps {
+ script {
+ echo "weekly tag is ${env.WEEKLY_TAG}"
+
+ currentBuild.displayName = env.WEEKLY_TAG
+ }
+ }
+ }
+ stage('Build & Deploy Drools') {
+ steps {
+ script {
+ def buildParams = getDefaultBuildParams()
+ addSkipTestsParam(buildParams)
+ addSkipIntegrationTestsParam(buildParams)
+
+ buildJob(DROOLS_DEPLOY, buildParams)
+ }
+ }
+ post {
+ failure {
+ addFailedStage(DROOLS_DEPLOY)
+ }
+ }
+ }
+ }
+ post {
+ unsuccessful {
+ sendPipelineErrorNotification()
+ }
+ }
+}
+
+def buildJob(String jobName, List buildParams, String jobKey = jobName) {
+ echo "[${jobKey}] Build ${jobName} with params ${buildParams}"
+
+ def job = build(job: "${jobName}", wait: true, parameters: buildParams,
propagate: false)
+ JOBS[jobKey] = job
+
+ // Set Unstable if job did not succeed
+ if (!isJobSucceeded(jobKey)) {
+ addUnstableStage(jobKey)
+ unstable("Job ${jobName} finished with result ${job.result}")
+ }
+ return job
+}
+
+def getJob(String jobKey) {
+ return JOBS[jobKey]
+}
+
+String getJobUrl(String jobKey) {
+ echo "getJobUrl for ${jobKey}"
+ return getJob(jobKey)?.absoluteUrl ?: ''
+}
+
+boolean isJobSucceeded(String jobKey) {
+ return getJob(jobKey)?.result == 'SUCCESS'
+}
+
+void addFailedStage(String jobKey = '') {
+ FAILED_STAGES.put("${env.STAGE_NAME}", jobKey)
+}
+void addUnstableStage(String jobKey = '') {
+ UNSTABLE_STAGES.put("${env.STAGE_NAME}", jobKey)
+}
+
+void sendPipelineErrorNotification() {
+ String bodyMsg = "Kogito weekly job #${env.BUILD_NUMBER} was:
${currentBuild.currentResult}"
+
+ paramsStr = ''
+ if (params.SKIP_TESTS) {
+ paramsStr += '\n- Tests skipped'
+ }
+ bodyMsg += paramsStr ? "\n\nConfiguration:${paramsStr}" : '\n'
+
+ if (FAILED_STAGES.size() > 0) {
+ bodyMsg += '\nFailed stages: \n- '
+ bodyMsg += FAILED_STAGES.collect { "${it.key} =>
${getJobUrl(it.value)}" }.join('\n- ')
+ }
+ bodyMsg += '\n'
+ if (UNSTABLE_STAGES.size() > 0) {
+ bodyMsg += '\nUnstable stages: \n- '
+ bodyMsg += UNSTABLE_STAGES.collect { "${it.key} =>
${getJobUrl(it.value)}" }.join('\n- ')
+ }
+ bodyMsg += '\n'
+ bodyMsg += "\nPlease look here: ${env.BUILD_URL}"
+ emailext body: bodyMsg, subject: "[${getBuildBranch()}][d] Full Pipeline",
+ to: env.DROOLS_CI_EMAIL
+}
+
+List getDefaultBuildParams() {
+ List params = []
+ addStringParam(params, 'DISPLAY_NAME', "${env.WEEKLY_TAG}")
+ addStringParam(params, 'GIT_CHECKOUT_DATETIME', getCheckoutDatetime())
+ addBooleanParam(params, 'SEND_NOTIFICATION', true)
+
+ return params
+}
+
+void addSkipTestsParam(buildParams) {
+ addBooleanParam(buildParams, 'SKIP_TESTS', params.SKIP_TESTS)
+}
+
+void addSkipIntegrationTestsParam(buildParams) {
+ addBooleanParam(buildParams, 'SKIP_INTEGRATION_TESTS', params.SKIP_TESTS)
+}
+
+void addStringParam(List buildParams, String key, String value) {
+ buildParams.add(string(name: key, value: value))
+}
+
+void addBooleanParam(List buildParams, String key, boolean value) {
+ buildParams.add(booleanParam(name: key, value: value))
+}
+
+String getBuildBranch() {
+ return env.GIT_BRANCH_NAME
+}
+
+String getCurrentDate() {
+ return sh(returnStdout: true, script: 'date -u "+%Y-%m-%d"').trim()
+}
+
+String getCheckoutDatetime() {
+ return getCurrentDate() + ' 02:00' // Cut-off 02:00AM
+}
\ No newline at end of file
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]