github-actions[bot] commented on code in PR #65488:
URL: https://github.com/apache/doris/pull/65488#discussion_r3566315986


##########
tools/release-tools/04-release-complete.sh:
##########
@@ -0,0 +1,214 @@
+#!/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.
+
+# Step 04 - publish the passed RC source artifact to the Apache release SVN
+# and generate the [ANNOUNCE] email draft.
+#
+# The release SVN commit is public and requires PMC permission. This script
+# pauses for confirmation before changing SVN, and it never sends email.
+set -euo pipefail
+HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
+# shellcheck source=release.env
+source "${HERE}/release.env"
+
+ok()   { echo "[ OK ] $*"; }
+warn() { echo "[WARN] $*"; }
+die()  { echo "[FAIL] $*" >&2; exit 1; }
+confirm() { local a; read -r -p "$1 [y/N] " a; [[ "$a" == y || "$a" == Y ]]; }
+
+mail_only=0
+usage() {
+  cat <<EOF
+Usage: $0 [--mail-only]
+
+Publishes Apache Doris ${TAG} source artifacts from dev SVN to release SVN as
+Apache Doris ${VERSION}, then writes the [ANNOUNCE] email draft.
+
+Options:
+  --mail-only   Only write announce-email.txt and announce-email.eml.
+EOF
+}
+
+while [[ $# -gt 0 ]]; do
+  case "$1" in
+    --mail-only) mail_only=1; shift ;;
+    -h|--help) usage; exit 0 ;;
+    *) die "unknown argument: $1" ;;
+  esac
+done
+
+svn_auth=(--non-interactive --no-auth-cache)
+[[ -n "${ASF_USERNAME:-}" ]] && svn_auth+=(--username "$ASF_USERNAME")
+[[ -n "${ASF_PASSWORD:-}" ]] && svn_auth+=(--password "$ASF_PASSWORD")
+svnmucc_auth=(--non-interactive --no-auth-cache)
+[[ -n "${ASF_USERNAME:-}" ]] && svnmucc_auth+=(-u "$ASF_USERNAME")
+[[ -n "${ASF_PASSWORD:-}" ]] && svnmucc_auth+=(-p "$ASF_PASSWORD")
+
+RELEASE_PKG_BASE="${RELEASE_PKG_BASE:-apache-doris-${VERSION}-src}"
+RELEASE_SERIES="${RELEASE_SERIES:-${VERSION%.*}}"
+RELEASE_SVN_DIR="${RELEASE_SVN_DIR:-${RELEASE_SVN_BASE}/${RELEASE_SERIES}/${VERSION}}"
+DOWNLOAD_PAGE_URL="${DOWNLOAD_PAGE_URL:-https://doris.apache.org/download/}";
+ANNOUNCE_RELEASE_NOTES_URL="${ANNOUNCE_RELEASE_NOTES_URL:-}"
+
+require_tool() {
+  command -v "$1" >/dev/null 2>&1 || die "missing tool: $1"
+}
+
+write_announce_email() {
+  local rn subject body_file eml_file
+
+  rn="${ANNOUNCE_RELEASE_NOTES_URL:-${RELEASE_NOTES_URL:-}}"
+  if [[ -z "$rn" ]]; then
+    read -r -p "Release Notes URL for announce email: " rn
+  fi
+  [[ -n "$rn" ]] || die "release notes url required"
+
+  mkdir -p "$WORK_DIR"
+  subject="[ANNOUNCE] Apache Doris ${VERSION} release"
+  body_file="$WORK_DIR/announce-email.txt"
+  eml_file="$WORK_DIR/announce-email.eml"
+
+  read -r -d '' BODY <<EOF || true
+Hi All,
+
+We are pleased to announce the release of Apache Doris ${VERSION}.
+
+Apache Doris is a real-time analytics and hybrid search database for AI agents.
+
+The release is available at:
+${DOWNLOAD_PAGE_URL}
+
+The source artifacts are available at:
+${RELEASE_SVN_DIR}/
+
+Thanks to everyone who has contributed to this release, and the release note 
can be found here:
+${rn}
+
+Best Regards,
+
+On behalf of the Doris team,
+${SIGNER_NAME}
+EOF
+
+  printf '%s\n' "$BODY" > "$body_file"
+  {
+    echo "To: ${DEV_LIST}"
+    echo "Subject: ${subject}"
+    echo "Content-Type: text/plain; charset=UTF-8"
+    echo
+    printf '%s\n' "$BODY"
+  } > "$eml_file"
+
+  ok "subject: ${subject}"
+  ok "body:    ${body_file}"
+  ok "eml:     ${eml_file}  (open in your apache.org mail client)"
+  echo "----------------------------------------------------------------"
+  cat "$body_file"
+  echo "----------------------------------------------------------------"
+  echo "Review, then SEND MANUALLY from your @apache.org address to 
${DEV_LIST}."
+  echo "(Not auto-sent by design - it's a public ASF list.)"
+}
+
+publish_to_release_svn() {
+  local src_tar src_asc src_sha512 dst_tar dst_asc dst_sha512 checksum_dir 
src_tar_file final_sha512_file
+
+  require_tool svn
+  require_tool svnmucc
+  require_tool gpg
+  require_tool sha512sum
+
+  src_tar="${DEV_SVN_DIR}/${PKG_BASE}.tar.gz"
+  src_asc="${src_tar}.asc"
+  src_sha512="${src_tar}.sha512"
+  dst_tar="${RELEASE_PKG_BASE}.tar.gz"
+  dst_asc="${dst_tar}.asc"
+  dst_sha512="${dst_tar}.sha512"
+
+  echo "== Apache Doris ${TAG} - complete release =="
+  echo "Source dev SVN folder:     ${DEV_SVN_DIR}/"
+  echo "Target release SVN folder: ${RELEASE_SVN_DIR}/"
+  echo
+  echo "Source files:"
+  echo "  ${PKG_BASE}.tar.gz"
+  echo "  ${PKG_BASE}.tar.gz.asc"
+  echo "  ${PKG_BASE}.tar.gz.sha512"
+  echo "Target files:"
+  echo "  ${dst_tar}"
+  echo "  ${dst_asc}"
+  echo "  ${dst_sha512}"
+  echo
+  warn "Only PMC members can write to the release SVN directory."
+
+  svn info "${svn_auth[@]}" "$src_tar" >/dev/null || die "source artifact not 
found: $src_tar"
+  svn info "${svn_auth[@]}" "$src_asc" >/dev/null || die "source signature not 
found: $src_asc"
+  svn info "${svn_auth[@]}" "$src_sha512" >/dev/null || die "source checksum 
not found: $src_sha512"
+  if svn info "${svn_auth[@]}" "$RELEASE_SVN_DIR" >/dev/null 2>&1; then
+    die "release SVN folder already exists: $RELEASE_SVN_DIR (use --mail-only 
to regenerate the email)"
+  fi
+
+  checksum_dir="$(mktemp -d)"
+  src_tar_file="${PKG_BASE}.tar.gz"
+  final_sha512_file="${checksum_dir}/${dst_sha512}"
+  svn cat "${svn_auth[@]}" "$src_tar" > "${checksum_dir}/${src_tar_file}"
+  svn cat "${svn_auth[@]}" "$src_sha512" > 
"${checksum_dir}/${src_tar_file}.sha512"
+  svn cat "${svn_auth[@]}" "$src_asc" > "${checksum_dir}/${src_tar_file}.asc"
+  (
+    cd "$checksum_dir"
+    sha512sum --check "${src_tar_file}.sha512"
+    gpg --verify "${src_tar_file}.asc" "$src_tar_file"
+    cp "$src_tar_file" "$dst_tar"
+    sha512sum "$dst_tar" > "$dst_sha512"
+    sha512sum --check "$dst_sha512"
+  )
+  ok "source RC checksum and signature verified: ${src_tar_file}"
+  ok "final sha512 ok: ${dst_sha512}"
+
+  echo "--- svnmucc operations ---"
+  echo "mkdir ${RELEASE_SVN_DIR}"
+  echo "mv    ${src_tar}"
+  echo "  ->  ${RELEASE_SVN_DIR}/${dst_tar}"
+  echo "mv    ${src_asc}"
+  echo "  ->  ${RELEASE_SVN_DIR}/${dst_asc}"
+  echo "put   ${final_sha512_file}"
+  echo "  ->  ${RELEASE_SVN_DIR}/${dst_sha512}"
+  echo "rm    ${DEV_SVN_DIR}"
+  echo
+  echo "Will commit the URL operations above in one SVN revision."
+  confirm "FINAL confirm - publish release SVN and remove dev RC now?" || { 
warn "stopping before SVN commit."; rm -rf "$checksum_dir"; exit 0; }
+
+  if ! svnmucc "${svnmucc_auth[@]}" -m "Release Doris ${VERSION}" \
+    mkdir "$RELEASE_SVN_DIR" \
+    mv "$src_tar" "${RELEASE_SVN_DIR}/${dst_tar}" \

Review Comment:
   This verifies `${src_tar}` and `${src_asc}` from local files fetched by `svn 
cat`, but the final commit still moves the live SVN URLs with `svnmucc mv`. If 
the dev SVN artifact or signature changes after the verification step and 
before this commit, the release directory can receive bytes that were never 
verified, while `${final_sha512_file}` was generated from the earlier local 
tarball. Please either publish the already verified local tarball/signature 
with `svnmucc put`, or capture/pin the verified source revision so a concurrent 
source change makes the commit fail instead of publishing unverified bytes.



##########
tools/release-tools/04-release-complete.sh:
##########
@@ -0,0 +1,214 @@
+#!/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.
+
+# Step 04 - publish the passed RC source artifact to the Apache release SVN
+# and generate the [ANNOUNCE] email draft.
+#
+# The release SVN commit is public and requires PMC permission. This script
+# pauses for confirmation before changing SVN, and it never sends email.
+set -euo pipefail
+HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
+# shellcheck source=release.env
+source "${HERE}/release.env"
+
+ok()   { echo "[ OK ] $*"; }
+warn() { echo "[WARN] $*"; }
+die()  { echo "[FAIL] $*" >&2; exit 1; }
+confirm() { local a; read -r -p "$1 [y/N] " a; [[ "$a" == y || "$a" == Y ]]; }
+
+mail_only=0
+usage() {
+  cat <<EOF
+Usage: $0 [--mail-only]
+
+Publishes Apache Doris ${TAG} source artifacts from dev SVN to release SVN as
+Apache Doris ${VERSION}, then writes the [ANNOUNCE] email draft.
+
+Options:
+  --mail-only   Only write announce-email.txt and announce-email.eml.
+EOF
+}
+
+while [[ $# -gt 0 ]]; do
+  case "$1" in
+    --mail-only) mail_only=1; shift ;;
+    -h|--help) usage; exit 0 ;;
+    *) die "unknown argument: $1" ;;
+  esac
+done
+
+svn_auth=(--non-interactive --no-auth-cache)
+[[ -n "${ASF_USERNAME:-}" ]] && svn_auth+=(--username "$ASF_USERNAME")
+[[ -n "${ASF_PASSWORD:-}" ]] && svn_auth+=(--password "$ASF_PASSWORD")
+svnmucc_auth=(--non-interactive --no-auth-cache)
+[[ -n "${ASF_USERNAME:-}" ]] && svnmucc_auth+=(-u "$ASF_USERNAME")
+[[ -n "${ASF_PASSWORD:-}" ]] && svnmucc_auth+=(-p "$ASF_PASSWORD")
+
+RELEASE_PKG_BASE="${RELEASE_PKG_BASE:-apache-doris-${VERSION}-src}"
+RELEASE_SERIES="${RELEASE_SERIES:-${VERSION%.*}}"
+RELEASE_SVN_DIR="${RELEASE_SVN_DIR:-${RELEASE_SVN_BASE}/${RELEASE_SERIES}/${VERSION}}"
+DOWNLOAD_PAGE_URL="${DOWNLOAD_PAGE_URL:-https://doris.apache.org/download/}";
+ANNOUNCE_RELEASE_NOTES_URL="${ANNOUNCE_RELEASE_NOTES_URL:-}"
+
+require_tool() {
+  command -v "$1" >/dev/null 2>&1 || die "missing tool: $1"
+}
+
+write_announce_email() {
+  local rn subject body_file eml_file
+
+  rn="${ANNOUNCE_RELEASE_NOTES_URL:-${RELEASE_NOTES_URL:-}}"
+  if [[ -z "$rn" ]]; then
+    read -r -p "Release Notes URL for announce email: " rn
+  fi
+  [[ -n "$rn" ]] || die "release notes url required"
+
+  mkdir -p "$WORK_DIR"
+  subject="[ANNOUNCE] Apache Doris ${VERSION} release"
+  body_file="$WORK_DIR/announce-email.txt"
+  eml_file="$WORK_DIR/announce-email.eml"
+
+  read -r -d '' BODY <<EOF || true
+Hi All,
+
+We are pleased to announce the release of Apache Doris ${VERSION}.
+
+Apache Doris is a real-time analytics and hybrid search database for AI agents.
+
+The release is available at:
+${DOWNLOAD_PAGE_URL}
+
+The source artifacts are available at:
+${RELEASE_SVN_DIR}/
+
+Thanks to everyone who has contributed to this release, and the release note 
can be found here:
+${rn}
+
+Best Regards,
+
+On behalf of the Doris team,
+${SIGNER_NAME}
+EOF
+
+  printf '%s\n' "$BODY" > "$body_file"
+  {
+    echo "To: ${DEV_LIST}"
+    echo "Subject: ${subject}"
+    echo "Content-Type: text/plain; charset=UTF-8"
+    echo
+    printf '%s\n' "$BODY"
+  } > "$eml_file"
+
+  ok "subject: ${subject}"
+  ok "body:    ${body_file}"
+  ok "eml:     ${eml_file}  (open in your apache.org mail client)"
+  echo "----------------------------------------------------------------"
+  cat "$body_file"
+  echo "----------------------------------------------------------------"
+  echo "Review, then SEND MANUALLY from your @apache.org address to 
${DEV_LIST}."
+  echo "(Not auto-sent by design - it's a public ASF list.)"
+}
+
+publish_to_release_svn() {
+  local src_tar src_asc src_sha512 dst_tar dst_asc dst_sha512 checksum_dir 
src_tar_file final_sha512_file
+
+  require_tool svn
+  require_tool svnmucc
+  require_tool gpg
+  require_tool sha512sum
+
+  src_tar="${DEV_SVN_DIR}/${PKG_BASE}.tar.gz"
+  src_asc="${src_tar}.asc"
+  src_sha512="${src_tar}.sha512"
+  dst_tar="${RELEASE_PKG_BASE}.tar.gz"
+  dst_asc="${dst_tar}.asc"
+  dst_sha512="${dst_tar}.sha512"
+
+  echo "== Apache Doris ${TAG} - complete release =="
+  echo "Source dev SVN folder:     ${DEV_SVN_DIR}/"
+  echo "Target release SVN folder: ${RELEASE_SVN_DIR}/"
+  echo
+  echo "Source files:"
+  echo "  ${PKG_BASE}.tar.gz"
+  echo "  ${PKG_BASE}.tar.gz.asc"
+  echo "  ${PKG_BASE}.tar.gz.sha512"
+  echo "Target files:"
+  echo "  ${dst_tar}"
+  echo "  ${dst_asc}"
+  echo "  ${dst_sha512}"
+  echo
+  warn "Only PMC members can write to the release SVN directory."
+
+  svn info "${svn_auth[@]}" "$src_tar" >/dev/null || die "source artifact not 
found: $src_tar"
+  svn info "${svn_auth[@]}" "$src_asc" >/dev/null || die "source signature not 
found: $src_asc"
+  svn info "${svn_auth[@]}" "$src_sha512" >/dev/null || die "source checksum 
not found: $src_sha512"
+  if svn info "${svn_auth[@]}" "$RELEASE_SVN_DIR" >/dev/null 2>&1; then
+    die "release SVN folder already exists: $RELEASE_SVN_DIR (use --mail-only 
to regenerate the email)"
+  fi
+
+  checksum_dir="$(mktemp -d)"
+  src_tar_file="${PKG_BASE}.tar.gz"
+  final_sha512_file="${checksum_dir}/${dst_sha512}"
+  svn cat "${svn_auth[@]}" "$src_tar" > "${checksum_dir}/${src_tar_file}"
+  svn cat "${svn_auth[@]}" "$src_sha512" > 
"${checksum_dir}/${src_tar_file}.sha512"
+  svn cat "${svn_auth[@]}" "$src_asc" > "${checksum_dir}/${src_tar_file}.asc"
+  (
+    cd "$checksum_dir"
+    sha512sum --check "${src_tar_file}.sha512"
+    gpg --verify "${src_tar_file}.asc" "$src_tar_file"
+    cp "$src_tar_file" "$dst_tar"
+    sha512sum "$dst_tar" > "$dst_sha512"
+    sha512sum --check "$dst_sha512"
+  )
+  ok "source RC checksum and signature verified: ${src_tar_file}"
+  ok "final sha512 ok: ${dst_sha512}"
+
+  echo "--- svnmucc operations ---"
+  echo "mkdir ${RELEASE_SVN_DIR}"
+  echo "mv    ${src_tar}"
+  echo "  ->  ${RELEASE_SVN_DIR}/${dst_tar}"
+  echo "mv    ${src_asc}"
+  echo "  ->  ${RELEASE_SVN_DIR}/${dst_asc}"
+  echo "put   ${final_sha512_file}"
+  echo "  ->  ${RELEASE_SVN_DIR}/${dst_sha512}"
+  echo "rm    ${DEV_SVN_DIR}"
+  echo
+  echo "Will commit the URL operations above in one SVN revision."
+  confirm "FINAL confirm - publish release SVN and remove dev RC now?" || { 
warn "stopping before SVN commit."; rm -rf "$checksum_dir"; exit 0; }
+
+  if ! svnmucc "${svnmucc_auth[@]}" -m "Release Doris ${VERSION}" \
+    mkdir "$RELEASE_SVN_DIR" \

Review Comment:
   `RELEASE_SVN_DIR` now points at 
`${RELEASE_SVN_BASE}/${RELEASE_SERIES}/${VERSION}`, but this commit only does 
`mkdir "$RELEASE_SVN_DIR"`. `svnmucc mkdir` does not create missing 
intermediate parents, so the first release in a new series such as `4.1.0` will 
fail here if `release/doris/4.1` has not already been created. Please 
check/create `${RELEASE_SVN_BASE}/${RELEASE_SERIES}` before the leaf mkdir, or 
fail early with an explicit instruction, and cover the missing-parent case in 
the fake-`svnmucc` test.



##########
tools/release-tools/README.md:
##########
@@ -19,81 +19,249 @@ under the License.
 
 # Doris release helper scripts
 
-Helper scripts for an Apache Doris Release Manager (RM) to cut a **source** 
release candidate:
-package and sign the source tarball, upload it to the Apache dev SVN, and 
draft the `[VOTE]` email.
+This directory contains helper scripts for an Apache Doris Release Manager (RM)
+to create and complete a source release candidate (RC). The scripts package and
+sign the source tarball, upload the source artifacts to the Apache dev SVN,
+draft the `[VOTE]` email, publish the passed RC to the Apache release SVN, and
+draft the `[ANNOUNCE]` email.
+
+These scripts are not a full release automation system. They assume the release
+branch, release notes, cherry-picks, build validation, and release tag have
+already been prepared.
+
+## If you are an AI agent
+
+When a user says something like "read this file and tell me how to start
+releasing Doris 4.0.7", give the RM a concrete checklist. Do not just summarize
+the scripts.
+
+For `4.0.7`, explain this sequence:
+
+1. Confirm the RC number. If the RM does not provide one, ask whether this is
+   `rc01` or a later candidate such as `rc02`. The tag is
+   `${VERSION}-${RC}`, for example `4.0.7-rc01`.
+2. Confirm that the tag already exists locally and on the Apache Doris GitHub
+   remote. These scripts verify the tag, but they do not create it.
+3. Tell the RM to edit `release.env` before running any script.
+4. Tell the RM to export ASF SVN credentials in the shell.
+5. Run `./01-check-env.sh` until it reports `environment looks READY`.
+6. Run `./02-package-sign-upload.sh` only after the RM has checked the target
+   dev SVN URL and is ready to publish the RC source artifacts.
+7. Run `./03-vote-mail.sh`, review the generated vote email, then send it
+   manually from the RM's `@apache.org` address.
+8. After the vote passes and the `[RESULT]` email has been sent manually, run
+   `./04-release-complete.sh` to publish the source release artifacts and draft
+   the announce email.
+
+Also make these boundaries clear:
+
+- The vote artifacts in Apache dist SVN are source-only.
+- `BIN_FILES` is optional. If set, step 02 signs convenience binary tarballs
+  locally, but the scripts do not upload those binaries.
+- The scripts never send public emails. The RM must review and send the vote,
+  result, and announce emails manually.
+- Step 04 writes to the Apache release SVN and requires PMC permission.
+
+## Quick start for a new RC
+
+Run all commands from this directory:
+
+```bash
+cd tools/release-tools
+```
+
+Before running any script, edit `release.env` for the target version and RC.
+For example, to prepare Doris `4.0.7-rc01`:
+
+```bash
+VERSION="4.0.7"
+RC="rc01"
+TAG="${VERSION}-${RC}"
+GIT_REMOTE="upstream-apache"
+
+APACHE_ID="<your-apache-id>"
+APACHE_EMAIL="<your-apache-id>@apache.org"
+SIGNER_NAME="<your display name>"
+SIGNING_KEY="<your signing key fingerprint, or leave empty if only one secret 
key exists>"
+
+RELEASE_NOTES_URL="<release notes or issue URL>"
+ANNOUNCE_RELEASE_NOTES_URL="<release notes URL, or leave empty to 
reuse/prompt>"
+```
+
+If you need to advertise convenience binaries in the vote email, set
+`BIN_FILES` to absolute paths for those prebuilt tarballs. Leave `BIN_FILES=()`
+for the source-only flow.
+
+Export ASF credentials in the same shell. The scripts use these credentials for
+SVN upload and KEYS publishing:
+
+```bash
+export ASF_USERNAME=<your-apache-id>
+export ASF_PASSWORD='<your-apache-ldap-password>'
+```
+
+Then run the release flow:
+
+```bash
+./01-check-env.sh
+./02-package-sign-upload.sh
+./03-vote-mail.sh
+```
+
+Review the generated vote email in `WORK_DIR`, then send it manually to
+`[email protected]` from your `@apache.org` address.
+
+After the vote passes:
+
+1. Tally the votes and send the `[RESULT]` email manually.
+2. Run `./04-release-complete.sh`.
+3. Review the generated announce email in `WORK_DIR`, then send it manually.

Review Comment:
   This sequence tells the RM to send the announce right after 
`04-release-complete.sh`, but that script generates the email immediately after 
the SVN commit and the body says the release is available at 
`${DOWNLOAD_PAGE_URL}`. ASF Infra guidance says to check that the release has 
appeared on `downloads.apache.org`, then wait for the download/CDN caches 
before announcing general availability. Please make the post-publish order 
explicit here: verify downloads.apache.org/Doris download-page availability, 
wait for the propagation window, update the website/download metadata as 
needed, and only then send `[ANNOUNCE]`.



##########
tools/release-tools/tests/test-check-env-required-tools.sh:
##########
@@ -0,0 +1,29 @@
+#!/usr/bin/env bash

Review Comment:
   These new shell tests have shebangs but are committed as `100644`, and I 
could not find any CI or documented release-tool test runner that invokes them 
with `bash`. As a result, `bash tools/release-tools/tests/...` passes, but 
direct `./tools/release-tools/tests/...` execution fails with `Permission 
denied`, and the added coverage can be silently skipped. Please either make the 
tests executable and add a documented/CI-invoked runner, or document/run them 
explicitly through `bash` from an existing validation path.



##########
tools/release-tools/04-release-complete.sh:
##########
@@ -0,0 +1,214 @@
+#!/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.
+
+# Step 04 - publish the passed RC source artifact to the Apache release SVN
+# and generate the [ANNOUNCE] email draft.
+#
+# The release SVN commit is public and requires PMC permission. This script
+# pauses for confirmation before changing SVN, and it never sends email.
+set -euo pipefail
+HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
+# shellcheck source=release.env
+source "${HERE}/release.env"
+
+ok()   { echo "[ OK ] $*"; }
+warn() { echo "[WARN] $*"; }
+die()  { echo "[FAIL] $*" >&2; exit 1; }
+confirm() { local a; read -r -p "$1 [y/N] " a; [[ "$a" == y || "$a" == Y ]]; }
+
+mail_only=0
+usage() {
+  cat <<EOF
+Usage: $0 [--mail-only]
+
+Publishes Apache Doris ${TAG} source artifacts from dev SVN to release SVN as
+Apache Doris ${VERSION}, then writes the [ANNOUNCE] email draft.
+
+Options:
+  --mail-only   Only write announce-email.txt and announce-email.eml.
+EOF
+}
+
+while [[ $# -gt 0 ]]; do
+  case "$1" in
+    --mail-only) mail_only=1; shift ;;
+    -h|--help) usage; exit 0 ;;
+    *) die "unknown argument: $1" ;;
+  esac
+done
+
+svn_auth=(--non-interactive --no-auth-cache)
+[[ -n "${ASF_USERNAME:-}" ]] && svn_auth+=(--username "$ASF_USERNAME")
+[[ -n "${ASF_PASSWORD:-}" ]] && svn_auth+=(--password "$ASF_PASSWORD")
+svnmucc_auth=(--non-interactive --no-auth-cache)
+[[ -n "${ASF_USERNAME:-}" ]] && svnmucc_auth+=(-u "$ASF_USERNAME")

Review Comment:
   With `ASF_USERNAME` set, this builds `svnmucc_auth` with `-u 
"$ASF_USERNAME"`, but `svnmucc` documents the username option as `--username` 
while `-U` is the root-url option and `-p` is only the password short option. 
The README tells release managers to export these credentials before running 
the flow, so the normal credentialed step 04 path can fail only at the final 
publish even though `01-check-env.sh` passed. Please use `--username 
"$ASF_USERNAME"` here and add a test case that exports both ASF credential 
variables and asserts the fake `svnmucc` receives the supported flags.



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

To unsubscribe, e-mail: [email protected]

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


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

Reply via email to