Copilot commented on code in PR #7123:
URL: https://github.com/apache/incubator-kie/pull/7123#discussion_r4217621221


##########
.ci/jenkins/project/Jenkinsfile.103xplus.release:
##########
@@ -0,0 +1,91 @@
+/*
+ * 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.
+ */
+
+pipeline {
+    agent {
+        label 'ubuntu'
+    }
+
+    options {
+        timestamps()
+        timeout(time: 360, unit: 'MINUTES')
+    }
+
+    parameters {
+        string(name: 'RELEASE_VERSION', defaultValue: '10.3.0', description: 
'Exact release version, e.g. 10.3.0', trim: true)
+        string(name: 'TAG_NAME', defaultValue: '10.3.0-rc1', description: 'RC 
or Release tag name, e.g. 10.3.0-rc1', trim: true)
+        booleanParam(name: 'SKIP_TESTS', defaultValue: true, description: 
'Skip running tests during reactor build')
+        booleanParam(name: 'DEPLOY', defaultValue: true, description: 'Deploy 
artifacts to Apache Nexus staging')
+        string(name: 'STAGING_URL', defaultValue: '', description: 'Custom 
Nexus staging URL (optional)')
+        booleanParam(name: 'PUSH_TAG', defaultValue: true, description: 'Push 
the git tag to origin')
+        string(name: 'EXTRA_MAVEN_OPTS', defaultValue: '', description: 'Extra 
Maven CLI options to pass to build.sh')
+        booleanParam(name: 'DRY_RUN', defaultValue: false, description: 'Dry 
run without making remote git or staging changes')
+    }
+
+    stages {
+        stage('Initialize & Validate') {
+            steps {
+                script {
+                    assert params.RELEASE_VERSION : 'RELEASE_VERSION parameter 
is mandatory'
+                    assert params.TAG_NAME : 'TAG_NAME parameter is mandatory'
+                    currentBuild.displayName = "Release 
${params.RELEASE_VERSION} (${params.TAG_NAME})"
+                }
+            }
+        }
+
+        stage('Execute Release Scripts') {
+            steps {
+                script {
+                    def releaseCmd = "./script/release/release-all.sh 
--version ${params.RELEASE_VERSION} --tag ${params.TAG_NAME}"
+
+                    if (params.SKIP_TESTS) {
+                        releaseCmd += ' --skip-tests'
+                    }
+                    if (params.DEPLOY) {
+                        releaseCmd += ' --deploy'
+                    }
+                    if (params.STAGING_URL?.trim()) {
+                        releaseCmd += " --staging-url 
\"${params.STAGING_URL.trim()}\""
+                    }
+                    if (params.PUSH_TAG) {
+                        releaseCmd += ' --push-tag'
+                    }
+                    if (params.EXTRA_MAVEN_OPTS?.trim()) {
+                        releaseCmd += " --maven-opts 
\"${params.EXTRA_MAVEN_OPTS.trim()}\""
+                    }
+                    if (params.DRY_RUN) {
+                        releaseCmd += ' --dry-run'
+                    }
+
+                    sh """#!/usr/bin/env bash
+                    set -euo pipefail
+                    chmod +x script/release/*.sh
+                    ${releaseCmd}
+                    """

Review Comment:
   Parameter values are interpolated into a shell command string, which enables 
command injection if a job parameter contains shell metacharacters (e.g., 
`TAG_NAME` or `EXTRA_MAVEN_OPTS` containing `"; ...` or backticks). Prefer 
passing parameters as quoted shell variables (or building an argv-style list) 
and invoking `./script/release/release-all.sh` with each argument safely quoted 
rather than concatenating strings.



##########
.ci/jenkins/Jenkinsfile.103xplus.deploy:
##########
@@ -0,0 +1,246 @@
+/*
+ * 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 (isCreatePr()) {
+                        // Verify version is set
+                        assert getProjectVersion()
+                    }
+
+                    dir(getRepoName()) {
+                        checkoutRepo()
+
+                        setDeployPropertyIfNeeded('git.branch', 
getBuildBranch())
+                        setDeployPropertyIfNeeded('git.author', getGitAuthor())
+                        setDeployPropertyIfNeeded('project.version', 
getProjectVersion())
+                    }
+                }
+            }
+        }
+
+        stage('Update project version') {
+            steps {
+                script {
+                    dir(getRepoName()) {
+                        if (getProjectVersion()) {
+                            maven.mvnVersionsSet(
+                                getMavenCommand(),
+                                getProjectVersion(),
+                                !isStreamDevVersion(),
+                                false,
+                                getRootPomPath()
+                            )
+                        }
+                    }
+                }
+            }
+        }
+
+        stage('Build & Deploy repo') {
+            steps {
+                script {
+                    dir(getRepoName()) {
+                        withCredentials([usernamePassword(credentialsId: 
env.MAVEN_REPO_CREDS_ID, usernameVariable: 'REPOSITORY_USER', passwordVariable: 
'REPOSITORY_TOKEN')]) {
+                            configFileProvider([configFile(fileId: 
env.MAVEN_SETTINGS_CONFIG_FILE_ID, variable: 'MAVEN_SETTINGS_FILE')]) {
+                                String installOrDeploy = 
shouldDeployToRepository() ? 'deploy' : 'install'
+                                mavenCommand = getMavenCommand()
+                                    .withOptions(env.BUILD_MVN_OPTS ? [ 
env.BUILD_MVN_OPTS ] : [])
+                                    .withOptions(env.DROOLS_BUILD_MVN_OPTS ? [ 
env.DROOLS_BUILD_MVN_OPTS ] : [])
+                                    .withProperty('quickTests')
+                                    .withProperty('maven.test.failure.ignore', 
true)
+                                    .skipTests(params.SKIP_TESTS)
+
+                                configFileProvider([configFile(fileId: 
env.MAVEN_SETTINGS_CONFIG_FILE_ID, variable: 'MAVEN_SETTINGS_FILE')]) {
+                                    
mavenCommand.withSettingsXmlFile(MAVEN_SETTINGS_FILE).run("clean 
$installOrDeploy")
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+            post {

Review Comment:
   The PR description states the new `103xplus.deploy`/`103xplus.promote` 
pipelines are streamlined to avoid duplicating release logic by delegating to 
the new local scripts. However, this deploy pipeline still performs its own 
version update and Maven build/deploy via shared-library steps and does not 
invoke `script/release/*`. Either update the PR description to reflect the 
actual scope (only the release pipeline delegates), or adjust these pipelines 
to call the new scripts if delegation is intended.



##########
script/release/03-build.sh:
##########
@@ -0,0 +1,94 @@
+#!/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
+
+# Builds the Apache KIE repo for a release (skipping tests by default).
+#
+# Because drools, optaplanner, kogito-runtimes, and kogito-apps now all live in
+# the same reactor, a single `mvn clean install` is enough.
+#
+# Usage:
+#   ./script/release/build.sh [--skip-tests] [--maven-opts <opts>]
+#
+# Flags:
+#   --skip-tests          Skip all tests (default: tests are run)
+#   --maven-opts <opts>   Extra Maven options appended to the command
+#
+# Examples:
+#   ./script/release/build.sh --skip-tests
+#   ./script/release/build.sh --skip-tests --maven-opts "-T 4"
+
+SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
+REPO_ROOT="$(cd "${SCRIPT_DIR}/../.." && pwd)"
+
+SKIP_TESTS=false
+EXTRA_MVN_OPTS=""
+
+while [[ $# -gt 0 ]]; do
+    case $1 in
+        --skip-tests)
+            SKIP_TESTS=true
+            shift
+            ;;
+        --maven-opts)
+            EXTRA_MVN_OPTS="${2:-}"
+            shift 2
+            ;;
+        *)
+            echo "Unknown option: $1"
+            echo "Usage: $0 [--skip-tests] [--maven-opts <opts>]"
+            exit 1
+            ;;
+    esac
+done
+
+cd "${REPO_ROOT}"
+
+# ── Assemble Maven flags 
───────────────────────────────────────────────────────
+
+MVN_FLAGS="-Dfull"
+
+if [[ "${SKIP_TESTS}" == "true" ]]; then
+    MVN_FLAGS="${MVN_FLAGS} -DskipTests"
+fi
+
+if [[ -n "${EXTRA_MVN_OPTS}" ]]; then
+    MVN_FLAGS="${MVN_FLAGS} ${EXTRA_MVN_OPTS}"
+fi
+
+# ── Build 
──────────────────────────────────────────────────────────────────────
+
+echo "========================================"
+echo "Apache KIE repo — build"
+echo "Skip tests        : ${SKIP_TESTS}"
+echo "Maven flags       : ${MVN_FLAGS}"
+echo "========================================"
+echo ""
+
+# shellcheck disable=SC2086
+mvn clean install ${MVN_FLAGS}

Review Comment:
   Concatenating user-provided `EXTRA_MVN_OPTS` into a single string and 
expanding it unquoted allows command substitution and unintended shell 
interpretation (e.g., `$(...)`) when this script is driven by Jenkins 
parameters. Prefer building a Bash array of Maven args and invoking Maven with 
quoted array expansion; for “extra opts”, consider supporting repeated flags 
(e.g., `--maven-opt <arg>`) or parsing into an array without eval/command 
substitution.



##########
script/release/04-deploy-to-staging.sh:
##########
@@ -0,0 +1,164 @@
+#!/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
+
+# Deploys the locally-built JARs (already in ~/.m2) to a Nexus staging
+# repository for Apache release voting.
+#
+# By default this script runs in DRY RUN mode and will NOT push anything
+# remotely.  Pass --deploy to actually upload to Nexus.
+#
+# Usage:
+#   ./script/release/deploy-to-staging.sh --tag <rc-tag> [--deploy] 
[--staging-url <url>]
+#
+# Examples:
+#   # dry run (safe — prints the Maven command that would be run)
+#   ./script/release/deploy-to-staging.sh --tag 10.3.0-rc1
+#
+#   # actually deploy to Apache Nexus staging
+#   ./script/release/deploy-to-staging.sh --tag 10.3.0-rc1 --deploy
+#
+#   # deploy to a custom staging URL
+#   ./script/release/deploy-to-staging.sh --tag 10.3.0-rc1 --deploy \
+#       --staging-url 
https://repository.apache.org/service/local/staging/deploy/maven2
+#
+# Environment variables consumed when --deploy is active:
+#   MAVEN_SETTINGS   Path to a settings.xml with Nexus credentials (required).
+#                    The settings file must define a server with id 
"apache.releases.https"
+#                    (or the id set via --server-id) carrying the deployer 
credentials.
+#   MAVEN_GPG_PASSPHRASE   GPG passphrase for signing (required for Apache 
releases).
+
+SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
+REPO_ROOT="$(cd "${SCRIPT_DIR}/../.." && pwd)"
+
+TAG_NAME=""
+DEPLOY=false
+STAGING_URL="https://repository.apache.org/service/local/staging/deploy/maven2";
+SERVER_ID="apache.releases.https"
+
+while [[ $# -gt 0 ]]; do
+    case $1 in
+        --tag)
+            TAG_NAME="${2:-}"
+            shift 2
+            ;;
+        --deploy)
+            DEPLOY=true
+            shift
+            ;;
+        --staging-url)
+            STAGING_URL="${2:-}"
+            shift 2
+            ;;
+        --server-id)
+            SERVER_ID="${2:-}"
+            shift 2
+            ;;
+        *)
+            echo "Unknown option: $1"
+            echo "Usage: $0 --tag <rc-tag> [--deploy] [--staging-url <url>] 
[--server-id <id>]"
+            exit 1
+            ;;
+    esac
+done
+
+if [[ -z "${TAG_NAME}" ]]; then
+    echo "ERROR: --tag is required."
+    echo "Usage: $0 --tag 10.3.0-rc1 [--deploy]"
+    exit 1
+fi
+
+cd "${REPO_ROOT}"
+
+# ── Resolve the version from the tag name ────────────────────────────────────
+# Tag format: <version>-rc<N>  (e.g. 10.3.0-rc1)
+RELEASE_VERSION="$(echo "${TAG_NAME}" | sed 's/-rc[0-9]*$//')"
+
+echo "========================================"
+echo "Apache KIE repo — deploy to staging"
+echo "Tag             : ${TAG_NAME}"
+echo "Release version : ${RELEASE_VERSION}"
+echo "Staging URL     : ${STAGING_URL}"
+echo "Server ID       : ${SERVER_ID}"
+echo "Deploy (real)   : ${DEPLOY}"
+echo "========================================"
+
+# ── Verify we are on / can resolve the RC tag ────────────────────────────────
+if ! git rev-parse "${TAG_NAME}" &>/dev/null; then
+    echo ""
+    echo "ERROR: Git tag '${TAG_NAME}' not found in this repository."
+    echo "       Run rc-commit.sh first, or check out the tag manually."
+    exit 1
+fi
+
+# ── Assemble Maven flags ─────────────────────────────────────────────────────
+
+DEPLOY_MVN_FLAGS=(
+    "-DskipTests"
+    "-Dfull"
+    "-DaltDeploymentRepository=${SERVER_ID}::default::${STAGING_URL}"
+)
+
+if [[ -n "${MAVEN_SETTINGS:-}" ]]; then
+    DEPLOY_MVN_FLAGS+=("-s" "${MAVEN_SETTINGS}")
+fi
+
+if [[ -n "${MAVEN_GPG_PASSPHRASE:-}" ]]; then
+    DEPLOY_MVN_FLAGS+=("-Dgpg.passphrase=${MAVEN_GPG_PASSPHRASE}")
+fi
+
+echo ""
+if [[ "${DEPLOY}" == "false" ]]; then
+    echo "[DRY RUN] Would run from tag ${TAG_NAME}:"
+    echo ""
+    echo "  git checkout ${TAG_NAME}"
+    echo "  mvn deploy ${DEPLOY_MVN_FLAGS[*]}"
+    echo "  git checkout -"
+    echo ""
+    echo "Pass --deploy to actually upload artifacts."
+    exit 0
+fi
+
+# ── Checkout the exact tag commit before deploying ───────────────────────────
+ORIG_REF="$(git rev-parse --abbrev-ref HEAD)"
+
+echo "--- Checking out tag ${TAG_NAME} ---"
+git checkout "${TAG_NAME}"
+
+echo ""
+echo "--- Deploying to Nexus staging (${STAGING_URL}) ---"
+# shellcheck disable=SC2068
+mvn deploy ${DEPLOY_MVN_FLAGS[@]}
+
+echo ""
+echo "--- Returning to ${ORIG_REF} ---"
+git checkout "${ORIG_REF}"

Review Comment:
   `mvn deploy ${DEPLOY_MVN_FLAGS[@]}` is unquoted, so elements containing 
spaces (notably `MAVEN_SETTINGS` paths) will be split into multiple arguments 
and can break the deploy. Use quoted array expansion for the actual Maven 
invocation (and you can remove the `SC2068` suppression once fixed). Also, 
since the header states `MAVEN_SETTINGS`/`MAVEN_GPG_PASSPHRASE` are required 
when `--deploy` is active, the script should fail fast with a clear error when 
`DEPLOY=true` and required env vars are missing.



##########
script/release/release-all.sh:
##########
@@ -0,0 +1,204 @@
+#!/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
+
+# Master orchestrator for the local-first release workflow.
+#
+# Runs the individual release scripts in the correct order for a full release
+# candidate cycle (02-rc-commit.sh -> 03-build.sh -> 04-deploy-to-staging.sh).
+# Each step can also be run independently — see script/release/README.md.
+#
+# Usage:
+#   ./script/release/release-all.sh <version> [--tag <tag>] [OPTIONS]
+#   ./script/release/release-all.sh --version <version> [--tag <tag>] [OPTIONS]
+#
+# Required (one of):
+#   <version> or --version <ver>   Exact release version, e.g. 10.3.0
+#
+# Optional tags:
+#   --tag <tag> | --rc-tag <tag>   RC tag name, e.g. 10.3.0-rc1 (defaults to 
<version>-rc1)
+#   --rc                           Explicit flag indicating RC mode
+#
+# Optional build flags:
+#   --skip-tests | --skip-build    Skip tests during the build
+#   --maven-opts <opts>            Extra Maven options forwarded to build.sh
+#
+# Optional deploy/publish flags:
+#   --deploy | --publish           Deploy JARs to Nexus staging after the build
+#   --staging-url <url>            Nexus staging URL (default: Apache Nexus)
+#
+# Optional git flags:
+#   --push | --push-tag            Push the RC tag to origin after creating it
+#
+# Other:
+#   --dry-run                      Print what would happen without executing 
anything
+#
+# Examples:
+#   # Positional or flag version
+#   ./script/release/release-all.sh 10.3.0 --rc --skip-tests
+#   ./script/release/release-all.sh --version 10.3.0 --tag 10.3.0-rc1 
--skip-tests
+#
+#   # Full RC with deploy to Apache Nexus staging and push tag to origin
+#   ./script/release/release-all.sh 10.3.0 --tag 10.3.0-rc1 --skip-tests 
--deploy --push-tag
+
+SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
+REPO_ROOT="$(cd "${SCRIPT_DIR}/../.." && pwd)"
+
+RELEASE_VERSION=""
+TAG_NAME=""
+SKIP_TESTS=false
+EXTRA_MVN_OPTS=""
+DEPLOY=false
+STAGING_URL=""
+PUSH_TAG=false
+DRY_RUN=false
+
+while [[ $# -gt 0 ]]; do
+    case $1 in
+        --version)       RELEASE_VERSION="${2:-}"; shift 2 ;;
+        --tag|--rc-tag)  TAG_NAME="${2:-}"; shift 2 ;;
+        --rc)            shift ;; # Accepted for parity with tools repo
+        --skip-tests|--skip-build) SKIP_TESTS=true; shift ;;
+        --maven-opts)    EXTRA_MVN_OPTS="${2:-}"; shift 2 ;;
+        --deploy|--publish) DEPLOY=true; shift ;;
+        --staging-url)   STAGING_URL="${2:-}"; shift 2 ;;
+        --push|--push-tag) PUSH_TAG=true; shift ;;
+        --dry-run)       DRY_RUN=true; shift ;;
+        *)
+            if [[ -z "${RELEASE_VERSION}" && ! "$1" =~ ^- ]]; then
+                RELEASE_VERSION="$1"
+                shift
+            else
+                echo "Unknown option: $1"
+                echo "Usage: $0 [<version> | --version <version>] [--tag 
<tag>] [OPTIONS]"
+                exit 1
+            fi
+            ;;
+    esac
+done
+
+if [[ -z "${RELEASE_VERSION}" ]]; then
+    echo "ERROR: Version is required."
+    echo "Usage: $0 10.3.0 [--tag 10.3.0-rc1] [OPTIONS]"
+    exit 1
+fi
+
+if [[ -z "${TAG_NAME}" ]]; then
+    TAG_NAME="${RELEASE_VERSION}-rc1"
+fi
+
+cd "${REPO_ROOT}"
+
+echo ""
+echo "=========================================="
+echo "Apache KIE repo — release-all"
+echo "Version         : ${RELEASE_VERSION}"
+echo "RC tag          : ${TAG_NAME}"
+echo "Skip tests      : ${SKIP_TESTS}"
+echo "Deploy staging  : ${DEPLOY}"
+echo "Push tag        : ${PUSH_TAG}"
+echo "Dry run         : ${DRY_RUN}"
+echo "=========================================="
+echo ""
+
+# ── Helper ───────────────────────────────────────────────────────────────────
+
+run_step() {
+    local step_name="$1"
+    shift
+    echo ""
+    echo "────────────────────────────────────────"
+    echo "STEP: ${step_name}"
+    echo "────────────────────────────────────────"
+    if [[ "${DRY_RUN}" == "true" ]]; then
+        echo "[DRY RUN] $*"
+    else
+        "$@"
+    fi
+    echo "✅  ${step_name} — done"
+}
+
+# ── STEP 1 (Automation D.1): R commit + RC tag ───────────────────────────────
+
+RC_COMMIT_SCRIPT="${SCRIPT_DIR}/02-rc-commit.sh"
+[[ ! -f "${RC_COMMIT_SCRIPT}" ]] && 
RC_COMMIT_SCRIPT="${SCRIPT_DIR}/rc-commit.sh"
+
+RC_COMMIT_ARGS=("${RC_COMMIT_SCRIPT}" "--version" "${RELEASE_VERSION}" "--tag" 
"${TAG_NAME}")
+[[ "${PUSH_TAG}" == "true" ]] && RC_COMMIT_ARGS+=("--push")
+[[ "${DRY_RUN}" == "true" ]]  && RC_COMMIT_ARGS+=("--dry-run")
+
+run_step "R commit + RC tag (02-rc-commit.sh)" "${RC_COMMIT_ARGS[@]}"
+
+# ── STEP 2 (Automation D.2): Build ───────────────────────────────────────────
+
+BUILD_SCRIPT="${SCRIPT_DIR}/03-build.sh"
+[[ ! -f "${BUILD_SCRIPT}" ]] && BUILD_SCRIPT="${SCRIPT_DIR}/build.sh"
+
+BUILD_ARGS=("${BUILD_SCRIPT}")
+[[ "${SKIP_TESTS}" == "true" ]]       && BUILD_ARGS+=("--skip-tests")
+[[ -n "${EXTRA_MVN_OPTS}" ]]          && BUILD_ARGS+=("--maven-opts" 
"${EXTRA_MVN_OPTS}")
+
+# The build must run at the RC tag commit. 02-rc-commit.sh leaves HEAD on the
+# development branch, so we check out the tag, build, then return.
+if [[ "${DRY_RUN}" == "true" ]]; then
+    run_step "Build @ ${TAG_NAME} (03-build.sh)" echo "[DRY RUN] git checkout 
${TAG_NAME} && ${BUILD_ARGS[*]} && git checkout -"
+else
+    echo ""
+    echo "────────────────────────────────────────"
+    echo "STEP: Build @ ${TAG_NAME} (03-build.sh)"
+    echo "────────────────────────────────────────"
+    git checkout "${TAG_NAME}"
+    "${BUILD_ARGS[@]}"
+    git checkout -
+    echo "✅  Build — done"
+fi

Review Comment:
   In dry-run mode this nests dry-run messaging (`run_step` already prefixes 
output) and prints a command string via `echo` rather than showing the actual 
argv that would be executed. Consider having `run_step` accept a human-readable 
message for dry-run output (or pass a `bash -lc '...'` string consistently) so 
the dry-run output is clear and not duplicated.



##########
script/release/01-update-version.sh:
##########
@@ -0,0 +1,97 @@
+#!/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
+
+# Updates the Maven version across the Apache KIE repo (drools + optaplanner +
+# kogito-runtimes + kogito-apps are all modules of the same root POM since the
+# 10.3.x consolidation).
+#
+# Usage:
+#   ./script/release/update-version.sh <version>
+#
+# Examples:
+#   ./script/release/update-version.sh 10.3.999-SNAPSHOT   # dev/stream version
+#   ./script/release/update-version.sh 10.3.0              # release version
+#
+# The script also updates the data-index ephemeral image tag property that 
lives
+# inside kogito-quarkus (was a separate step in the old multi-repo flow).
+
+SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
+REPO_ROOT="$(cd "${SCRIPT_DIR}/../.." && pwd)"
+
+NEW_VERSION="${1:-}"
+
+if [[ -z "${NEW_VERSION}" ]]; then
+    echo "Usage: $0 <version>"
+    echo "  e.g. $0 10.3.999-SNAPSHOT"
+    echo "  e.g. $0 10.3.0"
+    exit 1
+fi
+
+# Derive the stream name (e.g. 10.3.0 → 10.3.x, 10.3.999-SNAPSHOT → 10.3.x).
+# Used for the data-index image tag property.
+STREAM_NAME="$(echo "${NEW_VERSION}" | sed 's/^\([0-9]*\.[0-9]*\)\..*/\1.x/')"
+
+# Detect the current version from the root POM so we can pass -DoldVersion,
+# which skips the full reactor scan and is much faster on a large multi-module
+# repo like this one.
+CURRENT_VERSION="$(mvn -q help:evaluate -Dexpression=project.version 
-DforceStdout -f "${REPO_ROOT}/pom.xml" 2>/dev/null)"
+
+echo "========================================"
+echo "Apache KIE repo — version update"
+echo "Current version : ${CURRENT_VERSION}"
+echo "New version     : ${NEW_VERSION}"
+echo "Stream name     : ${STREAM_NAME}"
+echo "========================================"
+
+cd "${REPO_ROOT}"
+
+echo ""
+echo "--- Updating all Maven module versions ---"
+mvn versions:set \
+    -DoldVersion="${CURRENT_VERSION}" \
+    -DnewVersion="${NEW_VERSION}" \
+    -DprocessAllModules \
+    -DgenerateBackupPoms=false

Review Comment:
   If `mvn help:evaluate` fails (e.g., Maven not available, POM not 
resolvable), `CURRENT_VERSION` becomes empty and the script continues with 
`-DoldVersion=""`, which can lead to unintended or failed version updates. Add 
an explicit check after resolving `CURRENT_VERSION` and abort with an 
actionable error message if it’s empty.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


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

Reply via email to