This is an automated email from the ASF dual-hosted git repository.
snazy pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/polaris.git
The following commit(s) were added to refs/heads/main by this push:
new 10bb2ba37 Automate the release guide - Take 2 - Github workflows
(#2383)
10bb2ba37 is described below
commit 10bb2ba370ab065005b5858de3c8cf8ebc962b14
Author: Pierre Laporte <[email protected]>
AuthorDate: Tue Nov 18 17:48:40 2025 +0100
Automate the release guide - Take 2 - Github workflows (#2383)
The release automation is simplified to four GitHub workflows that just
require the really mandatory user input: the version number.
1. workflow: Trigger the creation of the release branch
2. workflow: Upgrade the release branch with the version and build the the
final change-log for that version
3. workflow: Build the RC artifacts from the release branch and push those
to the various staging repositories
4. workflow: Eventually release the artifacts.
See also the [email
announcement](https://lists.apache.org/thread/d0smz07gnr509yj5dc6omo3cvkf1pnh7).
---------
Co-authored-by: Robert Stupp <[email protected]>
---
.github/workflows/gradle.yml | 2 +-
.github/workflows/helm.yml | 2 +-
.github/workflows/python-client.yml | 2 +-
.github/workflows/regtest.yml | 2 +-
.../workflows/release-1-create-release-branch.yml | 122 +++++++
.../release-2-update-release-candidate.yml | 206 +++++++++++
.../release-3-build-and-publish-artifacts.yml | 400 +++++++++++++++++++++
.github/workflows/release-4-publish-release.yml | 379 +++++++++++++++++++
.github/workflows/spark_client_regtests.yml | 2 +-
releasey/README.md | 61 ++++
releasey/libs/_constants.sh | 40 +++
releasey/libs/_exec.sh | 46 +++
releasey/libs/_github.sh | 72 ++++
releasey/libs/_log.sh | 63 ++++
releasey/libs/_version.sh | 177 +++++++++
releasey/release-process-flowchart.mmd | 39 ++
releasey/release-process-flowchart.png | Bin 0 -> 226494 bytes
17 files changed, 1610 insertions(+), 5 deletions(-)
diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml
index c1241df70..06ad5a123 100644
--- a/.github/workflows/gradle.yml
+++ b/.github/workflows/gradle.yml
@@ -30,7 +30,7 @@ on:
push:
branches: [ "main" ]
pull_request:
- branches: [ "main" ]
+ branches: [ "main", "release/*" ]
env:
GRADLE_TOS_ACCEPTED: ${{ vars.GRADLE_TOS_ACCEPTED }}
diff --git a/.github/workflows/helm.yml b/.github/workflows/helm.yml
index 832bf1663..337e8605f 100644
--- a/.github/workflows/helm.yml
+++ b/.github/workflows/helm.yml
@@ -28,7 +28,7 @@ on:
push:
branches: [ "main" ]
pull_request:
- branches: [ "main" ]
+ branches: [ "main", "release/*" ]
env:
GRADLE_TOS_ACCEPTED: ${{ vars.GRADLE_TOS_ACCEPTED }}
diff --git a/.github/workflows/python-client.yml
b/.github/workflows/python-client.yml
index b8d9b0fab..adab68132 100644
--- a/.github/workflows/python-client.yml
+++ b/.github/workflows/python-client.yml
@@ -30,7 +30,7 @@ on:
push:
branches: [ "main" ]
pull_request:
- branches: [ "main" ]
+ branches: [ "main", "release/*" ]
env:
GRADLE_TOS_ACCEPTED: ${{ vars.GRADLE_TOS_ACCEPTED }}
diff --git a/.github/workflows/regtest.yml b/.github/workflows/regtest.yml
index d72e215ff..c4c746833 100644
--- a/.github/workflows/regtest.yml
+++ b/.github/workflows/regtest.yml
@@ -22,7 +22,7 @@ on:
push:
branches: [ "main" ]
pull_request:
- branches: [ "main" ]
+ branches: [ "main", "release/*" ]
env:
GRADLE_TOS_ACCEPTED: ${{ vars.GRADLE_TOS_ACCEPTED }}
diff --git a/.github/workflows/release-1-create-release-branch.yml
b/.github/workflows/release-1-create-release-branch.yml
new file mode 100644
index 000000000..cde0fafd0
--- /dev/null
+++ b/.github/workflows/release-1-create-release-branch.yml
@@ -0,0 +1,122 @@
+#
+# 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.
+#
+
+name: Release - 1 - Create Release Branch
+
+on:
+ workflow_dispatch:
+ inputs:
+ version:
+ description: 'Release version without RC number (e.g.,
1.0.0-incubating)'
+ required: true
+ type: string
+ dry_run:
+ description: 'Dry run mode (check to enable, uncheck to perform actual
operations)'
+ required: false
+ type: boolean
+ default: true
+
+jobs:
+ create-release-branch:
+ name: Release - 1 - Create Release Branch
+ runs-on: ubuntu-latest
+ permissions:
+ contents: write
+
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5
+ with:
+ # Fetch full history for proper branch operations
+ fetch-depth: 0
+ # Use a token with write permissions
+ token: ${{ secrets.GITHUB_TOKEN }}
+
+ - name: Setup test environment
+ uses: ./.github/actions/setup-test-env
+
+ - name: Set up environment variables
+ run: |
+ echo "RELEASEY_DIR=$(pwd)/releasey" >> $GITHUB_ENV
+ echo "LIBS_DIR=$(pwd)/releasey/libs" >> $GITHUB_ENV
+
+ echo "## Mode" >> $GITHUB_STEP_SUMMARY
+ if [[ "${{ github.event.inputs.dry_run }}" == "true" ]]; then
+ echo "DRY_RUN=1" >> $GITHUB_ENV
+ echo "‼️ DRY_RUN mode enabled - No actual changes will be made" >>
$GITHUB_STEP_SUMMARY
+ else
+ echo "DRY_RUN=0" >> $GITHUB_ENV
+ echo "DRY_RUN mode disabled - Performing actual operations" >>
$GITHUB_STEP_SUMMARY
+ fi
+
+ - name: Configure Git
+ run: |
+ git config --global user.name "github-actions[bot]"
+ git config --global user.email
"github-actions[bot]@users.noreply.github.com"
+
+ - name: Validate release parameters
+ run: |
+ source "${LIBS_DIR}/_version.sh"
+
+ # Extract release parameters from workflow inputs
+ version="${{ github.event.inputs.version }}"
+
+ echo "## Parameters" >> $GITHUB_STEP_SUMMARY
+
+ # Validate version format and extract components
+ if ! validate_and_extract_polaris_version "${version}"; then
+ echo "❌ Invalid version format. Expected:
major.minor.patch-incubating, got: ${version}" >> $GITHUB_STEP_SUMMARY
+ exit 1
+ fi
+
+ echo "Version: \`${version}\`" >> $GITHUB_STEP_SUMMARY
+
+ # Create branch name in major.minor.x format
+ branch_name="${major}.${minor}.x"
+
+ # Export parameters for next step
+ echo "version=${version}" >> $GITHUB_ENV
+ echo "branch_name=${branch_name}" >> $GITHUB_ENV
+
+ - name: Create release branch
+ run: |
+ source "${LIBS_DIR}/_exec.sh"
+
+ release_branch="release/${branch_name}"
+
+ echo "## Summary" >> $GITHUB_STEP_SUMMARY
+
+ # Check if release branch already exists
+ if git show-ref --verify --quiet
"refs/remotes/origin/${release_branch}"; then
+ echo "❌ Release branch ${release_branch} already exists. Delete
the existing branch manually if you want to recreate it." >>
$GITHUB_STEP_SUMMARY
+ exit 1
+ fi
+
+ exec_process git branch "${release_branch}"
+ exec_process git push origin "${release_branch}" --set-upstream
+
+ cat <<EOT >> $GITHUB_STEP_SUMMARY
+ 🎉 Release branch created successfully:
+
+ | Name | Value |
+ | --- | --- |
+ | Release branch name | \`${release_branch}\` |
+ | Ref | \`$(git rev-parse HEAD)\` |
+ | Version | \`${version}\` |
+ EOT
\ No newline at end of file
diff --git a/.github/workflows/release-2-update-release-candidate.yml
b/.github/workflows/release-2-update-release-candidate.yml
new file mode 100644
index 000000000..f659a77b7
--- /dev/null
+++ b/.github/workflows/release-2-update-release-candidate.yml
@@ -0,0 +1,206 @@
+#
+# 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.
+#
+
+name: Release - 2 - Update version and Changelog for Release Candidate
+
+on:
+ workflow_dispatch:
+ inputs:
+ dry_run:
+ description: 'Dry run mode (check to enable, uncheck to perform actual
operations)'
+ required: false
+ type: boolean
+ default: true
+
+jobs:
+ update-release-candidate:
+ name: Release - 2 - Update version and Changelog for Release Candidate
+ runs-on: ubuntu-latest
+ permissions:
+ contents: write
+
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5
+ with:
+ # Fetch full history. Branch operations require this.
+ fetch-depth: 0
+ # Use a token with write permissions
+ token: ${{ secrets.GITHUB_TOKEN }}
+
+ - name: Setup test environment
+ uses: ./.github/actions/setup-test-env
+
+ - name: Configure Git
+ run: |
+ git config --global user.name "github-actions[bot]"
+ git config --global user.email
"github-actions[bot]@users.noreply.github.com"
+
+ - name: Set up environment variables
+ run: |
+ echo "RELEASEY_DIR=$(pwd)/releasey" >> $GITHUB_ENV
+ echo "LIBS_DIR=$(pwd)/releasey/libs" >> $GITHUB_ENV
+
+ echo "## Mode" >> $GITHUB_STEP_SUMMARY
+ if [[ "${{ github.event.inputs.dry_run }}" == "true" ]]; then
+ echo "DRY_RUN=1" >> $GITHUB_ENV
+ echo "‼️ DRY_RUN mode enabled - No actual changes will be made" >>
$GITHUB_STEP_SUMMARY
+ else
+ echo "DRY_RUN=0" >> $GITHUB_ENV
+ echo "DRY_RUN mode disabled - Performing actual operations" >>
$GITHUB_STEP_SUMMARY
+ fi
+
+ - name: Auto-determine release branch and next RC number
+ run: |
+ source "${LIBS_DIR}/_version.sh"
+
+ # Get the current branch name
+ current_branch=$(git branch --show-current)
+
+ echo "## Parameters" >> $GITHUB_STEP_SUMMARY
+
+ # Validate that we're on a release branch
+ if [[ ! "${current_branch}" =~ ^release/(.+)$ ]]; then
+ echo "❌ Invalid branch: \`${current_branch}\`. This workflow must
be run from a release branch (release/major.minor.x)" >> $GITHUB_STEP_SUMMARY
+ exit 1
+ fi
+
+ # Extract version from release branch name
+ branch_version="${BASH_REMATCH[1]}"
+
+ # Validate branch version format and extract components
+ if ! validate_and_extract_branch_version "${branch_version}"; then
+ echo "❌ Invalid release branch version format:
\`${branch_version}\`, expected: major.minor.x" >> $GITHUB_STEP_SUMMARY
+ exit 1
+ fi
+
+ # Find the next available patch number for this major.minor version
+ find_next_patch_number "${major}" "${minor}"
+
+ # Build the target version using branch major.minor and determined
patch
+ version_without_rc="${major}.${minor}.${patch}-incubating"
+
+ # Find the next available RC number by checking existing tags
+ find_next_rc_number "${version_without_rc}"
+
+ # Build the new release tag
+ release_tag="apache-polaris-${version_without_rc}-rc${rc_number}"
+
+ # Export all variables for next steps
+ echo "release_tag=${release_tag}" >> $GITHUB_ENV
+ echo "major=${major}" >> $GITHUB_ENV
+ echo "minor=${minor}" >> $GITHUB_ENV
+ echo "patch=${patch}" >> $GITHUB_ENV
+ echo "rc_number=${rc_number}" >> $GITHUB_ENV
+ echo "version_without_rc=${version_without_rc}" >> $GITHUB_ENV
+ echo "release_branch=${current_branch}" >> $GITHUB_ENV
+
+ cat <<EOT >> $GITHUB_STEP_SUMMARY
+ | Parameter | Value |
+ | --- | --- |
+ | Release branch | \`${current_branch}\` |
+ | Version without RC | \`${version_without_rc}\` |
+ | RC number | \`${rc_number}\` |
+ | Release tag | \`${release_tag}\` |
+ EOT
+
+ - name: Verify GitHub checks are passing
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ run: |
+ source "${LIBS_DIR}/_github.sh"
+
+ # Get the current HEAD commit SHA
+ current_commit=$(git rev-parse HEAD)
+
+ echo "## Validation" >> $GITHUB_STEP_SUMMARY
+
+ # Verify all GitHub checks are passing
+ if ! check_github_checks_passed "${current_commit}"; then
+ echo "❌ GitHub checks are not all passing for commit
\`${current_commit}\`. Please ensure all checks pass before updating the
release candidate." >> $GITHUB_STEP_SUMMARY
+ exit 1
+ fi
+
+ echo "All GitHub checks are passing for commit
\`${current_commit}\`" >> $GITHUB_STEP_SUMMARY
+
+ - name: Set up Java
+ uses: actions/setup-java@dded0888837ed1f317902acf8a20df0ad188d165 # v5
+ with:
+ distribution: 'temurin'
+ java-version: '21'
+
+ - name: Update project versions
+ run: |
+ source "${LIBS_DIR}/_version.sh"
+
+ update_version "${version_without_rc}"
+ cat <<EOT >> $GITHUB_STEP_SUMMARY
+ ## Version update
+ All version files updated to \`${version_without_rc}\`
+ EOT
+
+ - name: Update changelog
+ run: |
+ source "${LIBS_DIR}/_exec.sh"
+ exec_process ./gradlew patchChangelog
+
+ cat <<EOT >> $GITHUB_STEP_SUMMARY
+ ## Changelog
+ Changelog patched successfully
+ EOT
+
+ - name: Commit and push changes
+ run: |
+ source "${LIBS_DIR}/_constants.sh"
+ source "${LIBS_DIR}/_exec.sh"
+
+ # Commit version files and changelog
+ exec_process git add \
+ "$VERSION_FILE" \
+ "$HELM_CHART_YAML_FILE" \
+ "$HELM_README_FILE" \
+ "$CHANGELOG_FILE"
+ exec_process git commit -m "[chore] Bump version to
${version_without_rc} for release candidate ${rc_number}"
+
+ # Push the changes
+ exec_process git push origin "${release_branch}"
+
+ # Get the new commit SHA after our changes
+ new_tag_ref=$(git rev-parse HEAD)
+ echo "new_tag_ref=${new_tag_ref}" >> $GITHUB_ENV
+
+ - name: Create RC tag at new commit
+ run: |
+ source "${LIBS_DIR}/_exec.sh"
+
+ # Create the tag at the new commit
+ exec_process git tag "${release_tag}" "${new_tag_ref}"
+ exec_process git push origin "${release_tag}"
+
+ echo "## Summary" >> $GITHUB_STEP_SUMMARY
+ cat <<EOT >> $GITHUB_STEP_SUMMARY
+ 🎉 Release candidate tag created successfully:
+
+ | Name | Value |
+ | --- | --- |
+ | Release candidate tag | \`${release_tag}\` |
+ | Commit | \`${new_tag_ref}\` |
+ | Version | \`${version_without_rc}\` |
+ | RC number | \`${rc_number}\` |
+ EOT
\ No newline at end of file
diff --git a/.github/workflows/release-3-build-and-publish-artifacts.yml
b/.github/workflows/release-3-build-and-publish-artifacts.yml
new file mode 100644
index 000000000..bf4cdfa49
--- /dev/null
+++ b/.github/workflows/release-3-build-and-publish-artifacts.yml
@@ -0,0 +1,400 @@
+#
+# 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.
+#
+
+name: Release - 3 - Build and Publish Release Artifacts
+
+on:
+ workflow_dispatch:
+ inputs:
+ dry_run:
+ description: 'Dry run mode (check to enable, uncheck to perform actual
operations)'
+ required: false
+ type: boolean
+ default: true
+
+jobs:
+ prerequisite-checks:
+ name: Prerequisite Checks
+ runs-on: ubuntu-latest
+ permissions:
+ contents: read
+ outputs:
+ dry_run: ${{ steps.set-outputs.outputs.dry_run }}
+ git_tag: ${{ steps.validate-tag.outputs.git_tag }}
+ version_without_rc: ${{ steps.validate-tag.outputs.version_without_rc }}
+ rc_number: ${{ steps.validate-tag.outputs.rc_number }}
+
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5
+ with:
+ fetch-depth: 0
+
+ - name: Setup test environment
+ uses: ./.github/actions/setup-test-env
+
+ - name: Set up environment variables
+ id: set-outputs
+ run: |
+ echo "RELEASEY_DIR=$(pwd)/releasey" >> $GITHUB_ENV
+ echo "LIBS_DIR=$(pwd)/releasey/libs" >> $GITHUB_ENV
+
+ echo "## Mode" >> $GITHUB_STEP_SUMMARY
+ if [[ "${{ github.event.inputs.dry_run }}" == "true" ]]; then
+ echo "DRY_RUN=1" >> $GITHUB_ENV
+ echo "dry_run=1" >> $GITHUB_OUTPUT
+ echo "‼️ DRY_RUN mode enabled - No actual changes will be made" >>
$GITHUB_STEP_SUMMARY
+ else
+ echo "DRY_RUN=0" >> $GITHUB_ENV
+ echo "dry_run=0" >> $GITHUB_OUTPUT
+ echo "DRY_RUN mode disabled - Performing actual operations" >>
$GITHUB_STEP_SUMMARY
+ fi
+
+ - name: Validate release candidate tag
+ id: validate-tag
+ run: |
+ source "${LIBS_DIR}/_version.sh"
+
+ echo "## Parameters" >> $GITHUB_STEP_SUMMARY
+
+ if ! git_tag=$(git describe --tags --exact-match HEAD 2>/dev/null);
then
+ echo "❌ Current HEAD is not on a release candidate tag. Please
checkout a release candidate tag first." >> $GITHUB_STEP_SUMMARY
+ exit 1
+ fi
+
+ # Validate git tag format and extract version components
+ if ! validate_and_extract_git_tag_version "${git_tag}"; then
+ echo "❌ Invalid git tag format: \`${git_tag}\`. Expected format:
apache-polaris-x.y.z-incubating-rcN." >> $GITHUB_STEP_SUMMARY
+ exit 1
+ fi
+
+ # Export variables for next steps and job outputs
+ echo "git_tag=${git_tag}" >> $GITHUB_ENV
+ echo "version_without_rc=${version_without_rc}" >> $GITHUB_ENV
+ echo "rc_number=${rc_number}" >> $GITHUB_ENV
+
+ echo "git_tag=${git_tag}" >> $GITHUB_OUTPUT
+ echo "version_without_rc=${version_without_rc}" >> $GITHUB_OUTPUT
+ echo "rc_number=${rc_number}" >> $GITHUB_OUTPUT
+
+ cat <<EOT >> $GITHUB_STEP_SUMMARY
+ | Parameter | Value |
+ | --- | --- |
+ | Git tag | \`${git_tag}\` |
+ | Version | \`${version_without_rc}\` |
+ | RC number | \`${rc_number}\` |
+ EOT
+
+ build-and-publish-artifacts:
+ name: Build and Publish Release Artifacts
+ runs-on: ubuntu-latest
+ needs: prerequisite-checks
+ permissions:
+ contents: read
+ env:
+ DRY_RUN: ${{ needs.prerequisite-checks.outputs.dry_run }}
+ git_tag: ${{ needs.prerequisite-checks.outputs.git_tag }}
+ version_without_rc: ${{
needs.prerequisite-checks.outputs.version_without_rc }}
+ rc_number: ${{ needs.prerequisite-checks.outputs.rc_number }}
+
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5
+ with:
+ fetch-depth: 0
+
+ - name: Setup test environment
+ uses: ./.github/actions/setup-test-env
+
+ - name: Set up environment variables
+ run: |
+ echo "RELEASEY_DIR=$(pwd)/releasey" >> $GITHUB_ENV
+ echo "LIBS_DIR=$(pwd)/releasey/libs" >> $GITHUB_ENV
+
+ - name: Set up Java
+ uses: actions/setup-java@dded0888837ed1f317902acf8a20df0ad188d165 # v5
+ with:
+ distribution: 'temurin'
+ java-version: '21'
+
+ - name: Install Subversion
+ run: |
+ sudo apt-get update
+ sudo apt-get install -y subversion
+
+ - name: Import GPG key
+ uses:
crazy-max/ghaction-import-gpg@e89d40939c28e39f97cf32126055eeae86ba74ec # v6.3.0
+ with:
+ gpg_private_key: ${{ secrets.GPG_PRIVATE_KEY }}
+ passphrase: ${{ secrets.GPG_PASSPHRASE }}
+ git_user_signingkey: true
+ git_commit_gpgsign: true
+
+ - name: Build source and binary distributions
+ run: |
+ source "${LIBS_DIR}/_exec.sh"
+
+ exec_process ./gradlew assemble sourceTarball -Prelease -PuseGpgAgent
+
+ cat <<EOT >> $GITHUB_STEP_SUMMARY
+ ## Build
+ Source and binary distributions built successfully
+ EOT
+
+ - name: Stage artifacts to Apache dist dev repository
+ env:
+ SVN_USERNAME: ${{ secrets.APACHE_USERNAME }}
+ SVN_PASSWORD: ${{ secrets.APACHE_PASSWORD }}
+ run: |
+ echo "::add-mask::$SVN_PASSWORD"
+
+ source "${LIBS_DIR}/_constants.sh"
+ source "${LIBS_DIR}/_exec.sh"
+
+ dist_dev_dir=${RELEASEY_DIR}/polaris-dist-dev
+ exec_process svn checkout --username "$SVN_USERNAME" --password
"$SVN_PASSWORD" --non-interactive "${APACHE_DIST_URL}${APACHE_DIST_PATH}"
"${dist_dev_dir}"
+
+ version_dir="${dist_dev_dir}/${version_without_rc}"
+ exec_process mkdir -p "${version_dir}"
+ exec_process cp build/distributions/* "${version_dir}/"
+ exec_process cp runtime/distribution/build/distributions/*
"${version_dir}/"
+
+ exec_process cd "${dist_dev_dir}"
+ exec_process svn add "${version_without_rc}"
+
+ exec_process svn commit --username "$SVN_USERNAME" --password
"$SVN_PASSWORD" --non-interactive -m "Stage Apache Polaris
${version_without_rc} RC${rc_number}"
+
+ cat <<EOT >> $GITHUB_STEP_SUMMARY
+ ## Staging to dist dev
+ Artifacts staged to Apache dist dev repository
+ EOT
+
+ - name: Publish and close Apache Nexus staging repository
+ env:
+ ORG_GRADLE_PROJECT_apacheUsername: ${{ secrets.APACHE_USERNAME }}
+ ORG_GRADLE_PROJECT_apachePassword: ${{ secrets.APACHE_PASSWORD }}
+ run: |
+ source "${LIBS_DIR}/_exec.sh"
+
+ # Publish artifacts to staging repository
+ exec_process ./gradlew publishToApache closeApacheStagingRepository
-Prelease -PuseGpgAgent --info 2>&1 | tee gradle_publish_output.txt
+
+ # Extract staging repository ID and URL from Gradle output
+ staging_repo_id=""
+ staging_repo_url=""
+
+ # Look for staging repository ID in the output
+ if grep -q "Created staging repository" gradle_publish_output.txt;
then
+ staging_repo_id=$(grep "Created staging repository"
gradle_publish_output.txt | sed --regexp-extended "s/^Created staging
repository .([a-z0-9-]+). at (.*)/\1/")
+ staging_repo_url=$(grep "Created staging repository"
gradle_publish_output.txt | sed --regexp-extended "s/^Created staging
repository .([a-z0-9-]+). at (.*)/\2/")
+ fi
+
+ cat <<EOT >> $GITHUB_STEP_SUMMARY
+ ## Nexus Staging Repository
+ Artifacts published and staging repository closed successfully
+
+ | Property | Value |
+ | --- | --- |
+ | Staging Repository ID | \`${staging_repo_id:-"Not extracted"}\` |
+ | Staging Repository URL | ${staging_repo_url:-"Not extracted"} |
+
+ ## Summary
+ 🎉 Artifacts built and published successfully:
+
+ | Operation | Status |
+ | --- | --- |
+ | Build source and binary distributions | ✅ |
+ | Stage artifacts to Apache dist dev repository | ✅ |
+ | Stage artifacts to Apache Nexus staging repository | ✅ |
+ | Close Nexus staging repository | ✅ |
+ EOT
+
+ build-docker:
+ name: Build Docker Images
+ runs-on: ubuntu-latest
+ needs: [prerequisite-checks, build-and-publish-artifacts]
+ permissions:
+ contents: read
+ env:
+ DRY_RUN: ${{ needs.prerequisite-checks.outputs.dry_run }}
+ git_tag: ${{ needs.prerequisite-checks.outputs.git_tag }}
+ version_without_rc: ${{
needs.prerequisite-checks.outputs.version_without_rc }}
+ rc_number: ${{ needs.prerequisite-checks.outputs.rc_number }}
+
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5
+ with:
+ fetch-depth: 0
+
+ - name: Setup test environment
+ uses: ./.github/actions/setup-test-env
+
+ - name: Set up environment variables
+ run: |
+ echo "RELEASEY_DIR=$(pwd)/releasey" >> $GITHUB_ENV
+ echo "LIBS_DIR=$(pwd)/releasey/libs" >> $GITHUB_ENV
+
+ - name: Set up Docker Buildx
+ run: |
+ docker buildx use default
+ docker buildx create \
+ --platform linux/amd64,linux/arm64 \
+ --use \
+ --name polarisbuild \
+ --driver-opt network=host || docker buildx use polarisbuild
+ docker buildx inspect
+
+ - name: Set up Java
+ uses: actions/setup-java@dded0888837ed1f317902acf8a20df0ad188d165 # v5
+ with:
+ distribution: 'temurin'
+ java-version: '21'
+
+ - name: Build Polaris Server Docker image
+ run: |
+ source "${LIBS_DIR}/_exec.sh"
+
+ exec_process ./gradlew :polaris-server:assemble
:polaris-server:quarkusAppPartsBuild --rerun \
+ -Dquarkus.container-image.build=true \
+ -Dquarkus.container-image.push=false \
+ -Dquarkus.docker.buildx.platform="linux/amd64,linux/arm64" \
+ -Dquarkus.container-image.tag="${version_without_rc}"
+
+ - name: Build Polaris Admin Tool Docker image
+ run: |
+ source "${LIBS_DIR}/_exec.sh"
+
+ exec_process ./gradlew :polaris-admin:assemble
:polaris-admin:quarkusAppPartsBuild --rerun \
+ -Dquarkus.container-image.build=true \
+ -Dquarkus.container-image.push=false \
+ -Dquarkus.docker.buildx.platform="linux/amd64,linux/arm64" \
+ -Dquarkus.container-image.tag="${version_without_rc}"
+
+ echo "## Docker Images Summary" >> $GITHUB_STEP_SUMMARY
+ cat <<EOT >> $GITHUB_STEP_SUMMARY
+ 🎉 Docker images built successfully:
+
+ | Component | Status |
+ | --- | --- |
+ | Polaris Server Docker image | ✅ Built |
+ | Polaris Admin Tool Docker image | ✅ Built |
+ EOT
+
+ build-and-stage-helm-chart:
+ name: Build and Stage Helm Chart
+ runs-on: ubuntu-latest
+ needs: [prerequisite-checks, build-docker]
+ permissions:
+ contents: read
+ env:
+ DRY_RUN: ${{ needs.prerequisite-checks.outputs.dry_run }}
+ git_tag: ${{ needs.prerequisite-checks.outputs.git_tag }}
+ version_without_rc: ${{
needs.prerequisite-checks.outputs.version_without_rc }}
+ rc_number: ${{ needs.prerequisite-checks.outputs.rc_number }}
+
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5
+ with:
+ fetch-depth: 0
+
+ - name: Setup test environment
+ uses: ./.github/actions/setup-test-env
+
+ - name: Set up environment variables
+ run: |
+ echo "RELEASEY_DIR=$(pwd)/releasey" >> $GITHUB_ENV
+ echo "LIBS_DIR=$(pwd)/releasey/libs" >> $GITHUB_ENV
+
+ - name: Set up Helm
+ uses: azure/setup-helm@1a275c3b69536ee54be43f2070a358922e12c8d4 #
v4.3.1
+ with:
+ version: 'latest'
+
+ - name: Install Subversion
+ run: |
+ sudo apt-get update
+ sudo apt-get install -y subversion
+
+ - name: Import GPG key
+ uses:
crazy-max/ghaction-import-gpg@e89d40939c28e39f97cf32126055eeae86ba74ec # v6.3.0
+ with:
+ gpg_private_key: ${{ secrets.GPG_PRIVATE_KEY }}
+ passphrase: ${{ secrets.GPG_PASSPHRASE }}
+ git_user_signingkey: true
+ git_commit_gpgsign: true
+
+ - name: Create Helm package
+ env:
+ GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }}
+ run: |
+ echo "::add-mask::$GPG_PASSPHRASE"
+
+ source "${LIBS_DIR}/_exec.sh"
+
+ # Make sure these files are always deleted
+ trap "rm -f /tmp/secring.gpg /tmp/pubring.gpg /tmp/passphrase" EXIT
+
+ echo "$GPG_PASSPHRASE" > /tmp/passphrase
+ gpg --batch --pinentry-mode loopback --passphrase-file
/tmp/passphrase --export-secret-keys > /tmp/secring.gpg
+ gpg --batch --pinentry-mode loopback --export > /tmp/pubring.gpg
+
+ exec_process cd helm
+ exec_process helm package polaris --sign --key "." --keyring
/tmp/secring.gpg --passphrase-file /tmp/passphrase
+ exec_process helm verify polaris-${version_without_rc}.tgz --keyring
/tmp/pubring.gpg
+
+ calculate_sha512 polaris-${version_without_rc}.tgz
+ exec_process gpg --armor --output
polaris-${version_without_rc}.tgz.asc --detach-sig
polaris-${version_without_rc}.tgz
+ calculate_sha512 polaris-${version_without_rc}.tgz.prov
+ exec_process gpg --armor --output
polaris-${version_without_rc}.tgz.prov.asc --detach-sig
polaris-${version_without_rc}.tgz.prov
+
+ - name: Stage Helm chart to Apache dist dev repository
+ env:
+ SVN_USERNAME: ${{ secrets.APACHE_USERNAME }}
+ SVN_PASSWORD: ${{ secrets.APACHE_PASSWORD }}
+ run: |
+ echo "::add-mask::$SVN_PASSWORD"
+
+ source "${LIBS_DIR}/_constants.sh"
+ source "${LIBS_DIR}/_exec.sh"
+
+ dist_dev_dir=${RELEASEY_DIR}/polaris-dist-dev
+ exec_process svn checkout --username "$SVN_USERNAME" --password
"$SVN_PASSWORD" --non-interactive "${APACHE_DIST_URL}${APACHE_DIST_PATH}"
"${dist_dev_dir}"
+
+ exec_process mkdir -p
"${dist_dev_dir}/helm-chart/${version_without_rc}"
+ exec_process cp helm/polaris-${version_without_rc}.tgz*
"${dist_dev_dir}/helm-chart/${version_without_rc}/"
+
+ exec_process cd "${dist_dev_dir}/helm-chart"
+ exec_process helm repo index .
+
+ exec_process cd "${dist_dev_dir}"
+ exec_process svn add "helm-chart/${version_without_rc}"
+
+ exec_process svn commit --username "$SVN_USERNAME" --password
"$SVN_PASSWORD" --non-interactive -m "Stage Apache Polaris Helm chart
${version_without_rc} RC${rc_number}"
+
+ echo "## Helm Chart Summary" >> $GITHUB_STEP_SUMMARY
+ cat <<EOT >> $GITHUB_STEP_SUMMARY
+ 🎉 Helm chart built and staged successfully:
+
+ | Component | Status |
+ | --- | --- |
+ | Helm package | ✅ Created and signed |
+ | Apache dist dev repository | ✅ Staged |
+ EOT
diff --git a/.github/workflows/release-4-publish-release.yml
b/.github/workflows/release-4-publish-release.yml
new file mode 100644
index 000000000..b00f1e506
--- /dev/null
+++ b/.github/workflows/release-4-publish-release.yml
@@ -0,0 +1,379 @@
+#
+# 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.
+#
+
+name: Release - 4 - Publish Release After Vote Success
+
+on:
+ workflow_dispatch:
+ inputs:
+ dry_run:
+ description: 'Dry run mode (check to enable, uncheck to perform actual
operations)'
+ required: false
+ type: boolean
+ default: true
+ staging_repository_id:
+ description: 'Nexus staging repository ID to release (e.g.,
orgapachepolaris-1234)'
+ required: true
+ type: string
+
+jobs:
+ publish-release:
+ name: Release - 4 - Publish Release After Vote Success
+ runs-on: ubuntu-latest
+ permissions:
+ contents: write
+
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5
+ with:
+ # Fetch full history for proper branch operations
+ fetch-depth: 0
+ # Use a token with write permissions
+ token: ${{ secrets.GITHUB_TOKEN }}
+
+ - name: Setup test environment
+ uses: ./.github/actions/setup-test-env
+
+ - name: Configure Git
+ run: |
+ git config --global user.name "github-actions[bot]"
+ git config --global user.email
"github-actions[bot]@users.noreply.github.com"
+
+ - name: Set up environment variables
+ run: |
+ echo "RELEASEY_DIR=$(pwd)/releasey" >> $GITHUB_ENV
+ echo "LIBS_DIR=$(pwd)/releasey/libs" >> $GITHUB_ENV
+
+ echo "## Mode" >> $GITHUB_STEP_SUMMARY
+ if [[ "${{ github.event.inputs.dry_run }}" == "true" ]]; then
+ echo "DRY_RUN=1" >> $GITHUB_ENV
+ echo "‼️ DRY_RUN mode enabled - No actual changes will be made" >>
$GITHUB_STEP_SUMMARY
+ else
+ echo "DRY_RUN=0" >> $GITHUB_ENV
+ echo "DRY_RUN mode disabled - Performing actual operations" >>
$GITHUB_STEP_SUMMARY
+ fi
+
+ # Validate staging repository ID parameter
+ staging_repo_id="${{ github.event.inputs.staging_repository_id }}"
+ if [[ -z "${staging_repo_id}" ]]; then
+ echo "❌ Staging repository ID is required but not provided." >>
$GITHUB_STEP_SUMMARY
+ exit 1
+ fi
+ echo "STAGING_REPOSITORY_ID=${staging_repo_id}" >> $GITHUB_ENV
+
+ - name: Install Subversion
+ run: |
+ sudo apt-get update
+ sudo apt-get install -y subversion
+
+ echo "## Input Parameters" >> $GITHUB_STEP_SUMMARY
+ echo "| Parameter | Value |" >> $GITHUB_STEP_SUMMARY
+ echo "| --- | --- |" >> $GITHUB_STEP_SUMMARY
+ echo "| Staging Repository ID | \`${staging_repo_id}\` |" >>
$GITHUB_STEP_SUMMARY
+
+ - name: Auto-determine release parameters from branch and Git state
+ run: |
+ source "${LIBS_DIR}/_version.sh"
+
+ # Get the current branch name
+ current_branch=$(git branch --show-current)
+
+ echo "## Parameters" >> $GITHUB_STEP_SUMMARY
+
+ # Validate that we're on a release branch
+ if [[ ! "${current_branch}" =~ ^release/(.+)$ ]]; then
+ echo "❌ This workflow must be run from a release branch
(release/major.minor.x). Current branch: \`${current_branch}\`." >>
$GITHUB_STEP_SUMMARY
+ exit 1
+ fi
+
+ # Extract version from release branch name
+ branch_version="${BASH_REMATCH[1]}"
+
+ # Validate branch version format and extract components
+ if ! validate_and_extract_branch_version "${branch_version}"; then
+ echo "❌ Invalid release branch version format:
\`${branch_version}\`. Expected format: major.minor.x." >> $GITHUB_STEP_SUMMARY
+ exit 1
+ fi
+
+ # Find the next patch number for this major.minor version by looking
at existing tags
+ find_next_patch_number "${major}" "${minor}"
+ next_patch=$((patch))
+ latest_patch=$((next_patch - 1))
+
+ if [[ ${next_patch} -eq 0 ]]; then
+ echo "❌ No existing tags found for version
\`${major}.${minor}.0\`. Expected at least one RC to be created before
publishing a release." >> $GITHUB_STEP_SUMMARY
+ exit 1
+ fi
+
+ # Build the version string for the latest existing patch
+ version_without_rc="${major}.${minor}.${latest_patch}-incubating"
+
+ # Find the latest RC tag for this version
+ find_next_rc_number "${version_without_rc}"
+ latest_rc=$((rc_number - 1))
+
+ if [[ ${latest_rc} -lt 0 ]]; then
+ echo "❌ No RC tags found for version \`${version_without_rc}\`.
Expected at least one RC to be created before publishing a release." >>
$GITHUB_STEP_SUMMARY
+ exit 1
+ fi
+
+ rc_tag="apache-polaris-${version_without_rc}-rc${latest_rc}"
+
+ # Verify the RC tag exists
+ if ! git rev-parse "${rc_tag}" >/dev/null 2>&1; then
+ echo "❌ RC tag \`${rc_tag}\` does not exist in repository." >>
$GITHUB_STEP_SUMMARY
+ exit 1
+ fi
+
+ # Create final release tag name
+ final_release_tag="apache-polaris-${version_without_rc}"
+
+ # Check if final release tag already exists
+ if git rev-parse "${final_release_tag}" >/dev/null 2>&1; then
+ echo "❌ Final release tag \`${final_release_tag}\` already exists.
This release may have already been published." >> $GITHUB_STEP_SUMMARY
+ exit 1
+ fi
+
+ # Export variables for next steps
+ echo "version_without_rc=${version_without_rc}" >> $GITHUB_ENV
+ echo "rc_tag=${rc_tag}" >> $GITHUB_ENV
+ echo "final_release_tag=${final_release_tag}" >> $GITHUB_ENV
+ echo "release_branch=${current_branch}" >> $GITHUB_ENV
+
+ cat <<EOT >> $GITHUB_STEP_SUMMARY
+ | Parameter | Value |
+ | --- | --- |
+ | Version | \`${version_without_rc}\` |
+ | RC tag to promote | \`${rc_tag}\` |
+ | Final release tag | \`${final_release_tag}\` |
+ | Release branch | \`${current_branch}\` |
+ EOT
+
+ - name: Copy distribution from SVN dev to release space
+ env:
+ SVN_USERNAME: ${{ secrets.APACHE_USERNAME }}
+ SVN_PASSWORD: ${{ secrets.APACHE_PASSWORD }}
+ run: |
+ echo "::add-mask::$SVN_PASSWORD"
+
+ source "${LIBS_DIR}/_constants.sh"
+ source "${LIBS_DIR}/_exec.sh"
+
+ # Define source and destination URLs
+
dev_artifacts_url="${APACHE_DIST_URL}/dev/incubator/polaris/${version_without_rc}"
+
release_artifacts_url="${APACHE_DIST_URL}/release/incubator/polaris/${version_without_rc}"
+
+
dev_helm_url="${APACHE_DIST_URL}/dev/incubator/polaris/helm-chart/${version_without_rc}"
+
release_helm_url="${APACHE_DIST_URL}/release/incubator/polaris/helm-chart/${version_without_rc}"
+
+ exec_process svn mv --username "$SVN_USERNAME" --password
"$SVN_PASSWORD" --non-interactive \
+ "${dev_artifacts_url}" "${release_artifacts_url}" \
+ -m "Release Apache Polaris ${version_without_rc}"
+
+ exec_process svn mv --username "$SVN_USERNAME" --password
"$SVN_PASSWORD" --non-interactive \
+ "${dev_helm_url}" "${release_helm_url}" \
+ -m "Release Apache Polaris Helm chart ${version_without_rc}"
+
+ cat <<EOT >> $GITHUB_STEP_SUMMARY
+ ## Distribution
+ Artifacts and Helm chart moved from dist dev to dist release
+ EOT
+
+ - name: Set up Helm
+ uses: azure/setup-helm@1a275c3b69536ee54be43f2070a358922e12c8d4 #
v4.3.1
+ with:
+ version: 'latest'
+
+ - name: Update Helm index in release space
+ env:
+ SVN_USERNAME: ${{ secrets.APACHE_USERNAME }}
+ SVN_PASSWORD: ${{ secrets.APACHE_PASSWORD }}
+ run: |
+ echo "::add-mask::$SVN_PASSWORD"
+
+ source "${LIBS_DIR}/_constants.sh"
+ source "${LIBS_DIR}/_exec.sh"
+
+ # Checkout the release Helm chart directory
+ release_helm_dir="${RELEASEY_DIR}/polaris-dist-release-helm-chart"
+
release_helm_url="${APACHE_DIST_URL}/release/incubator/polaris/helm-chart"
+
+ exec_process svn checkout --username "$SVN_USERNAME" --password
"$SVN_PASSWORD" --non-interactive "${release_helm_url}" "${release_helm_dir}"
+
+ exec_process cd "${release_helm_dir}"
+ exec_process helm repo index .
+ exec_process svn add index.yaml
+ exec_process svn commit --username "$SVN_USERNAME" --password
"$SVN_PASSWORD" --non-interactive -m "Update Helm index for
${version_without_rc} release"
+
+ cat <<EOT >> $GITHUB_STEP_SUMMARY
+ ## Helm Index
+ Helm index updated in dist release
+ EOT
+
+ - name: Create final release tag and push to Git repository
+ run: |
+ source "${LIBS_DIR}/_exec.sh"
+
+ # Get the commit SHA that the RC tag points to
+ rc_commit=$(git rev-parse "${rc_tag}")
+ echo "rc_commit=${rc_commit}" >> $GITHUB_ENV
+
+ exec_process git tag -a "${final_release_tag}" "${rc_commit}" -m
"Apache Polaris ${version_without_rc} Release"
+ exec_process git push apache "${final_release_tag}"
+
+ cat <<EOT >> $GITHUB_STEP_SUMMARY
+ ## Git Release Tag
+ Final release tag \`${final_release_tag}\` created and pushed
+ EOT
+
+ - name: Set up Docker Buildx
+ run: |
+ docker buildx use default
+ docker buildx create \
+ --platform linux/amd64,linux/arm64 \
+ --use \
+ --name polarisbuild \
+ --driver-opt network=host || docker buildx use polarisbuild
+ docker buildx inspect
+
+ - name: Set up Java
+ uses: actions/setup-java@dded0888837ed1f317902acf8a20df0ad188d165 # v5
+ with:
+ distribution: 'temurin'
+ java-version: '21'
+
+ - name: Log in to Docker Hub
+ if: env.DRY_RUN == '0'
+ run: |
+ echo "${{ secrets.DOCKERHUB_TOKEN }}" | docker login ghcr.io -u "${{
secrets.DOCKERHUB_USERNAME }}" --password-stdin
+
+ - name: Publish Polaris Server Docker image to Docker Hub
+ run: |
+ source "${LIBS_DIR}/_exec.sh"
+
+ exec_process ./gradlew :polaris-server:assemble
:polaris-server:quarkusAppPartsBuild --rerun \
+ -Dquarkus.container-image.build=true \
+ -Dquarkus.container-image.push=true \
+ -Dquarkus.docker.buildx.platform="linux/amd64,linux/arm64" \
+ -Dquarkus.container-image.tag="${final_release_tag}"
+
+ - name: Publish Polaris Admin Tool Docker image to Docker Hub
+ run: |
+ source "${LIBS_DIR}/_exec.sh"
+
+ exec_process ./gradlew :polaris-admin:assemble
:polaris-admin:quarkusAppPartsBuild --rerun \
+ -Dquarkus.container-image.build=true \
+ -Dquarkus.container-image.push=true \
+ -Dquarkus.docker.buildx.platform="linux/amd64,linux/arm64" \
+ -Dquarkus.container-image.tag="${final_release_tag}"
+
+ cat <<EOT >> $GITHUB_STEP_SUMMARY
+ ## Docker Images
+ ✅ Polaris Server and Admin Tool Docker images published to Docker Hub
+ EOT
+
+ - name: Create GitHub release with artifacts
+ env:
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ SVN_USERNAME: ${{ secrets.APACHE_USERNAME }}
+ SVN_PASSWORD: ${{ secrets.APACHE_PASSWORD }}
+ run: |
+ echo "::add-mask::$SVN_PASSWORD"
+
+ source "${LIBS_DIR}/_constants.sh"
+ source "${LIBS_DIR}/_exec.sh"
+
+ # Create a temporary directory for downloading artifacts
+ artifacts_dir="${RELEASEY_DIR}/release-artifacts"
+ exec_process mkdir -p "${artifacts_dir}"
+
+ # Download artifacts from Apache dist release space
+
release_artifacts_url="${APACHE_DIST_URL}/release/incubator/polaris/${version_without_rc}"
+
release_helm_url="${APACHE_DIST_URL}/release/incubator/polaris/helm-chart/${version_without_rc}"
+
+ # Download main artifacts
+ exec_process svn export --username "$SVN_USERNAME" --password
"$SVN_PASSWORD" --non-interactive \
+ "${release_artifacts_url}" "${artifacts_dir}/artifacts"
+
+ # Download Helm chart artifacts
+ exec_process svn export --username "$SVN_USERNAME" --password
"$SVN_PASSWORD" --non-interactive \
+ "${release_helm_url}" "${artifacts_dir}/helm"
+
+ # Prepare the content of the Github Release
+ #
********************************************************************************
+ release_title="Release ${version_without_rc}"
+ release_notes="Apache Polaris ${version_without_rc} Release
+
+ ## Release Artifacts
+ This release includes:
+ - Source and binary distributions
+ - Helm chart package
+ - Docker images published to Docker Hub
+ - Maven artifacts published to Maven Central
+
+ ## Verification
+ All artifacts have been signed with GPG and include SHA-512
checksums for verification.
+
+ ## Docker Images
+ - \`apache/polaris:${final_release_tag}\` - Polaris Server
+ - \`apache/polaris-admin:${final_release_tag}\` - Polaris Admin Tool"
+ #
********************************************************************************
+
+ # Create GitHub release
+ exec_process gh release create "${final_release_tag}" \
+ --title "${release_title}" \
+ --notes "${release_notes}" \
+ --target "${rc_commit}"
+
+ # Attach all artifacts from the artifacts directory
+ find "${artifacts_dir}" -type f -name "*.tar.gz" -o -name "*.tgz" -o
-name "*.asc" -o -name "*.sha512" -o -name "*.prov" | while read -r file; do
+ exec_process gh release upload "${final_release_tag}" "${file}"
+ done
+
+ cat <<EOT >> $GITHUB_STEP_SUMMARY
+ ## GitHub Release
+ GitHub release created: \`${final_release_tag}\`
+ EOT
+
+ - name: Release candidate repository on Nexus
+ env:
+ ORG_GRADLE_PROJECT_apacheUsername: ${{ secrets.APACHE_USERNAME }}
+ ORG_GRADLE_PROJECT_apachePassword: ${{ secrets.APACHE_PASSWORD }}
+ run: |
+ source "${LIBS_DIR}/_exec.sh"
+
+ # Use the Gradle task to release the Apache staging repository with
the specific staging repository ID
+ exec_process ./gradlew releaseApacheStagingRepository
--staging-repository-id "${STAGING_REPOSITORY_ID}"
+
+ cat <<EOT >> $GITHUB_STEP_SUMMARY
+ ## Summary
+ 🎉 Release published successfully:
+
+ | Component | Status |
+ | --- | --- |
+ | Distribution artifacts | ✅ Moved to release space |
+ | Helm chart and index | ✅ Updated in release space |
+ | Git release tag | ✅ Created and pushed |
+ | GitHub release | ✅ Created with artifacts attached |
+ | Docker images | ✅ Published to Docker Hub |
+ | Nexus repository | ✅ Released |
+ | Version | \`${version_without_rc}\` |
+ | Final release tag | \`${final_release_tag}\` |
+ EOT
diff --git a/.github/workflows/spark_client_regtests.yml
b/.github/workflows/spark_client_regtests.yml
index 450b11f53..12fe5c95d 100644
--- a/.github/workflows/spark_client_regtests.yml
+++ b/.github/workflows/spark_client_regtests.yml
@@ -22,7 +22,7 @@ on:
push:
branches: [ "main" ]
pull_request:
- branches: [ "main" ]
+ branches: [ "main", "release/*" ]
env:
GRADLE_TOS_ACCEPTED: ${{ vars.GRADLE_TOS_ACCEPTED }}
diff --git a/releasey/README.md b/releasey/README.md
new file mode 100644
index 000000000..9dc1ed826
--- /dev/null
+++ b/releasey/README.md
@@ -0,0 +1,61 @@
+<!--
+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.
+-->
+
+# Releasey Scripts
+
+## Important Notice
+
+⚠️ **These scripts are designed for automation and should only be used by
GitHub workflows.**
+
+The scripts in this directory are:
+- Optimized for the GitHub Actions environment
+- Designed to work with specific workflow contexts and environment variables
+- Not intended for manual execution by release managers
+
+## Release Process Overview
+
+The Polaris release automation follows a structured workflow as illustrated in
the flowchart below. The process involves both automated GitHub workflows and
manual steps performed by release managers.
+
+
+
+## GitHub Workflows
+
+The release automation is implemented through the following GitHub workflows:
+
+1. **[Create Release
Branch](../.github/workflows/release-1-create-release-branch.yml)** - Creates a
new release branch from a specified Git SHA
+2. **[Update Release
Candidate](../.github/workflows/release-2-update-release-candidate.yml)** -
Updates version files, finalizes changelog, and creates RC tags
+3. **[Build and Publish
Artifacts](../.github/workflows/release-3-build-and-publish-artifacts.yml)** -
Consolidated workflow that:
+ - Performs prerequisite checks (tag validation, version extraction)
+ - Builds source/binary artifacts and publishes to Nexus staging
+ - Builds Docker images for server and admin tool
+ - Builds Helm charts and stages them to dist dev repository
+4. **[Publish Release](../.github/workflows/release-4-publish-release.yml)** -
Finalizes the release:
+ - Copies distribution from dist dev to dist release space
+ - Creates a final release tag and GitHub release
+ - Publishes Docker images to Docker Hub
+ - Releases the candidate repository on Nexus
+
+## Directory Structure
+
+- `libs/` - Shared library functions used across release scripts
+ - `_constants.sh` - Common constants and configuration
+ - `_exec.sh` - Command execution utilities
+ - `_github.sh` - GitHub API interaction functions
+ - `_log.sh` - Logging utilities
+ - `_version.sh` - Version handling functions
\ No newline at end of file
diff --git a/releasey/libs/_constants.sh b/releasey/libs/_constants.sh
new file mode 100644
index 000000000..a59175ac6
--- /dev/null
+++ b/releasey/libs/_constants.sh
@@ -0,0 +1,40 @@
+#!/bin/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.
+#
+
+LIBS_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
+
+# Git/SVN repository constants
+APACHE_DIST_URL=${APACHE_DIST_URL:-"https://dist.apache.org/repos/dist"}
+APACHE_DIST_PATH=${APACHE_DIST_PATH:-"/dev/incubator/polaris"}
+
+# Execution mode constants
+DRY_RUN=${DRY_RUN:-1}
+
+# Version validation regex patterns
+VERSION_REGEX="([0-9]+)\.([0-9]+)\.([0-9]+)-incubating"
+VERSION_REGEX_GIT_TAG="^apache-polaris-$VERSION_REGEX-rc([0-9]+)$"
+# Branch validation regex pattern for major.minor.x format
+BRANCH_VERSION_REGEX="([0-9]+)\.([0-9]+)\.x"
+
+# Project file constants
+VERSION_FILE="$LIBS_DIR/../../version.txt"
+CHANGELOG_FILE="$LIBS_DIR/../../CHANGELOG.md"
+HELM_CHART_YAML_FILE="$LIBS_DIR/../../helm/polaris/Chart.yaml"
+HELM_README_FILE="$LIBS_DIR/../../helm/polaris/README.md"
diff --git a/releasey/libs/_exec.sh b/releasey/libs/_exec.sh
new file mode 100644
index 000000000..ae83c3fad
--- /dev/null
+++ b/releasey/libs/_exec.sh
@@ -0,0 +1,46 @@
+#!/bin/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.
+#
+
+LIBS_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
+
+source "$LIBS_DIR/_constants.sh"
+source "$LIBS_DIR/_log.sh"
+
+function exec_process {
+ if [[ ${DRY_RUN:-1} -ne 1 ]]; then
+ print_command "Executing '${*}'"
+ "$@"
+ else
+ print_command "Dry-run, WOULD execute '${*}'"
+ fi
+}
+
+function calculate_sha512 {
+ local source_file="$1"
+ local target_file="${source_file}.sha512"
+ # This function is only there for dry-run support. Because of the
+ # redirection, we cannot use exec_process with the exact command that will be
+ # executed.
+ if [[ ${DRY_RUN:-1} -ne 1 ]]; then
+ exec_process shasum -a 512 "${source_file}" > "${target_file}"
+ else
+ exec_process "shasum -a 512 ${source_file} > ${target_file}"
+ fi
+}
diff --git a/releasey/libs/_github.sh b/releasey/libs/_github.sh
new file mode 100755
index 000000000..18002def7
--- /dev/null
+++ b/releasey/libs/_github.sh
@@ -0,0 +1,72 @@
+#!/bin/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.
+#
+
+LIBS_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
+
+# Source common logging functions and constants
+source "${LIBS_DIR}/_log.sh"
+source "${LIBS_DIR}/_constants.sh"
+source "${LIBS_DIR}/_exec.sh"
+
+function get_remote_url() {
+ # Get the URL for a given remote, return non-zero if remote doesn't exist
+ local remote_name="$1"
+ git remote get-url "${remote_name}" 2>/dev/null || return 1
+}
+
+function check_github_checks_passed() {
+ # Check that all GitHub checks have passed for a specific commit SHA.
+ # More specifically, we check that all check runs have a conclusion of
"success" or "skipped".
+ # Returns 0 if all checks are "success" or "skipped", 1 otherwise
+ local commit_sha="$1"
+
+ print_info "Checking that all Github checks have passed for commit
${commit_sha}..."
+
+ # Get repository information from the current Git repository
+ local repo_info="$GITHUB_REPOSITORY"
+
+ local num_invalid_checks
+ local num_invalid_checks_retrieval_command="gh api
repos/${repo_info}/commits/${commit_sha}/check-runs --jq '[.check_runs[] |
select(.conclusion != \"success\" and .conclusion != \"skipped\" and (.name |
startswith(\"Release - \") | not))] | length'"
+ if [ ${DRY_RUN} -eq 1 ]; then
+ print_info "DRY_RUN is enabled, skipping GitHub check verification"
+ print_command "${num_invalid_checks_retrieval_command}"
+ num_invalid_checks=0
+ else
+ # Ideally, we should be able to use
num_invalid_checks=$(${num_invalid_checks_retrieval_command}) but it seems
Github does not like that. Use a temporary script instead.
+ local temp_script=$(mktemp)
+ echo "${num_invalid_checks_retrieval_command}" > "${temp_script}"
+ num_invalid_checks=$(bash "${temp_script}")
+ script_exit_code=$?
+ rm -f "${temp_script}"
+ fi
+
+ if [[ $script_exit_code -ne 0 ]]; then
+ print_error "Failed to fetch GitHub check runs for commit ${commit_sha}"
+ return 1
+ fi
+
+ if [[ ${num_invalid_checks} -ne 0 ]]; then
+ print_error "Found ${num_invalid_checks} failed or in-progress GitHub
checks for commit ${commit_sha}"
+ return 1
+ fi
+
+ print_info "All GitHub checks passed for commit ${commit_sha}"
+ return 0
+}
\ No newline at end of file
diff --git a/releasey/libs/_log.sh b/releasey/libs/_log.sh
new file mode 100644
index 000000000..a599c2420
--- /dev/null
+++ b/releasey/libs/_log.sh
@@ -0,0 +1,63 @@
+#!/bin/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.
+#
+
+#
+# Common Logging Functions
+#
+
+# Colors for output - only use colors if terminal supports them
+if [[ -t 2 ]] &&
+ [[ "${NO_COLOR:-}" != "1" ]] &&
+ [[ "${TERM:-}" != "dumb" ]] &&
+ command -v tput >/dev/null; then
+ RED=${RED:-$(tput setaf 1)}
+ GREEN=${GREEN:-$(tput setaf 2)}
+ YELLOW=${YELLOW:-$(tput bold; tput setaf 3)}
+ BLUE=${BLUE:-$(tput setaf 4)}
+ RESET=${RESET:-$(tput sgr0)}
+else
+ RED=${RED:-''}
+ GREEN=${GREEN:-''}
+ YELLOW=${YELLOW:-''}
+ BLUE=${BLUE:-''}
+ RESET=${RESET:-''}
+fi
+
+function print_error() {
+ echo -e "${RED}ERROR: $*${RESET}" >&2
+}
+
+function print_warning() {
+ echo -e "${YELLOW}WARNING: $*${RESET}" >&2
+}
+
+function print_info() {
+ echo "INFO: $*" >&2
+}
+
+function print_success() {
+ echo -e "${GREEN}SUCCESS: $*${RESET}" >&2
+}
+
+function print_command() {
+ # This function prints the bash commands that are executed by a script
+ # with a DEBUG prefix to stderr for visibility.
+ echo -e "${BLUE}DEBUG: $*${RESET}" >&2
+}
diff --git a/releasey/libs/_version.sh b/releasey/libs/_version.sh
new file mode 100644
index 000000000..7d812f130
--- /dev/null
+++ b/releasey/libs/_version.sh
@@ -0,0 +1,177 @@
+#!/bin/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.
+#
+
+#
+# Utility functions for version validation and version.txt manipulation
+#
+
+LIBS_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
+
+source "$LIBS_DIR/_constants.sh"
+source "$LIBS_DIR/_exec.sh"
+
+function validate_and_extract_branch_version {
+ # This function validates the format of a release branch version and
extracts its components (major.minor).
+ # It now accepts the major.minor.x format (e.g., "1.1.x") instead of exact
version format.
+ # It returns 0 if the version is valid and sets the global variables major,
minor.
+ # The patch version is not extracted from the branch name as it uses the "x"
placeholder.
+ # Otherwise, it returns 1.
+ local version="$1"
+
+ if [[ ! ${version} =~ ${BRANCH_VERSION_REGEX} ]]; then
+ return 1
+ fi
+
+ major="${BASH_REMATCH[1]}"
+ minor="${BASH_REMATCH[2]}"
+ # patch is not set from branch name since it uses "x" placeholder
+
+ return 0
+}
+
+function validate_and_extract_git_tag_version {
+ # This function validates the format of a git tag version and extracts its
components (major.minor.patch and rc number).
+ # It is similar to validate_and_extract_rc_version, but for git tag format.
+ # It returns 0 if the version is valid and sets the global variables major,
minor, patch, and rc_number.
+ # It also sets the global variable version_without_rc to the
"major.minor.patch-incubating" format without the rc number.
+ # Otherwise, it returns 1.
+ local version="$1"
+
+ if [[ ! ${version} =~ ${VERSION_REGEX_GIT_TAG} ]]; then
+ return 1
+ fi
+
+ major="${BASH_REMATCH[1]}"
+ minor="${BASH_REMATCH[2]}"
+ patch="${BASH_REMATCH[3]}"
+ rc_number="${BASH_REMATCH[4]}"
+ version_without_rc="${major}.${minor}.${patch}-incubating"
+
+ return 0
+}
+
+function validate_and_extract_polaris_version {
+ # This function validates the format of a Polaris version and extracts its
components (major.minor.patch).
+ # It accepts the full version format (e.g., "1.0.0-incubating") and sets the
global variables major, minor, patch.
+ # It also sets the global variable version_without_rc to the
"major.minor.patch-incubating" format.
+ # Returns 0 if the version is valid, 1 otherwise.
+ local version="$1"
+
+ if [[ ! ${version} =~ ${VERSION_REGEX} ]]; then
+ return 1
+ fi
+
+ major="${BASH_REMATCH[1]}"
+ minor="${BASH_REMATCH[2]}"
+ patch="${BASH_REMATCH[3]}"
+ version_without_rc="${major}.${minor}.${patch}-incubating"
+
+ return 0
+}
+
+function update_version {
+ local version="$1"
+ update_version_txt "${version}"
+ update_helm_version "${version}"
+}
+
+function update_version_txt {
+ local version="$1"
+ # This function is only there for dry-run support. Because of the
+ # redirection, we cannot use exec_process with the exact command that will be
+ # executed.
+ if [[ ${DRY_RUN:-1} -ne 1 ]]; then
+ exec_process echo "${version}" >$VERSION_FILE
+ else
+ exec_process "echo ${version} > $VERSION_FILE"
+ fi
+}
+
+function update_helm_version {
+ local new_version="$1"
+ exec_process sed -E -i~ "s/^version: .+/version: ${new_version}/g"
"$HELM_CHART_YAML_FILE"
+ exec_process sed -E -i~ "s/^appVersion: .+/appVersion: ${new_version}/g"
"$HELM_CHART_YAML_FILE"
+ exec_process sed -E -i~
"s/[0-9]+[.][0-9]+([.][0-9]+)?(-incubating)-SNAPSHOT/${new_version}/g"
"$HELM_README_FILE"
+ # The readme file may contain version with double dash for shields.io badges
+ # We need a second `sed` command to ensure that the version replacement
preserves this double-dash syntax.
+ local current_version_with_dash
+ local version_with_dash
+ current_version_with_dash="${old_version//-/--}"
+ version_with_dash="${version//-/--}"
+ exec_process sed -E -i~
"s/[0-9]+[.][0-9]+([.][0-9]+)?(--incubating)--SNAPSHOT/${version_with_dash}/g"
"$HELM_README_FILE"
+}
+
+function find_next_rc_number {
+ # This function finds the next available RC number for a given version.
+ # It returns 0 and sets the global variable rc_number to the next available
RC number.
+ # RC numbers start from 0. It takes the version_without_rc as input (e.g.,
"1.0.0-incubating").
+ local version_without_rc="$1"
+
+ # Get all existing RC tags for this version
+ local tag_pattern="apache-polaris-${version_without_rc}-rc*"
+ local existing_tags
+ existing_tags=$(git tag -l "${tag_pattern}" | sort -V)
+
+ if [[ -z "${existing_tags}" ]]; then
+ # No existing RC tags, start with RC0
+ rc_number=0
+ else
+ # Extract the highest RC number and increment
+ local highest_rc
+ highest_rc=$(echo "${existing_tags}" | sed
"s/apache-polaris-${version_without_rc}-rc//" | sort -n | tail -1)
+ rc_number=$((highest_rc + 1))
+ fi
+
+ return 0
+}
+
+function find_next_patch_number {
+ # This function finds the next available patch number for a given
major.minor version.
+ # It returns 0 and sets the global variable patch to the next available
patch number.
+ # Patch numbers start from 0. It takes major and minor as input (e.g., "1",
"0").
+ local major="$1"
+ local minor="$2"
+
+ # Get all existing tags for this major.minor version
+ local tag_pattern="apache-polaris-${major}.${minor}.*-incubating-rc*"
+ local existing_tags
+ existing_tags=$(git tag -l "${tag_pattern}" | sort -V)
+
+ if [[ -z "${existing_tags}" ]]; then
+ # No existing tags, start with patch 0
+ patch=0
+ else
+ # Extract all patch numbers and find the highest
+ local highest_patch=-1
+ while IFS= read -r tag; do
+ if [[ ${tag} =~
apache-polaris-${major}\.${minor}\.([0-9]+)-incubating-rc[0-9]+ ]]; then
+ local current_patch="${BASH_REMATCH[1]}"
+ if [[ ${current_patch} -gt ${highest_patch} ]]; then
+ highest_patch=${current_patch}
+ fi
+ fi
+ done <<< "${existing_tags}"
+
+ # Increment the highest patch number found
+ patch=$((highest_patch + 1))
+ fi
+
+ return 0
+}
\ No newline at end of file
diff --git a/releasey/release-process-flowchart.mmd
b/releasey/release-process-flowchart.mmd
new file mode 100644
index 000000000..61e33933f
--- /dev/null
+++ b/releasey/release-process-flowchart.mmd
@@ -0,0 +1,39 @@
+%% 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.
+
+flowchart TD
+ B["🤖 GitHub Workflow<br/>🔧 Manual trigger from release manager<br/><br/>•
Create a new branch from the Git SHA<br/>• Push the branch to the remote
repository"]
+
+ B --> C["👤 Release Manager<br/><br/>• Cherry pick the commits from main
branch to release branch<br/>• Ensure that the changelog is up to date<br/>•
Create a pull request to add the commits<br/>• Get the pull request approved
and merged"]
+
+ C --> D["🤖 GitHub Workflow<br/>🔧 Manual trigger from release
manager<br/><br/>• Verify that all Github checks are passing<br/>• Update the
project version files<br/>• Finalize the changelog for the release<br/>• Commit
the changes to release branch<br/>• Create the RC tag<br/>• Push the branch and
the tag"]
+
+ D --> E["🤖 GitHub Workflow<br/>🔧 Manual trigger from release manager<br/>•
Build the source and binary artifacts<br/>• Stage artifacts to dist dev
repository<br/>• Publish artifacts to Nexus staging repository<br/>• Close
Nexus staging repository<br/>• Build Docker images for server and admin
tool<br/>• Build the Helm chart<br/>• Create signature and checksum for Helm
package files<br/>• Copy package files to dist dev repository"]
+
+ E --> H["👤 Release Manager<br/><br/>• Start vote thread on dev mailing
list<br/>• Wait for the vote to pass<br/>• Start vote thread on incubator
mailing list<br/>• Wait for the vote to pass"]
+
+ H --> I["🤖 GitHub Workflow<br/>🔧 Manual trigger from release
manager<br/><br/>• Copy distribution from dist dev to dist release space<br/>•
Create a final release tag to Git repository<br/>• Create the GitHub
release<br/>• Publish Docker images to DockerHub<br/>• Release the candidate
repository on Nexus"]
+
+ I --> J["👤 Release Manager<br/><br/>• Update documentation - TBD - Process
yet to be determined"]
+
+ I --> K["👤 Release Manager<br/><br/>• Send announcement e-mail to dev
mailing list<br/>• Send announcement to announce Apache mailing list"]
+
+ %% Class definition for left-aligned text
+ classDef leftAlign text-align:left;
+
+ %% Apply left-align class to all nodes
+ class B,C,D,E,H,I,J,K leftAlign;
diff --git a/releasey/release-process-flowchart.png
b/releasey/release-process-flowchart.png
new file mode 100644
index 000000000..e5814512d
Binary files /dev/null and b/releasey/release-process-flowchart.png differ