You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@kie.apache.org by "Kusuma04-dev (via GitHub)" <gi...@apache.org> on 2026/09/18 08:33:40 UTC
[PR] 10.3.x+ stream: Re-write drools release jobs to be local scripts invoked in Apache Jenkins and remove old ones. [incubator-kie]
Kusuma04-dev opened a new pull request, #7123:
URL: https://github.com/apache/incubator-kie/pull/7123
This PR introduces local-first release automation scripts for the consolidated `incubator-kie` repository and updates the Jenkins release pipelines to use them.
**What the Release Scripts Do:**
- `script/release/update-version.sh`: Updates project versions across all modules.
- `script/release/rc-commit.sh`: Automates the release commit and creates the release candidate tag.
- `script/release/build.sh`: Runs the full Maven build and packages all reactor modules.
- `script/release/deploy-to-staging.sh`: Signs artifacts with GPG and deploys them to the Apache Nexus staging repository.
- `script/release/tag-release.sh`: Promotes an approved RC tag to the official release tag.
- `script/release/release-all.sh`: Master orchestrator that executes the entire RC workflow in sequence.
**Jenkins Pipeline Updates:**
- `.ci/jenkins/project/Jenkinsfile.release`: Updated to delegate the release workflow directly to `script/release/release-all.sh`.
- `.ci/jenkins/Jenkinsfile.deploy` & `.ci/jenkins/Jenkinsfile.promote`: Streamlined to avoid duplicating release tagging and signing logic.
- **Backups Preserved**: Kept `.backup` copies of all original Jenkinsfiles (`Jenkinsfile.release.backup`, `Jenkinsfile.deploy.backup`, `Jenkinsfile.promote.backup`) to ensure zero disruption until the new pipelines are verified in CI.
For testing Artifacts generated in local dry run, are available in :
https://github.com/Kusuma04-dev/kie-release-10.3/tree/main/artifacts_kie_tools
--
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: commits-unsubscribe@kie.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@kie.apache.org
For additional commands, e-mail: commits-help@kie.apache.org
Re: [PR] kie-issues#2404: 10.3.x+ stream: Re-write drools release jobs to be local scripts invoked in Apache Jenkins and remove old ones. [incubator-kie]
Posted by "Copilot (via GitHub)" <gi...@apache.org>.
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: commits-unsubscribe@kie.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@kie.apache.org
For additional commands, e-mail: commits-help@kie.apache.org
Re: [PR] [incubator-kie#7140] 10.3.x+ stream: Re-write drools release jobs to be local scripts invoked in Apache Jenkins and remove old ones. [incubator-kie]
Posted by "Copilot (via GitHub) via commits" <co...@kie.apache.org>.
Copilot commented on code in PR #7123:
URL: https://github.com/apache/incubator-kie/pull/7123#discussion_r4492209726
##########
.ci/jenkins/Jenkinsfile.103xplus.release-candidate:
##########
@@ -0,0 +1,211 @@
+/*
+ * 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.
+ */
+
+// 10.3.x+ release pipeline — fully independent, no kogito-pipelines / jobs.groovy dependency.
+// - No @Library, no DSL-injected env vars, no drools-deploy / drools-promote downstream jobs
+// - Create a plain "Pipeline script from SCM" job pointing at this file and run it
+// with a few parameters. Everything it needs is a parameter (with a default).
+// - Runs script/release/release-all.sh (R commit + RC tag -> build -> Nexus staging)
+//
+// MANDATORY parameters : RELEASE_VERSION, TAG_NAME
+// Real RC run : DEPLOY=true, PUSH_TAG=true, DRY_RUN=false (the defaults)
+// Branch cut (once per minor, before rc1 only):
+// CREATE_STREAM_BRANCH=true -> creates X.Y.x from main,
+// sets X.Y.999-SNAPSHOT, pushes it, then continues the RC on X.Y.x.
+// Leave it false for rc2, final and patch releases (branch already exists).
+
+pipeline {
+ agent {
+ label 'ubuntu'
+ }
+
+ tools {
+ maven 'maven_3.9.16'
+ jdk 'jdk_17_latest'
+ }
+
+ options {
+ timestamps()
+ timeout(time: 360, unit: 'MINUTES')
+ }
+
+ parameters {
+ string(name: 'RELEASE_VERSION', defaultValue: '', description: 'MANDATORY. Exact release version, e.g. 10.3.0', trim: true)
+ string(name: 'TAG_NAME', defaultValue: '', description: 'MANDATORY. RC tag name, e.g. 10.3.0-rc1 (must start with RELEASE_VERSION and be a new tag)', trim: true)
+ booleanParam(name: 'CREATE_STREAM_BRANCH', defaultValue: false, description: 'Branch cut: create X.Y.x (derived from RELEASE_VERSION) from main, set X.Y.999-SNAPSHOT and push it BEFORE building the RC. Only for the first RC of a new minor (e.g. 10.3.0-rc1). Fails if X.Y.x already exists')
+ 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')
+
+ // Jenkins IDs — defaults match the existing KIE Jenkins; override only if they differ.
+ string(name: 'MAVEN_SETTINGS_CONFIG_FILE_ID', defaultValue: 'kie-release-authn-settings', description: 'Config File Provider ID of the Maven settings.xml (must define server "apache.releases.https")', trim: true)
+ string(name: 'GPG_KEY_CREDS_ID', defaultValue: 'GPG_KEY_FILE', description: 'Secret FILE credential ID holding the armored GPG private key', trim: true)
+ string(name: 'GPG_PASSPHRASE_CREDS_ID', defaultValue: '', description: 'Optional. Secret TEXT credential ID holding the GPG key passphrase. Leave empty if the key has no passphrase (KIE release key has none)', trim: true)
+ string(name: 'GIT_PUSH_CREDS_ID', defaultValue: '84811880-2025-45b6-a44c-2f33bef30ad2', description: 'Username/password credential ID used to push the RC tag to GitHub', trim: true)
+ }
+
+ stages {
+ stage('Initialize & Validate') {
+ steps {
+ script {
+ if (!params.RELEASE_VERSION?.trim()) {
+ error 'RELEASE_VERSION parameter is mandatory (e.g. 10.3.0)'
+ }
+ if (!params.TAG_NAME?.trim()) {
+ error 'TAG_NAME parameter is mandatory (e.g. 10.3.0-rc1)'
+ }
+ if (!params.TAG_NAME.startsWith(params.RELEASE_VERSION)) {
+ error "TAG_NAME '${params.TAG_NAME}' must start with RELEASE_VERSION '${params.RELEASE_VERSION}'"
+ }
Review Comment:
A value such as `10.3$(...)` for RELEASE_VERSION passes the prefix check when TAG_NAME has the same prefix and survives the stream-branch replacement. It is then interpolated into the shell commands at lines 136–141, executing the substitution while release credentials are bound. Require a numeric X.Y.Z version and its matching X.Y.Z-rcN tag before constructing shell commands.
##########
script/release/05-tag-release.sh:
##########
@@ -0,0 +1,134 @@
+#!/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
+
+# Promotes an approved RC tag to the final release tag (AUTOMATION F).
+#
+# After the community vote passes on an RC (e.g. 10.3.0-rc2), this script
+# creates the final release tag pointing to the same commit:
+#
+# git tag 10.3.0 10.3.0-rc2
+#
+# By default the tag is created locally only. Pass --push to publish it.
+#
+# Usage:
+# ./script/release/05-tag-release.sh --rc-tag <rc-tag> [--push] [--dry-run]
+#
+# Examples:
+# ./script/release/05-tag-release.sh --rc-tag 10.3.0-rc2
+# ./script/release/05-tag-release.sh --rc-tag 10.3.0-rc2 --push
+
+SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
+REPO_ROOT="$(cd "${SCRIPT_DIR}/../.." && pwd)"
+
+RC_TAG=""
+PUSH=false
+DRY_RUN=false
+
+while [[ $# -gt 0 ]]; do
+ case $1 in
+ --rc-tag)
+ RC_TAG="${2:-}"
+ shift 2
+ ;;
+ --push)
+ PUSH=true
+ shift
+ ;;
+ --dry-run)
+ DRY_RUN=true
+ shift
+ ;;
+ *)
+ echo "Unknown option: $1"
+ echo "Usage: $0 --rc-tag <rc-tag> [--push] [--dry-run]"
+ exit 1
+ ;;
+ esac
+done
+
+if [[ -z "${RC_TAG}" ]]; then
+ echo "ERROR: --rc-tag is required."
+ echo "Usage: $0 --rc-tag 10.3.0-rc2 [--push]"
+ exit 1
+fi
+
+if [[ ! "${RC_TAG}" =~ -rc[0-9]+$ ]]; then
+ echo "ERROR: --rc-tag must be an RC tag ending in -rc<N> (e.g. 10.3.0-rc2), got '${RC_TAG}'."
+ exit 1
+fi
+
+# Derive the final release tag (strip -rcN suffix).
+RELEASE_TAG="$(echo "${RC_TAG}" | sed 's/-rc[0-9]*$//')"
+
+cd "${REPO_ROOT}"
+
+# Verify the RC tag exists.
+if ! git rev-parse "${RC_TAG}" &>/dev/null; then
+ echo "ERROR: RC tag '${RC_TAG}' not found."
+ echo " Make sure you have fetched the tag: git fetch origin ${RC_TAG}"
+ exit 1
+fi
+
+RC_COMMIT="$(git rev-parse "${RC_TAG}")"
+
+echo "========================================"
+echo "Apache KIE repo — tag release"
+echo "RC tag : ${RC_TAG} (${RC_COMMIT:0:12})"
+echo "Release tag : ${RELEASE_TAG}"
+echo "Push : ${PUSH}"
+echo "Dry run : ${DRY_RUN}"
+echo "========================================"
+
+if [[ "${DRY_RUN}" == "true" ]]; then
+ echo ""
+ echo "[DRY RUN] Would execute:"
+ echo " git tag -a ${RELEASE_TAG} ${RC_TAG} -m \"Release ${RELEASE_TAG}\""
+ if [[ "${PUSH}" == "true" ]]; then
+ echo " git push origin ${RELEASE_TAG}"
+ fi
+ exit 0
+fi
+
+echo ""
+echo "--- Creating release tag ${RELEASE_TAG} at ${RC_TAG} ---"
+git tag -a "${RELEASE_TAG}" "${RC_TAG}" -m "Release ${RELEASE_TAG}"
Review Comment:
If the final tag is pushed but GitHub Release creation fails, rerunning the promote pipeline stops here because the tag already exists. Allow an existing final tag only when it resolves to the approved RC commit, then continue to the push; fail without changing it if it points elsewhere.
##########
.ci/jenkins/Jenkinsfile.103xplus.release-promote:
##########
@@ -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.
+ */
+
+// 10.3.x+ promote / tag-release pipeline for incubator-kie.
+// Run after the IPMC vote passes to:
+// 1. Create and push the official release Git tag (e.g. 10.3.0) pointing to the approved RC commit.
+// 2. Create the GitHub Release for incubator-kie.
+
+pipeline {
+ agent {
+ label 'ubuntu'
+ }
+
+ tools {
+ maven 'maven_3.9.16'
+ jdk 'jdk_17_latest'
+ }
+
+ options {
+ timestamps()
+ timeout(time: 60, unit: 'MINUTES')
+ }
+
+ parameters {
+ string(name: 'PROJECT_VERSION', defaultValue: '', description: 'Release version (e.g. 10.3.0)', trim: true)
+ string(name: 'GIT_TAG', defaultValue: '', description: 'Approved RC tag (e.g. 10.3.0-rc1)', trim: true)
+ string(name: 'BUILD_BRANCH_NAME', defaultValue: '', description: 'Stream branch name (e.g. 10.3.x)', trim: true)
+ string(name: 'GIT_AUTHOR_PUSH_CREDS_ID', defaultValue: '84811880-2025-45b6-a44c-2f33bef30ad2', description: 'GitHub push credentials ID', trim: true)
+ }
+
+ stages {
+ stage('Initialization') {
+ steps {
+ script {
+ cleanWs()
+
+ assert params.PROJECT_VERSION : 'PROJECT_VERSION is required (e.g. 10.3.0)'
+ assert params.GIT_TAG : 'GIT_TAG (approved RC tag, e.g. 10.3.0-rc1) is required'
+ assert params.BUILD_BRANCH_NAME : 'BUILD_BRANCH_NAME (e.g. 10.3.x) is required'
+ assert params.GIT_TAG.startsWith("${params.PROJECT_VERSION}-rc") : "GIT_TAG '${params.GIT_TAG}' must be an RC tag for PROJECT_VERSION '${params.PROJECT_VERSION}' (e.g. ${params.PROJECT_VERSION}-rc1)"
Review Comment:
Prefix validation accepts a tag such as `10.3.0-rc1$(...)`. That value is interpolated directly into the shell commands at lines 92 and 96, so command substitutions execute before Git validates the tag, with the GitHub credential available. Validate the complete numeric release/RC formats and the stream branch format, or safely quote all parameter values passed to the shell.
##########
script/release/04-deploy-to-staging.sh:
##########
@@ -0,0 +1,193 @@
+#!/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/04-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/04-deploy-to-staging.sh --tag 10.3.0-rc1
+#
+# # actually deploy to Apache Nexus staging
+# ./script/release/04-deploy-to-staging.sh --tag 10.3.0-rc1 --deploy
+#
+# # deploy to a custom staging URL
+# ./script/release/04-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).
+# Passed to the GPG agent via the gpg-agent pinentry loopback
+# mechanism; NOT exposed on the Maven command line.
+
+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
+
+# Check there are no uncommitted changes (staged, unstaged, or untracked) before
+# deploying. Any local modifications could otherwise be included in the deployed artifacts.
+if ! git diff --quiet || ! git diff --cached --quiet; then
+ echo "ERROR: There are uncommitted changes in the working tree."
+ echo " Commit, stash, or clean them before running this script."
+ exit 1
+fi
+if [[ -n "$(git ls-files --others --exclude-standard)" ]]; then
+ echo "ERROR: There are untracked files in the working tree:"
+ git ls-files --others --exclude-standard | sed 's/^/ /'
+ echo " Remove or .gitignore them before running this script."
+ exit 1
+fi
+
+# ── Assemble Maven flags ─────────────────────────────────────────────────────
+
+DEPLOY_MVN_FLAGS=(
+ "-DskipTests"
+ "-Dfull"
+ # Activate the apache-release profile so the source/javadoc and GPG-signing
+ # goals defined there are executed (required for Apache releases).
+ "-Papache-release"
+ "-DaltDeploymentRepository=${SERVER_ID}::default::${STAGING_URL}"
+)
+
+if [[ -n "${MAVEN_SETTINGS:-}" ]]; then
+ DEPLOY_MVN_FLAGS+=("-s" "${MAVEN_SETTINGS}")
+fi
+
+# NOTE: MAVEN_GPG_PASSPHRASE is intentionally NOT added to the Maven command
+# line — exposing it there would print it in captured console logs.
+# The standard GPG Maven plugin (version 3+) reads the passphrase from the
+# environment variable MAVEN_GPG_PASSPHRASE via pinentry-loopback automatically.
+# For older plugin versions, configure loopback in ~/.gnupg/gpg-agent.conf:
+# allow-loopback-pinentry
+# and pass: -Dgpg.useagent=false -Dgpg.loopback=true in MAVEN_SETTINGS.
+
+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 ───────────────────────────
+# Save the original ref as the commit SHA when in detached HEAD state (e.g.,
+# Jenkins SCM checkout). `git rev-parse --abbrev-ref HEAD` returns "HEAD" when
+# detached, which cannot be used to restore the checkout afterwards.
+if git symbolic-ref --quiet HEAD &>/dev/null; then
+ ORIG_REF="$(git rev-parse --abbrev-ref HEAD)"
+else
+ ORIG_REF="$(git rev-parse HEAD)"
+fi
+
+echo "--- Checking out tag ${TAG_NAME} ---"
+git checkout "${TAG_NAME}"
+
+echo ""
+echo "--- Deploying to Nexus staging (${STAGING_URL}) ---"
+mvn deploy "${DEPLOY_MVN_FLAGS[@]}"
+
+echo ""
+echo "--- Returning to ${ORIG_REF} ---"
+git checkout "${ORIG_REF}"
Review Comment:
A signing or Nexus deployment failure exits immediately under `set -e`, so the saved ORIG_REF is never restored and the working tree remains detached at the RC. Use an EXIT trap around checkout/deployment to restore the original ref on failure as well as success.
##########
script/release/release-all.sh:
##########
@@ -0,0 +1,201 @@
+#!/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"
+
+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"
+
+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 -
Review Comment:
With `set -e`, a failed build exits before the following checkout, leaving the caller detached at the release commit instead of on the original development branch. A subsequent release-all invocation then starts from the release version rather than the stream snapshot. Restore the original branch or detached commit in an EXIT trap so build failures preserve the caller's checkout too.
##########
.ci/ci-image/start-docker.sh:
##########
@@ -0,0 +1,8 @@
+#!/bin/bash
Review Comment:
These new shell sources lack the ASF license header required by `docs/CONVENTIONS.md:40–41` and checked in CI. Add the standard header after the shebang, as in `.ci/jenkins/dsl/test.sh:3–20`; the same change is needed in `.ci/ci-image/entrypoint.sh:1`, `.ci/ci-image/wait-for-process.sh:1`, and `.ci/ci-image/wait-for-docker.sh:1`.
--
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: commits-unsubscribe@kie.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@kie.apache.org
For additional commands, e-mail: commits-help@kie.apache.org
Re: [PR] kie-issues#2404: 10.3.x+ stream: Re-write drools release jobs to be local scripts invoked in Apache Jenkins and remove old ones. [incubator-kie]
Posted by "Kusuma04-dev (via GitHub)" <gi...@apache.org>.
Kusuma04-dev commented on PR #7123:
URL: https://github.com/apache/incubator-kie/pull/7123#issuecomment-5728804005
Thanks @jomarko ,
You don't need to run a full build. Complete build logs and testable artifacts are already available in the [kie-release-10.3/evidence](https://github.com/Kusuma04-dev/kie-release-10.3/tree/main/artifacts_kie_tools) repository for verification.
- Authorized users: Anyone can run local builds or dry-runs. Official releases are executed through Jenkins.
- Credentials: No credentials are needed for local RC builds or testing. Publishing credentials (NPM, VSCE, GPG, etc.) are pre-configured in Jenkins and used only for official releases.
- Output and upload location: For a local dry-run, the scripts generate artifacts under release-artifacts (in kie-tools) and the local .m2 repository (in kie). If the release is run through Jenkins, the generated artifacts are uploaded to Apache SVN dev and Nexus Staging for voting, and are published to public registries after approval.
- CI vs local execution: Official releases run on Jenkins, but the release scripts can also be executed locally.
Dry-run commands:
- incubator-kie:
./script/release/release-all.sh --version 10.3.0 --tag 10.3.0-rc1 --skip-tests --dry-run
- incubator-kie-tools:
./scripts/release/release-all.sh 10.3.0 --rc --skip-build
- Repository isolation: Yes. The release scripts are self-contained within their respective repositories (incubator-kie and incubator-kie-tools).
- Build scope: Yes. Each script performs a clean production build of all modules in its repository for the specified release version and commit.
--
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: commits-unsubscribe@kie.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@kie.apache.org
For additional commands, e-mail: commits-help@kie.apache.org
Re: [PR] kie-issues#2404: 10.3.x+ stream: Re-write drools release jobs to be local scripts invoked in Apache Jenkins and remove old ones. [incubator-kie]
Posted by "Kusuma04-dev (via GitHub)" <gi...@apache.org>.
Kusuma04-dev commented on PR #7123:
URL: https://github.com/apache/incubator-kie/pull/7123#issuecomment-5813893877
Thanks @tiagobento for the review!
**1. .backup files — create new files, leave old ones as-is**
Done — created Jenkinsfile.103xplus.release-candidate and Jenkinsfile.103xplus.release-publish as new files, leaving all existing Jenkinsfiles untouched.
**2. Remove JITEXECUTOR_NATIVE flags from new release jobs**
Removed — JITEXECUTOR_NATIVE flags and GraalVM JDK for native references are not present in either new Jenkinsfile.
**3. Maven M2 repository missing from kie-release-10.3**
Added — the artefacts generated in local m2 are now present in https://github.com/Kusuma04-dev/kie-release-10.3/tree/main/kie_artifacts/org
**4. Standardize terminology + number/letter the scripts**
Done — scripts are prefixed 01–05 in both repos and automations are labelled A/D/E/F/G in release-procedure-10.3.md with consistent --rc/--publish flag naming across both incubator-kie and incubator-kie-tools.
**5. repo/RELEASING.md pointing to incubator-kie-website as single source of truth**
Done — Added repo/RELEASING.md in incubator-kie-tools.
**6. Align CLI arguments between the two repos**
Done — both repos now use the same release-all.sh <version> --rc / --publish pattern, with incubator-kie's release-all.sh accepting --rc and --publish as aliases for parity.
**7. "Drools unified repo" → "KIE repo"**
Fixed — all references now say "KIE repo" and the Repositories Matrix table label has been updated accordingly.
**8.data-index ephemeral image tag**
This is a historical artifact — packages/kogito-data-index-ephemeral-image no longer exists in the repo, so the references in the old Jenkinsfiles are stale and it can be removed.
--
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: commits-unsubscribe@kie.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@kie.apache.org
For additional commands, e-mail: commits-help@kie.apache.org
Re: [PR] kie-issues#2404: 10.3.x+ stream: Re-write drools release jobs to be local scripts invoked in Apache Jenkins and remove old ones. [incubator-kie]
Posted by "Kusuma04-dev (via GitHub)" <gi...@apache.org>.
Kusuma04-dev closed pull request #7123: kie-issues#2404: 10.3.x+ stream: Re-write drools release jobs to be local scripts invoked in Apache Jenkins and remove old ones.
URL: https://github.com/apache/incubator-kie/pull/7123
--
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: commits-unsubscribe@kie.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@kie.apache.org
For additional commands, e-mail: commits-help@kie.apache.org
Re: [PR] [incubator-kie#7140] 10.3.x+ stream: Re-write drools release jobs to be local scripts invoked in Apache Jenkins and remove old ones. [incubator-kie]
Posted by "tiagobento (via GitHub)" <gi...@apache.org>.
tiagobento commented on PR #7123:
URL: https://github.com/apache/incubator-kie/pull/7123#issuecomment-6433713929
I made some comments in the related Release Procedure PR (https://github.com/apache/incubator-kie-website/pull/62).
--
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: commits-unsubscribe@kie.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@kie.apache.org
For additional commands, e-mail: commits-help@kie.apache.org
Re: [PR] kie-issues#2404: 10.3.x+ stream: Re-write drools release jobs to be local scripts invoked in Apache Jenkins and remove old ones. [incubator-kie]
Posted by "Copilot (via GitHub)" <gi...@apache.org>.
Copilot commented on code in PR #7123:
URL: https://github.com/apache/incubator-kie/pull/7123#discussion_r4223227255
##########
.ci/jenkins/Jenkinsfile.103xplus.promote:
##########
@@ -0,0 +1,256 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import org.jenkinsci.plugins.workflow.libs.Library
+@Library('jenkins-pipeline-shared-libraries')_
+
+import org.kie.jenkins.MavenCommand
+
+deployProperties = [:]
+pipelineProperties = [:]
+
+pipeline {
+ agent {
+ docker {
+ image env.AGENT_DOCKER_BUILDER_IMAGE
+ args env.AGENT_DOCKER_BUILDER_ARGS
+ label util.avoidFaultyNodes()
+ }
+ }
+
+ options {
+ timestamps()
+ timeout(time: 180, unit: 'MINUTES')
+ }
+
+ environment {
+ DROOLS_CI_EMAIL_TO = credentials("${JENKINS_EMAIL_CREDS_ID}")
+ }
+
+ stages {
+ stage('Initialization') {
+ steps {
+ script {
+ cleanWs()
+
+ if (params.DISPLAY_NAME != '') {
+ currentBuild.displayName = params.DISPLAY_NAME
+ }
+
+ readDeployProperties()
+
+ assert getProjectVersion()
+ assert getBuildBranch() == util.getReleaseBranchFromVersion(getProjectVersion())
+ }
+ }
+ }
+
+ stage('Merge deploy PR and tag') {
+ steps {
+ script {
+ dir(getRepoName()) {
+ approveAndMergePR(getDeployPrLink())
+ checkoutRepo()
+ tagLatest()
+ }
+ }
+ }
+ }
+
+ stage('Create release') {
+ steps {
+ script {
+ dir(getRepoName()) {
+ checkoutRepo()
+ if (githubscm.isReleaseExist(getGitTag(), getGitAuthorCredsId())) {
+ githubscm.deleteRelease(getGitTag(), getGitAuthorPushCredsId())
+ }
+ githubscm.createReleaseWithGeneratedReleaseNotes(getGitTag(), getBuildBranch(), githubscm.getPreviousTagFromVersion(getGitTag()), getGitAuthorPushCredsId())
+ githubscm.updateReleaseBody(getGitTag(), getGitAuthorPushCredsId())
+ }
+ }
+ }
+ }
+
+ stage('Upload drools binaries and documentation') {
+ when {
+ expression { return isMainStream() }
+ }
+ steps {
+ script {
+ configFileProvider([configFile(fileId: env.MAVEN_SETTINGS_CONFIG_FILE_ID, variable: 'MAVEN_SETTINGS_FILE')]) {
+ getMavenCommand()
+ .withOptions(env.DROOLS_BUILD_MVN_OPTS ? [ env.DROOLS_BUILD_MVN_OPTS ] : [])
+ .withOptions(env.BUILD_MVN_OPTS_CURRENT ? [ env.BUILD_MVN_OPTS_CURRENT ] : [])
+ .inDirectory(getRepoName())
+ .skipTests(true)
+ .withProperty('full')
+ .withSettingsXmlFile(MAVEN_SETTINGS_FILE)
+ .run('clean install')
+ }
+ uploadFileMgmt(getRepoName())
+ }
+ }
+ }
+ }
+
+ post {
+ unsuccessful {
+ sendNotification()
+ }
+ cleanup {
+ script {
+ util.cleanNode()
+ }
+ }
+ }
+}
+
+void sendNotification() {
+ if (params.SEND_NOTIFICATION) {
+ mailer.sendMarkdownTestSummaryNotification('Promote', "[${getBuildBranch()}] Drools", [env.DROOLS_CI_EMAIL_TO])
+ } else {
+ echo 'No notification sent per configuration'
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// Deployment properties
+//////////////////////////////////////////////////////////////////////////////
+
+void readDeployProperties() {
+ String deployUrl = params.DEPLOY_BUILD_URL
+ if (deployUrl != '') {
+ if (!deployUrl.endsWith('/')) {
+ deployUrl += '/'
+ }
+ sh "wget ${deployUrl}artifact/${PROPERTIES_FILE_NAME} -O ${PROPERTIES_FILE_NAME}"
+ deployProperties = readProperties file: PROPERTIES_FILE_NAME
+ // echo all properties
+ echo deployProperties.collect { entry -> "${entry.key}=${entry.value}" }.join('\n')
+ }
+}
+
+boolean hasDeployProperty(String key) {
+ return deployProperties[key] != null
+}
+
+String getDeployProperty(String key) {
+ if (hasDeployProperty(key)) {
+ return deployProperties[key]
+ }
+ return ''
+}
+
+String getParamOrDeployProperty(String paramKey, String deployPropertyKey) {
+ if (params[paramKey] != '') {
+ return params[paramKey]
+ }
+ return getDeployProperty(deployPropertyKey)
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// Getter / Setter
+//////////////////////////////////////////////////////////////////////////////
+
+String getRepoName() {
+ return env.REPO_NAME
+}
+
+String getProjectVersion() {
+ return getParamOrDeployProperty('PROJECT_VERSION', 'project.version')
+}
+
+String getGitTag() {
+ return params.GIT_TAG != '' ? params.GIT_TAG : getProjectVersion()
+}
+
+String getBuildBranch() {
+ return params.BUILD_BRANCH_NAME
+}
+
+String getGitAuthor() {
+ return env.GIT_AUTHOR
+}
+
+String getGitAuthorCredsId() {
+ return env.GIT_AUTHOR_CREDS_ID
+}
+
+String getGitAuthorPushCredsId() {
+ return env.GIT_AUTHOR_PUSH_CREDS_ID
+}
+
+String getDeployPrLink() {
+ return getDeployProperty("${getRepoName()}.pr.link")
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// Git
+//////////////////////////////////////////////////////////////////////////////
+
+void checkoutRepo() {
+ deleteDir()
+ checkout(githubscm.resolveRepository(getRepoName(), getGitAuthor(), getBuildBranch(), false, getGitAuthorCredsId()))
+ // need to manually checkout branch since on a detached branch after checkout command
+ sh "git checkout ${getBuildBranch()}"
+}
+
+void approveAndMergePR(String prLink) {
+ if (prLink?.trim()) {
+ githubscm.approvePR(prLink, getGitAuthorPushCredsId())
+ githubscm.mergePR(prLink, getGitAuthorPushCredsId())
+ }
+}
+
+void tagLatest() {
+ if (getGitTag()) {
+ githubscm.tagLocalAndRemoteRepository('origin', getGitTag(), getGitAuthorPushCredsId(), env.BUILD_TAG, true)
Review Comment:
`checkoutRepo()` selects `getBuildBranch()`, so this creates the final tag at the branch tip rather than the approved RC commit. The new RC script deliberately keeps the release-version commit only under its RC tag, leaving the development branch unchanged. Promotion can therefore tag snapshot POMs or later, unvoted changes. Accept the winning RC tag and delegate final-tag creation to `05-tag-release.sh`; do not keep a second branch-tip tagging path.
##########
.ci/jenkins/Jenkinsfile.103xplus.deploy:
##########
@@ -0,0 +1,327 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import org.jenkinsci.plugins.workflow.libs.Library
+@Library('jenkins-pipeline-shared-libraries')_
+
+import org.kie.jenkins.MavenCommand
+
+deployProperties = [:]
+
+pipeline {
+ agent {
+ docker {
+ image env.AGENT_DOCKER_BUILDER_IMAGE
+ args env.AGENT_DOCKER_BUILDER_ARGS
+ label util.avoidFaultyNodes()
+ }
+ }
+
+ options {
+ timestamps()
+ timeout(time: 180, unit: 'MINUTES')
+ }
+
+ environment {
+ DROOLS_CI_EMAIL_TO = credentials("${JENKINS_EMAIL_CREDS_ID}")
+
+ PR_BRANCH_HASH = "${util.generateHash(10)}"
+ }
+
+ stages {
+ stage('Initialize') {
+ steps {
+ script {
+ cleanWs(disableDeferredWipeout: true)
+
+ if (params.DISPLAY_NAME) {
+ currentBuild.displayName = params.DISPLAY_NAME
+ }
+
+ if (isRelease() || isCreatePr()) {
+ // Verify version is set
+ assert getProjectVersion()
+
+ if (isRelease()) {
+ // Verify if on right release branch
+ assert getBuildBranch() == util.getReleaseBranchFromVersion(getProjectVersion())
+ }
+ }
+
+ dir(getRepoName()) {
+ checkoutRepo()
+ }
+ }
+ }
+ post {
+ success {
+ script {
+ setDeployPropertyIfNeeded('git.branch', getBuildBranch())
+ setDeployPropertyIfNeeded('git.author', getGitAuthor())
+ setDeployPropertyIfNeeded('project.version', getProjectVersion())
+ setDeployPropertyIfNeeded('release', isRelease())
+ }
+ }
+ }
+ }
+
+ stage('Prepare for PR') {
+ when {
+ expression { return isCreatePr() }
+ }
+ steps {
+ script {
+ dir(getRepoName()) {
+ if (githubscm.isBranchExist('origin', getPRBranch())) {
+ githubscm.removeRemoteBranch('origin', getPRBranch(), getGitAuthorPushCredsId())
+ }
+ githubscm.createBranch(getPRBranch())
+ }
+ }
+ }
+ }
+
+ stage('Update project version') {
+ when {
+ expression { return getProjectVersion() }
+ }
+ steps {
+ script {
+ configFileProvider([configFile(fileId: env.MAVEN_SETTINGS_CONFIG_FILE_ID, variable: 'MAVEN_SETTINGS_FILE')]) {
+ maven.mvnVersionsSet(
+ getMavenCommand().withSettingsXmlFile(MAVEN_SETTINGS_FILE),
+ getProjectVersion(),
+ !isRelease()
+ )
+ }
+ }
+ }
+ }
+
+ stage('Build & Deploy repo') {
+ steps {
+ script {
+ withCredentials([usernamePassword(credentialsId: env.MAVEN_REPO_CREDS_ID, usernameVariable: 'REPOSITORY_USER', passwordVariable: 'REPOSITORY_TOKEN')]) {
+ def installOrDeploy
+ if (shouldDeployToRepository()) {
+ installOrDeploy = "deploy -DdeployAtEnd -Dapache.repository.username=${REPOSITORY_USER} -Dapache.repository.password=${REPOSITORY_TOKEN} -DretryFailedDeploymentCount=5"
+ } else {
+ installOrDeploy = 'install'
+ }
+ def mavenCommand = getMavenCommand()
+ .withOptions(env.DROOLS_BUILD_MVN_OPTS ? [ env.DROOLS_BUILD_MVN_OPTS ] : [])
+ .withOptions(env.BUILD_MVN_OPTS_CURRENT ? [ env.BUILD_MVN_OPTS_CURRENT ] : [])
+ .withProperty('maven.test.failure.ignore', true)
+ .skipTests(params.SKIP_TESTS)
+
+ if (isRelease()) {
+ releaseUtils.gpgImportKeyFromStringWithoutPassword(getReleaseGpgSignKeyCredsId())
+ mavenCommand
+ .withProfiles(['apache-release'])
+ .withProperty('only.reproducible')
+ }
+
+ configFileProvider([configFile(fileId: env.MAVEN_SETTINGS_CONFIG_FILE_ID, variable: 'MAVEN_SETTINGS_FILE')]) {
+ mavenCommand.withSettingsXmlFile(MAVEN_SETTINGS_FILE).run("clean $installOrDeploy")
+ }
+ }
+ }
+ }
+ post {
+ always {
+ script {
+ saveReports()
+ util.archiveConsoleLog()
+ }
+ }
+ }
+ }
+
+ stage('Create PR') {
+ when {
+ expression { return isCreatePr() }
+ }
+ steps {
+ script {
+ dir(getRepoName()) {
+ if (githubscm.isThereAnyChanges()) {
+ commitAndCreatePR()
+ } else {
+ println '[WARN] no changes to commit'
+ }
+ }
+ }
+ }
+ post {
+ success {
+ script {
+ setDeployPropertyIfNeeded("${getRepoName()}.pr.source.uri", "https://github.com/${getGitAuthor()}/${getRepoName()}")
+ setDeployPropertyIfNeeded("${getRepoName()}.pr.source.ref", getPRBranch())
+ setDeployPropertyIfNeeded("${getRepoName()}.pr.target.uri", "https://github.com/${getGitAuthor()}/${getRepoName()}")
+ setDeployPropertyIfNeeded("${getRepoName()}.pr.target.ref", getBuildBranch())
+ }
+ }
+ }
+ }
+
+ stage('Commit and Create Tag') {
+ when {
+ expression { return isRelease() }
+ }
+ steps {
+ script {
+ dir(getRepoName()) {
+ if (githubscm.isThereAnyChanges()) {
+ def commitMsg = "[${getBuildBranch()}] Update version to ${getProjectVersion()}"
+ githubscm.setUserConfigFromCreds(getGitAuthorPushCredsId())
+ githubscm.commitChanges(commitMsg, {
+ githubscm.findAndStageNotIgnoredFiles('pom.xml')
+ githubscm.findAndStageNotIgnoredFiles('antora.yml')
+ })
+ } else {
+ println '[WARN] no changes to commit'
+ }
+ githubscm.tagRepository(getGitTagName())
+ githubscm.pushRemoteTag('origin', getGitTagName(), getGitAuthorPushCredsId())
Review Comment:
Issue #7140 requires Jenkins to call the local scripts instead of embedding release logic, but this new deploy pipeline still updates versions, builds, signs, commits, and pushes tags through Groovy/shared-library calls. It never invokes the local release workflow, leaving two separate release implementations. Delegate release mode to `release-all.sh` and standalone version updates to `01-update-version.sh`, while preserving credential setup and the non-release/PR-generation modes.
##########
.ci/jenkins/Jenkinsfile.103xplus.promote:
##########
@@ -0,0 +1,256 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import org.jenkinsci.plugins.workflow.libs.Library
+@Library('jenkins-pipeline-shared-libraries')_
+
+import org.kie.jenkins.MavenCommand
+
+deployProperties = [:]
+pipelineProperties = [:]
+
+pipeline {
+ agent {
+ docker {
+ image env.AGENT_DOCKER_BUILDER_IMAGE
+ args env.AGENT_DOCKER_BUILDER_ARGS
+ label util.avoidFaultyNodes()
+ }
+ }
+
+ options {
+ timestamps()
+ timeout(time: 180, unit: 'MINUTES')
+ }
+
+ environment {
+ DROOLS_CI_EMAIL_TO = credentials("${JENKINS_EMAIL_CREDS_ID}")
+ }
+
+ stages {
+ stage('Initialization') {
+ steps {
+ script {
+ cleanWs()
+
+ if (params.DISPLAY_NAME != '') {
+ currentBuild.displayName = params.DISPLAY_NAME
+ }
+
+ readDeployProperties()
+
+ assert getProjectVersion()
+ assert getBuildBranch() == util.getReleaseBranchFromVersion(getProjectVersion())
+ }
+ }
+ }
+
+ stage('Merge deploy PR and tag') {
+ steps {
+ script {
+ dir(getRepoName()) {
+ approveAndMergePR(getDeployPrLink())
+ checkoutRepo()
+ tagLatest()
+ }
+ }
+ }
+ }
+
+ stage('Create release') {
+ steps {
+ script {
+ dir(getRepoName()) {
+ checkoutRepo()
+ if (githubscm.isReleaseExist(getGitTag(), getGitAuthorCredsId())) {
+ githubscm.deleteRelease(getGitTag(), getGitAuthorPushCredsId())
+ }
+ githubscm.createReleaseWithGeneratedReleaseNotes(getGitTag(), getBuildBranch(), githubscm.getPreviousTagFromVersion(getGitTag()), getGitAuthorPushCredsId())
+ githubscm.updateReleaseBody(getGitTag(), getGitAuthorPushCredsId())
+ }
+ }
+ }
+ }
+
+ stage('Upload drools binaries and documentation') {
+ when {
+ expression { return isMainStream() }
+ }
+ steps {
+ script {
+ configFileProvider([configFile(fileId: env.MAVEN_SETTINGS_CONFIG_FILE_ID, variable: 'MAVEN_SETTINGS_FILE')]) {
+ getMavenCommand()
+ .withOptions(env.DROOLS_BUILD_MVN_OPTS ? [ env.DROOLS_BUILD_MVN_OPTS ] : [])
+ .withOptions(env.BUILD_MVN_OPTS_CURRENT ? [ env.BUILD_MVN_OPTS_CURRENT ] : [])
+ .inDirectory(getRepoName())
+ .skipTests(true)
+ .withProperty('full')
+ .withSettingsXmlFile(MAVEN_SETTINGS_FILE)
+ .run('clean install')
+ }
+ uploadFileMgmt(getRepoName())
+ }
+ }
+ }
+ }
+
+ post {
+ unsuccessful {
+ sendNotification()
+ }
+ cleanup {
+ script {
+ util.cleanNode()
+ }
+ }
+ }
+}
+
+void sendNotification() {
+ if (params.SEND_NOTIFICATION) {
+ mailer.sendMarkdownTestSummaryNotification('Promote', "[${getBuildBranch()}] Drools", [env.DROOLS_CI_EMAIL_TO])
+ } else {
+ echo 'No notification sent per configuration'
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// Deployment properties
+//////////////////////////////////////////////////////////////////////////////
+
+void readDeployProperties() {
+ String deployUrl = params.DEPLOY_BUILD_URL
+ if (deployUrl != '') {
+ if (!deployUrl.endsWith('/')) {
+ deployUrl += '/'
+ }
+ sh "wget ${deployUrl}artifact/${PROPERTIES_FILE_NAME} -O ${PROPERTIES_FILE_NAME}"
+ deployProperties = readProperties file: PROPERTIES_FILE_NAME
+ // echo all properties
+ echo deployProperties.collect { entry -> "${entry.key}=${entry.value}" }.join('\n')
+ }
+}
+
+boolean hasDeployProperty(String key) {
+ return deployProperties[key] != null
+}
+
+String getDeployProperty(String key) {
+ if (hasDeployProperty(key)) {
+ return deployProperties[key]
+ }
+ return ''
+}
+
+String getParamOrDeployProperty(String paramKey, String deployPropertyKey) {
+ if (params[paramKey] != '') {
+ return params[paramKey]
+ }
+ return getDeployProperty(deployPropertyKey)
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// Getter / Setter
+//////////////////////////////////////////////////////////////////////////////
+
+String getRepoName() {
+ return env.REPO_NAME
+}
+
+String getProjectVersion() {
+ return getParamOrDeployProperty('PROJECT_VERSION', 'project.version')
+}
+
+String getGitTag() {
+ return params.GIT_TAG != '' ? params.GIT_TAG : getProjectVersion()
+}
+
+String getBuildBranch() {
+ return params.BUILD_BRANCH_NAME
+}
+
+String getGitAuthor() {
+ return env.GIT_AUTHOR
+}
+
+String getGitAuthorCredsId() {
+ return env.GIT_AUTHOR_CREDS_ID
+}
+
+String getGitAuthorPushCredsId() {
+ return env.GIT_AUTHOR_PUSH_CREDS_ID
+}
+
+String getDeployPrLink() {
+ return getDeployProperty("${getRepoName()}.pr.link")
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// Git
+//////////////////////////////////////////////////////////////////////////////
+
+void checkoutRepo() {
+ deleteDir()
+ checkout(githubscm.resolveRepository(getRepoName(), getGitAuthor(), getBuildBranch(), false, getGitAuthorCredsId()))
+ // need to manually checkout branch since on a detached branch after checkout command
+ sh "git checkout ${getBuildBranch()}"
+}
+
+void approveAndMergePR(String prLink) {
+ if (prLink?.trim()) {
+ githubscm.approvePR(prLink, getGitAuthorPushCredsId())
+ githubscm.mergePR(prLink, getGitAuthorPushCredsId())
+ }
+}
+
+void tagLatest() {
+ if (getGitTag()) {
+ githubscm.tagLocalAndRemoteRepository('origin', getGitTag(), getGitAuthorPushCredsId(), env.BUILD_TAG, true)
+ }
+}
+
+MavenCommand getMavenCommand() {
+ mvnCmd = new MavenCommand(this, ['-fae', '-ntp'])
+ .withOptions(env.BUILD_MVN_OPTS ? [ env.BUILD_MVN_OPTS ] : [])
+ if (env.MAVEN_DEPENDENCIES_REPOSITORY) {
+ mvnCmd.withDependencyRepositoryInSettings('deps-repo', env.MAVEN_DEPENDENCIES_REPOSITORY)
+ }
+ return mvnCmd
+}
+
+void uploadFileMgmt(String directory) {
+ if (isNotTestingBuild()) {
+ echo "upload binaries and docs for ${directory}"
+ dir(directory) {
+ sshagent(['drools-filemgmt']) {
+ sh "script/release/upload_filemgmt.sh ${getProjectVersion()}"
Review Comment:
`script/release/upload_filemgmt.sh` is absent from this checkout. When `DROOLS_STREAM` is `main` and the Git author is `apache`, this command fails after the GitHub release has already been created, leaving distribution publishing incomplete. Supply the upload implementation or invoke an existing publishing mechanism before enabling this stage.
##########
script/release/02-rc-commit.sh:
##########
@@ -0,0 +1,220 @@
+#!/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
+
+# Creates the "R commit" (release commit) and the corresponding RC git tag.
+#
+# The R commit contains only the version bump to the exact release version.
+# It is made on a short-lived local release branch that is never pushed — only
+# the tag is pushed. This mirrors the branch strategy from release.txt:
+#
+# 10.2.x branch ──── c ──── c ──── [D commit] ──── c ────> ...
+# |
+# (local release branch)
+# └── [R commit] ──> tag: 10.3.0-rc1
+#
+# Usage:
+# ./script/release/02-rc-commit.sh <version> [--tag <tag-name>] [--push] [--dry-run]
+# ./script/release/02-rc-commit.sh --version <release-version> --tag <tag-name>
+#
+# Examples:
+# ./script/release/02-rc-commit.sh 10.3.0 --tag 10.3.0-rc1
+# ./script/release/02-rc-commit.sh --version 10.3.0 --tag 10.3.0-rc2 --push
+#
+# Options:
+# <version> | --version <ver> Exact release version, e.g. 10.3.0
+# --tag | --rc-tag <tag> Git tag name, e.g. 10.3.0-rc1 (defaults to <version>-rc1)
+# --rc Accepted for parity
+# --push | --push-tag Push the tag to origin (default: local only)
+# --dry-run Print what would happen without making any changes
+
+SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
+REPO_ROOT="$(cd "${SCRIPT_DIR}/../.." && pwd)"
+
+RELEASE_VERSION=""
+TAG_NAME=""
+PUSH=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
+ ;;
+ --push|--push-tag)
+ PUSH=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>] [--push] [--dry-run]"
+ 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] [--push] [--dry-run]"
+ exit 1
+fi
+
+if [[ -z "${TAG_NAME}" ]]; then
+ TAG_NAME="${RELEASE_VERSION}-rc1"
+fi
+
+# Derive the expected development branch name (e.g. 10.3.0 → 10.3.x).
+STREAM_BRANCH="$(echo "${RELEASE_VERSION}" | sed 's/^\([0-9]*\.[0-9]*\)\..*/\1.x/')"
+RELEASE_BRANCH="release/${TAG_NAME}"
+
+cd "${REPO_ROOT}"
+
+CURRENT_BRANCH="$(git rev-parse --abbrev-ref HEAD)"
+
+echo "========================================"
+echo "Apache KIE repo — RC commit + tag"
+echo "Release version : ${RELEASE_VERSION}"
+echo "Tag : ${TAG_NAME}"
+echo "Release branch : ${RELEASE_BRANCH} (local only)"
+echo "Push tag : ${PUSH}"
+echo "Dry run : ${DRY_RUN}"
+echo "Current branch : ${CURRENT_BRANCH}"
+echo "========================================"
+
+# Warn if we're not on the expected stream branch (not a fatal error — someone
+# may legitimately be on a different commit).
+if [[ "${CURRENT_BRANCH}" != "${STREAM_BRANCH}" ]]; then
+ echo ""
+ echo "WARNING: Current branch '${CURRENT_BRANCH}' is not the expected stream"
+ echo " branch '${STREAM_BRANCH}'. Proceed with caution."
+ echo ""
+fi
+
+# Check there are no uncommitted changes before we do anything.
+if ! git diff --quiet || ! git diff --cached --quiet; then
Review Comment:
These checks ignore untracked files, but the later `git add -A` includes them in the release commit. An unrelated, non-ignored local file can therefore be committed and pushed with the RC tag despite passing the clean-tree guard. Include untracked files in this check before creating the release branch.
##########
.ci/jenkins/project/Jenkinsfile.103xplus.release:
##########
@@ -0,0 +1,108 @@
+/*
+ * 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')_
+
+pipeline {
+ agent {
+ label util.avoidFaultyNodes('ubuntu')
+ }
+
+ options {
+ timestamps()
+ timeout(time: 360, unit: 'MINUTES')
+ }
+
+ environment {
+ DROOLS_CI_EMAIL_TO = credentials("${JENKINS_EMAIL_CREDS_ID}")
+ }
+
+ parameters {
+ string(name: 'RELEASE_VERSION', defaultValue: '', description: 'Exact release version, e.g. 10.3.0', trim: true)
+ string(name: 'TAG_NAME', defaultValue: '', 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')
+ booleanParam(name: 'SEND_NOTIFICATION', defaultValue: false, description: 'Send email notification on failure')
+ }
+
+ 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:
This invokes the scripts without Maven settings, a signing-key setup, Git author configuration, or authentication for their raw `git push`. Only the notification email is bound. On an agent without preconfigured release credentials, the default `DEPLOY=true` / `PUSH_TAG=true` workflow cannot complete. Bind the managed Maven settings as `MAVEN_SETTINGS`, provision the GPG key and any required passphrase, and configure Git identity and push authentication around this invocation, preserving the setup used by the existing deploy pipeline.
##########
.ci/jenkins/Jenkinsfile.103xplus.deploy:
##########
@@ -0,0 +1,327 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import org.jenkinsci.plugins.workflow.libs.Library
+@Library('jenkins-pipeline-shared-libraries')_
+
+import org.kie.jenkins.MavenCommand
+
+deployProperties = [:]
+
+pipeline {
+ agent {
+ docker {
+ image env.AGENT_DOCKER_BUILDER_IMAGE
+ args env.AGENT_DOCKER_BUILDER_ARGS
+ label util.avoidFaultyNodes()
+ }
+ }
+
+ options {
+ timestamps()
+ timeout(time: 180, unit: 'MINUTES')
+ }
+
+ environment {
+ DROOLS_CI_EMAIL_TO = credentials("${JENKINS_EMAIL_CREDS_ID}")
+
+ PR_BRANCH_HASH = "${util.generateHash(10)}"
+ }
+
+ stages {
+ stage('Initialize') {
+ steps {
+ script {
+ cleanWs(disableDeferredWipeout: true)
+
+ if (params.DISPLAY_NAME) {
+ currentBuild.displayName = params.DISPLAY_NAME
+ }
+
+ if (isRelease() || isCreatePr()) {
+ // Verify version is set
+ assert getProjectVersion()
+
+ if (isRelease()) {
+ // Verify if on right release branch
+ assert getBuildBranch() == util.getReleaseBranchFromVersion(getProjectVersion())
+ }
+ }
+
+ dir(getRepoName()) {
+ checkoutRepo()
+ }
+ }
+ }
+ post {
+ success {
+ script {
+ setDeployPropertyIfNeeded('git.branch', getBuildBranch())
+ setDeployPropertyIfNeeded('git.author', getGitAuthor())
+ setDeployPropertyIfNeeded('project.version', getProjectVersion())
+ setDeployPropertyIfNeeded('release', isRelease())
+ }
+ }
+ }
+ }
+
+ stage('Prepare for PR') {
+ when {
+ expression { return isCreatePr() }
+ }
+ steps {
+ script {
+ dir(getRepoName()) {
+ if (githubscm.isBranchExist('origin', getPRBranch())) {
+ githubscm.removeRemoteBranch('origin', getPRBranch(), getGitAuthorPushCredsId())
+ }
+ githubscm.createBranch(getPRBranch())
+ }
+ }
+ }
+ }
+
+ stage('Update project version') {
+ when {
+ expression { return getProjectVersion() }
+ }
+ steps {
+ script {
+ configFileProvider([configFile(fileId: env.MAVEN_SETTINGS_CONFIG_FILE_ID, variable: 'MAVEN_SETTINGS_FILE')]) {
+ maven.mvnVersionsSet(
+ getMavenCommand().withSettingsXmlFile(MAVEN_SETTINGS_FILE),
+ getProjectVersion(),
+ !isRelease()
+ )
+ }
+ }
+ }
+ }
+
+ stage('Build & Deploy repo') {
+ steps {
+ script {
+ withCredentials([usernamePassword(credentialsId: env.MAVEN_REPO_CREDS_ID, usernameVariable: 'REPOSITORY_USER', passwordVariable: 'REPOSITORY_TOKEN')]) {
+ def installOrDeploy
+ if (shouldDeployToRepository()) {
+ installOrDeploy = "deploy -DdeployAtEnd -Dapache.repository.username=${REPOSITORY_USER} -Dapache.repository.password=${REPOSITORY_TOKEN} -DretryFailedDeploymentCount=5"
+ } else {
+ installOrDeploy = 'install'
+ }
+ def mavenCommand = getMavenCommand()
+ .withOptions(env.DROOLS_BUILD_MVN_OPTS ? [ env.DROOLS_BUILD_MVN_OPTS ] : [])
+ .withOptions(env.BUILD_MVN_OPTS_CURRENT ? [ env.BUILD_MVN_OPTS_CURRENT ] : [])
+ .withProperty('maven.test.failure.ignore', true)
+ .skipTests(params.SKIP_TESTS)
+
+ if (isRelease()) {
+ releaseUtils.gpgImportKeyFromStringWithoutPassword(getReleaseGpgSignKeyCredsId())
+ mavenCommand
+ .withProfiles(['apache-release'])
+ .withProperty('only.reproducible')
+ }
+
+ configFileProvider([configFile(fileId: env.MAVEN_SETTINGS_CONFIG_FILE_ID, variable: 'MAVEN_SETTINGS_FILE')]) {
+ mavenCommand.withSettingsXmlFile(MAVEN_SETTINGS_FILE).run("clean $installOrDeploy")
+ }
+ }
+ }
+ }
+ post {
+ always {
+ script {
+ saveReports()
+ util.archiveConsoleLog()
+ }
+ }
+ }
+ }
+
+ stage('Create PR') {
+ when {
+ expression { return isCreatePr() }
+ }
+ steps {
+ script {
+ dir(getRepoName()) {
+ if (githubscm.isThereAnyChanges()) {
+ commitAndCreatePR()
+ } else {
+ println '[WARN] no changes to commit'
+ }
+ }
+ }
+ }
+ post {
+ success {
+ script {
+ setDeployPropertyIfNeeded("${getRepoName()}.pr.source.uri", "https://github.com/${getGitAuthor()}/${getRepoName()}")
+ setDeployPropertyIfNeeded("${getRepoName()}.pr.source.ref", getPRBranch())
+ setDeployPropertyIfNeeded("${getRepoName()}.pr.target.uri", "https://github.com/${getGitAuthor()}/${getRepoName()}")
+ setDeployPropertyIfNeeded("${getRepoName()}.pr.target.ref", getBuildBranch())
+ }
+ }
+ }
+ }
+
+ stage('Commit and Create Tag') {
+ when {
+ expression { return isRelease() }
+ }
+ steps {
+ script {
+ dir(getRepoName()) {
+ if (githubscm.isThereAnyChanges()) {
+ def commitMsg = "[${getBuildBranch()}] Update version to ${getProjectVersion()}"
+ githubscm.setUserConfigFromCreds(getGitAuthorPushCredsId())
+ githubscm.commitChanges(commitMsg, {
+ githubscm.findAndStageNotIgnoredFiles('pom.xml')
+ githubscm.findAndStageNotIgnoredFiles('antora.yml')
+ })
+ } else {
+ println '[WARN] no changes to commit'
+ }
+ githubscm.tagRepository(getGitTagName())
+ githubscm.pushRemoteTag('origin', getGitTagName(), getGitAuthorPushCredsId())
+ }
+ }
+ }
+ }
+ }
+
+ post {
+ always {
+ script {
+ setDeployPropertyIfNeeded("${getRepoName()}.deploy.build.run", true)
+ saveDeployProperties()
+ }
+ }
+ unsuccessful {
+ sendNotification()
+ }
+ cleanup {
+ cleanWs(notFailBuild: true, deleteDirs: true, patterns: [[pattern: 'deploy.properties', type: 'EXCLUDE']])
+ }
+ }
+}
+
+void saveReports() {
+ junit testResults: '**/target/surefire-reports/**/*.xml, **/target/failsafe-reports/**/*.xml, **/target/invoker-reports/**/TEST-*.xml', allowEmptyResults: true
+}
+
+void checkoutRepo() {
+ deleteDir()
+ checkout(githubscm.resolveRepository(getRepoName(), getGitAuthor(), getBuildBranch(), false, getGitAuthorCredsId()))
+ // need to manually checkout branch since on a detached branch after checkout command
+ sh "git checkout ${getBuildBranch()}"
+}
+
+void commitAndCreatePR() {
+ def commitMsg = "[${getBuildBranch()}] Update version to ${getProjectVersion()}"
+ def prBody = "Generated by build ${BUILD_TAG}: ${BUILD_URL}.\nPlease do not merge, it should be merged automatically."
+ githubscm.setUserConfigFromCreds(getGitAuthorPushCredsId())
+ githubscm.commitChanges(commitMsg, {
+ githubscm.findAndStageNotIgnoredFiles('pom.xml')
+ githubscm.findAndStageNotIgnoredFiles('antora.yml')
+ })
+ githubscm.pushObject('origin', getPRBranch(), getGitAuthorPushCredsId())
+ deployProperties["${getRepoName()}.pr.link"] = githubscm.createPRWithLabels(commitMsg, prBody, getBuildBranch(), ['skip-ci'] as String[], getGitAuthorCredsId())
+}
+
+void sendNotification() {
+ if (params.SEND_NOTIFICATION) {
+ mailer.sendMarkdownTestSummaryNotification('Deploy', "[${getBuildBranch()}] Drools", [env.DROOLS_CI_EMAIL_TO])
+ } else {
+ echo 'No notification sent per configuration'
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// Deployment properties
+//////////////////////////////////////////////////////////////////////////////
+
+void setDeployPropertyIfNeeded(String key, def value) {
+ if (value != null && value != '') {
+ deployProperties[key] = value
+ }
+}
+
+void saveDeployProperties(String propertiesFileName = 'deploy.properties') {
Review Comment:
With the existing job configuration, the producer and consumer use different artifact names. `.ci/jenkins/dsl/jobs.groovy` sets `PROPERTIES_FILE_NAME` to `deployment.properties`, and the new promote pipeline fetches that name, but this method archives `deploy.properties`. Promotion through `DEPLOY_BUILD_URL` therefore requests a missing artifact. Use the configured filename when writing and archiving the properties.
##########
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 02-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}")
Review Comment:
When `MAVEN_GPG_PASSPHRASE` is set, this adds its plaintext value to Maven's arguments. The default dry run prints the entire array at line 133, exposing the signing secret in captured console output; a real deployment also exposes it through process arguments. Use the inherited GPG plugin's supported environment or protected-settings mechanism instead of a plaintext command-line property, and keep the secret out of displayed commands.
##########
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 02-rc-commit.sh first, or check out the tag manually."
+ exit 1
+fi
+
+# ── Assemble Maven flags ─────────────────────────────────────────────────────
+
+DEPLOY_MVN_FLAGS=(
+ "-DskipTests"
+ "-Dfull"
Review Comment:
The Maven command never activates `apache-release`, which the existing deploy pipeline enables for artifact signing. Setting `gpg.passphrase` alone does not run the signing goal, so the default script stages unsigned artifacts instead of the signed release artifacts it promises. Activate the release profile here; signing-key provisioning must also be supplied by the caller.
--
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: commits-unsubscribe@kie.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@kie.apache.org
For additional commands, e-mail: commits-help@kie.apache.org
Re: [PR] kie-issues#2404: 10.3.x+ stream: Re-write drools release jobs to be local scripts invoked in Apache Jenkins and remove old ones. [incubator-kie]
Posted by "Copilot (via GitHub)" <gi...@apache.org>.
Copilot commented on code in PR #7123:
URL: https://github.com/apache/incubator-kie/pull/7123#discussion_r4229460540
##########
.ci/jenkins/Jenkinsfile.103xplus.promote:
##########
@@ -0,0 +1,293 @@
+/*
+ * 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.
+ */
+
+// 10.3.x+ promote pipeline — mirrors Jenkinsfile.promote with 10.3+ specifics:
+// - 'Create release' stage uses Nexus nexus-staging:release (same as old)
+// - 'Tag final release' stage delegates to 05-tag-release.sh (tags the
+// approved RC commit, not the branch tip as the old pipeline did)
+// - 'Upload drools binaries and documentation' stage retained for main stream
+
+import org.jenkinsci.plugins.workflow.libs.Library
+@Library('jenkins-pipeline-shared-libraries')_
+
+import org.kie.jenkins.MavenCommand
+
+deployProperties = [:]
+pipelineProperties = [:]
+
+pipeline {
+ agent {
+ docker {
+ image env.AGENT_DOCKER_BUILDER_IMAGE
+ args env.AGENT_DOCKER_BUILDER_ARGS
+ label util.avoidFaultyNodes()
+ }
+ }
+
+ options {
+ timestamps()
+ timeout(time: 180, unit: 'MINUTES')
+ }
+
+ environment {
+ DROOLS_CI_EMAIL_TO = credentials("${JENKINS_EMAIL_CREDS_ID}")
+ }
+
+ stages {
+ stage('Initialization') {
+ steps {
+ script {
+ cleanWs()
+
+ if (params.DISPLAY_NAME != '') {
+ currentBuild.displayName = params.DISPLAY_NAME
+ }
+
+ readDeployProperties()
+
+ assert getProjectVersion()
+ assert getBuildBranch() == util.getReleaseBranchFromVersion(getProjectVersion())
+ }
+ }
+ }
+
+ stage('Merge deploy PR') {
+ // NOTE: tagLatest() removed here intentionally.
+ // In the 103xplus flow the final release tag is created by the
+ // separate "Tag final release" stage below, which delegates to
+ // 05-tag-release.sh so the tag always points to the approved
+ // RC commit — NOT the current branch tip. Calling tagLatest()
+ // here would create a duplicate tag at the wrong commit.
+ steps {
+ script {
+ dir(getRepoName()) {
+ approveAndMergePR(getDeployPrLink())
+ checkoutRepo()
+ }
+ }
+ }
+ }
+
+ stage('Create release') {
+ steps {
+ script {
+ dir(getRepoName()) {
+ checkoutRepo()
+ if (githubscm.isReleaseExist(getGitTag(), getGitAuthorCredsId())) {
+ githubscm.deleteRelease(getGitTag(), getGitAuthorPushCredsId())
+ }
+ githubscm.createReleaseWithGeneratedReleaseNotes(getGitTag(), getBuildBranch(), githubscm.getPreviousTagFromVersion(getGitTag()), getGitAuthorPushCredsId())
+ githubscm.updateReleaseBody(getGitTag(), getGitAuthorPushCredsId())
+ }
+ }
+ }
+ }
+
+ stage('Tag final release') {
+ // Delegate final-tag creation to 05-tag-release.sh so the release tag
+ // always points to the approved RC commit — NOT the current branch tip.
+ // This matches the documented strategy: the R commit lives under the RC
+ // tag only; the development branch is never disturbed.
+ when {
+ expression { return getGitTag()?.trim() }
+ }
+ steps {
+ withCredentials([
+ sshUserPrivateKey(credentialsId: env.GIT_AUTHOR_PUSH_CREDS_ID, keyFileVariable: 'GIT_SSH_KEY')
+ ]) {
+ script {
+ dir(getRepoName()) {
+ sh """#!/usr/bin/env bash
+ set -euo pipefail
+ # Fetch the RC tag so the script can resolve it.
+ git fetch origin "refs/tags/${getGitTag()}:refs/tags/${getGitTag()}"
+ chmod +x script/release/05-tag-release.sh
+ ./script/release/05-tag-release.sh --rc-tag "${getGitTag()}" --push
+ """
+ }
+ }
+ }
+ }
+ }
Review Comment:
`05-tag-release.sh` expects an RC tag (e.g. `10.3.0-rc2`) as `--rc-tag`, but `getGitTag()` defaults to `getProjectVersion()` when `params.GIT_TAG` is empty. That default will pass a non-RC tag value (e.g. `10.3.0`) into `--rc-tag`, which will fail or behave incorrectly. Make `GIT_TAG` (or a renamed `RC_TAG`) mandatory for this stage and/or change the getter to avoid defaulting to the project version when the value is specifically used as an RC tag.
##########
.ci/jenkins/Jenkinsfile.103xplus.promote:
##########
@@ -0,0 +1,293 @@
+/*
+ * 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.
+ */
+
+// 10.3.x+ promote pipeline — mirrors Jenkinsfile.promote with 10.3+ specifics:
+// - 'Create release' stage uses Nexus nexus-staging:release (same as old)
+// - 'Tag final release' stage delegates to 05-tag-release.sh (tags the
+// approved RC commit, not the branch tip as the old pipeline did)
+// - 'Upload drools binaries and documentation' stage retained for main stream
+
+import org.jenkinsci.plugins.workflow.libs.Library
+@Library('jenkins-pipeline-shared-libraries')_
+
+import org.kie.jenkins.MavenCommand
+
+deployProperties = [:]
+pipelineProperties = [:]
+
+pipeline {
+ agent {
+ docker {
+ image env.AGENT_DOCKER_BUILDER_IMAGE
+ args env.AGENT_DOCKER_BUILDER_ARGS
+ label util.avoidFaultyNodes()
+ }
+ }
+
+ options {
+ timestamps()
+ timeout(time: 180, unit: 'MINUTES')
+ }
+
+ environment {
+ DROOLS_CI_EMAIL_TO = credentials("${JENKINS_EMAIL_CREDS_ID}")
+ }
+
+ stages {
+ stage('Initialization') {
+ steps {
+ script {
+ cleanWs()
+
+ if (params.DISPLAY_NAME != '') {
+ currentBuild.displayName = params.DISPLAY_NAME
+ }
+
+ readDeployProperties()
+
+ assert getProjectVersion()
+ assert getBuildBranch() == util.getReleaseBranchFromVersion(getProjectVersion())
+ }
+ }
+ }
+
+ stage('Merge deploy PR') {
+ // NOTE: tagLatest() removed here intentionally.
+ // In the 103xplus flow the final release tag is created by the
+ // separate "Tag final release" stage below, which delegates to
+ // 05-tag-release.sh so the tag always points to the approved
+ // RC commit — NOT the current branch tip. Calling tagLatest()
+ // here would create a duplicate tag at the wrong commit.
+ steps {
+ script {
+ dir(getRepoName()) {
+ approveAndMergePR(getDeployPrLink())
+ checkoutRepo()
+ }
+ }
+ }
+ }
+
+ stage('Create release') {
+ steps {
+ script {
+ dir(getRepoName()) {
+ checkoutRepo()
+ if (githubscm.isReleaseExist(getGitTag(), getGitAuthorCredsId())) {
+ githubscm.deleteRelease(getGitTag(), getGitAuthorPushCredsId())
+ }
+ githubscm.createReleaseWithGeneratedReleaseNotes(getGitTag(), getBuildBranch(), githubscm.getPreviousTagFromVersion(getGitTag()), getGitAuthorPushCredsId())
+ githubscm.updateReleaseBody(getGitTag(), getGitAuthorPushCredsId())
+ }
+ }
+ }
+ }
+
+ stage('Tag final release') {
+ // Delegate final-tag creation to 05-tag-release.sh so the release tag
+ // always points to the approved RC commit — NOT the current branch tip.
+ // This matches the documented strategy: the R commit lives under the RC
+ // tag only; the development branch is never disturbed.
+ when {
+ expression { return getGitTag()?.trim() }
+ }
+ steps {
+ withCredentials([
+ sshUserPrivateKey(credentialsId: env.GIT_AUTHOR_PUSH_CREDS_ID, keyFileVariable: 'GIT_SSH_KEY')
+ ]) {
+ script {
+ dir(getRepoName()) {
+ sh """#!/usr/bin/env bash
+ set -euo pipefail
+ # Fetch the RC tag so the script can resolve it.
+ git fetch origin "refs/tags/${getGitTag()}:refs/tags/${getGitTag()}"
+ chmod +x script/release/05-tag-release.sh
+ ./script/release/05-tag-release.sh --rc-tag "${getGitTag()}" --push
+ """
+ }
+ }
+ }
Review Comment:
Same as the release pipeline: `sshUserPrivateKey(..., keyFileVariable: 'GIT_SSH_KEY')` alone doesn’t ensure `git fetch` / `git push` uses that key. This can break both the `git fetch origin ...` and the `--push` inside `05-tag-release.sh`. Use `sshagent([env.GIT_AUTHOR_PUSH_CREDS_ID])` or set `GIT_SSH_COMMAND` to reference `$GIT_SSH_KEY` within the `sh` block so Git operations are authenticated reliably.
##########
.ci/jenkins/project/Jenkinsfile.103xplus.release:
##########
@@ -0,0 +1,134 @@
+/*
+ * 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')
+ booleanParam(name: 'SEND_NOTIFICATION', defaultValue: false, description: 'Send a notification on CI channel when pipeline finishes')
+ }
+
+ environment {
+ DROOLS_CI_EMAIL_TO = credentials("${JENKINS_EMAIL_CREDS_ID}")
+ }
+
+ 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 {
+ // MAVEN_SETTINGS_CONFIG_FILE_ID is a Jenkins Config File ID, not a
+ // secret credential — it must be injected via configFileProvider,
+ // which writes it to a temp path and exposes MAVEN_SETTINGS_FILE.
+ // GPG_PASSPHRASE_CREDS_ID and GIT_AUTHOR_PUSH_CREDS_ID are real
+ // credentials and use withCredentials.
+ configFileProvider([configFile(fileId: env.MAVEN_SETTINGS_CONFIG_FILE_ID, variable: 'MAVEN_SETTINGS_FILE')]) {
+ withCredentials([
+ string(credentialsId: env.GPG_PASSPHRASE_CREDS_ID, variable: 'MAVEN_GPG_PASSPHRASE'),
+ sshUserPrivateKey(credentialsId: env.GIT_AUTHOR_PUSH_CREDS_ID, keyFileVariable: 'GIT_SSH_KEY')
+ ]) {
+ script {
+ // Configure Git identity for the R commit.
+ sh """#!/usr/bin/env bash
+ set -euo pipefail
+ git config user.email "${env.GIT_AUTHOR_EMAIL ?: 'dev@kie.apache.org'}"
+ git config user.name "${env.GIT_AUTHOR ?: 'Apache KIE Release Bot'}"
+ """
+
+ // Build the argv array safely — each parameter is a
+ // separate shell word, no string concatenation or eval.
+ def releaseArgs = [
+ './script/release/release-all.sh',
+ '--version', params.RELEASE_VERSION,
+ '--tag', params.TAG_NAME
+ ]
+ if (params.SKIP_TESTS) releaseArgs << '--skip-tests'
+ if (params.DEPLOY) releaseArgs << '--deploy'
+ if (params.STAGING_URL?.trim()) releaseArgs += ['--staging-url', params.STAGING_URL.trim()]
+ if (params.PUSH_TAG) releaseArgs << '--push-tag'
+ if (params.EXTRA_MAVEN_OPTS?.trim()) releaseArgs += ['--maven-opts', params.EXTRA_MAVEN_OPTS.trim()]
+ if (params.DRY_RUN) releaseArgs << '--dry-run'
+
+ // MAVEN_SETTINGS_FILE is injected by configFileProvider above.
+ // MAVEN_GPG_PASSPHRASE is already in env from withCredentials
+ // and is read by the GPG plugin directly (not a CLI arg).
+ withEnv(["MAVEN_SETTINGS=${MAVEN_SETTINGS_FILE}"]) {
+ sh """#!/usr/bin/env bash
+ set -euo pipefail
+ chmod +x script/release/*.sh
+ ${releaseArgs.collect { "'${it.replace("'", "'\\''")}'" }.join(' ')}
+ """
Review Comment:
The pipeline binds an SSH private key to `GIT_SSH_KEY`, but `git push` inside `release-all.sh`/`02-rc-commit.sh` won’t automatically use that key. As written, `--push-tag` can fail due to missing SSH agent / SSH command configuration. Fix by using `sshagent([env.GIT_AUTHOR_PUSH_CREDS_ID])` around the script execution, or exporting `GIT_SSH_COMMAND=ssh -i \"$GIT_SSH_KEY\" -o IdentitiesOnly=yes` (and any required known_hosts handling) so Git consistently uses the injected key.
##########
.ci/jenkins/Jenkinsfile.103xplus.promote:
##########
@@ -0,0 +1,293 @@
+/*
+ * 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.
+ */
+
+// 10.3.x+ promote pipeline — mirrors Jenkinsfile.promote with 10.3+ specifics:
+// - 'Create release' stage uses Nexus nexus-staging:release (same as old)
+// - 'Tag final release' stage delegates to 05-tag-release.sh (tags the
+// approved RC commit, not the branch tip as the old pipeline did)
+// - 'Upload drools binaries and documentation' stage retained for main stream
+
+import org.jenkinsci.plugins.workflow.libs.Library
+@Library('jenkins-pipeline-shared-libraries')_
+
+import org.kie.jenkins.MavenCommand
+
+deployProperties = [:]
+pipelineProperties = [:]
+
+pipeline {
+ agent {
+ docker {
+ image env.AGENT_DOCKER_BUILDER_IMAGE
+ args env.AGENT_DOCKER_BUILDER_ARGS
+ label util.avoidFaultyNodes()
+ }
+ }
+
+ options {
+ timestamps()
+ timeout(time: 180, unit: 'MINUTES')
+ }
+
+ environment {
+ DROOLS_CI_EMAIL_TO = credentials("${JENKINS_EMAIL_CREDS_ID}")
+ }
+
+ stages {
+ stage('Initialization') {
+ steps {
+ script {
+ cleanWs()
+
+ if (params.DISPLAY_NAME != '') {
+ currentBuild.displayName = params.DISPLAY_NAME
+ }
+
+ readDeployProperties()
+
+ assert getProjectVersion()
+ assert getBuildBranch() == util.getReleaseBranchFromVersion(getProjectVersion())
+ }
+ }
+ }
+
+ stage('Merge deploy PR') {
+ // NOTE: tagLatest() removed here intentionally.
+ // In the 103xplus flow the final release tag is created by the
+ // separate "Tag final release" stage below, which delegates to
+ // 05-tag-release.sh so the tag always points to the approved
+ // RC commit — NOT the current branch tip. Calling tagLatest()
+ // here would create a duplicate tag at the wrong commit.
+ steps {
+ script {
+ dir(getRepoName()) {
+ approveAndMergePR(getDeployPrLink())
+ checkoutRepo()
+ }
+ }
+ }
+ }
+
+ stage('Create release') {
+ steps {
+ script {
+ dir(getRepoName()) {
+ checkoutRepo()
+ if (githubscm.isReleaseExist(getGitTag(), getGitAuthorCredsId())) {
+ githubscm.deleteRelease(getGitTag(), getGitAuthorPushCredsId())
+ }
+ githubscm.createReleaseWithGeneratedReleaseNotes(getGitTag(), getBuildBranch(), githubscm.getPreviousTagFromVersion(getGitTag()), getGitAuthorPushCredsId())
+ githubscm.updateReleaseBody(getGitTag(), getGitAuthorPushCredsId())
+ }
+ }
+ }
+ }
+
+ stage('Tag final release') {
+ // Delegate final-tag creation to 05-tag-release.sh so the release tag
+ // always points to the approved RC commit — NOT the current branch tip.
+ // This matches the documented strategy: the R commit lives under the RC
+ // tag only; the development branch is never disturbed.
+ when {
+ expression { return getGitTag()?.trim() }
+ }
+ steps {
+ withCredentials([
+ sshUserPrivateKey(credentialsId: env.GIT_AUTHOR_PUSH_CREDS_ID, keyFileVariable: 'GIT_SSH_KEY')
+ ]) {
+ script {
+ dir(getRepoName()) {
+ sh """#!/usr/bin/env bash
+ set -euo pipefail
+ # Fetch the RC tag so the script can resolve it.
+ git fetch origin "refs/tags/${getGitTag()}:refs/tags/${getGitTag()}"
+ chmod +x script/release/05-tag-release.sh
+ ./script/release/05-tag-release.sh --rc-tag "${getGitTag()}" --push
+ """
+ }
+ }
+ }
+ }
+ }
+
+ stage('Upload drools binaries and documentation') {
+ when {
+ expression { return isMainStream() }
+ }
+ steps {
+ script {
+ configFileProvider([configFile(fileId: env.MAVEN_SETTINGS_CONFIG_FILE_ID, variable: 'MAVEN_SETTINGS_FILE')]) {
+ getMavenCommand()
+ .withOptions(env.DROOLS_BUILD_MVN_OPTS ? [ env.DROOLS_BUILD_MVN_OPTS ] : [])
+ .withOptions(env.BUILD_MVN_OPTS_CURRENT ? [ env.BUILD_MVN_OPTS_CURRENT ] : [])
+ .inDirectory(getRepoName())
+ .skipTests(true)
+ .withProperty('full')
+ .withSettingsXmlFile(MAVEN_SETTINGS_FILE)
+ .run('clean install')
+ }
+ uploadFileMgmt(getRepoName())
+ }
+ }
+ }
+ }
+ post {
+ unsuccessful {
+ sendNotification()
+ }
+ cleanup {
+ script {
+ util.cleanNode()
+ }
+ }
+ }
+}
+
+void sendNotification() {
+ if (params.SEND_NOTIFICATION) {
+ mailer.sendMarkdownTestSummaryNotification('Promote', "[${getBuildBranch()}] Drools", [env.DROOLS_CI_EMAIL_TO])
+ } else {
+ echo 'No notification sent per configuration'
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// Deployment properties
+//////////////////////////////////////////////////////////////////////////////
+
+void readDeployProperties() {
+ String deployUrl = params.DEPLOY_BUILD_URL
+ if (deployUrl != '') {
+ if (!deployUrl.endsWith('/')) {
+ deployUrl += '/'
+ }
+ sh "wget ${deployUrl}artifact/${PROPERTIES_FILE_NAME} -O ${PROPERTIES_FILE_NAME}"
+ deployProperties = readProperties file: PROPERTIES_FILE_NAME
+ // echo all properties
+ echo deployProperties.collect { entry -> "${entry.key}=${entry.value}" }.join('\n')
+ }
+}
+
+boolean hasDeployProperty(String key) {
+ return deployProperties[key] != null
+}
+
+String getDeployProperty(String key) {
+ if (hasDeployProperty(key)) {
+ return deployProperties[key]
+ }
+ return ''
+}
+
+String getParamOrDeployProperty(String paramKey, String deployPropertyKey) {
+ if (params[paramKey] != '') {
+ return params[paramKey]
+ }
+ return getDeployProperty(deployPropertyKey)
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// Getter / Setter
+//////////////////////////////////////////////////////////////////////////////
+
+String getRepoName() {
+ return env.REPO_NAME
+}
+
+String getProjectVersion() {
+ return getParamOrDeployProperty('PROJECT_VERSION', 'project.version')
+}
+
+String getGitTag() {
+ return params.GIT_TAG != '' ? params.GIT_TAG : getProjectVersion()
Review Comment:
`05-tag-release.sh` expects an RC tag (e.g. `10.3.0-rc2`) as `--rc-tag`, but `getGitTag()` defaults to `getProjectVersion()` when `params.GIT_TAG` is empty. That default will pass a non-RC tag value (e.g. `10.3.0`) into `--rc-tag`, which will fail or behave incorrectly. Make `GIT_TAG` (or a renamed `RC_TAG`) mandatory for this stage and/or change the getter to avoid defaulting to the project version when the value is specifically used as an RC tag.
##########
script/release/03-build.sh:
##########
@@ -0,0 +1,98 @@
+#!/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/03-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/03-build.sh --skip-tests
+# ./script/release/03-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 Maven opts stored as an array so spaces inside individual opts are
+# preserved correctly (avoids unquoted word-splitting and command injection).
+EXTRA_MVN_OPTS=()
Review Comment:
The comment claims spaces inside individual opts are preserved, but `read -a` with `IFS=' '` does not honor shell-style quoting. For example, `--maven-opts '-Dfoo=\"a b\"'` will be split into multiple args incorrectly. Either adjust the contract/docs to state quoting isn’t supported, or change the interface to accept repeated `--maven-opt <singleOpt>` flags (so Jenkins/Groovy can pass each option as its own argv token without needing parsing).
##########
script/release/upload_filemgmt.sh:
##########
@@ -0,0 +1,127 @@
+#!/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
+
+# Uploads Drools release binaries and documentation to the Apache file
+# management server (people.apache.org) via SSH/rsync.
+#
+# Called by Jenkinsfile.103xplus.promote (and the original Jenkinsfile.promote)
+# inside an sshagent('drools-filemgmt') block, so SSH authentication is already
+# in the agent — no credential parameters needed here.
+#
+# Usage:
+# ./script/release/upload_filemgmt.sh <release-version>
+#
+# Examples:
+# ./script/release/upload_filemgmt.sh 10.3.0
+#
+# Environment variables (all have defaults):
+# FILEMGMT_HOST Remote host (default: people.apache.org)
+# FILEMGMT_BASE_PATH Remote base path (default: /home/drools/filemgmt)
+# DRY_RUN Set to 'true' to print commands without running them
+
+SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
+REPO_ROOT="$(cd "${SCRIPT_DIR}/../.." && pwd)"
+
+RELEASE_VERSION="${1:-}"
+
+if [[ -z "${RELEASE_VERSION}" ]]; then
+ echo "ERROR: release version argument is required."
+ echo "Usage: $0 <release-version>"
+ echo " e.g. $0 10.3.0"
+ exit 1
+fi
+
+FILEMGMT_HOST="${FILEMGMT_HOST:-people.apache.org}"
+FILEMGMT_BASE_PATH="${FILEMGMT_BASE_PATH:-/home/drools/filemgmt}"
+DRY_RUN="${DRY_RUN:-false}"
+
+# Derive major.minor stream (e.g. 10.3.0 → 10.3)
+STREAM="$(echo "${RELEASE_VERSION}" | sed 's/^\([0-9]*\.[0-9]*\)\..*/\1/')"
+
+REMOTE_BINARIES_DIR="${FILEMGMT_BASE_PATH}/docs_htdocs/drools/release/${STREAM}.x"
+REMOTE_DOCS_DIR="${FILEMGMT_BASE_PATH}/docs_htdocs/kogito/release/${STREAM}.x"
Review Comment:
The script header and Jenkins stage indicate this uploads 'Drools release binaries and documentation', but docs are uploaded under a `kogito` path while binaries go under `drools`. If these docs are meant to be Drools release docs, the remote docs directory should be under the Drools tree as well; if they’re intentionally Kogito docs, then the script name/comments (and Jenkins stage label) should be updated to avoid publishing to the wrong site tree.
##########
script/release/upload_filemgmt.sh:
##########
@@ -0,0 +1,127 @@
+#!/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
+
+# Uploads Drools release binaries and documentation to the Apache file
+# management server (people.apache.org) via SSH/rsync.
Review Comment:
The script header and Jenkins stage indicate this uploads 'Drools release binaries and documentation', but docs are uploaded under a `kogito` path while binaries go under `drools`. If these docs are meant to be Drools release docs, the remote docs directory should be under the Drools tree as well; if they’re intentionally Kogito docs, then the script name/comments (and Jenkins stage label) should be updated to avoid publishing to the wrong site tree.
##########
script/release/03-build.sh:
##########
@@ -0,0 +1,98 @@
+#!/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/03-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/03-build.sh --skip-tests
+# ./script/release/03-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 Maven opts stored as an array so spaces inside individual opts are
+# preserved correctly (avoids unquoted word-splitting and command injection).
+EXTRA_MVN_OPTS=()
+
+while [[ $# -gt 0 ]]; do
+ case $1 in
+ --skip-tests)
+ SKIP_TESTS=true
+ shift
+ ;;
+ --maven-opts)
+ # Accept a single-argument "extra opts" string and split it safely
+ # into array elements using read. No eval or command substitution.
+ IFS=' ' read -r -a _extra <<< "${2:-}"
+ EXTRA_MVN_OPTS+=("${_extra[@]}")
+ shift 2
Review Comment:
The comment claims spaces inside individual opts are preserved, but `read -a` with `IFS=' '` does not honor shell-style quoting. For example, `--maven-opts '-Dfoo=\"a b\"'` will be split into multiple args incorrectly. Either adjust the contract/docs to state quoting isn’t supported, or change the interface to accept repeated `--maven-opt <singleOpt>` flags (so Jenkins/Groovy can pass each option as its own argv token without needing parsing).
##########
script/release/05-tag-release.sh:
##########
@@ -0,0 +1,129 @@
+#!/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
+
+# Promotes an approved RC tag to the final release tag (AUTOMATION F).
+#
+# After the community vote passes on an RC (e.g. 10.3.0-rc2), this script
+# creates the final release tag pointing to the same commit:
+#
+# git tag 10.3.0 10.3.0-rc2
+#
+# By default the tag is created locally only. Pass --push to publish it.
+#
+# Usage:
+# ./script/release/05-tag-release.sh --rc-tag <rc-tag> [--push] [--dry-run]
+#
+# Examples:
+# ./script/release/05-tag-release.sh --rc-tag 10.3.0-rc2
+# ./script/release/05-tag-release.sh --rc-tag 10.3.0-rc2 --push
+
+SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
+REPO_ROOT="$(cd "${SCRIPT_DIR}/../.." && pwd)"
+
+RC_TAG=""
+PUSH=false
+DRY_RUN=false
+
+while [[ $# -gt 0 ]]; do
+ case $1 in
+ --rc-tag)
+ RC_TAG="${2:-}"
+ shift 2
+ ;;
+ --push)
+ PUSH=true
+ shift
+ ;;
+ --dry-run)
+ DRY_RUN=true
+ shift
+ ;;
+ *)
+ echo "Unknown option: $1"
+ echo "Usage: $0 --rc-tag <rc-tag> [--push] [--dry-run]"
+ exit 1
+ ;;
+ esac
+done
+
+if [[ -z "${RC_TAG}" ]]; then
+ echo "ERROR: --rc-tag is required."
+ echo "Usage: $0 --rc-tag 10.3.0-rc2 [--push]"
+ exit 1
+fi
+
Review Comment:
If `--rc-tag` is passed a value that doesn’t end in `-rc<N>` (e.g. `10.3.0`), `RELEASE_TAG` will equal `RC_TAG`, and the later `git tag -a \"${RELEASE_TAG}\" \"${RC_TAG}\" ...` will attempt to create a tag with the same name as an existing one. Add an explicit validation that `RC_TAG` matches the expected `*-rc[0-9]+` format and emit a clear error message if it doesn’t.
--
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: commits-unsubscribe@kie.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@kie.apache.org
For additional commands, e-mail: commits-help@kie.apache.org
Re: [PR] kie-issues#2404: 10.3.x+ stream: Re-write drools release jobs to be local scripts invoked in Apache Jenkins and remove old ones. [incubator-kie]
Posted by "Kusuma04-dev (via GitHub)" <gi...@apache.org>.
Kusuma04-dev commented on code in PR #7123:
URL: https://github.com/apache/incubator-kie/pull/7123#discussion_r4369863607
##########
.ci/jenkins/project/Jenkinsfile.103xplus.release:
##########
Review Comment:
old release job was following the project/ structure so i have included new one also there. I will update that Tiago. Thanks!
--
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: commits-unsubscribe@kie.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@kie.apache.org
For additional commands, e-mail: commits-help@kie.apache.org
Re: [PR] [incubator-kie#7140] 10.3.x+ stream: Re-write drools release jobs to be local scripts invoked in Apache Jenkins and remove old ones. [incubator-kie]
Posted by "Kusuma04-dev (via GitHub) via commits" <co...@kie.apache.org>.
Kusuma04-dev commented on code in PR #7123:
URL: https://github.com/apache/incubator-kie/pull/7123#discussion_r4493612517
##########
.ci/jenkins/Jenkinsfile.103xplus.release-candidate:
##########
@@ -0,0 +1,211 @@
+/*
+ * 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.
+ */
+
+// 10.3.x+ release pipeline — fully independent, no kogito-pipelines / jobs.groovy dependency.
+// - No @Library, no DSL-injected env vars, no drools-deploy / drools-promote downstream jobs
+// - Create a plain "Pipeline script from SCM" job pointing at this file and run it
+// with a few parameters. Everything it needs is a parameter (with a default).
+// - Runs script/release/release-all.sh (R commit + RC tag -> build -> Nexus staging)
+//
+// MANDATORY parameters : RELEASE_VERSION, TAG_NAME
+// Real RC run : DEPLOY=true, PUSH_TAG=true, DRY_RUN=false (the defaults)
+// Branch cut (once per minor, before rc1 only):
+// CREATE_STREAM_BRANCH=true -> creates X.Y.x from main,
+// sets X.Y.999-SNAPSHOT, pushes it, then continues the RC on X.Y.x.
+// Leave it false for rc2, final and patch releases (branch already exists).
+
+pipeline {
+ agent {
+ label 'ubuntu'
+ }
+
+ tools {
+ maven 'maven_3.9.16'
+ jdk 'jdk_17_latest'
+ }
+
+ options {
+ timestamps()
+ timeout(time: 360, unit: 'MINUTES')
+ }
+
+ parameters {
+ string(name: 'RELEASE_VERSION', defaultValue: '', description: 'MANDATORY. Exact release version, e.g. 10.3.0', trim: true)
+ string(name: 'TAG_NAME', defaultValue: '', description: 'MANDATORY. RC tag name, e.g. 10.3.0-rc1 (must start with RELEASE_VERSION and be a new tag)', trim: true)
+ booleanParam(name: 'CREATE_STREAM_BRANCH', defaultValue: false, description: 'Branch cut: create X.Y.x (derived from RELEASE_VERSION) from main, set X.Y.999-SNAPSHOT and push it BEFORE building the RC. Only for the first RC of a new minor (e.g. 10.3.0-rc1). Fails if X.Y.x already exists')
+ 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')
+
+ // Jenkins IDs — defaults match the existing KIE Jenkins; override only if they differ.
+ string(name: 'MAVEN_SETTINGS_CONFIG_FILE_ID', defaultValue: 'kie-release-authn-settings', description: 'Config File Provider ID of the Maven settings.xml (must define server "apache.releases.https")', trim: true)
+ string(name: 'GPG_KEY_CREDS_ID', defaultValue: 'GPG_KEY_FILE', description: 'Secret FILE credential ID holding the armored GPG private key', trim: true)
+ string(name: 'GPG_PASSPHRASE_CREDS_ID', defaultValue: '', description: 'Optional. Secret TEXT credential ID holding the GPG key passphrase. Leave empty if the key has no passphrase (KIE release key has none)', trim: true)
+ string(name: 'GIT_PUSH_CREDS_ID', defaultValue: '84811880-2025-45b6-a44c-2f33bef30ad2', description: 'Username/password credential ID used to push the RC tag to GitHub', trim: true)
+ }
+
+ stages {
+ stage('Initialize & Validate') {
+ steps {
+ script {
+ if (!params.RELEASE_VERSION?.trim()) {
+ error 'RELEASE_VERSION parameter is mandatory (e.g. 10.3.0)'
+ }
+ if (!params.TAG_NAME?.trim()) {
+ error 'TAG_NAME parameter is mandatory (e.g. 10.3.0-rc1)'
+ }
+ if (!params.TAG_NAME.startsWith(params.RELEASE_VERSION)) {
+ error "TAG_NAME '${params.TAG_NAME}' must start with RELEASE_VERSION '${params.RELEASE_VERSION}'"
+ }
Review Comment:
These strict regex validations are not needed.
--
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: commits-unsubscribe@kie.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@kie.apache.org
For additional commands, e-mail: commits-help@kie.apache.org
Re: [PR] kie-issues#2404: 10.3.x+ stream: Re-write drools release jobs to be local scripts invoked in Apache Jenkins and remove old ones. [incubator-kie]
Posted by "tiagobento (via GitHub)" <gi...@apache.org>.
tiagobento commented on PR #7123:
URL: https://github.com/apache/incubator-kie/pull/7123#issuecomment-5733092563
Thanks @Kusuma04-dev! Love to see this moving in this direction. I have a few observations to increase clarity and reduce friction in our development process.
1. The `.backup` files would require us to do a configuration change on Jenkins. Why not leave them as they are, and simply create new files, for new jobs? We can do like below for the new ones, and leave the old ones as they are. When we now the new jobs are working, we send a new PR deleting the files and update Jenkins to delete the old jobs.
- Jenkinsfile.103xplus.release
- Jenkinsfile.103xplus.deploy
- Jenkinsfile.103xplus.promote
---
2. We don't really have JITEXECUTOR_NATIVE anymore. You can remove those flags/configs from the new release jobs.
---
3. I don't see a Maven M2 repository in https://github.com/Kusuma04-dev/kie-release-10.3.
---
4. Can we standardize our terminology here? Release/build/publish/promote/deploy can be very confusing. I'd say we should even number (or identify with the automation letters) our scripts so that we understand exactly what order things are expected to be run.
---
5. Can we create a specific docs/RELEASING.md file here, and a `repo/RELEASING.md` file in `kie-tools`, pointing to a single source-of-truth? For the sake of democratizing our release process, I think this document should live in https://github.com/apache/incubator-kie-website under https://kie.apache.org/community/.
---
6. Is it possible to align the CLI arguments of each script between the two repos? The more in sync they are, the less friction we have during the release procedure. I'm sure they will be *very* similar to each other.
---
7. I see some references in the code and in comments saying "Drools unified repo", but we don't need to call it that. It's the KIE repo.
---
8. Is `data-index ephemeral image tag` issue still current, or is it something that is just a historical artifact from our old Jenkins automations?
--
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: commits-unsubscribe@kie.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@kie.apache.org
For additional commands, e-mail: commits-help@kie.apache.org
Re: [PR] kie-issues#2404: 10.3.x+ stream: Re-write drools release jobs to be local scripts invoked in Apache Jenkins and remove old ones. [incubator-kie]
Posted by "tiagobento (via GitHub)" <gi...@apache.org>.
tiagobento commented on code in PR #7123:
URL: https://github.com/apache/incubator-kie/pull/7123#discussion_r4360257221
##########
docs/RELEASING.md:
##########
@@ -0,0 +1,106 @@
+<!--
+ 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.
+-->
+
+# Apache KIE Release Guide
+
+The canonical release documentation and single source of truth for the Apache KIE release procedure is maintained on the Apache KIE community website:
+
+👉 **[Apache KIE Release Procedure](https://kie.apache.org/community/devs/release-procedure)** (hosted in the [`apache/incubator-kie-website`](https://github.com/apache/incubator-kie-website) repository under `docs/community/devs/release-procedure.md`).
+
+---
+
+## Who Runs These Scripts?
+
+The release scripts in this repository are intended for **Apache KIE Release Managers** — PMC members or designated committers who have:
+
+- Write access to the `apache/incubator-kie` repository (push tags to `git@github.com:apache/incubator-kie.git`).
+- An ASF Nexus account with `kie` staging privileges (username/password in Maven `settings.xml`).
+- A GPG signing key registered with the [Apache KEYS file](https://downloads.apache.org/kie/KEYS).
+
+In normal operation the scripts are invoked by the **Jenkins CI pipeline** (`.ci/jenkins/project/Jenkinsfile.103xplus.release`) using managed credentials. Release managers may also run them locally for testing or emergency releases.
+
+---
+
+## Credentials Required
+
+| Credential | Where it lives | Used by |
+|---|---|---|
+| Maven `settings.xml` with Nexus server entry (`apache.releases.https`) | Jenkins → `MAVEN_SETTINGS_CONFIG_FILE_ID`, or `~/.m2/settings.xml` locally | `04-deploy-to-staging.sh` via `MAVEN_SETTINGS` env var |
+| GPG passphrase | Jenkins → `GPG_PASSPHRASE_CREDS_ID` (masked), or GPG agent locally | `04-deploy-to-staging.sh` via `MAVEN_GPG_PASSPHRASE` env var (NOT a CLI arg) |
+| Git push credentials (SSH key or token) | Jenkins → `GIT_AUTHOR_PUSH_CREDS_ID`, or `~/.ssh/id_rsa` locally | `02-rc-commit.sh` (--push), `05-tag-release.sh` (--push) |
Review Comment:
This is for the website too.
##########
docs/RELEASING.md:
##########
@@ -0,0 +1,106 @@
+<!--
+ 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.
+-->
+
+# Apache KIE Release Guide
+
+The canonical release documentation and single source of truth for the Apache KIE release procedure is maintained on the Apache KIE community website:
+
+👉 **[Apache KIE Release Procedure](https://kie.apache.org/community/devs/release-procedure)** (hosted in the [`apache/incubator-kie-website`](https://github.com/apache/incubator-kie-website) repository under `docs/community/devs/release-procedure.md`).
+
+---
+
+## Who Runs These Scripts?
+
+The release scripts in this repository are intended for **Apache KIE Release Managers** — PMC members or designated committers who have:
+
+- Write access to the `apache/incubator-kie` repository (push tags to `git@github.com:apache/incubator-kie.git`).
+- An ASF Nexus account with `kie` staging privileges (username/password in Maven `settings.xml`).
+- A GPG signing key registered with the [Apache KEYS file](https://downloads.apache.org/kie/KEYS).
+
+In normal operation the scripts are invoked by the **Jenkins CI pipeline** (`.ci/jenkins/project/Jenkinsfile.103xplus.release`) using managed credentials. Release managers may also run them locally for testing or emergency releases.
Review Comment:
This is information for the release procedure page in the website.
##########
docs/RELEASING.md:
##########
@@ -0,0 +1,106 @@
+<!--
+ 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.
+-->
+
+# Apache KIE Release Guide
+
+The canonical release documentation and single source of truth for the Apache KIE release procedure is maintained on the Apache KIE community website:
+
+👉 **[Apache KIE Release Procedure](https://kie.apache.org/community/devs/release-procedure)** (hosted in the [`apache/incubator-kie-website`](https://github.com/apache/incubator-kie-website) repository under `docs/community/devs/release-procedure.md`).
+
+---
+
+## Who Runs These Scripts?
+
+The release scripts in this repository are intended for **Apache KIE Release Managers** — PMC members or designated committers who have:
+
+- Write access to the `apache/incubator-kie` repository (push tags to `git@github.com:apache/incubator-kie.git`).
+- An ASF Nexus account with `kie` staging privileges (username/password in Maven `settings.xml`).
+- A GPG signing key registered with the [Apache KEYS file](https://downloads.apache.org/kie/KEYS).
+
+In normal operation the scripts are invoked by the **Jenkins CI pipeline** (`.ci/jenkins/project/Jenkinsfile.103xplus.release`) using managed credentials. Release managers may also run them locally for testing or emergency releases.
+
+---
+
+## Credentials Required
+
+| Credential | Where it lives | Used by |
+|---|---|---|
+| Maven `settings.xml` with Nexus server entry (`apache.releases.https`) | Jenkins → `MAVEN_SETTINGS_CONFIG_FILE_ID`, or `~/.m2/settings.xml` locally | `04-deploy-to-staging.sh` via `MAVEN_SETTINGS` env var |
+| GPG passphrase | Jenkins → `GPG_PASSPHRASE_CREDS_ID` (masked), or GPG agent locally | `04-deploy-to-staging.sh` via `MAVEN_GPG_PASSPHRASE` env var (NOT a CLI arg) |
+| Git push credentials (SSH key or token) | Jenkins → `GIT_AUTHOR_PUSH_CREDS_ID`, or `~/.ssh/id_rsa` locally | `02-rc-commit.sh` (--push), `05-tag-release.sh` (--push) |
+
+---
+
+## What the Scripts Produce
+
+Each script is **isolated to this single consolidated repository** — there is no multi-repo coordination needed since Drools, OptaPlanner, Kogito Runtimes, and Kogito Apps all live here.
+
+| Step | Output |
+|---|---|
+| `01-update-version.sh` | POM versions bumped in the working tree (not committed) |
+| `02-rc-commit.sh` | A local RC git tag (e.g. `10.3.0-rc1`) pointing to the R commit; optionally pushed to `origin` |
+| `03-build.sh` | Release JARs installed to `~/.m2/repository` |
+| `04-deploy-to-staging.sh` | JARs signed (GPG) and uploaded to the Apache Nexus staging repository |
+| `05-tag-release.sh` | Final release git tag (e.g. `10.3.0`) pointing to the same commit as the winning RC |
+
+---
+
+## Repository-Specific Release Tooling
+
+This repository (`incubator-kie`) provides local-first release scripts located in [`script/release/`](../script/release/):
+
+- **[`script/release/README.md`](../script/release/README.md)**: Detailed documentation of all scripts, lifecycle definitions, and workflows.
+- **`01-update-version.sh`**: (Automation A / D) Updates reactor POM versions across all modules.
+- **`02-rc-commit.sh`**: (Automation D.1) Generates the temporary release branch, updates version to release version, tags the RC commit, and deletes the temporary branch.
+- **`03-build.sh`**: (Automation D.2) Builds the full Maven reactor and installs artifacts to local `~/.m2/repository`.
+- **`04-deploy-to-staging.sh`**: (Automation D.3) Deploys signed artifacts to the Apache Nexus staging repository.
+- **`05-tag-release.sh`**: (Automation F) Promotes an approved RC tag to the final release tag after a successful VOTE.
+- **`release-all.sh`**: Master orchestration script executing the RC workflow (`02` → `03` → `04`) in sequence.
+
+### Common Commands
+
+```bash
+# 1. Update version across reactor modules (Automation A or D)
+./script/release/01-update-version.sh 10.3.999-SNAPSHOT # stream snapshot
+./script/release/01-update-version.sh 999-SNAPSHOT # main stream (image tag → "main")
+./script/release/01-update-version.sh 10.3.0 # exact release version
+
+# 2. Master RC workflow (accepts positional version or --version flag)
+./script/release/release-all.sh 10.3.0 --rc --skip-tests
+# Full RC with upload + tag push (requires MAVEN_SETTINGS and MAVEN_GPG_PASSPHRASE env vars):
+MAVEN_SETTINGS=~/.m2/settings.xml \
+ ./script/release/release-all.sh --version 10.3.0 --tag 10.3.0-rc1 --skip-tests --deploy --push-tag
+
+# 3. Promote approved RC tag to final release tag (Automation F)
+./script/release/05-tag-release.sh --rc-tag 10.3.0-rc1 --push
+```
+
+### Dry-Run Safety
+
+All scripts that modify git state or push to remote accept `--dry-run`. Safe to run without credentials:
+
+```bash
+./script/release/release-all.sh 10.3.0 --tag 10.3.0-rc1 --deploy --push-tag --dry-run
+```
+
+For Jenkins pipeline jobs, see:
+- `.ci/jenkins/Jenkinsfile.103xplus.deploy` — stream-snapshot version bump and artifact deployment
+- `.ci/jenkins/Jenkinsfile.103xplus.promote` — PR merge, GitHub release creation, and final tag promotion
+- `.ci/jenkins/project/Jenkinsfile.103xplus.release` — top-level release orchestrator (invokes `release-all.sh`)
Review Comment:
This is for the website.
##########
.ci/jenkins/project/Jenkinsfile.103xplus.release:
##########
Review Comment:
Why make a `project` folder for this job in particular?
##########
docs/RELEASING.md:
##########
@@ -0,0 +1,106 @@
+<!--
+ 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.
+-->
+
+# Apache KIE Release Guide
+
+The canonical release documentation and single source of truth for the Apache KIE release procedure is maintained on the Apache KIE community website:
+
+👉 **[Apache KIE Release Procedure](https://kie.apache.org/community/devs/release-procedure)** (hosted in the [`apache/incubator-kie-website`](https://github.com/apache/incubator-kie-website) repository under `docs/community/devs/release-procedure.md`).
+
+---
+
+## Who Runs These Scripts?
+
+The release scripts in this repository are intended for **Apache KIE Release Managers** — PMC members or designated committers who have:
+
+- Write access to the `apache/incubator-kie` repository (push tags to `git@github.com:apache/incubator-kie.git`).
+- An ASF Nexus account with `kie` staging privileges (username/password in Maven `settings.xml`).
+- A GPG signing key registered with the [Apache KEYS file](https://downloads.apache.org/kie/KEYS).
+
+In normal operation the scripts are invoked by the **Jenkins CI pipeline** (`.ci/jenkins/project/Jenkinsfile.103xplus.release`) using managed credentials. Release managers may also run them locally for testing or emergency releases.
+
+---
+
+## Credentials Required
+
+| Credential | Where it lives | Used by |
+|---|---|---|
+| Maven `settings.xml` with Nexus server entry (`apache.releases.https`) | Jenkins → `MAVEN_SETTINGS_CONFIG_FILE_ID`, or `~/.m2/settings.xml` locally | `04-deploy-to-staging.sh` via `MAVEN_SETTINGS` env var |
+| GPG passphrase | Jenkins → `GPG_PASSPHRASE_CREDS_ID` (masked), or GPG agent locally | `04-deploy-to-staging.sh` via `MAVEN_GPG_PASSPHRASE` env var (NOT a CLI arg) |
+| Git push credentials (SSH key or token) | Jenkins → `GIT_AUTHOR_PUSH_CREDS_ID`, or `~/.ssh/id_rsa` locally | `02-rc-commit.sh` (--push), `05-tag-release.sh` (--push) |
+
+---
+
+## What the Scripts Produce
+
+Each script is **isolated to this single consolidated repository** — there is no multi-repo coordination needed since Drools, OptaPlanner, Kogito Runtimes, and Kogito Apps all live here.
+
+| Step | Output |
+|---|---|
+| `01-update-version.sh` | POM versions bumped in the working tree (not committed) |
+| `02-rc-commit.sh` | A local RC git tag (e.g. `10.3.0-rc1`) pointing to the R commit; optionally pushed to `origin` |
+| `03-build.sh` | Release JARs installed to `~/.m2/repository` |
+| `04-deploy-to-staging.sh` | JARs signed (GPG) and uploaded to the Apache Nexus staging repository |
+| `05-tag-release.sh` | Final release git tag (e.g. `10.3.0`) pointing to the same commit as the winning RC |
+
+---
+
+## Repository-Specific Release Tooling
+
+This repository (`incubator-kie`) provides local-first release scripts located in [`script/release/`](../script/release/):
+
+- **[`script/release/README.md`](../script/release/README.md)**: Detailed documentation of all scripts, lifecycle definitions, and workflows.
+- **`01-update-version.sh`**: (Automation A / D) Updates reactor POM versions across all modules.
+- **`02-rc-commit.sh`**: (Automation D.1) Generates the temporary release branch, updates version to release version, tags the RC commit, and deletes the temporary branch.
+- **`03-build.sh`**: (Automation D.2) Builds the full Maven reactor and installs artifacts to local `~/.m2/repository`.
+- **`04-deploy-to-staging.sh`**: (Automation D.3) Deploys signed artifacts to the Apache Nexus staging repository.
+- **`05-tag-release.sh`**: (Automation F) Promotes an approved RC tag to the final release tag after a successful VOTE.
+- **`release-all.sh`**: Master orchestration script executing the RC workflow (`02` → `03` → `04`) in sequence.
Review Comment:
This is probably for `script/release/README.md`.
##########
docs/RELEASING.md:
##########
@@ -0,0 +1,106 @@
+<!--
+ 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.
+-->
+
+# Apache KIE Release Guide
+
+The canonical release documentation and single source of truth for the Apache KIE release procedure is maintained on the Apache KIE community website:
+
+👉 **[Apache KIE Release Procedure](https://kie.apache.org/community/devs/release-procedure)** (hosted in the [`apache/incubator-kie-website`](https://github.com/apache/incubator-kie-website) repository under `docs/community/devs/release-procedure.md`).
+
+---
+
+## Who Runs These Scripts?
+
+The release scripts in this repository are intended for **Apache KIE Release Managers** — PMC members or designated committers who have:
+
+- Write access to the `apache/incubator-kie` repository (push tags to `git@github.com:apache/incubator-kie.git`).
+- An ASF Nexus account with `kie` staging privileges (username/password in Maven `settings.xml`).
+- A GPG signing key registered with the [Apache KEYS file](https://downloads.apache.org/kie/KEYS).
+
+In normal operation the scripts are invoked by the **Jenkins CI pipeline** (`.ci/jenkins/project/Jenkinsfile.103xplus.release`) using managed credentials. Release managers may also run them locally for testing or emergency releases.
+
+---
+
+## Credentials Required
+
+| Credential | Where it lives | Used by |
+|---|---|---|
+| Maven `settings.xml` with Nexus server entry (`apache.releases.https`) | Jenkins → `MAVEN_SETTINGS_CONFIG_FILE_ID`, or `~/.m2/settings.xml` locally | `04-deploy-to-staging.sh` via `MAVEN_SETTINGS` env var |
+| GPG passphrase | Jenkins → `GPG_PASSPHRASE_CREDS_ID` (masked), or GPG agent locally | `04-deploy-to-staging.sh` via `MAVEN_GPG_PASSPHRASE` env var (NOT a CLI arg) |
+| Git push credentials (SSH key or token) | Jenkins → `GIT_AUTHOR_PUSH_CREDS_ID`, or `~/.ssh/id_rsa` locally | `02-rc-commit.sh` (--push), `05-tag-release.sh` (--push) |
+
+---
+
+## What the Scripts Produce
+
+Each script is **isolated to this single consolidated repository** — there is no multi-repo coordination needed since Drools, OptaPlanner, Kogito Runtimes, and Kogito Apps all live here.
+
+| Step | Output |
+|---|---|
+| `01-update-version.sh` | POM versions bumped in the working tree (not committed) |
+| `02-rc-commit.sh` | A local RC git tag (e.g. `10.3.0-rc1`) pointing to the R commit; optionally pushed to `origin` |
+| `03-build.sh` | Release JARs installed to `~/.m2/repository` |
+| `04-deploy-to-staging.sh` | JARs signed (GPG) and uploaded to the Apache Nexus staging repository |
+| `05-tag-release.sh` | Final release git tag (e.g. `10.3.0`) pointing to the same commit as the winning RC |
+
+---
+
+## Repository-Specific Release Tooling
+
+This repository (`incubator-kie`) provides local-first release scripts located in [`script/release/`](../script/release/):
+
+- **[`script/release/README.md`](../script/release/README.md)**: Detailed documentation of all scripts, lifecycle definitions, and workflows.
+- **`01-update-version.sh`**: (Automation A / D) Updates reactor POM versions across all modules.
+- **`02-rc-commit.sh`**: (Automation D.1) Generates the temporary release branch, updates version to release version, tags the RC commit, and deletes the temporary branch.
+- **`03-build.sh`**: (Automation D.2) Builds the full Maven reactor and installs artifacts to local `~/.m2/repository`.
+- **`04-deploy-to-staging.sh`**: (Automation D.3) Deploys signed artifacts to the Apache Nexus staging repository.
+- **`05-tag-release.sh`**: (Automation F) Promotes an approved RC tag to the final release tag after a successful VOTE.
+- **`release-all.sh`**: Master orchestration script executing the RC workflow (`02` → `03` → `04`) in sequence.
+
+### Common Commands
+
+```bash
+# 1. Update version across reactor modules (Automation A or D)
+./script/release/01-update-version.sh 10.3.999-SNAPSHOT # stream snapshot
+./script/release/01-update-version.sh 999-SNAPSHOT # main stream (image tag → "main")
+./script/release/01-update-version.sh 10.3.0 # exact release version
+
+# 2. Master RC workflow (accepts positional version or --version flag)
+./script/release/release-all.sh 10.3.0 --rc --skip-tests
+# Full RC with upload + tag push (requires MAVEN_SETTINGS and MAVEN_GPG_PASSPHRASE env vars):
+MAVEN_SETTINGS=~/.m2/settings.xml \
+ ./script/release/release-all.sh --version 10.3.0 --tag 10.3.0-rc1 --skip-tests --deploy --push-tag
+
+# 3. Promote approved RC tag to final release tag (Automation F)
+./script/release/05-tag-release.sh --rc-tag 10.3.0-rc1 --push
+```
Review Comment:
Also for `script/release/README.md`.
--
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: commits-unsubscribe@kie.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@kie.apache.org
For additional commands, e-mail: commits-help@kie.apache.org
Re: [PR] [incubator-kie#7140] 10.3.x+ stream: Re-write drools release jobs to be local scripts invoked in Apache Jenkins and remove old ones. [incubator-kie]
Posted by "Copilot (via GitHub) via commits" <co...@kie.apache.org>.
Copilot commented on code in PR #7123:
URL: https://github.com/apache/incubator-kie/pull/7123#discussion_r4490909114
##########
.ci/jenkins/Jenkinsfile.103xplus.release-candidate:
##########
@@ -0,0 +1,181 @@
+/*
+ * 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.
+ */
+
+// 10.3.x+ release pipeline — fully independent, no kogito-pipelines / jobs.groovy dependency.
+// - No @Library, no DSL-injected env vars, no drools-deploy / drools-promote downstream jobs
+// - Create a plain "Pipeline script from SCM" job pointing at this file and run it
+// with a few parameters. Everything it needs is a parameter (with a default).
+// - Runs script/release/release-all.sh (R commit + RC tag -> build -> Nexus staging)
+//
+// MANDATORY parameters : RELEASE_VERSION, TAG_NAME
+// Real RC run : DEPLOY=true, PUSH_TAG=true, DRY_RUN=false (the defaults)
+// Branch cut (once per minor, before rc1 only):
+// CREATE_STREAM_BRANCH=true -> creates X.Y.x from main,
+// sets X.Y.999-SNAPSHOT, pushes it, then continues the RC on X.Y.x.
+// Leave it false for rc2, final and patch releases (branch already exists).
+
+pipeline {
+ agent {
+ label 'ubuntu'
+ }
+
+ tools {
+ maven 'maven_3.9.16'
+ jdk 'jdk_17_latest'
+ }
+
+ options {
+ timestamps()
+ timeout(time: 360, unit: 'MINUTES')
+ }
+
+ parameters {
+ string(name: 'RELEASE_VERSION', defaultValue: '', description: 'MANDATORY. Exact release version, e.g. 10.3.0', trim: true)
+ string(name: 'TAG_NAME', defaultValue: '', description: 'MANDATORY. RC tag name, e.g. 10.3.0-rc1 (must start with RELEASE_VERSION and be a new tag)', trim: true)
+ booleanParam(name: 'CREATE_STREAM_BRANCH', defaultValue: false, description: 'Branch cut: create X.Y.x (derived from RELEASE_VERSION) from main, set X.Y.999-SNAPSHOT and push it BEFORE building the RC. Only for the first RC of a new minor (e.g. 10.3.0-rc1). Fails if X.Y.x already exists')
+ 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')
+
+ // Jenkins IDs — defaults match the existing KIE Jenkins; override only if they differ.
+ string(name: 'MAVEN_SETTINGS_CONFIG_FILE_ID', defaultValue: 'kie-release-authn-settings', description: 'Config File Provider ID of the Maven settings.xml (must define server "apache.releases.https")', trim: true)
+ string(name: 'GPG_KEY_CREDS_ID', defaultValue: 'GPG_KEY_FILE', description: 'Secret FILE credential ID holding the armored GPG private key', trim: true)
+ string(name: 'GPG_PASSPHRASE_CREDS_ID', defaultValue: '', description: 'Optional. Secret TEXT credential ID holding the GPG key passphrase. Leave empty if the key has no passphrase (KIE release key has none)', trim: true)
+ string(name: 'GIT_PUSH_CREDS_ID', defaultValue: '84811880-2025-45b6-a44c-2f33bef30ad2', description: 'Username/password credential ID used to push the RC tag to GitHub', trim: true)
+ }
+
+ stages {
+ stage('Initialize & Validate') {
+ steps {
+ script {
+ if (!params.RELEASE_VERSION?.trim()) {
+ error 'RELEASE_VERSION parameter is mandatory (e.g. 10.3.0)'
+ }
+ if (!params.TAG_NAME?.trim()) {
+ error 'TAG_NAME parameter is mandatory (e.g. 10.3.0-rc1)'
+ }
+ if (!params.TAG_NAME.startsWith(params.RELEASE_VERSION)) {
+ error "TAG_NAME '${params.TAG_NAME}' must start with RELEASE_VERSION '${params.RELEASE_VERSION}'"
+ }
+ currentBuild.displayName = "Release ${params.RELEASE_VERSION} (${params.TAG_NAME})"
+ }
+ }
+ }
+
+ stage('Create Stream Branch') {
+ when {
+ expression { return params.CREATE_STREAM_BRANCH }
+ }
+ steps {
+ script {
+ withCredentials([usernamePassword(credentialsId: params.GIT_PUSH_CREDS_ID, usernameVariable: 'GITHUB_USER', passwordVariable: 'GITHUB_TOKEN')]) {
+ def branchArgs = [
+ './script/release/00-create-stream-branch.sh',
+ '--version', params.RELEASE_VERSION,
+ '--base', 'main',
+ '--push'
+ ]
+ if (params.DRY_RUN) branchArgs << '--dry-run'
+
+ sh """#!/usr/bin/env bash
+ set -euo pipefail
+ git config user.email "dev@kie.apache.org"
+ git config user.name "Apache KIE Release Bot"
+ git config --local credential.helper '!f() { echo username=\$GITHUB_USER; echo password=\$GITHUB_TOKEN; }; f'
+ chmod +x script/release/*.sh
+ ${branchArgs.collect { "'${it.replace("'", "'\\''")}'" }.join(' ')}
+ """
+ }
+ }
+ }
+ }
+
+ stage('Execute Release Scripts') {
+ steps {
+ // The Maven settings id is a Config File Provider id (not a secret) and is
+ // exposed as MAVEN_SETTINGS_FILE. GPG key/passphrase and the GitHub push
+ // credential are real credentials and use withCredentials.
+ script {
+ def creds = [
+ file(credentialsId: params.GPG_KEY_CREDS_ID, variable: 'GPG_KEY_FILE_PATH'),
+ usernamePassword(credentialsId: params.GIT_PUSH_CREDS_ID, usernameVariable: 'GITHUB_USER', passwordVariable: 'GITHUB_TOKEN')
+ ]
+ // Passphrase is optional: the KIE release signing key has none.
+ if (params.GPG_PASSPHRASE_CREDS_ID?.trim()) {
+ creds << string(credentialsId: params.GPG_PASSPHRASE_CREDS_ID, variable: 'MAVEN_GPG_PASSPHRASE')
+ }
+ configFileProvider([configFile(fileId: params.MAVEN_SETTINGS_CONFIG_FILE_ID, variable: 'MAVEN_SETTINGS_FILE')]) {
+ withCredentials(creds) {
+ // Import the signing key so the apache-release profile can sign
+ // artifacts. Passphrase is supplied later via MAVEN_GPG_PASSPHRASE.
+ sh '''#!/usr/bin/env bash
+ set -euo pipefail
+ gpg --batch --pinentry-mode=loopback --import "$GPG_KEY_FILE_PATH"
Review Comment:
This imports the release private key into the Ubuntu agent's default `~/.gnupg`, outside the workspace. Neither `withCredentials` nor `cleanWs` removes imported keys, so on a reused agent the signing key remains available to subsequent jobs running as the same user. Use a private, build-specific `GNUPGHOME` for both import and Maven signing, and remove it and its agent in guaranteed cleanup.
##########
.ci/jenkins/Jenkinsfile.103xplus.release-candidate:
##########
@@ -0,0 +1,181 @@
+/*
+ * 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.
+ */
+
+// 10.3.x+ release pipeline — fully independent, no kogito-pipelines / jobs.groovy dependency.
+// - No @Library, no DSL-injected env vars, no drools-deploy / drools-promote downstream jobs
+// - Create a plain "Pipeline script from SCM" job pointing at this file and run it
+// with a few parameters. Everything it needs is a parameter (with a default).
+// - Runs script/release/release-all.sh (R commit + RC tag -> build -> Nexus staging)
+//
+// MANDATORY parameters : RELEASE_VERSION, TAG_NAME
+// Real RC run : DEPLOY=true, PUSH_TAG=true, DRY_RUN=false (the defaults)
+// Branch cut (once per minor, before rc1 only):
+// CREATE_STREAM_BRANCH=true -> creates X.Y.x from main,
+// sets X.Y.999-SNAPSHOT, pushes it, then continues the RC on X.Y.x.
+// Leave it false for rc2, final and patch releases (branch already exists).
+
+pipeline {
+ agent {
+ label 'ubuntu'
+ }
+
+ tools {
+ maven 'maven_3.9.16'
+ jdk 'jdk_17_latest'
+ }
+
+ options {
+ timestamps()
+ timeout(time: 360, unit: 'MINUTES')
+ }
+
+ parameters {
+ string(name: 'RELEASE_VERSION', defaultValue: '', description: 'MANDATORY. Exact release version, e.g. 10.3.0', trim: true)
+ string(name: 'TAG_NAME', defaultValue: '', description: 'MANDATORY. RC tag name, e.g. 10.3.0-rc1 (must start with RELEASE_VERSION and be a new tag)', trim: true)
+ booleanParam(name: 'CREATE_STREAM_BRANCH', defaultValue: false, description: 'Branch cut: create X.Y.x (derived from RELEASE_VERSION) from main, set X.Y.999-SNAPSHOT and push it BEFORE building the RC. Only for the first RC of a new minor (e.g. 10.3.0-rc1). Fails if X.Y.x already exists')
+ 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')
+
+ // Jenkins IDs — defaults match the existing KIE Jenkins; override only if they differ.
+ string(name: 'MAVEN_SETTINGS_CONFIG_FILE_ID', defaultValue: 'kie-release-authn-settings', description: 'Config File Provider ID of the Maven settings.xml (must define server "apache.releases.https")', trim: true)
+ string(name: 'GPG_KEY_CREDS_ID', defaultValue: 'GPG_KEY_FILE', description: 'Secret FILE credential ID holding the armored GPG private key', trim: true)
+ string(name: 'GPG_PASSPHRASE_CREDS_ID', defaultValue: '', description: 'Optional. Secret TEXT credential ID holding the GPG key passphrase. Leave empty if the key has no passphrase (KIE release key has none)', trim: true)
+ string(name: 'GIT_PUSH_CREDS_ID', defaultValue: '84811880-2025-45b6-a44c-2f33bef30ad2', description: 'Username/password credential ID used to push the RC tag to GitHub', trim: true)
+ }
+
+ stages {
+ stage('Initialize & Validate') {
+ steps {
+ script {
+ if (!params.RELEASE_VERSION?.trim()) {
+ error 'RELEASE_VERSION parameter is mandatory (e.g. 10.3.0)'
+ }
+ if (!params.TAG_NAME?.trim()) {
+ error 'TAG_NAME parameter is mandatory (e.g. 10.3.0-rc1)'
+ }
+ if (!params.TAG_NAME.startsWith(params.RELEASE_VERSION)) {
+ error "TAG_NAME '${params.TAG_NAME}' must start with RELEASE_VERSION '${params.RELEASE_VERSION}'"
+ }
+ currentBuild.displayName = "Release ${params.RELEASE_VERSION} (${params.TAG_NAME})"
+ }
+ }
+ }
+
+ stage('Create Stream Branch') {
+ when {
+ expression { return params.CREATE_STREAM_BRANCH }
+ }
+ steps {
+ script {
+ withCredentials([usernamePassword(credentialsId: params.GIT_PUSH_CREDS_ID, usernameVariable: 'GITHUB_USER', passwordVariable: 'GITHUB_TOKEN')]) {
+ def branchArgs = [
+ './script/release/00-create-stream-branch.sh',
+ '--version', params.RELEASE_VERSION,
+ '--base', 'main',
+ '--push'
+ ]
+ if (params.DRY_RUN) branchArgs << '--dry-run'
+
+ sh """#!/usr/bin/env bash
+ set -euo pipefail
+ git config user.email "dev@kie.apache.org"
+ git config user.name "Apache KIE Release Bot"
+ git config --local credential.helper '!f() { echo username=\$GITHUB_USER; echo password=\$GITHUB_TOKEN; }; f'
+ chmod +x script/release/*.sh
+ ${branchArgs.collect { "'${it.replace("'", "'\\''")}'" }.join(' ')}
+ """
+ }
+ }
+ }
+ }
+
+ stage('Execute Release Scripts') {
+ steps {
+ // The Maven settings id is a Config File Provider id (not a secret) and is
+ // exposed as MAVEN_SETTINGS_FILE. GPG key/passphrase and the GitHub push
+ // credential are real credentials and use withCredentials.
+ script {
+ def creds = [
+ file(credentialsId: params.GPG_KEY_CREDS_ID, variable: 'GPG_KEY_FILE_PATH'),
+ usernamePassword(credentialsId: params.GIT_PUSH_CREDS_ID, usernameVariable: 'GITHUB_USER', passwordVariable: 'GITHUB_TOKEN')
+ ]
+ // Passphrase is optional: the KIE release signing key has none.
+ if (params.GPG_PASSPHRASE_CREDS_ID?.trim()) {
+ creds << string(credentialsId: params.GPG_PASSPHRASE_CREDS_ID, variable: 'MAVEN_GPG_PASSPHRASE')
+ }
+ configFileProvider([configFile(fileId: params.MAVEN_SETTINGS_CONFIG_FILE_ID, variable: 'MAVEN_SETTINGS_FILE')]) {
+ withCredentials(creds) {
+ // Import the signing key so the apache-release profile can sign
+ // artifacts. Passphrase is supplied later via MAVEN_GPG_PASSPHRASE.
+ sh '''#!/usr/bin/env bash
+ set -euo pipefail
+ gpg --batch --pinentry-mode=loopback --import "$GPG_KEY_FILE_PATH"
+ '''
+
+ // Configure Git identity for the R commit and authenticate the
+ // raw `git push` in 02-rc-commit.sh. The credential helper reads
+ // the token from the environment at push time, never from disk.
+ sh """#!/usr/bin/env bash
+ set -euo pipefail
+ git config user.email "dev@kie.apache.org"
+ git config user.name "Apache KIE Release Bot"
+ git config --local credential.helper '!f() { echo username=\$GITHUB_USER; echo password=\$GITHUB_TOKEN; }; f'
+ """
+
+ // Build the argv array safely — each parameter is a
+ // separate shell word, no string concatenation or eval.
+ def releaseArgs = [
+ './script/release/release-all.sh',
+ '--version', params.RELEASE_VERSION,
+ '--tag', params.TAG_NAME
+ ]
+ if (params.SKIP_TESTS) releaseArgs << '--skip-tests'
+ if (params.DEPLOY) releaseArgs << '--deploy'
+ if (params.STAGING_URL?.trim()) releaseArgs += ['--staging-url', params.STAGING_URL.trim()]
+ if (params.PUSH_TAG) releaseArgs << '--push-tag'
+ if (params.EXTRA_MAVEN_OPTS?.trim()) releaseArgs += ['--maven-opts', params.EXTRA_MAVEN_OPTS.trim()]
+ if (params.DRY_RUN) releaseArgs << '--dry-run'
+
+ // MAVEN_SETTINGS_FILE is injected by configFileProvider above.
+ // If a passphrase credential was given, MAVEN_GPG_PASSPHRASE is in
+ // env and read by the GPG plugin directly (not a CLI arg).
+ withEnv(["MAVEN_SETTINGS=${MAVEN_SETTINGS_FILE}"]) {
+ sh """#!/usr/bin/env bash
+ set -euo pipefail
+ chmod +x script/release/*.sh
+ ${releaseArgs.collect { "'${it.replace("'", "'\\''")}'" }.join(' ')}
Review Comment:
When CREATE_STREAM_BRANCH is false (the default), nothing checks out the stream branch before this invocation. The RC is therefore created from the job's implicit SCM checkout: a job loading this Jenkinsfile from main will tag and stage main even for a 10.3.x release, because 02-rc-commit.sh only warns about the mismatch. Fetch and check out the stream derived from RELEASE_VERSION, or reject an unexpected checkout before creating the RC.
##########
.ci/jenkins/Jenkinsfile.103xplus.release-promote:
##########
@@ -0,0 +1,139 @@
+/*
+ * 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.
+ */
+
+// 10.3.x+ promote / tag-release pipeline for incubator-kie.
+// Run after the IPMC vote passes to:
+// 1. Create and push the official release Git tag (e.g. 10.3.0) pointing to the approved RC commit.
+// 2. Create the GitHub Release for incubator-kie.
+
+pipeline {
+ agent {
+ label 'ubuntu'
+ }
+
+ tools {
+ maven 'maven_3.9.16'
+ jdk 'jdk_17_latest'
+ }
+
+ options {
+ timestamps()
+ timeout(time: 60, unit: 'MINUTES')
+ }
+
+ parameters {
+ string(name: 'PROJECT_VERSION', defaultValue: '', description: 'Release version (e.g. 10.3.0)', trim: true)
+ string(name: 'GIT_TAG', defaultValue: '', description: 'Approved RC tag (e.g. 10.3.0-rc1)', trim: true)
+ string(name: 'BUILD_BRANCH_NAME', defaultValue: '', description: 'Stream branch name (e.g. 10.3.x)', trim: true)
+ string(name: 'GIT_AUTHOR_PUSH_CREDS_ID', defaultValue: '84811880-2025-45b6-a44c-2f33bef30ad2', description: 'GitHub push credentials ID', trim: true)
+ }
+
+ stages {
+ stage('Initialization') {
+ steps {
+ script {
+ cleanWs()
+
+ assert params.PROJECT_VERSION : 'PROJECT_VERSION is required (e.g. 10.3.0)'
+ assert params.GIT_TAG : 'GIT_TAG (approved RC tag, e.g. 10.3.0-rc1) is required'
Review Comment:
With PROJECT_VERSION=10.3.1 and GIT_TAG=10.3.0-rc1, the tagging stage pushes 10.3.0, but the GitHub-release stage requests 10.3.1. Because `gh release create` supplies `--target` without `--verify-tag`, it can create the missing tag at the development branch tip and publish unapproved code. Require GIT_TAG to be an RC tag for PROJECT_VERSION before making any remote changes.
##########
script/release/04-deploy-to-staging.sh:
##########
@@ -0,0 +1,179 @@
+#!/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/04-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/04-deploy-to-staging.sh --tag 10.3.0-rc1
+#
+# # actually deploy to Apache Nexus staging
+# ./script/release/04-deploy-to-staging.sh --tag 10.3.0-rc1 --deploy
+#
+# # deploy to a custom staging URL
+# ./script/release/04-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).
+# Passed to the GPG agent via the gpg-agent pinentry loopback
+# mechanism; NOT exposed on the Maven command line.
+
+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"
+ # Activate the apache-release profile so the source/javadoc and GPG-signing
+ # goals defined there are executed (required for Apache releases).
+ "-Papache-release"
+ "-DaltDeploymentRepository=${SERVER_ID}::default::${STAGING_URL}"
+)
+
+if [[ -n "${MAVEN_SETTINGS:-}" ]]; then
+ DEPLOY_MVN_FLAGS+=("-s" "${MAVEN_SETTINGS}")
+fi
+
+# NOTE: MAVEN_GPG_PASSPHRASE is intentionally NOT added to the Maven command
+# line — exposing it there would print it in captured console logs.
+# The standard GPG Maven plugin (version 3+) reads the passphrase from the
+# environment variable MAVEN_GPG_PASSPHRASE via pinentry-loopback automatically.
+# For older plugin versions, configure loopback in ~/.gnupg/gpg-agent.conf:
+# allow-loopback-pinentry
+# and pass: -Dgpg.useagent=false -Dgpg.loopback=true in MAVEN_SETTINGS.
+
+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 ───────────────────────────
+# Save the original ref as the commit SHA when in detached HEAD state (e.g.,
+# Jenkins SCM checkout). `git rev-parse --abbrev-ref HEAD` returns "HEAD" when
+# detached, which cannot be used to restore the checkout afterwards.
+if git symbolic-ref --quiet HEAD &>/dev/null; then
+ ORIG_REF="$(git rev-parse --abbrev-ref HEAD)"
+else
+ ORIG_REF="$(git rev-parse HEAD)"
+fi
+
+echo "--- Checking out tag ${TAG_NAME} ---"
+git checkout "${TAG_NAME}"
Review Comment:
Checking out the tag does not guarantee a clean release tree: Git preserves local edits when they do not conflict with the checkout, including when HEAD is already at this tag. Running this standalone script with an edited Java source can therefore sign and deploy artifacts that do not match the RC commit. Reject staged, unstaged and untracked changes before checkout, as `02-rc-commit.sh` already does.
##########
.ci/ci-image/wait-for-docker.sh:
##########
@@ -0,0 +1,4 @@
+#!/bin/bash
+source wait-for-process.sh
+
+wait_for_process dockerd
Review Comment:
This only waits for dockerd to have a PID, not for its socket/API to be ready. On a slow cold start it can return while the daemon is still initializing, so start-docker.sh's chown and the image smoke test's docker info can fail even though Docker subsequently starts successfully. Use a bounded daemon API readiness probe and synchronize the socket setup before allowing callers to proceed.
##########
.ci/jenkins/Jenkinsfile.103xplus.release-promote:
##########
@@ -0,0 +1,139 @@
+/*
+ * 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.
+ */
+
+// 10.3.x+ promote / tag-release pipeline for incubator-kie.
+// Run after the IPMC vote passes to:
+// 1. Create and push the official release Git tag (e.g. 10.3.0) pointing to the approved RC commit.
+// 2. Create the GitHub Release for incubator-kie.
+
+pipeline {
+ agent {
+ label 'ubuntu'
+ }
+
+ tools {
+ maven 'maven_3.9.16'
+ jdk 'jdk_17_latest'
+ }
+
+ options {
+ timestamps()
+ timeout(time: 60, unit: 'MINUTES')
+ }
+
+ parameters {
+ string(name: 'PROJECT_VERSION', defaultValue: '', description: 'Release version (e.g. 10.3.0)', trim: true)
+ string(name: 'GIT_TAG', defaultValue: '', description: 'Approved RC tag (e.g. 10.3.0-rc1)', trim: true)
+ string(name: 'BUILD_BRANCH_NAME', defaultValue: '', description: 'Stream branch name (e.g. 10.3.x)', trim: true)
+ string(name: 'GIT_AUTHOR_PUSH_CREDS_ID', defaultValue: '84811880-2025-45b6-a44c-2f33bef30ad2', description: 'GitHub push credentials ID', trim: true)
+ }
+
+ stages {
+ stage('Initialization') {
+ steps {
+ script {
+ cleanWs()
+
+ assert params.PROJECT_VERSION : 'PROJECT_VERSION is required (e.g. 10.3.0)'
+ assert params.GIT_TAG : 'GIT_TAG (approved RC tag, e.g. 10.3.0-rc1) is required'
+ assert params.BUILD_BRANCH_NAME : 'BUILD_BRANCH_NAME (e.g. 10.3.x) is required'
+
+ currentBuild.displayName = "${params.PROJECT_VERSION} (${params.GIT_TAG})"
+ }
+ }
+ }
+
+ stage('Checkout repository') {
+ steps {
+ script {
+ dir('incubator-kie') {
+ checkout([$class: 'GitSCM',
+ branches: [[name: "*/${params.BUILD_BRANCH_NAME}"]],
+ userRemoteConfigs: [[
+ url: 'https://github.com/apache/incubator-kie.git',
+ credentialsId: params.GIT_AUTHOR_PUSH_CREDS_ID
+ ]]
+ ])
+ }
+ }
+ }
+ }
+
+ stage('Tag final release') {
+ steps {
+ dir('incubator-kie') {
+ withCredentials([
+ usernamePassword(credentialsId: params.GIT_AUTHOR_PUSH_CREDS_ID, usernameVariable: 'GITHUB_USER', passwordVariable: 'GITHUB_TOKEN')
+ ]) {
+ sh """#!/usr/bin/env bash
+ set -euo pipefail
+ git config user.email "dev@kie.apache.org"
+ git config user.name "Apache KIE Release Bot"
+ git config --local credential.helper '!f() { echo username=\$GITHUB_USER; echo password=\$GITHUB_TOKEN; }; f'
+
+ # Fetch the approved RC tag
+ git fetch origin "refs/tags/${params.GIT_TAG}:refs/tags/${params.GIT_TAG}"
+
+ # Create and push the final release tag
+ chmod +x script/release/05-tag-release.sh
+ ./script/release/05-tag-release.sh --rc-tag "${params.GIT_TAG}" --push
+ """
+ }
+ }
+ }
+ }
+
+ stage('Create GitHub Release') {
+ steps {
+ dir('incubator-kie') {
+ withCredentials([
+ usernamePassword(credentialsId: params.GIT_AUTHOR_PUSH_CREDS_ID, usernameVariable: 'GITHUB_USER', passwordVariable: 'GITHUB_TOKEN')
+ ]) {
+ sh """#!/usr/bin/env bash
+ set -euo pipefail
+ git config --local credential.helper '!f() { echo username=\$GITHUB_USER; echo password=\$GITHUB_TOKEN; }; f'
+
+ FINAL_TAG="${params.PROJECT_VERSION}"
+
+ # Delete any pre-existing release for this tag if needed
+ if gh release view "\${FINAL_TAG}" --repo "apache/incubator-kie" &>/dev/null; then
+ gh release delete "\${FINAL_TAG}" --repo "apache/incubator-kie" --yes
+ fi
+
+ PREV_TAG="\$(git tag --sort=-version:refname | grep -v "^\${FINAL_TAG}\$" | head -1 || true)"
Review Comment:
The fetched RC tag is included in this search. For a normal 10.3.0 promotion, the selected tag will be 10.3.0-rc1 rather than the previous final release; the RC and final tag resolve to the same commit, so --notes-start-tag produces an empty release changelog. Select the preceding final release tag, excluding RC tags and tags from later release streams.
--
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: commits-unsubscribe@kie.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@kie.apache.org
For additional commands, e-mail: commits-help@kie.apache.org