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

JingsongLi pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/paimon-vector-index.git


The following commit(s) were added to refs/heads/main by this push:
     new e46ce05  ci: move Java staging deploy to local release script (#54)
e46ce05 is described below

commit e46ce05189946c74daf94785417f41e120f2ac79
Author: jianguotian <[email protected]>
AuthorDate: Wed Jul 22 11:13:47 2026 +0800

    ci: move Java staging deploy to local release script (#54)
---
 .github/workflows/release-java.yml |  29 +-
 .github/workflows/release.yml      |   1 -
 tools/README.md                    | 185 +++++++++++++
 tools/deploy_java_staging.sh       | 550 +++++++++++++++++++++++++++++++++++++
 4 files changed, 745 insertions(+), 20 deletions(-)

diff --git a/.github/workflows/release-java.yml 
b/.github/workflows/release-java.yml
index a87122d..ecf7f10 100644
--- a/.github/workflows/release-java.yml
+++ b/.github/workflows/release-java.yml
@@ -119,7 +119,7 @@ jobs:
           name: native-${{ matrix.os_name }}-${{ matrix.arch }}
           path: target/${{ matrix.target }}/release/${{ matrix.lib_name }}
 
-  deploy-staging:
+  package-java:
     if: github.repository == 'apache/paimon-vector-index' && 
startsWith(github.ref, 'refs/tags/') && contains(github.ref_name, '-rc')
     runs-on: ubuntu-latest
     needs: [build-native]
@@ -158,26 +158,17 @@ jobs:
         with:
           java-version: ${{ env.JDK_VERSION }}
           distribution: 'temurin'
-          server-id: apache.releases.https
-          server-username: MAVEN_USERNAME
-          server-password: MAVEN_PASSWORD
-          gpg-private-key: ${{ secrets.GPG_SECRET_KEY }}
-          gpg-passphrase: MAVEN_GPG_PASSPHRASE
+          cache: maven
 
       - name: Show Maven version
         run: mvn --version
 
-      - name: Deploy to Apache Nexus staging
+      - name: Package Java artifact
         working-directory: java
-        run: |
-          REF="${{ github.ref_name }}"
-          VERSION="${REF#v}"
-          DESC="Apache Paimon Vector Index, version ${VERSION%-rc*}, release 
candidate ${VERSION#*-rc}"
-          mvn clean deploy \
-            -Prelease \
-            -DskipTests \
-            -DstagingDescription="$DESC"
-        env:
-          MAVEN_USERNAME: ${{ secrets.NEXUS_STAGE_DEPLOYER_USER }}
-          MAVEN_PASSWORD: ${{ secrets.NEXUS_STAGE_DEPLOYER_PW }}
-          MAVEN_GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }}
+        run: mvn clean verify -Prelease -Dgpg.skip=true -DskipTests
+
+      - name: Upload Java package
+        uses: actions/upload-artifact@v5
+        with:
+          name: java-package
+          path: java/target/*.jar
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 7c1f516..9339be0 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -44,7 +44,6 @@ jobs:
   java:
     name: Java release
     uses: ./.github/workflows/release-java.yml
-    secrets: inherit
 
   python-wheels:
     name: Python wheels
diff --git a/tools/README.md b/tools/README.md
new file mode 100644
index 0000000..e6a55a7
--- /dev/null
+++ b/tools/README.md
@@ -0,0 +1,185 @@
+# Release tools
+
+This directory contains helper scripts used by release managers and committers.
+
+## Java staging deploy
+
+`deploy_java_staging.sh` deploys the Java release candidate artifacts to Apache
+Nexus staging from a committer/RM machine.
+
+GitHub Actions does **not** sign or deploy the Java staging artifacts. The
+release workflow only:
+
+1. builds the four JNI native libraries;
+2. verifies the Java release profile with GPG disabled; and
+3. uploads the native libraries and verified Java jars as workflow artifacts.
+
+The committer then runs this script locally. The script checks that the release
+workflow run succeeded for the current RC tag, downloads the native libraries,
+verifies their platform formats, places them into the Java resource tree, and
+runs Maven locally.
+
+### Required local setup
+
+- `gh` GitHub CLI, authenticated with access to `apache/paimon-vector-index`;
+- JDK and Maven;
+- local GPG setup for the release signing key;
+- Maven credentials for server id `apache.releases.https`.
+
+Maven credentials can be supplied by one of these methods:
+
+- configure `~/.m2/settings.xml`;
+- pass `--maven-settings /path/to/settings.xml`;
+- set `NEXUS_STAGE_DEPLOYER_USER` and `NEXUS_STAGE_DEPLOYER_PW` so the script 
can
+  create a temporary Maven settings file.
+
+### Pre-flight checks
+
+Run these checks before the first dry-run:
+
+```bash
+gh auth status
+gpg --list-secret-keys --keyid-format LONG
+mvn --version
+```
+
+Confirm the signing key's public key is already published in Paimon KEYS:
+
+```text
+https://downloads.apache.org/paimon/KEYS
+```
+
+Confirm Maven can use server id `apache.releases.https`. A typical
+`~/.m2/settings.xml` entry is:
+
+```xml
+<settings>
+  <servers>
+    <server>
+      <id>apache.releases.https</id>
+      <username>YOUR_NEXUS_TOKEN_USER</username>
+      <password>YOUR_NEXUS_TOKEN_PASSWORD</password>
+    </server>
+  </servers>
+</settings>
+```
+
+The Nexus token is from:
+
+```text
+https://repository.apache.org/ -> Profile -> User Token
+```
+
+### Find the run id
+
+After pushing the RC tag, open the GitHub Actions run for that RC tag. Use the
+`Release` workflow run triggered by the tag, for example `v0.2.0-rc1`.
+
+The run id is the number in the workflow run URL:
+
+```text
+https://github.com/apache/paimon-vector-index/actions/runs/12345678901
+```
+
+The run id is:
+
+```text
+12345678901
+```
+
+Do not use the job id, artifact id, PR number, or commit SHA. The script checks
+that this run completed successfully and that the run's commit matches the RC 
tag
+checked out locally.
+
+### Parameters
+
+Required for the normal release flow:
+
+- `--release-version 0.2.0`: Java artifact version in `java/pom.xml`. This does
+  not include the RC suffix.
+- `--rc 1`: RC number. Together with `--release-version`, this derives the tag
+  `v0.2.0-rc1`.
+- `--run-id 12345678901`: GitHub Actions run id from the RC tag's `Release`
+  workflow URL. The script uses it to download the four `native-*` artifacts.
+
+Common options:
+
+- `--dry-run`: verify locally without signing or deploying to Nexus.
+- `--maven-settings FILE`: use a specific Maven `settings.xml` containing 
server
+  id `apache.releases.https`.
+- `--staging-description TEXT`: override the Nexus staging description.
+- `--no-skip-tests`: run Maven tests during dry-run or deploy.
+
+Less common options:
+
+- `--tag TAG`: use an explicit RC tag instead of deriving `vVERSION-rcN`.
+- `--repo OWNER/REPO`: GitHub repository for `gh`; defaults to
+  `apache/paimon-vector-index`.
+- `--no-cleanup`: keep `java/src/main/resources/native` after the script exits.
+- `--skip-native-file-check`: skip native binary format checks.
+
+The last option is an escape hatch. Avoid it for normal releases.
+
+### Dry-run before publishing
+
+Always run a dry-run first with the real RC workflow artifacts:
+
+```bash
+./tools/deploy_java_staging.sh \
+  --release-version 0.2.0 \
+  --rc 1 \
+  --run-id 12345678901 \
+  --dry-run
+```
+
+Dry-run mode validates the GitHub Actions run id, downloads the native
+libraries, and runs:
+
+```bash
+mvn clean verify -Prelease -Dgpg.skip=true -DskipTests
+```
+
+It does not sign and does not deploy to Nexus. It verifies:
+
+- `java/pom.xml` version matches `--release-version`;
+- current checkout matches the RC tag, such as `v0.2.0-rc1`;
+- Java package inputs have no local changes;
+- the GitHub Actions run is a successful tag-push `Release` workflow run and 
its
+  commit matches the RC tag;
+- all four native libraries are present;
+- native library file formats match their target platforms;
+- the Java jar, sources jar, and javadoc jar are produced;
+- the Java jar contains all four native library entries.
+
+### Deploy to Nexus staging
+
+After the dry-run succeeds, run the same command without `--dry-run`:
+
+```bash
+./tools/deploy_java_staging.sh \
+  --release-version 0.2.0 \
+  --rc 1 \
+  --run-id 12345678901
+```
+
+The script repeats the local preflight before creating any remote staging
+artifacts:
+
+```bash
+mvn clean verify -Prelease -Dgpg.skip=true -DskipTests
+```
+
+After that passes, it runs the local Nexus staging deploy:
+
+```bash
+mvn deploy -Prelease -DskipTests \
+  -DstagingDescription="Apache Paimon Vector Index, version 0.2.0, release 
candidate 1"
+```
+
+The Maven output contains the Nexus staging repository id, for example:
+
+```text
+orgapachepaimon-XXXX
+```
+
+Use that id in the release vote email.
diff --git a/tools/deploy_java_staging.sh b/tools/deploy_java_staging.sh
new file mode 100755
index 0000000..736524c
--- /dev/null
+++ b/tools/deploy_java_staging.sh
@@ -0,0 +1,550 @@
+#!/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 -o errexit
+set -o nounset
+set -o pipefail
+
+MVN=${MVN:-mvn}
+
+SCRIPT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
+REPO_DIR=$(cd "$SCRIPT_DIR/.." && pwd)
+
+RELEASE_VERSION=
+RC_NUMBER=
+TAG=
+NATIVE_DIR=
+RUN_ID=
+DRY_RUN=false
+SKIP_TESTS=true
+CLEANUP_NATIVE_RESOURCES=true
+MAVEN_SETTINGS=
+STAGING_DESCRIPTION=
+CHECK_NATIVE_FILES=true
+
+usage() {
+  cat <<'EOF'
+Usage:
+  deploy_java_staging.sh --release-version VERSION --rc N --run-id RUN_ID 
[options]
+
+Deploy Apache Paimon Vector Index Java RC artifacts to Apache Nexus staging 
from a
+committer/RM machine. Pass the GitHub Actions run id that built the RC native
+libraries; the script verifies the run, downloads the native artifacts, and 
then
+runs the local Maven deploy.
+
+Required:
+  --release-version VERSION  Release version in java/pom.xml, for example 
0.2.0.
+  --rc N                     RC number, for example 1 for v0.2.0-rc1.
+  --run-id RUN_ID            GitHub Actions run id containing native-* 
artifacts.
+
+Options:
+  --tag TAG                  RC tag. Defaults to vVERSION-rcN.
+  --repo REPO                GitHub repository. Defaults to 
apache/paimon-vector-index.
+  --dry-run                  Build and verify release artifacts locally only.
+                             Does not sign or deploy to Nexus.
+  --maven-settings FILE      Maven settings.xml containing 
apache.releases.https.
+  --staging-description TXT  Nexus staging description.
+  --no-skip-tests            Run Maven tests.
+  --no-cleanup               Keep java/src/main/resources/native after exit.
+  --skip-native-file-check   Do not check native binary file formats.
+  -h, --help                 Show this help.
+
+Validate with the real RC artifacts before publishing:
+  ./tools/deploy_java_staging.sh --release-version 0.2.0 --rc 1 \
+    --run-id 12345678901 --dry-run
+
+Publish staging after the dry run succeeds:
+  ./tools/deploy_java_staging.sh --release-version 0.2.0 --rc 1 \
+    --run-id 12345678901
+
+Maven/GPG requirements:
+  Real deploy uses the committer's local GPG setup and Maven credentials for
+  server id apache.releases.https. Configure ~/.m2/settings.xml, pass
+  --maven-settings FILE, or set NEXUS_STAGE_DEPLOYER_USER and
+  NEXUS_STAGE_DEPLOYER_PW for a temporary settings.xml.
+
+gh CLI requirement:
+  --run-id uses the GitHub CLI to check the workflow run and fetch native
+  artifacts. Run `gh auth login` first.
+EOF
+}
+
+require_option_value() {
+  local option=$1
+  local value=${2-}
+  if [[ $# -lt 2 || -z "$value" ]]; then
+    echo "$option requires a value" >&2
+    usage >&2
+    exit 1
+  fi
+}
+
+while [[ $# -gt 0 ]]; do
+  case "$1" in
+    --release-version)
+      require_option_value "$@"
+      RELEASE_VERSION=$2
+      shift 2
+      ;;
+    --rc)
+      require_option_value "$@"
+      RC_NUMBER=$2
+      shift 2
+      ;;
+    --tag)
+      require_option_value "$@"
+      TAG=$2
+      shift 2
+      ;;
+    --run-id)
+      require_option_value "$@"
+      RUN_ID=$2
+      shift 2
+      ;;
+    --repo)
+      require_option_value "$@"
+      REPO=$2
+      shift 2
+      ;;
+    --dry-run)
+      DRY_RUN=true
+      shift
+      ;;
+    --maven-settings)
+      require_option_value "$@"
+      MAVEN_SETTINGS=$2
+      shift 2
+      ;;
+    --staging-description)
+      require_option_value "$@"
+      STAGING_DESCRIPTION=$2
+      shift 2
+      ;;
+    --no-skip-tests)
+      SKIP_TESTS=false
+      shift
+      ;;
+    --no-cleanup)
+      CLEANUP_NATIVE_RESOURCES=false
+      shift
+      ;;
+    --skip-native-file-check)
+      CHECK_NATIVE_FILES=false
+      shift
+      ;;
+    -h|--help)
+      usage
+      exit 0
+      ;;
+    *)
+      echo "Unknown argument: $1" >&2
+      usage >&2
+      exit 1
+      ;;
+  esac
+done
+
+require_value() {
+  local name=$1
+  local value=$2
+  if [[ -z "$value" ]]; then
+    echo "$name is required" >&2
+    usage >&2
+    exit 1
+  fi
+}
+
+REPO=${REPO:-apache/paimon-vector-index}
+
+require_value "--release-version" "$RELEASE_VERSION"
+
+if [[ -z "$TAG" ]]; then
+  require_value "--rc" "$RC_NUMBER"
+  TAG="v${RELEASE_VERSION}-rc${RC_NUMBER}"
+fi
+
+if [[ -z "$STAGING_DESCRIPTION" ]]; then
+  if [[ -n "$RC_NUMBER" ]]; then
+    STAGING_DESCRIPTION="Apache Paimon Vector Index, version 
${RELEASE_VERSION}, release candidate ${RC_NUMBER}"
+  else
+    STAGING_DESCRIPTION="Apache Paimon Vector Index, version 
${RELEASE_VERSION}, release candidate ${TAG#*-rc}"
+  fi
+fi
+
+if [[ -z "$RUN_ID" ]]; then
+  echo "--run-id is required" >&2
+  usage >&2
+  exit 1
+fi
+
+NATIVE_DIR="$SCRIPT_DIR/release/java-native-${TAG}"
+
+if [[ -n "$MAVEN_SETTINGS" && ! -f "$MAVEN_SETTINGS" ]]; then
+  echo "--maven-settings does not exist: $MAVEN_SETTINGS" >&2
+  exit 1
+fi
+
+POM_VERSION=$(
+  sed -n 's#.*<version>\([^<]*\)</version>.*#\1#p' "$REPO_DIR/java/pom.xml" |
+    sed -n '2p'
+)
+if [[ "$POM_VERSION" != "$RELEASE_VERSION" ]]; then
+  echo "java/pom.xml version is $POM_VERSION, expected $RELEASE_VERSION" >&2
+  echo "Check out the RC tag after bumping versions, then run this script 
again." >&2
+  exit 1
+fi
+
+if ! git -C "$REPO_DIR" rev-parse -q --verify "$TAG^{commit}" >/dev/null; then
+  echo "Tag $TAG does not exist locally." >&2
+  echo "Run: git fetch --tags && git checkout $TAG" >&2
+  exit 1
+else
+  TAG_COMMIT=$(git -C "$REPO_DIR" rev-parse "$TAG^{commit}")
+  HEAD_COMMIT=$(git -C "$REPO_DIR" rev-parse HEAD)
+  if [[ "$TAG_COMMIT" != "$HEAD_COMMIT" ]]; then
+    echo "Current HEAD is not $TAG." >&2
+    echo "Run: git checkout $TAG" >&2
+    exit 1
+  fi
+fi
+
+check_java_package_inputs_clean() {
+  local paths=(java DEPENDENCIES.rust.tsv)
+  local untracked
+
+  if ! git -C "$REPO_DIR" diff --quiet -- "${paths[@]}" ||
+     ! git -C "$REPO_DIR" diff --cached --quiet -- "${paths[@]}"; then
+    echo "Java package inputs have local changes. Commit or revert them before 
publishing." >&2
+    git -C "$REPO_DIR" status --short -- "${paths[@]}" >&2
+    exit 1
+  fi
+
+  untracked=$(git -C "$REPO_DIR" ls-files --others --exclude-standard -- 
"${paths[@]}")
+  if [[ -n "$untracked" ]]; then
+    echo "Java package inputs contain untracked files. Remove or commit them 
before publishing." >&2
+    printf '%s\n' "$untracked" >&2
+    exit 1
+  fi
+}
+
+check_java_package_inputs_clean
+
+validate_github_run() {
+  local run_output
+  local run_info
+  if ! run_output=$(
+    gh run view "$RUN_ID" \
+      --repo "$REPO" \
+      --json status,conclusion,headSha,headBranch,workflowName,event \
+      --template '{{printf "%s\n%s\n%s\n%s\n%s\n%s\n" .status .conclusion 
.headSha (or .headBranch "") (or .workflowName "") (or .event "")}}'
+  ); then
+    echo "Failed to read GitHub Actions run: $RUN_ID" >&2
+    exit 1
+  fi
+  mapfile -t run_info <<<"$run_output"
+
+  local run_status=${run_info[0]:-}
+  local run_conclusion=${run_info[1]:-}
+  local run_head_sha=${run_info[2]:-}
+  local run_head_branch=${run_info[3]:-}
+  local run_workflow_name=${run_info[4]:-}
+  local run_event=${run_info[5]:-}
+
+  if [[ "$run_status" != "completed" || "$run_conclusion" != "success" ]]; then
+    echo "GitHub Actions run $RUN_ID is not a successful completed run." >&2
+    echo "status=$run_status conclusion=$run_conclusion" >&2
+    exit 1
+  fi
+
+  if [[ "$run_workflow_name" != "Release" ]]; then
+    echo "GitHub Actions run $RUN_ID is from workflow '$run_workflow_name', 
expected 'Release'." >&2
+    exit 1
+  fi
+
+  if [[ "$run_event" != "push" ]]; then
+    echo "GitHub Actions run $RUN_ID was triggered by '$run_event', expected a 
tag push." >&2
+    exit 1
+  fi
+
+  if [[ "$run_head_sha" != "$TAG_COMMIT" ]]; then
+    echo "GitHub Actions run $RUN_ID does not match $TAG." >&2
+    echo "run headSha: $run_head_sha" >&2
+    echo "tag commit:  $TAG_COMMIT" >&2
+    exit 1
+  fi
+
+  echo "Using GitHub Actions run $RUN_ID for native artifacts:"
+  echo "  workflow: ${run_workflow_name:-unknown}"
+  echo "  event:    ${run_event:-unknown}"
+  echo "  ref:      ${run_head_branch:-unknown}"
+  echo "  headSha:  ${run_head_sha:-unknown}"
+}
+
+if ! command -v gh >/dev/null 2>&1; then
+  echo "gh CLI is required when --run-id is used" >&2
+  exit 1
+fi
+
+validate_github_run
+
+rm -rf "$NATIVE_DIR"
+mkdir -p "$NATIVE_DIR"
+for artifact in \
+  native-linux-x86_64 \
+  native-linux-aarch64 \
+  native-macos-aarch64 \
+  native-windows-x86_64
+do
+  gh run download "$RUN_ID" \
+    --repo "$REPO" \
+    --name "$artifact" \
+    --dir "$NATIVE_DIR/$artifact"
+done
+
+if [[ ! -d "$NATIVE_DIR" ]]; then
+  echo "Native artifact download directory does not exist: $NATIVE_DIR" >&2
+  exit 1
+fi
+
+find_native() {
+  local artifact_layout=$1
+  local resource_layout=$2
+  local resource_without_native=${resource_layout#native/}
+
+  for candidate in \
+    "$NATIVE_DIR/$artifact_layout" \
+    "$NATIVE_DIR/$resource_layout" \
+    "$NATIVE_DIR/$resource_without_native"
+  do
+    if [[ -f "$candidate" ]]; then
+      printf '%s\n' "$candidate"
+      return 0
+    fi
+  done
+
+  echo "Missing native artifact. Tried:" >&2
+  echo "  $NATIVE_DIR/$artifact_layout" >&2
+  echo "  $NATIVE_DIR/$resource_layout" >&2
+  echo "  $NATIVE_DIR/$resource_without_native" >&2
+  exit 1
+}
+
+validate_native_file() {
+  local source_file=$1
+  local label=$2
+
+  if [[ "$CHECK_NATIVE_FILES" != "true" ]]; then
+    return
+  fi
+
+  if ! command -v file >/dev/null 2>&1; then
+    echo "WARNING: 'file' command not found; skipping native file format 
checks." >&2
+    return
+  fi
+
+  local info
+  info=$(file "$source_file")
+  case "$label" in
+    linux-x86_64)
+      if ! grep -Eq 'ELF 64-bit.*(x86-64|x86_64)' <<<"$info"; then
+        echo "Unexpected linux x86_64 native file: $info" >&2
+        exit 1
+      fi
+      ;;
+    linux-aarch64)
+      if ! grep -Eq 'ELF 64-bit.*(ARM aarch64|AArch64|aarch64|ARM64)' 
<<<"$info"; then
+        echo "Unexpected linux aarch64 native file: $info" >&2
+        exit 1
+      fi
+      ;;
+    macos-aarch64)
+      if ! grep -Eq 'Mach-O 64-bit.*(arm64|aarch64)' <<<"$info"; then
+        echo "Unexpected macOS aarch64 native file: $info" >&2
+        exit 1
+      fi
+      ;;
+    windows-x86_64)
+      if ! grep -Eq 'PE32\+.*(x86-64|x86_64)' <<<"$info"; then
+        echo "Unexpected windows x86_64 native file: $info" >&2
+        exit 1
+      fi
+      ;;
+    *)
+      echo "Unknown native file label: $label" >&2
+      exit 1
+      ;;
+  esac
+}
+
+copy_native() {
+  local source_file=$1
+  local target_rel=$2
+  local label=$3
+  local target_file="$REPO_DIR/java/src/main/resources/$target_rel"
+
+  validate_native_file "$source_file" "$label"
+  mkdir -p "$(dirname "$target_file")"
+  cp "$source_file" "$target_file"
+}
+
+cleanup_native_resources() {
+  if [[ "$CLEANUP_NATIVE_RESOURCES" == "true" ]]; then
+    rm -rf "$REPO_DIR/java/src/main/resources/native"
+  fi
+}
+
+TEMP_SETTINGS=
+cleanup_temp_settings() {
+  if [[ -n "$TEMP_SETTINGS" ]]; then
+    rm -f "$TEMP_SETTINGS"
+  fi
+}
+
+xml_escape() {
+  printf '%s' "$1" |
+    sed \
+      -e 's/&/\&amp;/g' \
+      -e 's/</\&lt;/g' \
+      -e 's/>/\&gt;/g'
+}
+
+cleanup_all() {
+  cleanup_native_resources
+  cleanup_temp_settings
+}
+trap cleanup_all EXIT
+
+rm -rf "$REPO_DIR/java/src/main/resources/native"
+
+copy_native \
+  "$(find_native native-linux-x86_64/libpaimon_vindex_jni.so 
native/linux/x86_64/libpaimon_vindex_jni.so)" \
+  native/linux/x86_64/libpaimon_vindex_jni.so \
+  linux-x86_64
+copy_native \
+  "$(find_native native-linux-aarch64/libpaimon_vindex_jni.so 
native/linux/aarch64/libpaimon_vindex_jni.so)" \
+  native/linux/aarch64/libpaimon_vindex_jni.so \
+  linux-aarch64
+copy_native \
+  "$(find_native native-macos-aarch64/libpaimon_vindex_jni.dylib 
native/macos/aarch64/libpaimon_vindex_jni.dylib)" \
+  native/macos/aarch64/libpaimon_vindex_jni.dylib \
+  macos-aarch64
+copy_native \
+  "$(find_native native-windows-x86_64/paimon_vindex_jni.dll 
native/windows/x86_64/paimon_vindex_jni.dll)" \
+  native/windows/x86_64/paimon_vindex_jni.dll \
+  windows-x86_64
+
+echo "Native libraries staged for Java package:"
+find "$REPO_DIR/java/src/main/resources/native" -type f | sort
+
+if [[ "$DRY_RUN" != "true" &&
+      -z "$MAVEN_SETTINGS" &&
+      ( -n "${NEXUS_STAGE_DEPLOYER_USER:-}" || -n 
"${NEXUS_STAGE_DEPLOYER_PW:-}" ) ]]; then
+  if [[ -z "${NEXUS_STAGE_DEPLOYER_USER:-}" || -z 
"${NEXUS_STAGE_DEPLOYER_PW:-}" ]]; then
+    echo "Both NEXUS_STAGE_DEPLOYER_USER and NEXUS_STAGE_DEPLOYER_PW are 
required" >&2
+    exit 1
+  fi
+
+  TEMP_SETTINGS=$(mktemp)
+  NEXUS_STAGE_DEPLOYER_USER_XML=$(xml_escape "$NEXUS_STAGE_DEPLOYER_USER")
+  NEXUS_STAGE_DEPLOYER_PW_XML=$(xml_escape "$NEXUS_STAGE_DEPLOYER_PW")
+  cat > "$TEMP_SETTINGS" <<EOF
+<settings>
+  <servers>
+    <server>
+      <id>apache.releases.https</id>
+      <username>${NEXUS_STAGE_DEPLOYER_USER_XML}</username>
+      <password>${NEXUS_STAGE_DEPLOYER_PW_XML}</password>
+    </server>
+  </servers>
+</settings>
+EOF
+  MAVEN_SETTINGS="$TEMP_SETTINGS"
+fi
+
+MVN_BASE_CMD=("$MVN")
+if [[ -n "$MAVEN_SETTINGS" ]]; then
+  MVN_BASE_CMD+=("-s" "$MAVEN_SETTINGS")
+fi
+
+VERIFY_CMD=("${MVN_BASE_CMD[@]}" clean verify -Prelease -Dgpg.skip=true)
+if [[ "$SKIP_TESTS" == "true" ]]; then
+  VERIFY_CMD+=(-DskipTests)
+fi
+
+validate_maven_artifacts() {
+  local 
jar_file="$REPO_DIR/java/target/paimon-vector-index-java-${RELEASE_VERSION}.jar"
+  local 
sources_jar="$REPO_DIR/java/target/paimon-vector-index-java-${RELEASE_VERSION}-sources.jar"
+  local 
javadoc_jar="$REPO_DIR/java/target/paimon-vector-index-java-${RELEASE_VERSION}-javadoc.jar"
+  local artifact
+  local native_entry
+
+  for artifact in "$jar_file" "$sources_jar" "$javadoc_jar"; do
+    if [[ ! -f "$artifact" ]]; then
+      echo "Expected Maven artifact is missing: $artifact" >&2
+      exit 1
+    fi
+  done
+
+  for native_entry in \
+    native/linux/x86_64/libpaimon_vindex_jni.so \
+    native/linux/aarch64/libpaimon_vindex_jni.so \
+    native/macos/aarch64/libpaimon_vindex_jni.dylib \
+    native/windows/x86_64/paimon_vindex_jni.dll
+  do
+    if ! jar tf "$jar_file" | grep -qx "$native_entry"; then
+      echo "Packaged jar is missing native entry: $native_entry" >&2
+      exit 1
+    fi
+  done
+}
+
+if [[ "$DRY_RUN" == "true" ]]; then
+  echo "Dry-running Java staging build. No artifacts will be deployed to 
Nexus."
+else
+  echo "Running Java staging preflight before deploying to Apache Nexus."
+  echo "Staging description: $STAGING_DESCRIPTION"
+fi
+
+(
+  cd "$REPO_DIR/java"
+  "${VERIFY_CMD[@]}"
+)
+
+validate_maven_artifacts
+
+echo ""
+if [[ "$DRY_RUN" == "true" ]]; then
+  echo "Java staging dry run finished successfully."
+else
+  DEPLOY_CMD=("${MVN_BASE_CMD[@]}" deploy -Prelease 
"-DstagingDescription=$STAGING_DESCRIPTION")
+  if [[ "$SKIP_TESTS" == "true" ]]; then
+    DEPLOY_CMD+=(-DskipTests)
+  fi
+
+  echo "Preflight passed. Deploying Java artifacts to Apache Nexus staging."
+  (
+    cd "$REPO_DIR/java"
+    "${DEPLOY_CMD[@]}"
+  )
+  validate_maven_artifacts
+
+  echo ""
+  echo "Java staging deploy finished."
+  echo "Check the Maven output for the orgapachepaimon-XXXX staging repository 
id."
+fi

Reply via email to