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]

Reply via email to