This is an automated email from the ASF dual-hosted git repository.

Kusuma04-dev pushed a commit to branch test_10.3.x
in repository https://gitbox.apache.org/repos/asf/incubator-kie-tools.git

commit d865c8d49189c620eff8c4fa1f923217b251e87d
Author: Kusuma <[email protected]>
AuthorDate: Mon Oct 12 19:52:31 2026 +0530

    tset
---
 .ci/incubator-kie-tools-ci-build.Dockerfile        |   4 +-
 .ci/jenkins/Jenkinsfile.103xplus.release-candidate | 305 ++++++++
 .ci/jenkins/Jenkinsfile.103xplus.release-publish   | 249 +++++++
 .ci/jenkins/shared-scripts/pipelineVars.groovy     |   1 +
 scripts/release/CHROME_STORE_SETUP.md              | 190 +++++
 scripts/release/README.md                          | 160 +++++
 scripts/release/create-source-tarball.sh           |  93 +++
 scripts/release/release-all.sh                     | 773 +++++++++++++++++++++
 8 files changed, 1773 insertions(+), 2 deletions(-)

diff --git a/.ci/incubator-kie-tools-ci-build.Dockerfile 
b/.ci/incubator-kie-tools-ci-build.Dockerfile
index 7dcb5d47329..730758348a8 100644
--- a/.ci/incubator-kie-tools-ci-build.Dockerfile
+++ b/.ci/incubator-kie-tools-ci-build.Dockerfile
@@ -100,8 +100,8 @@ RUN curl -s "https://get.sdkman.io"; | bash && \
     sdk flush
 
 # Golang setup
-RUN wget https://go.dev/dl/go1.26.7.linux-amd64.tar.gz -P /tmp && \
-    sudo tar xzf /tmp/go1.26.7.linux-amd64.tar.gz -C /opt && rm 
/tmp/go1.26.7.linux-amd64.tar.gz && \
+RUN wget https://go.dev/dl/go1.26.5.linux-amd64.tar.gz -P /tmp && \
+    sudo tar xzf /tmp/go1.26.5.linux-amd64.tar.gz -C /opt && rm 
/tmp/go1.26.5.linux-amd64.tar.gz && \
     echo 'export GOPATH=${HOME}/go' | sudo tee /etc/profile.d/go.sh && \
     echo 'export PATH=${PATH}:/opt/go/bin:${GOPATH}/bin' | sudo tee -a 
/etc/profile.d/go.sh && \
     echo "source /etc/profile.d/go.sh" >> $HOME/.bashrc && \
diff --git a/.ci/jenkins/Jenkinsfile.103xplus.release-candidate 
b/.ci/jenkins/Jenkinsfile.103xplus.release-candidate
new file mode 100644
index 00000000000..c2281d53db7
--- /dev/null
+++ b/.ci/jenkins/Jenkinsfile.103xplus.release-candidate
@@ -0,0 +1,305 @@
+/*
+ * 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.
+ */
+
+@Library('jenkins-pipeline-shared-libraries')_
+
+// PHASE 1: Create Release Candidate for Apache Voting
+// This job builds artifacts, signs them, and publishes to Apache SVN for 
community vote
+// Does NOT publish to npm, VSCode Marketplace, or Chrome Web Store
+//
+// NOTE: kogito-data-index-ephemeral is NOT included in this pipeline because 
the
+// packages/kogito-data-index-ephemeral-image package no longer exists in this 
repo.
+// Its presence in older Jenkinsfiles (Jenkinsfile.release-candidate RUNNERS 
list and
+// release-jobs/Jenkinsfile.kogito-data-index-ephemeral-image) is a historical 
artifact
+// from pre-10.3 automation and can be cleaned up in a follow-up PR.
+
+pipeline {
+    agent {
+        docker {
+            image 'docker.io/apache/incubator-kie-tools-ci-build:main'
+            args '--shm-size=2g --privileged --group-add docker'
+            label util.avoidFaultyNodes()
+        }
+    }
+
+    options {
+        timeout(time: 480, unit: 'MINUTES')
+    }
+
+    parameters {
+        string(
+            name: 'RELEASE_VERSION',
+            description: 'Release version (e.g., 1.0.0)',
+            defaultValue: '0.0.0'
+        )
+        string(
+            name: 'RELEASE_CANDIDATE_VERSION',
+            description: 'Release candidate version (e.g., 10.3.0-rc1)',
+            defaultValue: '0.0.0-rc1'
+        )
+        string(
+            name: 'BASE_REF',
+            description: 'Git branch or tag to release from',
+            defaultValue: 'main'
+        )
+    }
+
+    environment {
+        KIE_TOOLS_BUILD__runLinters = 'false'
+        KIE_TOOLS_BUILD__runTests = 'false'
+        KIE_TOOLS_BUILD__runEndToEndTests = 'false'
+        KIE_TOOLS_BUILD__buildContainerImages = 'true'
+
+        CHROME_EXTENSION__routerTargetOrigin = 'https://apache.github.io'
+        CHROME_EXTENSION__routerRelativePath = 
"incubator-kie-kogito-online/chrome-extension/${params.RELEASE_VERSION}"
+        CHROME_EXTENSION__manifestFile = 'manifest.prod.json'
+        CHROME_EXTENSION__onlineEditorUrl = 
'https://apache.github.io/incubator-kie-kogito-online'
+
+        ONLINE_EDITOR__corsProxyUrl = 
'https://cors-proxy-kie-sandbox.rhba-0ad6762cc85bcef5745bb684498c2436-0000.us-south.containers.appdomain.cloud'
+        ONLINE_EDITOR__buildInfo = "${params.RELEASE_VERSION}"
+        ONLINE_EDITOR__extendedServicesCompatibleVersion = 
"${params.RELEASE_VERSION}"
+        ONLINE_EDITOR__devDeploymentBaseImageRegistry = 'docker.io'
+        ONLINE_EDITOR__devDeploymentBaseImageAccount = 'apache'
+        ONLINE_EDITOR__devDeploymentBaseImageName = 
'incubator-kie-sandbox-dev-deployment-base'
+        ONLINE_EDITOR__devDeploymentBaseImageTag = "${params.RELEASE_VERSION}"
+        ONLINE_EDITOR__devDeploymentDmnFormWebappImageRegistry = 'docker.io'
+        ONLINE_EDITOR__devDeploymentDmnFormWebappImageAccount = 'apache'
+        ONLINE_EDITOR__devDeploymentDmnFormWebappImageName = 
'incubator-kie-sandbox-dev-deployment-dmn-form-webapp'
+        ONLINE_EDITOR__devDeploymentDmnFormWebappImageTag = 
"${params.RELEASE_VERSION}"
+        ONLINE_EDITOR__devDeploymentQuarkusBlankAppImageRegistry = 'docker.io'
+        ONLINE_EDITOR__devDeploymentQuarkusBlankAppImageAccount = 'apache'
+        ONLINE_EDITOR__devDeploymentQuarkusBlankAppImageName = 
'incubator-kie-sandbox-dev-deployment-quarkus-blank-app'
+        ONLINE_EDITOR__devDeploymentQuarkusBlankAppImageTag = 
"${params.RELEASE_VERSION}"
+    }
+
+    stages {
+        stage('Load local shared scripts') {
+            steps {
+                script {
+                    pipelineVars = load 
'.ci/jenkins/shared-scripts/pipelineVars.groovy'
+                    buildUtils = load 
'.ci/jenkins/shared-scripts/buildUtils.groovy'
+                    githubUtils = load 
'.ci/jenkins/shared-scripts/githubUtils.groovy'
+                    releaseUtils = load 
'.ci/jenkins/shared-scripts/releaseUtils.groovy'
+                }
+            }
+        }
+
+        stage('Start required services') {
+            steps {
+                script {
+                    buildUtils.startRequiredServices()
+                }
+            }
+        }
+
+        stage('Clean workspace') {
+            steps {
+                cleanWs(deleteDirs: true, disableDeferredWipeout: true)
+            }
+        }
+
+        stage('Checkout kie-tools') {
+            steps {
+                dir('kie-tools') {
+                    script {
+                        githubUtils.checkoutRepo(
+                            
"http://github.com/${pipelineVars.githubRepositorySlug}.git";,
+                            "${params.BASE_REF}",
+                            "${pipelineVars.kieToolsBotGithubCredentialsId}"
+                        )
+                    }
+                }
+            }
+        }
+
+        stage('Setup PNPM') {
+            steps {
+                dir('kie-tools') {
+                    script {
+                        
buildUtils.setupPnpm("${pipelineVars.mavenSettingsReleaseConfigFileId}")
+                    }
+                }
+            }
+        }
+
+        stage('Setup Git repository') {
+            steps {
+                dir('kie-tools') {
+                    script {
+                        sh """#!/bin/bash -el
+                        git config user.email [email protected]
+                        git config user.name asf-ci-kie
+                        git checkout ${params.BASE_REF}
+                        """.trim()
+                    }
+                }
+            }
+        }
+
+        stage('Bootstrap') {
+            steps {
+                dir('kie-tools') {
+                    sh '''#!/bin/bash -el
+                    pnpm bootstrap
+                    '''
+                }
+            }
+        }
+
+        stage('Update versions') {
+            steps {
+                dir('kie-tools') {
+                    sh """#!/bin/bash -el
+                    pnpm update-version-to ${params.RELEASE_VERSION}
+                    pnpm update-kogito-version-to --maven 
${params.RELEASE_VERSION}
+                    pnpm update-stream-name-to ${params.RELEASE_VERSION}
+                    """
+                }
+            }
+        }
+
+        stage('Commit changes') {
+            steps {
+                dir('kie-tools') {
+                    script {
+                        sh """#!/bin/bash -el
+                        git add .
+                        git commit --allow-empty -am "Apache KIE 
${params.RELEASE_VERSION} release candidate ${params.RELEASE_CANDIDATE_VERSION}"
+                        """.trim()
+                    }
+                }
+            }
+        }
+
+        stage('Check release version against package.json') {
+            steps {
+                dir('kie-tools') {
+                    script {
+                        def packageVersion = sh(
+                            returnStdout: true,
+                            script: "#!/bin/bash -el \n node -p 
\"require('./package.json').version\""
+                        ).trim()
+                        if (packageVersion != params.RELEASE_VERSION) {
+                            error("Version mismatch! package.json has 
${packageVersion} but RELEASE_VERSION is ${params.RELEASE_VERSION}")
+                        }
+                    }
+                }
+            }
+        }
+
+        stage('Create and push RC tag') {
+            steps {
+                dir('kie-tools') {
+                    script {
+                        
githubUtils.createTag("${params.RELEASE_CANDIDATE_VERSION}")
+                        githubUtils.pushObject('origin', 
"${params.RELEASE_CANDIDATE_VERSION}", 
"${pipelineVars.asfGithubPushCredentialsId}")
+                        sleep(time: 1, unit: 'MINUTES')
+                    }
+                }
+            }
+        }
+
+        stage('Build Release Candidate Artifacts') {
+            steps {
+                dir('kie-tools') {
+                    script {
+                        echo "Building release candidate artifacts..."
+                        echo "Version: ${params.RELEASE_VERSION}"
+                        echo "RC: ${params.RELEASE_CANDIDATE_VERSION}"
+
+                        // Build artifacts WITHOUT publishing (no --publish 
flag)
+                        // The --rc flag creates artifacts for Apache SVN
+                        sh """#!/bin/bash -el
+                        ./scripts/release/release-all.sh 
${params.RELEASE_VERSION} --rc --git-ref ${params.RELEASE_CANDIDATE_VERSION}
+                        """
+                    }
+                }
+            }
+        }
+
+        stage('Sign Release Candidate Artifacts') {
+            steps {
+                dir('kie-tools/release-artifacts') {
+                    script {
+                        
releaseUtils.setupSigningKey("${pipelineVars.asfReleaseGPGKeyCredentialsId}")
+                        
+                        sh """#!/bin/bash -el
+                        echo "Signing all artifacts..."
+                        for file in *.zip *.vsix *.tar.gz; do
+                            if [ -f "\$file" ]; then
+                                echo "Signing \$file"
+                                gpg --no-tty --batch --sign --pinentry-mode 
loopback --output "\$file.asc" --detach-sig "\$file"
+                                shasum -a 512 "\$file" > "\$file.sha512"
+                            fi
+                        done
+
+                        echo "Artifacts signed:"
+                        ls -lh
+                        """
+                    }
+                }
+            }
+        }
+
+        stage('Publish to Apache SVN (for voting)') {
+            steps {
+                dir('kie-tools/release-artifacts') {
+                    script {
+                        echo "Publishing to Apache SVN staging repository..."
+                        echo "Repository: 
${pipelineVars.asfReleaseStagingRepository}"
+                        echo "RC Version: ${params.RELEASE_CANDIDATE_VERSION}"
+                        
+                        releaseUtils.publishArtifacts(
+                            "${WORKSPACE}/kie-tools/release-artifacts",
+                            "${pipelineVars.asfReleaseStagingRepository}",
+                            "${params.RELEASE_CANDIDATE_VERSION}",
+                            "${pipelineVars.asfReleaseSVNStagingCredentialsId}"
+                        )
+                        
+                        echo "✅ Release candidate published to:"
+                        echo "   
${pipelineVars.asfReleaseStagingRepository}/${params.RELEASE_CANDIDATE_VERSION}/"
+                    }
+                }
+            }
+        }
+    }
+
+    post {
+        success {
+            echo "=========================================="
+            echo "✅ Release Candidate Created Successfully!"
+            echo "=========================================="
+            echo "Version: ${params.RELEASE_VERSION}"
+            echo "RC: ${params.RELEASE_CANDIDATE_VERSION}"
+            echo ""
+            echo "Artifacts published to:"
+            echo 
"${pipelineVars.asfReleaseStagingRepository}/${params.RELEASE_CANDIDATE_VERSION}/"
+            echo ""
+            echo "Next steps:"
+            echo "1. Start a vote thread on [email protected]"
+            echo "2. Wait for vote to pass (72 hours, 3 +1 votes)"
+            echo "3. Run Jenkinsfile.103xplus.release-publish to publish to 
registries"
+            echo "=========================================="
+        }
+        failure {
+            echo "❌ Release candidate creation failed!"
+        }
+        always {
+            cleanWs(deleteDirs: true)
+        }
+    }
+}
\ No newline at end of file
diff --git a/.ci/jenkins/Jenkinsfile.103xplus.release-publish 
b/.ci/jenkins/Jenkinsfile.103xplus.release-publish
new file mode 100644
index 00000000000..3b992d0eb1b
--- /dev/null
+++ b/.ci/jenkins/Jenkinsfile.103xplus.release-publish
@@ -0,0 +1,249 @@
+/*
+ * 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.
+ */
+
+@Library('jenkins-pipeline-shared-libraries')_
+
+// PHASE 2: Publish Release After Vote Passes
+// This job publishes the approved release candidate to public registries
+// Publishes to: npm, VSCode Marketplace, Chrome Web Store, GitHub Releases
+//
+// NOTE: kogito-data-index-ephemeral is NOT included in this pipeline because 
the
+// packages/kogito-data-index-ephemeral-image package no longer exists in this 
repo.
+// Its presence in older Jenkinsfiles (Jenkinsfile.release-candidate RUNNERS 
list and
+// release-jobs/Jenkinsfile.kogito-data-index-ephemeral-image) is a historical 
artifact
+// from pre-10.3 automation and can be cleaned up in a follow-up PR.
+
+pipeline {
+    agent {
+        docker {
+            image 'docker.io/apache/incubator-kie-tools-ci-build:main'
+            args '--shm-size=2g --privileged --group-add docker'
+            label util.avoidFaultyNodes()
+        }
+    }
+
+    options {
+        timeout(time: 480, unit: 'MINUTES')
+    }
+
+    parameters {
+        string(
+            name: 'RELEASE_VERSION',
+            description: 'Release version (e.g., 1.0.0) - must match the voted 
RC',
+            defaultValue: '0.0.0'
+        )
+        string(
+            name: 'BASE_REF',
+            description: 'Git tag to release from (should be the RC tag)',
+            defaultValue: '0.0.0-rc1'
+        )
+        string(
+            name: 'GITHUB_RELEASE_TAG',
+            description: 'GitHub release tag (for uploading assets to the 
GitHub Release)',
+            defaultValue: ''
+        )
+    }
+
+    environment {
+        KIE_TOOLS_BUILD__runLinters = 'false'
+        KIE_TOOLS_BUILD__runTests = 'false'
+        KIE_TOOLS_BUILD__runEndToEndTests = 'false'
+        KIE_TOOLS_BUILD__buildContainerImages = 'true'
+
+        CHROME_EXTENSION__routerTargetOrigin = 'https://apache.github.io'
+        CHROME_EXTENSION__routerRelativePath = 
"incubator-kie-kogito-online/chrome-extension/${params.RELEASE_VERSION}"
+        CHROME_EXTENSION__manifestFile = 'manifest.prod.json'
+        CHROME_EXTENSION__onlineEditorUrl = 
'https://apache.github.io/incubator-kie-kogito-online'
+
+        ONLINE_EDITOR__corsProxyUrl = 
'https://cors-proxy-kie-sandbox.rhba-0ad6762cc85bcef5745bb684498c2436-0000.us-south.containers.appdomain.cloud'
+        ONLINE_EDITOR__buildInfo = "${params.RELEASE_VERSION}"
+        ONLINE_EDITOR__extendedServicesCompatibleVersion = 
"${params.RELEASE_VERSION}"
+        ONLINE_EDITOR__devDeploymentBaseImageRegistry = 'docker.io'
+        ONLINE_EDITOR__devDeploymentBaseImageAccount = 'apache'
+        ONLINE_EDITOR__devDeploymentBaseImageName = 
'incubator-kie-sandbox-dev-deployment-base'
+        ONLINE_EDITOR__devDeploymentBaseImageTag = "${params.RELEASE_VERSION}"
+        ONLINE_EDITOR__devDeploymentDmnFormWebappImageRegistry = 'docker.io'
+        ONLINE_EDITOR__devDeploymentDmnFormWebappImageAccount = 'apache'
+        ONLINE_EDITOR__devDeploymentDmnFormWebappImageName = 
'incubator-kie-sandbox-dev-deployment-dmn-form-webapp'
+        ONLINE_EDITOR__devDeploymentDmnFormWebappImageTag = 
"${params.RELEASE_VERSION}"
+        ONLINE_EDITOR__devDeploymentQuarkusBlankAppImageRegistry = 'docker.io'
+        ONLINE_EDITOR__devDeploymentQuarkusBlankAppImageAccount = 'apache'
+        ONLINE_EDITOR__devDeploymentQuarkusBlankAppImageName = 
'incubator-kie-sandbox-dev-deployment-quarkus-blank-app'
+        ONLINE_EDITOR__devDeploymentQuarkusBlankAppImageTag = 
"${params.RELEASE_VERSION}"
+
+        DOCKER_CONFIG = "${WORKSPACE}/.docker"
+        HELM_REGISTRY = 'docker.io/apache'
+    }
+
+    stages {
+        stage('Load local shared scripts') {
+            steps {
+                script {
+                    pipelineVars = load 
'.ci/jenkins/shared-scripts/pipelineVars.groovy'
+                    buildUtils = load 
'.ci/jenkins/shared-scripts/buildUtils.groovy'
+                    githubUtils = load 
'.ci/jenkins/shared-scripts/githubUtils.groovy'
+                }
+            }
+        }
+
+        stage('Start required services') {
+            steps {
+                script {
+                    buildUtils.startRequiredServices()
+                }
+            }
+        }
+
+        stage('Clean workspace') {
+            steps {
+                cleanWs(deleteDirs: true, disableDeferredWipeout: true)
+            }
+        }
+
+        stage('Checkout kie-tools') {
+            steps {
+                dir('kie-tools') {
+                    script {
+                        githubUtils.checkoutRepo(
+                            
"http://github.com/${pipelineVars.githubRepositorySlug}.git";,
+                            "${params.BASE_REF}",
+                            "${pipelineVars.kieToolsBotGithubCredentialsId}"
+                        )
+                    }
+                }
+            }
+        }
+
+        stage('Verify version') {
+            steps {
+                dir('kie-tools') {
+                    script {
+                        def packageVersion = sh(
+                            returnStdout: true,
+                            script: "node -p 
\"require('./package.json').version\""
+                        ).trim()
+                        
+                        if (packageVersion != params.RELEASE_VERSION) {
+                            error("Version mismatch! package.json has 
${packageVersion} but RELEASE_VERSION is ${params.RELEASE_VERSION}")
+                        }
+                        
+                        echo "✅ Version verified: ${packageVersion}"
+                    }
+                }
+            }
+        }
+
+        stage('Setup PNPM') {
+            steps {
+                dir('kie-tools') {
+                    script {
+                        
buildUtils.setupPnpm("${pipelineVars.mavenSettingsReleaseConfigFileId}")
+                    }
+                }
+            }
+        }
+
+        stage('Bootstrap') {
+            steps {
+                dir('kie-tools') {
+                    sh '''#!/bin/bash -el
+                    pnpm bootstrap
+                    '''
+                }
+            }
+        }
+
+        stage('Build and Publish to Registries') {
+            steps {
+                dir('kie-tools') {
+                    script {
+                        echo "Publishing release to public registries..."
+                        echo "Version: ${params.RELEASE_VERSION}"
+
+                        withCredentials([
+                            string(credentialsId: 
"${pipelineVars.npmTokenCredentialsId}",                  variable: 
'NPM_TOKEN'),
+                            string(credentialsId: 
"${pipelineVars.vscePatCredentialsId}",                   variable: 'VSCE_PAT'),
+                            usernamePassword(credentialsId: 
"${pipelineVars.chromeStoreCredentialsId}",
+                                             usernameVariable: 
'CHROME_CLIENT_ID',
+                                             passwordVariable: 
'CHROME_CLIENT_SECRET'),
+                            string(credentialsId: 
"${pipelineVars.chromeStoreRefreshTokenCredentialsId}",   variable: 
'CHROME_REFRESH_TOKEN'),
+                            string(credentialsId: 
"${pipelineVars.chromeExtensionIdCredentialsId}",         variable: 
'CHROME_KIE_EDITORS_EXTENSION_ID'),
+                            string(credentialsId: 
"${pipelineVars.dockerHubUserCredentialsId}",             variable: 
'DOCKER_USERNAME'),
+                            string(credentialsId: 
"${pipelineVars.dockerHubTokenCredentialsId}",            variable: 
'DOCKER_PASSWORD'),
+                            // Helm charts use the same Docker Hub credentials 
as the old helm jobs
+                            string(credentialsId: 
"${pipelineVars.dockerHubUserCredentialsId}",             variable: 
'HELM_USERNAME'),
+                            string(credentialsId: 
"${pipelineVars.dockerHubTokenCredentialsId}",            variable: 
'HELM_PASSWORD'),
+                            string(credentialsId: 
"${pipelineVars.kieToolsBotGithubTokenCredentialsId}",    variable: 
'GITHUB_TOKEN')
+                        ]) {
+                            script {
+                                def uploadUrlFlag = ''
+                                if (params.GITHUB_RELEASE_TAG != '') {
+                                    def releaseJson = sh(
+                                        returnStdout: true,
+                                        script: """
+                                            curl -sSf -H "Authorization: token 
\${GITHUB_TOKEN}" \
+                                                
"https://api.github.com/repos/${pipelineVars.githubRepositorySlug}/releases/tags/${params.GITHUB_RELEASE_TAG}";
+                                        """
+                                    ).trim()
+                                    def releaseInfo = readJSON text: 
releaseJson
+                                    uploadUrlFlag = "--upload-url 
'${releaseInfo.upload_url.replaceAll('\\{.*\\}', '')}'"
+                                }
+
+                                sh """#!/bin/bash -el
+                                ./scripts/release/release-all.sh 
${params.RELEASE_VERSION} --publish ${uploadUrlFlag}
+                                """
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    post {
+        success {
+            echo "=========================================="
+            echo "✅ Release Published Successfully!"
+            echo "=========================================="
+            echo "Version: ${params.RELEASE_VERSION}"
+            echo ""
+            echo "Published to:"
+            echo "  ✅ npm registry"
+            echo "  ✅ VSCode Marketplace"
+            echo "  ✅ Chrome Web Store"
+            echo "  ✅ Container registry"
+            echo "  ✅ Helm registry"
+            echo "  ✅ GitHub Pages"
+            if (params.GITHUB_RELEASE_TAG != '') {
+                echo "  ✅ GitHub Release: ${params.GITHUB_RELEASE_TAG}"
+            }
+            echo ""
+            echo "Next steps:"
+            echo "1. Verify packages are available in registries"
+            echo "2. Move artifacts from dev/ to release/ in Apache SVN"
+            echo "3. Announce the release"
+            echo "=========================================="
+        }
+        failure {
+            echo "❌ Release publishing failed!"
+            echo "Check logs above for details"
+        }
+        always {
+            cleanWs(deleteDirs: true)
+        }
+    }
+}
\ No newline at end of file
diff --git a/.ci/jenkins/shared-scripts/pipelineVars.groovy 
b/.ci/jenkins/shared-scripts/pipelineVars.groovy
index d83f6327b78..71171345877 100644
--- a/.ci/jenkins/shared-scripts/pipelineVars.groovy
+++ b/.ci/jenkins/shared-scripts/pipelineVars.groovy
@@ -22,6 +22,7 @@ class PipelineVars implements Serializable {
     String quayPushCredentialsId = 'quay-io-kie-tools-token'
     String dockerHubUserCredentialsId = 'DOCKERHUB_USER'
     String dockerHubTokenCredentialsId = 'DOCKERHUB_TOKEN'
+    String vscePatCredentialsId = 'kie-tools-vsce-pat'
     String openshiftCredentialsId = 'openshift-kie-tools-token'
     String kieToolsBotGithubCredentialsId = 'kie-tools-bot-gh'
     String kieToolsBotGithubTokenCredentialsId = 'kie-tools-bot-gh-token'
diff --git a/scripts/release/CHROME_STORE_SETUP.md 
b/scripts/release/CHROME_STORE_SETUP.md
new file mode 100644
index 00000000000..b9445290e92
--- /dev/null
+++ b/scripts/release/CHROME_STORE_SETUP.md
@@ -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.
+-->
+
+# Chrome Web Store Publishing Setup
+
+## Overview
+
+The `release-all.sh` script publishes Chrome extensions to the Chrome Web 
Store using the Chrome Web Store API.
+
+## Required Credentials
+
+You need 4 environment variables:
+
+### 1. OAuth Credentials
+
+Get these from Google Cloud Console:
+
+1. Go to https://console.cloud.google.com/
+2. Create a project (or use existing)
+3. Enable "Chrome Web Store API"
+4. Create OAuth 2.0 credentials:
+   - Application type: "Web application"
+   - Add authorized redirect URI: `http://localhost`
+5. Note the **Client ID** and **Client Secret**
+
+### 2. Refresh Token
+
+Generate a refresh token:
+
+```bash
+# 1. Get authorization code
+# Open this URL in browser (replace CLIENT_ID):
+https://accounts.google.com/o/oauth2/auth?response_type=code&scope=https://www.googleapis.com/auth/chromewebstore&client_id=YOUR_CLIENT_ID&redirect_uri=http://localhost
+
+# 2. After authorizing, you'll be redirected to:
+# http://localhost/?code=AUTHORIZATION_CODE
+# Copy the AUTHORIZATION_CODE
+
+# 3. Exchange code for refresh token:
+curl -X POST https://oauth2.googleapis.com/token \
+  -d "client_id=YOUR_CLIENT_ID" \
+  -d "client_secret=YOUR_CLIENT_SECRET" \
+  -d "code=AUTHORIZATION_CODE" \
+  -d "grant_type=authorization_code" \
+  -d "redirect_uri=http://localhost";
+
+# Response will include "refresh_token" - save this!
+```
+
+### 3. Extension IDs
+
+Get this from Chrome Web Store Developer Dashboard:
+
+1. Go to https://chrome.google.com/webstore/devconsole
+2. Find the KIE Editors extension
+3. Copy the extension ID from the URL
+
+## Environment Variables
+
+Set these before running the release script with `--publish`:
+
+```bash
+export CHROME_CLIENT_ID="your-client-id.apps.googleusercontent.com"
+export CHROME_CLIENT_SECRET="your-client-secret"
+export CHROME_REFRESH_TOKEN="your-refresh-token"
+export CHROME_KIE_EDITORS_EXTENSION_ID="kie-editors-extension-id"
+```
+
+## Usage
+
+### Test Build (No Publishing)
+
+```bash
+./scripts/release/release-all.sh 10.3.0
+```
+
+### Publish to Chrome Web Store
+
+```bash
+# Set credentials
+export CHROME_CLIENT_ID="..."
+export CHROME_CLIENT_SECRET="..."
+export CHROME_REFRESH_TOKEN="..."
+export CHROME_KIE_EDITORS_EXTENSION_ID="..."
+
+# Publish
+./scripts/release/release-all.sh 10.3.0 --publish
+```
+
+## Jenkins Setup
+
+In Jenkins, credentials are configured in 
`.ci/jenkins/Jenkinsfile.103xplus.release-publish` using:
+
+- `CHROME_CLIENT_ID` / `CHROME_CLIENT_SECRET`: `chromeStoreCredentialsId`
+- `CHROME_REFRESH_TOKEN`: `chromeStoreRefreshTokenCredentialsId`
+- `CHROME_KIE_EDITORS_EXTENSION_ID`: `chromeExtensionIdCredentialsId`
+
+## How It Works
+
+The script:
+
+1. **Gets OAuth Token**: Exchanges refresh token for access token via 
`https://oauth2.googleapis.com/token`
+2. **Uploads Extension**: Uploads the `.zip` file to Chrome Web Store API
+3. **Publishes Extension**: Publishes the uploaded item and validates API 
response status (`OK` or `PUBLISHED_WITH_FRICTION_WARNING`)
+
+## API Endpoints Used
+
+- **Token**: `https://oauth2.googleapis.com/token`
+- **Upload**: 
`https://www.googleapis.com/upload/chromewebstore/v1.1/items/{extensionId}`
+- **Publish**: 
`https://www.googleapis.com/chromewebstore/v1.1/items/{extensionId}/publish`
+
+## Error Handling
+
+The script will:
+
+- ✅ Check for required credentials before starting
+- ✅ Validate upload success before publishing
+- ✅ Show detailed error messages
+- ✅ Exit with error code if anything fails
+
+## Testing
+
+### Test with Dry Run
+
+```bash
+# Build only (safe) — builds Chrome extension without publishing
+./scripts/release/release-all.sh 0.0.0-test
+```
+
+### Test with Test Extension
+
+1. Create a test extension in Chrome Web Store
+2. Get its extension ID
+3. Use test credentials
+4. Publish to test extension
+
+```bash
+export CHROME_CLIENT_ID="test-client-id"
+export CHROME_CLIENT_SECRET="test-secret"
+export CHROME_REFRESH_TOKEN="test-token"
+export CHROME_KIE_EDITORS_EXTENSION_ID="test-extension-id"
+
+./scripts/release/release-all.sh 0.0.0-test --publish
+```
+
+## Troubleshooting
+
+### "Failed to get access token"
+
+- Check CLIENT_ID and CLIENT_SECRET are correct
+- Check REFRESH_TOKEN is valid (they can expire)
+- Regenerate refresh token if needed
+
+### "Upload failed"
+
+- Check extension ID is correct
+- Check you have permission to upload to this extension
+- Check the .zip file is valid
+
+### "Publish status: ITEM_NOT_UPDATABLE"
+
+- Extension might be in review
+- Wait for previous version to be published
+- Check Chrome Web Store dashboard
+
+## Security Notes
+
+- ⚠️ Never commit credentials to git
+- ✅ Use Jenkins credentials manager
+- ✅ Rotate tokens regularly
+- ✅ Use separate credentials for test/production
+
+## References
+
+- [Chrome Web Store API 
Documentation](https://developer.chrome.com/docs/webstore/api_index/)
+- [OAuth 2.0 for Web Server 
Applications](https://developers.google.com/identity/protocols/oauth2/web-server)
diff --git a/scripts/release/README.md b/scripts/release/README.md
new file mode 100644
index 00000000000..1f26431dcf3
--- /dev/null
+++ b/scripts/release/README.md
@@ -0,0 +1,160 @@
+<!--
+   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.
+-->
+
+# Release Scripts
+
+Local-first scripts for releasing Apache KIE Tools. All components are 
released together under a single unified build.
+
+## Available Scripts
+
+| Script                     | What it does                                    
                             |
+| -------------------------- | 
---------------------------------------------------------------------------- |
+| `release-all.sh`           | **The** release script — builds all components 
and optionally publishes them |
+| `create-source-tarball.sh` | Utility: creates an Apache-compliant source zip 
from the current `HEAD`      |
+
+## Usage
+
+```bash
+./scripts/release/release-all.sh <version>             # build all components 
(dry run — nothing published)
+./scripts/release/release-all.sh <version> --rc        # build + collect 
Apache RC artifacts
+./scripts/release/release-all.sh <version> --publish   # build + publish to 
all public registries
+```
+
+### Optional flags
+
+| Flag                 | Effect                                                
                          |
+| -------------------- | 
------------------------------------------------------------------------------- 
|
+| _(none)_             | Build everything locally — nothing is published or 
uploaded                     |
+| `--rc`               | Build and collect all artifacts into 
`release-artifacts/` for an Apache RC vote |
+| `--publish`          | Build and push/publish to all public registries and 
services                    |
+| `--skip-build`       | Skip `pnpm build:prod` (use existing `dist/` output)  
                          |
+| `--upload-url <url>` | GitHub Release upload URL (required by `--publish` 
for binary assets)           |
+| `--registry <url>`   | Container registry (default: `docker.io/apache`)      
                          |
+
+## What is released
+
+`release-all.sh` covers all KIE Tools components in one build:
+
+1. **NPM packages** — all public packages under `packages/`
+2. **Chrome extensions** — `chrome-extension-pack-kogito-kie-editors`
+3. **VSCode extensions** — all `.vsix` packages
+4. **Container images** — all Kogito / sandbox images
+5. **Helm charts** — sandbox and runtime-tools-consoles charts
+6. **GitHub Pages / webapp** — online-editor, standalone editors, Quarkus 
accelerator
+7. **dev-deployment-upload-service** — cross-platform binaries
+8. **Source tarball** — Apache-compliant source zip
+
+## Prerequisites
+
+- Node.js 22, pnpm, Go, Helm 3, Docker — depending on which components you need
+- Repository bootstrapped: `pnpm bootstrap`
+- Credentials set as environment variables (only needed for `--publish`)
+
+## Local Testing
+
+### Full RC dry-run from a fresh clone
+
+```bash
+# 1. Bootstrap once
+pnpm bootstrap
+
+# 2. Build and collect all RC artifacts (linters/tests/e2e suppressed 
automatically)
+./scripts/release/release-all.sh 10.3.0 --rc
+
+# 3. Inspect
+ls -lh release-artifacts/
+```
+
+### Fast iteration (repo already built)
+
+If you have already run a full build and just want to re-collect artifacts:
+
+```bash
+rm -rf release-artifacts/
+./scripts/release/release-all.sh 10.3.0 --rc --skip-build
+```
+
+`--skip-build` skips the `pnpm build:prod` step and goes straight to 
zipping/copying
+from the existing `dist/` folders. Artifact collection is identical to a full 
run.
+
+## RC Artifact Names
+
+All artifacts produced by `--rc` follow the Apache incubator convention:
+`apache-kie-<version>-incubating-<artifact-name>.<ext>`
+
+```
+apache-kie-<version>-incubating-tools-npm-packages.zip
+apache-kie-<version>-incubating-business-automation-chrome-extension.zip
+apache-kie-<version>-incubating-business-automation-chrome-extension-editors.zip
+apache-kie-<version>-incubating-bpmn-vscode-extension.vsix
+apache-kie-<version>-incubating-dmn-vscode-extension.vsix
+apache-kie-<version>-incubating-drl-vscode-extension.vsix
+apache-kie-<version>-incubating-pmml-vscode-extension.vsix
+apache-kie-<version>-incubating-kogito-bundle-vscode-extension.vsix
+apache-kie-<version>-incubating-business-automation-bundle-vscode-extension.vsix
+apache-kie-<version>-incubating-extended-services-vscode-extension.vsix
+apache-kie-<version>-incubating-sandbox-webapp.zip
+apache-kie-<version>-incubating-business-automation-standalone-editors.zip
+apache-kie-<version>-incubating-sandbox-accelerator-quarkus.zip
+apache-kie-<version>-incubating-sandbox-helm-chart.tar.gz
+apache-kie-<version>-incubating-runtime-tools-console-helm-chart.tar.gz
+apache-kie-<version>-incubating-<image-name>-image.tar.gz  (one per container 
image)
+apache-kie-<version>-incubating-sandbox-dev-deployment-upload-service-macOS-arm64.tar.gz
+apache-kie-<version>-incubating-sandbox-dev-deployment-upload-service-macOS-x86.tar.gz
+apache-kie-<version>-incubating-sandbox-dev-deployment-upload-service-linux-x86.tar.gz
+apache-kie-<version>-incubating-sandbox-dev-deployment-upload-service-windows-x86.tar.gz
+apache-kie-<version>-incubating-sources.zip  (source zip — always created)
+```
+
+Container image names (`<image-name>`):
+`cors-proxy`, `sandbox-webapp`, `sandbox-extended-services`,
+`sandbox-dev-deployment-base`, `sandbox-dev-deployment-dmn-form-webapp`,
+`sandbox-dev-deployment-quarkus-blank-app`, `kogito-management-console`
+
+## Credentials (for `--publish`)
+
+| Component                     | Required environment variables               
                                                         |
+| ----------------------------- | 
-----------------------------------------------------------------------------------------------------
 |
+| NPM packages                  | `NPM_TOKEN`                                  
                                                         |
+| VSCode extensions             | `VSCE_PAT`                                   
                                                         |
+| Chrome extensions             | `CHROME_CLIENT_ID`, `CHROME_CLIENT_SECRET`, 
`CHROME_REFRESH_TOKEN`, `CHROME_KIE_EDITORS_EXTENSION_ID` |
+| Container images              | `DOCKER_USERNAME`, `DOCKER_PASSWORD`         
                                                         |
+| Helm charts                   | `HELM_REGISTRY` (default: 
`docker.io/apache`), optionally `HELM_USERNAME` / `HELM_PASSWORD`           |
+| GitHub Pages / webapp         | `GITHUB_TOKEN`                               
                                                         |
+| dev-deployment-upload-service | `GITHUB_TOKEN`, `--upload-url`               
                                                         |
+
+See [`CHROME_STORE_SETUP.md`](CHROME_STORE_SETUP.md) for Chrome Web Store 
credential setup.
+
+## Version Management
+
+Before running the release script, update the version throughout the repo:
+
+```bash
+pnpm update-version-to 10.3.0
+pnpm update-kogito-version-to --maven 10.3.0
+pnpm update-stream-name-to 10.3.0
+```
+
+## Troubleshooting
+
+**Permission denied** — `chmod +x scripts/release/release-all.sh`
+
+**pnpm not found** — `npm install -g pnpm`
+
+**Build fails** — run `pnpm bootstrap` first
+
+**NPM publish fails** — verify `NPM_TOKEN` is set and you have publish rights 
to `@kie-tools` packages
diff --git a/scripts/release/create-source-tarball.sh 
b/scripts/release/create-source-tarball.sh
new file mode 100755
index 00000000000..d8e005e9bbb
--- /dev/null
+++ b/scripts/release/create-source-tarball.sh
@@ -0,0 +1,93 @@
+#!/usr/bin/env bash
+#
+# 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.
+#
+
+set -euo pipefail
+
+SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
+REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
+
+usage() {
+    echo "Usage: $0 <version> [--git-ref <ref>] [--output-dir <dir>]"
+    echo ""
+    echo "Arguments:"
+    echo "    version           Release or RC version (e.g., 10.2.0 or 
10.2.0-rc1)"
+    echo ""
+    echo "Options:"
+    echo "    --git-ref <ref>   Git reference to archive (default: HEAD)"
+    echo "    --output-dir <d>  Output directory (default: 
./release-artifacts)"
+    echo "    --help"
+    exit 1
+}
+
+VERSION=""
+GIT_REF="HEAD"
+OUTPUT_DIR="$REPO_ROOT/release-artifacts"
+
+while [[ $# -gt 0 ]]; do
+    case $1 in
+        --git-ref)    GIT_REF="$2";    shift 2 ;;
+        --output-dir) OUTPUT_DIR="$2"; shift 2 ;;
+        --help)       usage ;;
+        *)
+            if [[ -z "$VERSION" ]]; then VERSION="$1"; else echo "Unknown 
argument: $1"; usage; fi
+            shift ;;
+    esac
+done
+
+[[ -z "$VERSION" ]] && { echo "ERROR: version is required"; usage; }
+
+echo "=========================================="
+echo "Source Tarball"
+echo "Version:   $VERSION"
+echo "Git ref:   $GIT_REF"
+echo "Output:    $OUTPUT_DIR"
+echo "=========================================="
+
+mkdir -p "$OUTPUT_DIR"
+ZIPFILE="$OUTPUT_DIR/apache-kie-$VERSION-incubating-sources.zip"
+
+cd "$REPO_ROOT"
+local_archive_ref="$GIT_REF"
+if [[ "$local_archive_ref" == "HEAD" ]] && ! git diff --quiet HEAD 
2>/dev/null; then
+    stash_sha=$(git stash create 2>/dev/null || true)
+    if [[ -n "$stash_sha" ]]; then
+        local_archive_ref="$stash_sha"
+    fi
+fi
+
+echo "Creating git archive from ref $local_archive_ref..."
+git archive --format=zip --prefix="apache-kie-$VERSION-incubating/" 
"$local_archive_ref" > "$ZIPFILE"
+
+if ! unzip -t "$ZIPFILE" > /dev/null 2>&1; then
+    echo "ERROR: zip verification failed"
+    exit 1
+fi
+
+SIZE=$(du -h "$ZIPFILE" | cut -f1)
+echo "Created: $ZIPFILE ($SIZE)"
+
+zip_contents=$(unzip -l "$ZIPFILE")
+for required in LICENSE NOTICE DISCLAIMER-WIP; do
+    if ! echo "$zip_contents" | grep -q 
"apache-kie-$VERSION-incubating/$required"; then
+        echo "WARN: $required not found in zip"
+    fi
+done
+
+echo "=========================================="
+echo "DONE"
+echo "=========================================="
\ No newline at end of file
diff --git a/scripts/release/release-all.sh b/scripts/release/release-all.sh
new file mode 100755
index 00000000000..af8ff40d8b4
--- /dev/null
+++ b/scripts/release/release-all.sh
@@ -0,0 +1,773 @@
+#!/usr/bin/env bash
+#
+# 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.
+#
+
+set -euo pipefail
+
+# Release script for Apache KIE Tools — builds and optionally releases all 
components
+# under a single unified build.
+#
+# Usage:
+#   ./release-all.sh <version>            # dry run (build only, nothing 
published)
+#   ./release-all.sh <version> --rc       # build + collect Apache RC artifacts
+#   ./release-all.sh <version> --publish  # build + publish to all public 
registries
+#
+# Optional flags:
+#   --skip-build           Skip pnpm build:prod (use existing dist/ output)
+#   --upload-url <url>     GitHub Release upload URL (required by --publish 
for binary assets)
+#   --registry <url>       Container registry (default: docker.io/apache)
+#   --git-ref <ref>        Git reference for source tarball (default: HEAD)
+#
+# Credentials (required only for --publish, sourced from env):
+#   NPM_TOKEN, VSCE_PAT,
+#   CHROME_CLIENT_ID, CHROME_CLIENT_SECRET, CHROME_REFRESH_TOKEN, 
CHROME_KIE_EDITORS_EXTENSION_ID,
+#   DOCKER_USERNAME, DOCKER_PASSWORD,
+#   HELM_REGISTRY (default: docker.io/apache), HELM_USERNAME (optional), 
HELM_PASSWORD (optional),
+#   GITHUB_TOKEN
+
+export KIE_TOOLS_BUILD__runLinters=false
+export KIE_TOOLS_BUILD__runTests=false
+export KIE_TOOLS_BUILD__runEndToEndTests=false
+
+SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
+REPO_ROOT="$(cd "${SCRIPT_DIR}/../.." && pwd)"
+
+# ---------------------------------------------------------------------------
+# Argument parsing
+# ---------------------------------------------------------------------------
+VERSION="${1:-}"
+PUBLISH=false
+RC_MODE=false
+SKIP_BUILD=false
+UPLOAD_URL=""
+REGISTRY="docker.io/apache"
+GIT_REF="HEAD"
+
+shift || true
+while [[ $# -gt 0 ]]; do
+    case $1 in
+        --publish)     PUBLISH=true;        shift ;;
+        --rc)          RC_MODE=true;        shift ;;
+        --skip-build)  SKIP_BUILD=true;     shift ;;
+        --upload-url)  UPLOAD_URL="${2:-}";  shift 2 ;;
+        --registry)    REGISTRY="${2:-}";   shift 2 ;;
+        --git-ref)     GIT_REF="${2:-}";    shift 2 ;;
+        *)
+            echo "Unknown option: $1"
+            echo "Usage: $0 <version> [--publish] [--rc] [--skip-build] 
[--upload-url <url>] [--registry <url>] [--git-ref <ref>]"
+            exit 1
+            ;;
+    esac
+done
+
+if [[ -z "${VERSION}" ]]; then
+    echo "Usage: $0 <version> [--publish] [--rc] [--skip-build] [--upload-url 
<url>] [--registry <url>]"
+    echo "Example: $0 10.2.0 --rc"
+    echo "Example: $0 10.2.0 --publish"
+    exit 1
+fi
+
+ARTIFACTS_DIR="${REPO_ROOT}/release-artifacts"
+
+echo "=========================================="
+echo "KIE Tools Release"
+echo "Version:    ${VERSION}"
+echo "RC mode:    ${RC_MODE}"
+echo "Publish:    ${PUBLISH}"
+echo "Skip build: ${SKIP_BUILD}"
+echo "Registry:   ${REGISTRY}"
+echo "=========================================="
+
+cd "${REPO_ROOT}"
+if [[ "${SKIP_BUILD}" == "false" ]]; then
+    echo ""
+    echo "--- Bumping workspace version to ${VERSION} ---"
+    pnpm update-version-to "${VERSION}"
+    pnpm update-kogito-version-to --maven "${VERSION}"
+    pnpm update-stream-name-to "${VERSION}"
+fi
+
+# ---------------------------------------------------------------------------
+# Helper: sign and upload a single asset to a GitHub Release
+# ---------------------------------------------------------------------------
+upload_github_asset() {
+    local file="$1"
+    local asset_name="$2"
+    local content_type="${3:-application/octet-stream}"
+    if [[ ! -f "${file}" ]]; then
+        echo "  SKIP  ${asset_name} (file not found)"
+        return
+    fi
+    echo "  UPLOAD  ${asset_name}"
+    curl -sSf \
+        -H "Authorization: token ${GITHUB_TOKEN}" \
+        -H "Content-Type: ${content_type}" \
+        --data-binary "@${file}" \
+        "${UPLOAD_URL}?name=${asset_name}"
+}
+
+# ---------------------------------------------------------------------------
+# 1. NPM packages
+# ---------------------------------------------------------------------------
+release_npm_packages() {
+    echo ""
+    echo "--- NPM packages ---"
+
+    if [[ "${SKIP_BUILD}" == "false" ]]; then
+        echo "Building public NPM packages..."
+        local filter
+        filter=$(pnpm -r exec bash -c \
+            'if [[ $(jq -r ".private" package.json) != "true" ]]; then echo 
"-F $(jq -r ".name" package.json)..."; fi')
+        pnpm ${filter} build:prod
+    fi
+
+    if [[ "${RC_MODE}" == "true" ]]; then
+        local tmp_dir="${ARTIFACTS_DIR}/npm-packages-tmp"
+        local 
zip_file="apache-kie-${VERSION}-incubating-tools-npm-packages.zip"
+        mkdir -p "${tmp_dir}" "${ARTIFACTS_DIR}"
+        local pub_filter
+        pub_filter=$(pnpm -r exec bash -c \
+            'if [[ $(jq -r ".private" package.json) != "true" ]]; then echo 
"-F $(jq -r ".name" package.json)"; fi')
+        pnpm ${pub_filter} exec bash -c "pnpm pack --pack-destination 
${tmp_dir}"
+        (cd "${tmp_dir}" && zip -r "${ARTIFACTS_DIR}/${zip_file}" .)
+        rm -rf "${tmp_dir}"
+        echo "RC artifact: ${ARTIFACTS_DIR}/${zip_file}"
+    fi
+
+    if [[ "${PUBLISH}" == "true" ]]; then
+        if [[ -z "${NPM_TOKEN:-}" ]]; then
+            echo "ERROR: NPM_TOKEN is required for publishing npm packages"
+            return 1
+        fi
+        local npmrc_tmp
+        npmrc_tmp=$(mktemp)
+        trap "rm -f '${npmrc_tmp}'" EXIT
+        echo "//registry.npmjs.org/:_authToken=${NPM_TOKEN}" > "${npmrc_tmp}"
+        export NPM_CONFIG_USERCONFIG="${npmrc_tmp}"
+
+        local pub_filter
+        pub_filter=$(pnpm -r exec bash -c \
+            'if [[ $(jq -r ".private" package.json) != "true" ]]; then echo 
"-F $(jq -r ".name" package.json)"; fi')
+        pnpm ${pub_filter} exec bash -c '
+            PKG_NAME=$(jq -r ".name" package.json)
+            if ! npm view ${PKG_NAME}@'"${VERSION}"' name --userconfig 
"'"${npmrc_tmp}"'" &>/dev/null; then
+                echo "Publishing ${PKG_NAME}@'"${VERSION}"'"
+                pnpm publish --no-git-checks --access public --userconfig 
"'"${npmrc_tmp}"'"
+            else
+                echo "Skipping ${PKG_NAME}@'"${VERSION}"' (already published)"
+            fi
+        '
+        rm -f "${npmrc_tmp}"
+        trap - EXIT
+        echo "NPM packages published."
+    fi
+}
+
+# ---------------------------------------------------------------------------
+# 2. Chrome extensions
+# ---------------------------------------------------------------------------
+release_chrome_extensions() {
+    echo ""
+    echo "--- Chrome extensions ---"
+
+    if [[ "${SKIP_BUILD}" == "false" ]]; then
+        echo "Building Chrome extensions..."
+        pnpm -F "chrome-extension-pack-kogito-kie-editors..." build:prod
+    fi
+
+    local kie_editors_zip
+    kie_editors_zip=$(find 
"packages/chrome-extension-pack-kogito-kie-editors/dist" \
+        -maxdepth 1 -name "chrome_extension_kogito_kie_editors_*.zip" 
2>/dev/null | head -1)
+    if [[ -z "${kie_editors_zip}" ]]; then
+        echo "ERROR: chrome_extension_kogito_kie_editors_*.zip not found — was 
the build successful?"
+        return 1
+    fi
+
+    if [[ "${RC_MODE}" == "true" ]]; then
+        mkdir -p "${ARTIFACTS_DIR}"
+        cp "${kie_editors_zip}" \
+            
"${ARTIFACTS_DIR}/apache-kie-${VERSION}-incubating-business-automation-chrome-extension.zip"
+
+        local tmp_kie="${ARTIFACTS_DIR}/kie-editors-tmp"
+        mkdir -p "${tmp_kie}"
+        cp -r 
packages/chrome-extension-pack-kogito-kie-editors/dist/{fonts,*-envelope.*} 
"${tmp_kie}/"
+        (cd "${tmp_kie}" && zip -r \
+            
"${ARTIFACTS_DIR}/apache-kie-${VERSION}-incubating-business-automation-chrome-extension-editors.zip"
 .)
+        rm -rf "${tmp_kie}"
+        echo "RC artifacts created in: ${ARTIFACTS_DIR}"
+    fi
+
+    if [[ "${PUBLISH}" == "true" ]]; then
+        if [[ -z "${CHROME_CLIENT_ID:-}" || -z "${CHROME_CLIENT_SECRET:-}" || 
-z "${CHROME_REFRESH_TOKEN:-}" ]]; then
+            echo "ERROR: CHROME_CLIENT_ID, CHROME_CLIENT_SECRET, and 
CHROME_REFRESH_TOKEN are required"
+            return 1
+        fi
+
+        local token_res
+        token_res=$(curl -sSf -X POST "https://oauth2.googleapis.com/token"; \
+            -d "client_id=${CHROME_CLIENT_ID}" \
+            -d "client_secret=${CHROME_CLIENT_SECRET}" \
+            -d "refresh_token=${CHROME_REFRESH_TOKEN}" \
+            -d "grant_type=refresh_token")
+        local access_token
+        access_token=$(echo "${token_res}" | jq -r '.access_token // empty')
+
+        if [[ -z "${access_token}" ]]; then
+            echo "ERROR: Failed to obtain Chrome Web Store OAuth token: 
${token_res}"
+            return 1
+        fi
+
+        _chrome_upload() {
+            local ext_id="$1" zip="$2"
+            local res state
+            res=$(curl -sSf -X PUT \
+                
"https://www.googleapis.com/upload/chromewebstore/v1.1/items/${ext_id}"; \
+                -H "Authorization: Bearer ${access_token}" \
+                -H "x-goog-api-version:2" \
+                -T "${zip}")
+            state=$(echo "${res}" | jq -r '.uploadState // empty')
+            if [[ "${state}" != "SUCCESS" ]]; then
+                echo "ERROR: Chrome Web Store upload failed for ${ext_id}: 
${res}"
+                return 1
+            fi
+        }
+        _chrome_publish() {
+            local ext_id="$1"
+            local res pub_status
+            res=$(curl -sSf -X POST \
+                
"https://www.googleapis.com/chromewebstore/v1.1/items/${ext_id}/publish"; \
+                -H "Authorization: Bearer ${access_token}" \
+                -H "x-goog-api-version:2" \
+                -H "Content-Length: 0")
+            pub_status=$(echo "${res}" | jq -r '.status[0] // .status // 
empty')
+            if [[ "${pub_status}" != "OK" && "${pub_status}" != 
"PUBLISHED_WITH_FRICTION_WARNING" ]]; then
+                echo "ERROR: Chrome Web Store publish failed for ${ext_id}: 
${res}"
+                return 1
+            fi
+        }
+
+        if [[ -n "${CHROME_KIE_EDITORS_EXTENSION_ID:-}" ]]; then
+            _chrome_upload "${CHROME_KIE_EDITORS_EXTENSION_ID}" 
"${kie_editors_zip}"
+            _chrome_publish "${CHROME_KIE_EDITORS_EXTENSION_ID}"
+            echo "Chrome extension published."
+        else
+            echo "WARN: CHROME_KIE_EDITORS_EXTENSION_ID not set — skipping 
Chrome publish"
+        fi
+    fi
+}
+
+# ---------------------------------------------------------------------------
+# 3. VSCode extensions
+# ---------------------------------------------------------------------------
+release_vscode() {
+    echo ""
+    echo "--- VSCode extensions ---"
+
+    declare -A EXTENSIONS=(
+        ["bpmn-vscode-extension"]="bpmn-vscode-extension"
+        ["dmn-vscode-extension"]="dmn-vscode-extension"
+        ["drl-vscode-extension"]="drl-vscode-extension"
+        ["pmml-vscode-extension"]="pmml-vscode-extension"
+        ["vscode-extension-kogito-bundle"]="kogito-bundle-vscode-extension"
+        
["vscode-extension-kie-ba-bundle"]="business-automation-bundle-vscode-extension"
+        
["extended-services-vscode-extension"]="extended-services-vscode-extension"
+    )
+
+    if [[ "${SKIP_BUILD}" == "false" ]]; then
+        local filter=""
+        for ext in "${!EXTENSIONS[@]}"; do filter="${filter} -F ${ext}..."; 
done
+        echo "Building VSCode extensions..."
+        pnpm ${filter} build:prod
+    fi
+
+    if [[ "${RC_MODE}" == "true" ]]; then
+        mkdir -p "${ARTIFACTS_DIR}"
+        for ext in "${!EXTENSIONS[@]}"; do
+            local suffix="${EXTENSIONS[$ext]}"
+            local vsix
+            vsix=$(find "packages/${ext}" -maxdepth 2 -name "*.vsix" 
2>/dev/null | head -1)
+            if [[ -n "${vsix}" ]]; then
+                local 
dest="${ARTIFACTS_DIR}/apache-kie-${VERSION}-incubating-${suffix}.vsix"
+                echo "  COPY  $(basename "${dest}")"
+                cp "${vsix}" "${dest}"
+            else
+                echo "  SKIP  ${ext} (no .vsix found)"
+            fi
+        done
+        echo "VSIX files in: ${ARTIFACTS_DIR}/"
+    fi
+
+    if [[ "${PUBLISH}" == "true" ]]; then
+        if [[ -z "${VSCE_PAT:-}" ]]; then
+            echo "ERROR: VSCE_PAT is required for publishing VSCode extensions"
+            return 1
+        fi
+        echo "Publishing to VSCode Marketplace..."
+        for ext in "${!EXTENSIONS[@]}"; do
+            find "packages/${ext}" -maxdepth 2 -name "*.vsix" | while read -r 
vsix; do
+                echo "  Publishing: ${vsix}"
+                npx vsce publish --packagePath "${vsix}" --pat "${VSCE_PAT}"
+            done
+        done
+        echo "VSCode extensions published."
+    fi
+
+    if [[ "${PUBLISH}" == "true" && -n "${UPLOAD_URL:-}" && -n 
"${GITHUB_TOKEN:-}" ]]; then
+        echo "Uploading .vsix files to GitHub Release..."
+        for ext in "${!EXTENSIONS[@]}"; do
+            find "packages/${ext}" -maxdepth 2 -name "*.vsix" | while read -r 
vsix; do
+                upload_github_asset "${vsix}" "$(basename "${vsix}")" 
"application/zip"
+            done
+        done
+    fi
+}
+
+# ---------------------------------------------------------------------------
+# 4. Container images
+# ---------------------------------------------------------------------------
+release_container_images() {
+    echo ""
+    echo "--- Container images ---"
+
+    declare -A IMAGES=(
+        ["cors-proxy"]="packages/cors-proxy-image:incubator-kie-cors-proxy"
+        
["sandbox-webapp"]="packages/kie-sandbox-webapp-image:incubator-kie-sandbox-webapp"
+        
["sandbox-extended-services"]="packages/kie-sandbox-extended-services-image:incubator-kie-sandbox-extended-services"
+        
["sandbox-dev-deployment-base"]="packages/dev-deployment-base-image:incubator-kie-sandbox-dev-deployment-base"
+        
["sandbox-dev-deployment-dmn-form-webapp"]="packages/dev-deployment-dmn-form-webapp-image:incubator-kie-sandbox-dev-deployment-dmn-form-webapp"
+        
["sandbox-dev-deployment-quarkus-blank-app"]="packages/dev-deployment-quarkus-blank-app-image:incubator-kie-sandbox-dev-deployment-quarkus-blank-app"
+        
["kogito-management-console"]="packages/kogito-management-console:incubator-kie-kogito-management-console"
+    )
+
+    export KIE_TOOLS_BUILD__buildContainerImages=true
+
+    if [[ "${SKIP_BUILD}" == "false" ]]; then
+        if ! docker info &>/dev/null; then
+            echo "WARN: Docker is not running — skipping container image build"
+            return 0
+        fi
+        echo "Building container images..."
+        for artifact_name in "${!IMAGES[@]}"; do
+            local mapping="${IMAGES[$artifact_name]}"
+            local pkg_path="${mapping%%:*}"
+            if [[ ! -d "${pkg_path}" ]]; then
+                echo "ERROR: Image package directory ${pkg_path} not found"
+                return 1
+            fi
+            local pkg_name
+            pkg_name=$(node -p "require('./${pkg_path}/package.json').name" 
2>/dev/null || basename "${pkg_path}")
+            echo "  BUILD  ${artifact_name} (${pkg_name})"
+            pnpm --filter "${pkg_name}..." build:prod
+        done
+    else
+        if ! docker info &>/dev/null; then
+            echo "SKIP: Docker is not running — cannot save container image 
tarballs with --skip-build"
+            return 0
+        fi
+    fi
+
+    local output_dir="${ARTIFACTS_DIR}"
+    [[ "${RC_MODE}" == "true" ]] && mkdir -p "${output_dir}"
+
+    echo "Tagging images..."
+    for artifact_name in "${!IMAGES[@]}"; do
+        local mapping="${IMAGES[$artifact_name]}"
+        local pkg_path="${mapping%%:*}"
+        local image_name="${mapping##*:}"
+        if [[ ! -d "${pkg_path}" ]]; then
+            echo "ERROR: Image package directory ${pkg_path} not found"
+            return 1
+        fi
+        local target_image="${REGISTRY}/${image_name}:${VERSION}"
+
+        # Resolve built image from local docker daemon
+        local source_image=""
+        for candidate in \
+            "docker.io/apache/${image_name}:${VERSION}" \
+            "apache/${image_name}:${VERSION}" \
+            "${image_name}:${VERSION}" \
+            "docker.io/apache/${image_name}:latest" \
+            "apache/${image_name}:latest" \
+            "${image_name}:latest"; do
+            if docker image inspect "${candidate}" &>/dev/null; then
+                source_image="${candidate}"
+                break
+            fi
+        done
+
+        if [[ -n "${source_image}" ]]; then
+            docker tag "${source_image}" "${target_image}"
+        else
+            echo "  WARN  could not find local image for ${artifact_name} 
(${image_name})"
+        fi
+
+        if [[ "${RC_MODE}" == "true" ]]; then
+            if docker image inspect "${target_image}" &>/dev/null; then
+                local 
tarball="${output_dir}/apache-kie-${VERSION}-incubating-${artifact_name}-image.tar.gz"
+                echo "  SAVE  ${tarball}"
+                docker save "${target_image}" | gzip > "${tarball}"
+            else
+                echo "ERROR: Image ${target_image} not found locally for RC 
export"
+                return 1
+            fi
+        fi
+    done
+
+    if [[ "${PUBLISH}" == "true" ]]; then
+        if [[ -z "${DOCKER_USERNAME:-}" || -z "${DOCKER_PASSWORD:-}" ]]; then
+            echo "ERROR: DOCKER_USERNAME and DOCKER_PASSWORD are required for 
publishing container images"
+            return 1
+        fi
+        echo "Pushing images to ${REGISTRY}..."
+        echo "${DOCKER_PASSWORD}" | docker login "$(echo "${REGISTRY}" | cut 
-d/ -f1)" \
+            -u "${DOCKER_USERNAME}" --password-stdin
+        for artifact_name in "${!IMAGES[@]}"; do
+            local mapping="${IMAGES[$artifact_name]}"
+            local image_name="${mapping##*:}"
+            local full_image="${REGISTRY}/${image_name}:${VERSION}"
+            echo "  PUSH  ${full_image}"
+            docker push "${full_image}"
+        done
+        docker logout "$(echo "${REGISTRY}" | cut -d/ -f1)"
+        echo "Container images pushed."
+    fi
+}
+
+# ---------------------------------------------------------------------------
+# 5. Helm charts
+# ---------------------------------------------------------------------------
+release_helm_charts() {
+    echo ""
+    echo "--- Helm charts ---"
+
+    if ! command -v helm &>/dev/null; then
+        echo "WARN: helm not found — skipping Helm chart release"
+        return 0
+    fi
+
+    declare -A CHARTS=(
+        ["sandbox-helm-chart"]="packages/kie-sandbox-helm-chart"
+        
["runtime-tools-console-helm-chart"]="packages/runtime-tools-consoles-helm-chart"
+    )
+
+    local output_dir="${ARTIFACTS_DIR}"
+    mkdir -p "${output_dir}"
+
+    local helm_tmp_pkg
+    helm_tmp_pkg=$(mktemp -d)
+    trap "rm -rf ${helm_tmp_pkg}" EXIT
+
+    echo "Packaging Helm charts..."
+    for slug in "${!CHARTS[@]}"; do
+        local chart_pkg="${CHARTS[$slug]}"
+        [[ -d "${chart_pkg}" ]] || { echo "ERROR: Helm chart directory 
${chart_pkg} not found"; return 1; }
+
+        local chart_yaml=""
+        for candidate in "${chart_pkg}/src/Chart.yaml" 
"${chart_pkg}/Chart.yaml"; do
+            [[ -f "${candidate}" ]] && { chart_yaml="${candidate}"; break; }
+        done
+        [[ -z "${chart_yaml}" ]] && { echo "ERROR: Chart.yaml not found in 
${chart_pkg}"; return 1; }
+
+        local chart_dir
+        chart_dir="$(dirname "${chart_yaml}")"
+        local tmp_dir
+        tmp_dir=$(mktemp -d)
+        cp -r "${chart_dir}/." "${tmp_dir}/chart"
+        sed -i.bak "s/^version:.*/version: ${VERSION}/" 
"${tmp_dir}/chart/Chart.yaml"
+        sed -i.bak "s/^appVersion:.*/appVersion: \"${VERSION}\"/" 
"${tmp_dir}/chart/Chart.yaml"
+        rm -f "${tmp_dir}/chart/Chart.yaml.bak"
+        helm package "${tmp_dir}/chart" --destination "${helm_tmp_pkg}"
+        rm -rf "${tmp_dir}"
+
+        local found
+        found=$(find "${helm_tmp_pkg}" -maxdepth 1 -name "*-${VERSION}.tgz" | 
head -1)
+        if [[ -n "${found}" ]]; then
+            cp "${found}" 
"${output_dir}/apache-kie-${VERSION}-incubating-${slug}.tar.gz"
+            echo "  DONE  
${output_dir}/apache-kie-${VERSION}-incubating-${slug}.tar.gz"
+        else
+            echo "ERROR: Failed to package helm chart for ${slug}"
+            return 1
+        fi
+    done
+
+    if [[ "${PUBLISH}" == "true" ]]; then
+        local helm_reg="${HELM_REGISTRY:-docker.io/apache}"
+        if [[ -z "${helm_reg}" ]]; then
+            echo "ERROR: HELM_REGISTRY is required for publishing Helm charts"
+            return 1
+        fi
+        if [[ -n "${HELM_USERNAME:-}" && -n "${HELM_PASSWORD:-}" ]]; then
+            echo "${HELM_PASSWORD}" | helm registry login "$(echo 
"${helm_reg}" | cut -d/ -f1)" \
+                --username "${HELM_USERNAME}" --password-stdin
+        fi
+        for tgz in "${helm_tmp_pkg}"/*-"${VERSION}".tgz; do
+            if [[ -f "${tgz}" ]]; then
+                echo "  PUSH  ${tgz} -> oci://${helm_reg}"
+                helm push "${tgz}" "oci://${helm_reg}"
+            fi
+        done
+        echo "Helm charts pushed."
+    fi
+    rm -rf "${helm_tmp_pkg}"
+    trap - EXIT
+}
+
+# ---------------------------------------------------------------------------
+# 6. GitHub Pages / webapp / accelerator
+# ---------------------------------------------------------------------------
+release_github_pages() {
+    echo ""
+    echo "--- GitHub Pages / webapp / accelerator ---"
+
+    if [[ "${SKIP_BUILD}" == "false" ]]; then
+        echo "Building online-editor, kie-editors-standalone, 
chrome-extension-pack-kogito-kie-editors, kie-sandbox-accelerator-quarkus..."
+        export ONLINE_EDITOR__buildInfo="${VERSION}"
+        export ONLINE_EDITOR__extendedServicesCompatibleVersion="${VERSION}"
+        export ONLINE_EDITOR__devDeploymentBaseImageRegistry="docker.io"
+        export ONLINE_EDITOR__devDeploymentBaseImageAccount="apache"
+        export 
ONLINE_EDITOR__devDeploymentBaseImageName="incubator-kie-sandbox-dev-deployment-base"
+        export ONLINE_EDITOR__devDeploymentBaseImageTag="${VERSION}"
+        export 
ONLINE_EDITOR__devDeploymentDmnFormWebappImageRegistry="docker.io"
+        export ONLINE_EDITOR__devDeploymentDmnFormWebappImageAccount="apache"
+        export 
ONLINE_EDITOR__devDeploymentDmnFormWebappImageName="incubator-kie-sandbox-dev-deployment-dmn-form-webapp"
+        export ONLINE_EDITOR__devDeploymentDmnFormWebappImageTag="${VERSION}"
+        export 
ONLINE_EDITOR__devDeploymentQuarkusBlankAppImageRegistry="docker.io"
+        export ONLINE_EDITOR__devDeploymentQuarkusBlankAppImageAccount="apache"
+        export 
ONLINE_EDITOR__devDeploymentQuarkusBlankAppImageName="incubator-kie-sandbox-dev-deployment-quarkus-blank-app"
+        export ONLINE_EDITOR__devDeploymentQuarkusBlankAppImageTag="${VERSION}"
+        pnpm \
+            -F "@kie-tools/online-editor..." \
+            -F "@kie-tools/kie-editors-standalone..." \
+            -F "@kie-tools/chrome-extension-pack-kogito-kie-editors..." \
+            -F "@kie-tools/kie-sandbox-accelerator-quarkus..." \
+            build:prod
+    fi
+
+    if [[ "${RC_MODE}" == "true" ]]; then
+        mkdir -p "${ARTIFACTS_DIR}"
+        for src_path_suffix in \
+            
"packages/online-editor/dist:apache-kie-${VERSION}-incubating-sandbox-webapp.zip"
 \
+            
"packages/kie-editors-standalone/dist:apache-kie-${VERSION}-incubating-business-automation-standalone-editors.zip"
 \
+            
"packages/kie-sandbox-accelerator-quarkus/dist:apache-kie-${VERSION}-incubating-sandbox-accelerator-quarkus.zip"
+        do
+            local src="${REPO_ROOT}/${src_path_suffix%%:*}"
+            local zip_name="${src_path_suffix##*:}"
+            if [[ -d "${src}" ]]; then
+                echo "  ZIP  ${zip_name}"
+                (cd "${src}" && zip -r "${ARTIFACTS_DIR}/${zip_name}" .)
+            else
+                echo "  SKIP  ${zip_name} (${src} not found)"
+            fi
+        done
+        echo "RC artifacts in: ${ARTIFACTS_DIR}"
+    fi
+
+    if [[ "${PUBLISH}" == "true" ]]; then
+        if [[ -z "${GITHUB_TOKEN:-}" ]]; then
+            echo "ERROR: GITHUB_TOKEN is required for publishing to GitHub 
Pages"
+            return 1
+        fi
+
+        local 
kogito_online_repo="https://github.com/apache/incubator-kie-kogito-online.git";
+        local 
accelerator_repo="https://github.com/apache/incubator-kie-sandbox-quarkus-accelerator.git";
+        local tmp_dir
+        tmp_dir=$(mktemp -d)
+        trap "rm -rf ${tmp_dir}" EXIT
+
+        local 
auth_url="${kogito_online_repo/https:\/\//https://${GITHUB_TOKEN}@}";
+        git clone --branch gh-pages --depth 1 "${auth_url}" 
"${tmp_dir}/kogito-online"
+        (
+            cd "${tmp_dir}/kogito-online"
+            git config user.email "[email protected]"
+            git config user.name "Apache KIE Release Bot"
+            find . -maxdepth 1 ! -name '.' ! -name 'dev' ! -name 'editors' ! 
-name 'standalone' \
+                ! -name 'chrome-extension' ! -name '.nojekyll' ! -name 'CNAME' 
-exec rm -rf {} +
+
+            local online_dist="${REPO_ROOT}/packages/online-editor/dist"
+            if [[ -d "${online_dist}" ]]; then
+                local editors_dir="editors/${VERSION}"
+                rm -rf "${editors_dir}" && mkdir -p "${editors_dir}"
+                rm -rf editors/latest && ln -s "${VERSION}" editors/latest
+                cp -r "${online_dist}/." .
+            fi
+            local 
standalone_dist="${REPO_ROOT}/packages/kie-editors-standalone/dist"
+            [[ -d "${standalone_dist}" ]] && cp -r "${standalone_dist}/." 
"editors/${VERSION}/"
+            local 
chrome_dist="${REPO_ROOT}/packages/chrome-extension-pack-kogito-kie-editors/dist"
+            if [[ -d "${chrome_dist}" ]]; then
+                local chrome_dir="chrome-extension/${VERSION}"
+                rm -rf "${chrome_dir}" && mkdir -p "${chrome_dir}"
+                cp -r "${chrome_dist}/fonts" "${chrome_dir}/" 2>/dev/null || 
true
+                cp "${chrome_dist}"/*-envelope.* "${chrome_dir}/" 2>/dev/null 
|| true
+            fi
+            git add .
+            git commit -m "Deploy ${VERSION} (Online Editor + Standalone 
Editors + Chrome Extension editors)" \
+                || echo "  (nothing to commit)"
+            git push origin gh-pages
+        )
+        echo "Pushed to GitHub Pages."
+
+        local 
accel_content="${REPO_ROOT}/packages/kie-sandbox-accelerator-quarkus/dist/git-repo-content"
+        if [[ -d "${accel_content}" ]]; then
+            local 
auth_accel="${accelerator_repo/https:\/\//https://${GITHUB_TOKEN}@}";
+            git clone --depth 1 "${auth_accel}" "${tmp_dir}/accelerator"
+            (
+                cd "${tmp_dir}/accelerator"
+                git config user.email "[email protected]"
+                git config user.name "Apache KIE Release Bot"
+                git checkout --orphan "${VERSION}"
+                cp -r "${accel_content}/." .
+                git add .
+                git commit -m "Apache KIE Sandbox Quarkus Accelerator 
${VERSION}"
+                git tag "${VERSION}"
+                git push origin "refs/heads/${VERSION}:refs/heads/${VERSION}" 
"refs/tags/${VERSION}:refs/tags/${VERSION}"
+            )
+            echo "Pushed accelerator to tag ${VERSION}."
+        fi
+    fi
+}
+
+# ---------------------------------------------------------------------------
+# 7. dev-deployment-upload-service
+# ---------------------------------------------------------------------------
+release_dev_deployment_upload_service() {
+    echo ""
+    echo "--- dev-deployment-upload-service ---"
+
+    if [[ "${SKIP_BUILD}" == "false" ]]; then
+        echo "Building dev-deployment-upload-service..."
+        DDUS_VERSION="${VERSION}" pnpm -F 
"@kie-tools/dev-deployment-upload-service..." build:prod
+    fi
+
+    local dist="${REPO_ROOT}/packages/dev-deployment-upload-service/dist"
+    if [[ ! -d "${dist}" ]]; then
+        echo "ERROR: packages/dev-deployment-upload-service/dist not found"
+        return 1
+    fi
+
+    declare -A PLATFORM_MAP=(
+        
["dev-deployment-upload-service-darwin-arm64-${VERSION}.tar.gz"]="apache-kie-${VERSION}-incubating-sandbox-dev-deployment-upload-service-macOS-arm64.tar.gz"
+        
["dev-deployment-upload-service-darwin-amd64-${VERSION}.tar.gz"]="apache-kie-${VERSION}-incubating-sandbox-dev-deployment-upload-service-macOS-x86.tar.gz"
+        
["dev-deployment-upload-service-linux-amd64-${VERSION}.tar.gz"]="apache-kie-${VERSION}-incubating-sandbox-dev-deployment-upload-service-linux-x86.tar.gz"
+        
["dev-deployment-upload-service-windows-amd64-${VERSION}.tar.gz"]="apache-kie-${VERSION}-incubating-sandbox-dev-deployment-upload-service-windows-x86.tar.gz"
+    )
+
+    if [[ "${RC_MODE}" == "true" ]]; then
+        mkdir -p "${ARTIFACTS_DIR}"
+        for src_name in "${!PLATFORM_MAP[@]}"; do
+            local rc_name="${PLATFORM_MAP[$src_name]}"
+            if [[ -f "${dist}/${src_name}" ]]; then
+                cp "${dist}/${src_name}" "${ARTIFACTS_DIR}/${rc_name}"
+                echo "  COPY  ${rc_name}"
+            else
+                echo "ERROR: Artifact ${dist}/${src_name} not found"
+                return 1
+            fi
+        done
+        echo "RC artifacts in: ${ARTIFACTS_DIR}"
+    fi
+
+    if [[ "${PUBLISH}" == "true" ]]; then
+        if [[ -z "${GITHUB_TOKEN:-}" || -z "${UPLOAD_URL:-}" ]]; then
+            echo "ERROR: GITHUB_TOKEN and --upload-url are required for 
publishing dev-deployment-upload-service"
+            return 1
+        fi
+        for src_name in "${!PLATFORM_MAP[@]}"; do
+            upload_github_asset "${dist}/${src_name}" "${src_name}" 
"application/gzip"
+        done
+        echo "dev-deployment-upload-service binaries uploaded."
+    fi
+}
+
+# ---------------------------------------------------------------------------
+# 8. Source tarball (always created; no --publish step)
+# ---------------------------------------------------------------------------
+release_source_tarball() {
+    echo ""
+    echo "--- Source tarball ---"
+    mkdir -p "${ARTIFACTS_DIR}"
+    local 
zipfile="${ARTIFACTS_DIR}/apache-kie-${VERSION}-incubating-sources.zip"
+    local archive_ref="${GIT_REF}"
+
+    # If archiving HEAD and there are uncommitted working tree modifications 
(e.g. local version bumps),
+    # create a stash commit to ensure the working tree state is preserved in 
the archive.
+    if [[ "${archive_ref}" == "HEAD" ]] && ! git diff --quiet HEAD 
2>/dev/null; then
+        local stash_sha
+        stash_sha=$(git stash create 2>/dev/null || true)
+        if [[ -n "${stash_sha}" ]]; then
+            archive_ref="${stash_sha}"
+        fi
+    fi
+
+    echo "Creating git archive from ref ${archive_ref}..."
+    git archive --format=zip --prefix="apache-kie-${VERSION}-incubating/" 
"${archive_ref}" > "${zipfile}"
+    if ! unzip -t "${zipfile}" > /dev/null 2>&1; then
+        echo "ERROR: Source zip verification failed"
+        return 1
+    fi
+    local size
+    size=$(du -h "${zipfile}" | cut -f1)
+    echo "Created: ${zipfile} (${size})"
+    local zip_contents
+    zip_contents=$(unzip -l "${zipfile}")
+    for required in LICENSE NOTICE DISCLAIMER-WIP; do
+        echo "${zip_contents}" | grep -q 
"apache-kie-${VERSION}-incubating/${required}" \
+            || echo "WARN: ${required} not found in source zip"
+    done
+}
+
+# ---------------------------------------------------------------------------
+# Run all release steps
+# ---------------------------------------------------------------------------
+FAILED=()
+run_step() {
+    local name="$1" fn="$2"
+    local status=0
+    (
+        set -euo pipefail
+        "${fn}"
+    ) || status=$?
+
+    if [[ ${status} -eq 0 ]]; then
+        echo "✅ ${name} — OK"
+    else
+        echo "❌ ${name} — FAILED (exit code ${status})"
+        FAILED+=("${name}")
+    fi
+}
+
+run_step "npm-packages"                    release_npm_packages
+run_step "chrome-extensions"               release_chrome_extensions
+run_step "vscode"                          release_vscode
+run_step "container-images"               release_container_images
+run_step "helm-charts"                    release_helm_charts
+run_step "github-pages"                   release_github_pages
+run_step "dev-deployment-upload-service"  release_dev_deployment_upload_service
+run_step "source-tarball"                 release_source_tarball
+
+echo ""
+echo "=========================================="
+echo "Release Summary"
+echo "=========================================="
+if [[ ${#FAILED[@]} -eq 0 ]]; then
+    echo "✅ All components completed successfully!"
+    [[ "${RC_MODE}" == "true" || "${PUBLISH}" == "true" ]] && echo "Artifacts 
in: ${ARTIFACTS_DIR}"
+    exit 0
+else
+    echo "❌ Failed components:"
+    for c in "${FAILED[@]}"; do echo "  - ${c}"; done
+    exit 1
+fi


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to