From d3ae3ab16b8ed404e4241b086dc806b9217a7044 Mon Sep 17 00:00:00 2001 From: morningman Date: Sun, 12 Jul 2026 10:48:46 +0800 Subject: [PATCH 1/8] [improvement](release) Add release completion script ### What problem does this PR solve? Issue Number: None Related PR: None Problem Summary: The release helper scripts stopped after generating the vote email. After a release vote passes, the release manager still had to manually copy source artifacts from dev SVN to release SVN, remove the RC suffix from release file names, and draft the announce email. This adds a fourth helper script that prepares the final release SVN artifacts from the voted RC, recomputes the checksum file with the final name, verifies the detached signature, removes the dev RC folder after the release commit succeeds, and writes the announce email draft. ### Release note None ### Check List (For Author) - Test: Manual test - bash -n tools/release-tools/01-check-env.sh tools/release-tools/02-package-sign-upload.sh tools/release-tools/03-vote-mail.sh tools/release-tools/04-release-complete.sh - git diff --check -- tools/release-tools/README.md tools/release-tools/release.env tools/release-tools/04-release-complete.sh - tools/release-tools/04-release-complete.sh --help - printf 'https://github.com/apache/doris/releases\n' | tools/release-tools/04-release-complete.sh --mail-only - Behavior changed: No - Does this need documentation: Yes, included in tools/release-tools/README.md --- tools/release-tools/04-release-complete.sh | 190 +++++++++++++++++++++ tools/release-tools/README.md | 34 +++- tools/release-tools/release.env | 13 +- 3 files changed, 225 insertions(+), 12 deletions(-) create mode 100755 tools/release-tools/04-release-complete.sh diff --git a/tools/release-tools/04-release-complete.sh b/tools/release-tools/04-release-complete.sh new file mode 100755 index 00000000000000..8743e731deca58 --- /dev/null +++ b/tools/release-tools/04-release-complete.sh @@ -0,0 +1,190 @@ +#!/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 </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 < "$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 + + require_tool svn + require_tool svnmucc + + 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 + + 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 "mv ${src_sha512}" + 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."; exit 0; } + + svnmucc "${svnmucc_auth[@]}" -m "Release Doris ${VERSION}" \ + mkdir "$RELEASE_SVN_DIR" \ + mv "$src_tar" "${RELEASE_SVN_DIR}/${dst_tar}" \ + mv "$src_asc" "${RELEASE_SVN_DIR}/${dst_asc}" \ + mv "$src_sha512" "${RELEASE_SVN_DIR}/${dst_sha512}" \ + rm "$DEV_SVN_DIR" + ok "committed release artifacts: ${RELEASE_SVN_DIR}/" + ok "removed dev RC folder: ${DEV_SVN_DIR}/" +} + +if [[ "$mail_only" -eq 0 ]]; then + publish_to_release_svn +else + ok "mail-only mode: skipping SVN publish" +fi + +write_announce_email diff --git a/tools/release-tools/README.md b/tools/release-tools/README.md index 20e34504d96ad5..f74f21babf1150 100644 --- a/tools/release-tools/README.md +++ b/tools/release-tools/README.md @@ -19,15 +19,16 @@ 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. +Helper scripts for an Apache Doris Release Manager (RM) to cut and complete a **source** release: +package and sign the source tarball, upload it to the Apache dev SVN, draft the `[VOTE]` email, +publish the passed RC to the Apache release SVN, and draft the `[ANNOUNCE]` email. ## Prerequisites Have these ready before you run anything: - The release **tag is already created and pushed** to `apache/doris` — these scripts only verify it (branch prep, patch merges and tag creation are out of scope). - A local clone of `apache/doris` with that tag fetched. -- These tools on `PATH`: `git`, `gpg`, `svn`, `sha512sum`, `curl`, `gzip`. +- These tools on `PATH`: `git`, `gpg`, `svn`, `svnmucc`, `sha512sum`, `curl`, `gzip`. - A GPG signing key — or let step 01 import an existing one, or generate and publish a new one. - ASF credentials exported in your shell (used for the SVN upload and the KEYS publish): ```bash @@ -45,6 +46,10 @@ Run from this directory, in order: the final confirm. 3. **Draft the vote email** — `./03-vote-mail.sh`. Prompts for the Release Notes URL and prints the draft; review it and send it yourself from your `@apache.org` address. +4. **Complete the release** — after the vote result has passed, `./04-release-complete.sh` copies the + source artifacts from dev SVN to release SVN with the `rc` suffix removed from file names, removes + the RC folder from dev SVN, and drafts the `[ANNOUNCE]` email. This step requires PMC permission + for the release SVN commit. --- @@ -56,6 +61,8 @@ Everything below is reference detail. - `02-package-sign-upload.sh` — `git archive` the tag, GPG-sign, sha512, sign any prebuilt binaries locally, then upload the source artifacts to the dev SVN. - `03-vote-mail.sh` — generate the `[VOTE]` email draft. +- `04-release-complete.sh` — publish the passed RC source artifacts to the release SVN and generate + the `[ANNOUNCE]` email draft. ## Configuration The scripts are reusable across releases — they hold no version; edit `release.env` each time. @@ -72,10 +79,13 @@ Set at least: `REPO_DIR` defaults to the enclosing checkout (`${ROOT}/../../`) since these scripts live inside `apache/doris`; override it only if you run them against a different clone. -The SVN URLs, dev mailing list and verify-guide link rarely change; the defaults target the official -Doris dist repos. The **vote SVN artifacts are source-only**: `apache-doris--src.tar.gz` + `.asc` -+ `.sha512`. All script output (source tarball, signatures, SVN checkouts, email draft) goes to -`WORK_DIR` (`/`, i.e. `tools/release-tools/`, by default). +The SVN URLs, dev mailing list, download page and verify-guide link rarely change; the defaults +target the official Doris dist repos. The **vote SVN artifacts are source-only**: +`apache-doris--src.tar.gz` + `.asc` + `.sha512`. The **release SVN artifacts** are published +under `release/doris///` and drop the RC suffix from the file names: +`apache-doris--src.tar.gz` + `.asc` + `.sha512`. All script output (source tarball, +signatures, SVN checkouts, email drafts) goes to `WORK_DIR` (`/`, i.e. +`tools/release-tools/`, by default). ## What each step does - **01** verifies the required tools, your `GPG_TTY` / `gpg.conf`, resolves (or helps you create) a @@ -90,10 +100,16 @@ Doris dist repos. The **vote SVN artifacts are source-only**: `apache-doris-//`, move the tarball, detached signature, and checksum there + with RC-free file names, and remove `dev/doris//` in one SVN revision. It then writes + `announce-email.txt` and `announce-email.eml`; use `./04-release-complete.sh --mail-only` to + regenerate the email without touching SVN. ## Not automated (on purpose) - Sending the vote email — it goes to a public ASF list, so you review and send it manually. - Uploading binary packages — step 02 can *sign* the tarballs listed in `BIN_FILES`, but binaries are not part of the ASF source vote, so you upload them (with their `.asc`/`.sha512`) manually. -- Post-vote steps — tallying the result, the result email, and moving the artifacts from `dev/` to - `release/` once the vote passes. +- Tallying the vote result and sending the `[RESULT]` email before step 04. +- Publishing Maven staging repositories, updating the website / GitHub release notes, and cleaning + up old release versions beyond the current RC folder. diff --git a/tools/release-tools/release.env b/tools/release-tools/release.env index 024296f9b8fcf5..f6f4c3d3e79e39 100644 --- a/tools/release-tools/release.env +++ b/tools/release-tools/release.env @@ -16,7 +16,7 @@ # under the License. # Shared config for the Apache Doris release helper scripts. -# Edit values here; 01/02/03 all `source` this file. +# Edit values here; 01/02/03/04 all `source` this file. # # This release: 4.0.6-rc02 (tag already created & pushed to apache/doris) @@ -30,10 +30,11 @@ TAG="${VERSION}-${RC}" # 4.0.6-rc02 GIT_REMOTE="upstream-apache" # remote pointing at github.com/apache/doris # --- Artifact naming --- -# Matches the live convention in release/doris/4.0/4.0.5/ : -# the rc IS kept in the file name; only the release *folder* drops it. +# Vote artifacts keep the RC in the file name. Step 04 publishes the final +# release artifacts with the RC removed from the file name. PKG_BASE="apache-doris-${TAG}-src" # -> apache-doris-4.0.6-rc02-src.tar.gz ARCHIVE_PREFIX="${PKG_BASE}/" # top-level dir inside the tarball +RELEASE_PKG_BASE="apache-doris-${VERSION}-src" # --- Work area (OUTSIDE the git repo: artifacts + svn checkouts live here) --- WORK_DIR="${ROOT}/${TAG}" @@ -67,6 +68,8 @@ SIGNING_KEY="" # use `gpg --list-keys` to get DEV_SVN_BASE="https://dist.apache.org/repos/dist/dev/doris" DEV_SVN_DIR="${DEV_SVN_BASE}/${TAG}" # <-- vote folder. VERIFY this URL before committing. RELEASE_SVN_BASE="https://dist.apache.org/repos/dist/release/doris" +RELEASE_SERIES="${VERSION%.*}" # e.g. 4.0.7 -> 4.0 +RELEASE_SVN_DIR="${RELEASE_SVN_BASE}/${RELEASE_SERIES}/${VERSION}" # final release folder, no RC suffix KEYS_URL="https://downloads.apache.org/doris/KEYS" # --- ASF credentials: export in your shell before running (NOT stored here) --- @@ -77,3 +80,7 @@ KEYS_URL="https://downloads.apache.org/doris/KEYS" DEV_LIST="dev@doris.apache.org" RELEASE_NOTES_URL="" # leave empty -> step 03 will prompt you for the issue link VERIFY_GUIDE_URL="https://doris.apache.org/community/release-and-verify/release-verify" + +# --- Announce email --- +DOWNLOAD_PAGE_URL="https://doris.apache.org/download/" +ANNOUNCE_RELEASE_NOTES_URL="" # leave empty -> step 04 will reuse RELEASE_NOTES_URL or prompt From 2d071d13598b8a8535412a9511e70fec09577b68 Mon Sep 17 00:00:00 2001 From: morningman Date: Sun, 12 Jul 2026 11:55:13 +0800 Subject: [PATCH 2/8] [doc](release) Clarify release tools runbook ### What problem does this PR solve? Issue Number: None Related PR: None Problem Summary: The release tools README described the helper scripts, but it did not give an AI agent enough structure to turn a request such as starting the Doris 4.0.7 release into a concrete release-manager checklist. This change rewrites the README around the release workflow, explains how to map a version and RC to the tag and release.env fields, and calls out manual boundaries around SVN publishing, source-only vote artifacts, convenience binaries, and public emails. ### Release note None ### Check List (For Author) - Test: No need to test (documentation-only change); ran git diff --check for the README. - Behavior changed: No - Does this need documentation: No --- tools/release-tools/README.md | 332 ++++++++++++++++++++++++---------- 1 file changed, 241 insertions(+), 91 deletions(-) diff --git a/tools/release-tools/README.md b/tools/release-tools/README.md index f74f21babf1150..5267c2f2841f3e 100644 --- a/tools/release-tools/README.md +++ b/tools/release-tools/README.md @@ -19,97 +19,247 @@ under the License. # Doris release helper scripts -Helper scripts for an Apache Doris Release Manager (RM) to cut and complete a **source** release: -package and sign the source tarball, upload it to the Apache dev SVN, draft the `[VOTE]` email, -publish the passed RC to the Apache release SVN, and draft the `[ANNOUNCE]` 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="" +APACHE_EMAIL="@apache.org" +SIGNER_NAME="" +SIGNING_KEY="" + +RELEASE_NOTES_URL="" +ANNOUNCE_RELEASE_NOTES_URL="" +``` + +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= +export ASF_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 +`dev@doris.apache.org` 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. + +Use this command only when the release SVN step has already been done and you +only need to regenerate the announce email: + +```bash +./04-release-complete.sh --mail-only +``` ## Prerequisites + Have these ready before you run anything: -- The release **tag is already created and pushed** to `apache/doris` — these scripts only verify it - (branch prep, patch merges and tag creation are out of scope). -- A local clone of `apache/doris` with that tag fetched. -- These tools on `PATH`: `git`, `gpg`, `svn`, `svnmucc`, `sha512sum`, `curl`, `gzip`. -- A GPG signing key — or let step 01 import an existing one, or generate and publish a new one. -- ASF credentials exported in your shell (used for the SVN upload and the KEYS publish): - ```bash - export ASF_USERNAME= - export ASF_PASSWORD='' - ``` -- `release.env` filled in for this release — see [Configuration](#configuration) for the fields. - -## Steps -Run from this directory, in order: -1. **Check the signing environment** — `./01-check-env.sh`. Re-run until it ends with - `environment looks READY`. -2. **Package, sign & upload** — `./02-package-sign-upload.sh`. Builds and signs the source tarball - and uploads it to the dev SVN. It pauses twice for confirmation; nothing public happens before - the final confirm. -3. **Draft the vote email** — `./03-vote-mail.sh`. Prompts for the Release Notes URL and prints the - draft; review it and send it yourself from your `@apache.org` address. -4. **Complete the release** — after the vote result has passed, `./04-release-complete.sh` copies the - source artifacts from dev SVN to release SVN with the `rc` suffix removed from file names, removes - the RC folder from dev SVN, and drafts the `[ANNOUNCE]` email. This step requires PMC permission - for the release SVN commit. - ---- - -Everything below is reference detail. - -## Files -- `release.env` — all configuration (version, paths, signing key, SVN URLs, email). **Edit this first.** -- `01-check-env.sh` — check / prepare the GPG signing environment and ASF credentials. -- `02-package-sign-upload.sh` — `git archive` the tag, GPG-sign, sha512, sign any prebuilt binaries - locally, then upload the source artifacts to the dev SVN. -- `03-vote-mail.sh` — generate the `[VOTE]` email draft. -- `04-release-complete.sh` — publish the passed RC source artifacts to the release SVN and generate - the `[ANNOUNCE]` email draft. - -## Configuration -The scripts are reusable across releases — they hold no version; edit `release.env` each time. -Set at least: -- `VERSION` / `RC` — e.g. `4.0.6` and `rc02`; `TAG` is derived as `${VERSION}-${RC}`. -- `GIT_REMOTE` — the git remote pointing at `github.com/apache/doris`. -- `APACHE_ID` / `APACHE_EMAIL` / `SIGNER_NAME` — your committer id, `@apache.org` email, and the - display name used to sign the vote email. -- `SIGNING_KEY` — fingerprint of the key to sign with (leave empty to auto-detect a single local secret key). -- `BIN_FILES` — optional absolute paths to prebuilt binary tarballs to sign locally (see below). Leave - the list empty (the default) to skip binary signing and run the source-only flow. When set, step 03 - advertises each binary in the vote email under `BIN_DOWNLOAD_BASE`; when empty that section is omitted. - -`REPO_DIR` defaults to the enclosing checkout (`${ROOT}/../../`) since these scripts live inside -`apache/doris`; override it only if you run them against a different clone. - -The SVN URLs, dev mailing list, download page and verify-guide link rarely change; the defaults -target the official Doris dist repos. The **vote SVN artifacts are source-only**: -`apache-doris--src.tar.gz` + `.asc` + `.sha512`. The **release SVN artifacts** are published -under `release/doris///` and drop the RC suffix from the file names: -`apache-doris--src.tar.gz` + `.asc` + `.sha512`. All script output (source tarball, -signatures, SVN checkouts, email drafts) goes to `WORK_DIR` (`/`, i.e. -`tools/release-tools/`, by default). - -## What each step does -- **01** verifies the required tools, your `GPG_TTY` / `gpg.conf`, resolves (or helps you create) a - signing key, checks it is present in the live published `KEYS`, runs a test sign + verify, and - confirms your ASF credentials. It is read-mostly: every state-changing action (edit `gpg.conf`, - import / generate a key, publish `KEYS`) prompts before acting. -- **02** checks the local tag matches `GIT_REMOTE`, builds the source tarball from the tag with - `git archive`, signs it and writes the `.sha512`. If `BIN_FILES` is non-empty it then GPG-signs and - sha512s each prebuilt binary tarball, writing the `.asc` / `.sha512` sidecars **next to** each binary - (these are NOT uploaded — you upload the binaries and their sidecars yourself). Finally it uploads - the three **source** files to `dev/doris//` on the Apache dist SVN. **Eyeball the target URL** - at the confirm prompt before committing — nothing public happens until the final confirm. -- **03** writes `vote-email.txt` and `vote-email.eml` into `WORK_DIR` and prints the draft. Review it - and send it yourself from your `@apache.org` address. -- **04** checks the passed RC artifacts in dev SVN, then uses `svnmucc` URL operations to create - `release/doris///`, move the tarball, detached signature, and checksum there - with RC-free file names, and remove `dev/doris//` in one SVN revision. It then writes - `announce-email.txt` and `announce-email.eml`; use `./04-release-complete.sh --mail-only` to - regenerate the email without touching SVN. - -## Not automated (on purpose) -- Sending the vote email — it goes to a public ASF list, so you review and send it manually. -- Uploading binary packages — step 02 can *sign* the tarballs listed in `BIN_FILES`, but binaries are - not part of the ASF source vote, so you upload them (with their `.asc`/`.sha512`) manually. -- Tallying the vote result and sending the `[RESULT]` email before step 04. -- Publishing Maven staging repositories, updating the website / GitHub release notes, and cleaning - up old release versions beyond the current RC folder. + +- The release tag has already been created and pushed to `apache/doris`. + Branch preparation, patch merges, validation, and tag creation are out of + scope for these scripts. +- The local Doris checkout has fetched that tag. +- `release.env` is filled in for this exact release. +- These tools are on `PATH`: `git`, `gpg`, `svn`, `svnmucc`, `sha512sum`, + `curl`, and `gzip`. +- A GPG signing key is available locally, or the RM is ready to let + `01-check-env.sh` import an existing key or generate and publish a new key. +- ASF credentials are exported as `ASF_USERNAME` and `ASF_PASSWORD`. +- The RM can write to the required Apache SVN locations. Step 04 requires PMC + permission for the release SVN commit. + +## Configuration reference + +All scripts source `release.env`. Edit it once per RC. + +Set these fields first: + +- `VERSION`: Final release version, for example `4.0.7`. +- `RC`: Candidate number, for example `rc01` or `rc02`. +- `TAG`: Derived as `${VERSION}-${RC}`. Do not set it to the final version + without the RC suffix. +- `GIT_REMOTE`: Git remote that points at `github.com/apache/doris`. +- `APACHE_ID`: Apache committer id. +- `APACHE_EMAIL`: Apache email address. +- `SIGNER_NAME`: Display name used in generated emails. +- `SIGNING_KEY`: Fingerprint passed to `gpg -u`. Leave it empty only when this + machine has exactly one usable local secret key. +- `RELEASE_NOTES_URL`: Link used in the vote email. If empty, step 03 prompts. +- `ANNOUNCE_RELEASE_NOTES_URL`: Link used in the announce email. If empty, step + 04 reuses `RELEASE_NOTES_URL` or prompts. +- `BIN_FILES`: Optional absolute paths to prebuilt convenience binary tarballs. + +The default `REPO_DIR` is the enclosing Doris checkout because these scripts +live under `tools/release-tools`. Override it only when you deliberately run the +scripts against another clone. + +The default SVN URLs target the official Doris dist repositories: + +- Dev RC source artifacts: + `https://dist.apache.org/repos/dist/dev/doris/-/` +- Final source release artifacts: + `https://dist.apache.org/repos/dist/release/doris///` + +Step 02 uploads source artifacts with the RC suffix: + +- `apache-doris---src.tar.gz` +- `apache-doris---src.tar.gz.asc` +- `apache-doris---src.tar.gz.sha512` + +Step 04 publishes final source artifacts without the RC suffix: + +- `apache-doris--src.tar.gz` +- `apache-doris--src.tar.gz.asc` +- `apache-doris--src.tar.gz.sha512` + +All generated files go to `WORK_DIR`, which defaults to +`tools/release-tools/-`. + +## Script details + +### 01-check-env.sh + +Use this script to prepare and verify the signing environment. It checks +required tools, `GPG_TTY`, GPG SHA512 digest preferences, the signing key, live +published `KEYS`, test signing, and ASF credentials. + +This script is mostly read-only. It prompts before every state-changing action, +including editing `gpg.conf`, importing or generating a key, and publishing the +key to the Doris KEYS files. + +Expected success line: + +```text +environment looks READY for - +``` + +### 02-package-sign-upload.sh + +Use this script to build, sign, checksum, and upload the RC source artifacts. + +It verifies that the local tag exists, the tag exists on `GIT_REMOTE`, and both +tags point to the same commit. It then creates the source tarball with +`git archive`, writes `.asc` and `.sha512` sidecars, verifies both, and uploads +the three source files to the Apache dev SVN. + +If `BIN_FILES` is non-empty, this script also signs and checksums those binary +tarballs in place. It does not upload binaries. + +This script pauses twice before touching the public dev SVN. Check the printed +target URL before confirming. + +### 03-vote-mail.sh + +Use this script to generate the `[VOTE]` email draft. It writes: + +- `vote-email.txt` +- `vote-email.eml` + +Review the draft and send it manually from the RM's `@apache.org` address to +`dev@doris.apache.org`. + +### 04-release-complete.sh + +Use this script only after the vote has passed and the `[RESULT]` email has +been sent manually. + +It checks the passed RC source artifacts in the dev SVN, then uses `svnmucc` to +create the final release SVN directory, move the source tarball, detached +signature, and checksum there with RC-free file names, and remove the dev RC +folder in one SVN revision. + +It then writes: + +- `announce-email.txt` +- `announce-email.eml` + +Review the announce draft and send it manually. + +Use `./04-release-complete.sh --mail-only` to regenerate the announce email +without touching SVN. + +## Manual work not automated + +The RM must still do these tasks manually: + +- Prepare the release branch and tag. +- Validate the release before starting the RC upload flow. +- Send the `[VOTE]` email. +- Upload convenience binaries, if the release includes them. +- Tally the vote and send the `[RESULT]` email. +- Send the `[ANNOUNCE]` email. +- Publish Maven staging repositories, update the website and GitHub release + notes, and clean up old release versions when applicable. From 06c223c725b5b812f6218ffca089cd5727d8e45b Mon Sep 17 00:00:00 2001 From: morningman Date: Sun, 12 Jul 2026 13:03:53 +0800 Subject: [PATCH 3/8] [fix](release) Fix final source checksum publishing ### What problem does this PR solve? Issue Number: None Related PR: None Problem Summary: The release completion script moved the RC source checksum sidecar to the final release filename without updating the filename stored inside the sidecar. As a result, running sha512sum --check against the final release checksum looked for the removed RC tarball name and failed. This change regenerates the final checksum from the dev SVN source tarball using the RC-free release filename, verifies it locally, and uploads that regenerated sidecar in the atomic svnmucc release transaction. The release-tools README now documents that behavior, and a shell regression test covers the checksum publishing flow with fake SVN commands. ### Release note None ### Check List (For Author) - Test: Manual test - bash -n tools/release-tools/01-check-env.sh tools/release-tools/02-package-sign-upload.sh tools/release-tools/03-vote-mail.sh tools/release-tools/04-release-complete.sh tools/release-tools/tests/test-release-complete-checksum.sh - bash tools/release-tools/tests/test-release-complete-checksum.sh - Behavior changed: No - Does this need documentation: No --- tools/release-tools/04-release-complete.sh | 27 ++++- tools/release-tools/README.md | 9 +- .../tests/test-release-complete-checksum.sh | 110 ++++++++++++++++++ 3 files changed, 136 insertions(+), 10 deletions(-) create mode 100644 tools/release-tools/tests/test-release-complete-checksum.sh diff --git a/tools/release-tools/04-release-complete.sh b/tools/release-tools/04-release-complete.sh index 8743e731deca58..70b71f7db55f4a 100755 --- a/tools/release-tools/04-release-complete.sh +++ b/tools/release-tools/04-release-complete.sh @@ -124,10 +124,11 @@ EOF } publish_to_release_svn() { - local src_tar src_asc src_sha512 dst_tar dst_asc dst_sha512 + local src_tar src_asc src_sha512 dst_tar dst_asc dst_sha512 checksum_dir final_sha512_file require_tool svn require_tool svnmucc + require_tool sha512sum src_tar="${DEV_SVN_DIR}/${PKG_BASE}.tar.gz" src_asc="${src_tar}.asc" @@ -158,25 +159,39 @@ publish_to_release_svn() { die "release SVN folder already exists: $RELEASE_SVN_DIR (use --mail-only to regenerate the email)" fi + checksum_dir="$(mktemp -d)" + final_sha512_file="${checksum_dir}/${dst_sha512}" + svn cat "${svn_auth[@]}" "$src_tar" > "${checksum_dir}/${dst_tar}" + ( + cd "$checksum_dir" + sha512sum "$dst_tar" > "$dst_sha512" + sha512sum --check "$dst_sha512" + ) + 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 "mv ${src_sha512}" + 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."; exit 0; } + confirm "FINAL confirm - publish release SVN and remove dev RC now?" || { warn "stopping before SVN commit."; rm -rf "$checksum_dir"; exit 0; } - svnmucc "${svnmucc_auth[@]}" -m "Release Doris ${VERSION}" \ + if ! svnmucc "${svnmucc_auth[@]}" -m "Release Doris ${VERSION}" \ mkdir "$RELEASE_SVN_DIR" \ mv "$src_tar" "${RELEASE_SVN_DIR}/${dst_tar}" \ mv "$src_asc" "${RELEASE_SVN_DIR}/${dst_asc}" \ - mv "$src_sha512" "${RELEASE_SVN_DIR}/${dst_sha512}" \ - rm "$DEV_SVN_DIR" + put "$final_sha512_file" "${RELEASE_SVN_DIR}/${dst_sha512}" \ + rm "$DEV_SVN_DIR"; then + rm -rf "$checksum_dir" + die "svnmucc release publish failed" + fi + rm -rf "$checksum_dir" ok "committed release artifacts: ${RELEASE_SVN_DIR}/" ok "removed dev RC folder: ${DEV_SVN_DIR}/" } diff --git a/tools/release-tools/README.md b/tools/release-tools/README.md index 5267c2f2841f3e..8eaa4f556f0d0f 100644 --- a/tools/release-tools/README.md +++ b/tools/release-tools/README.md @@ -236,10 +236,11 @@ Review the draft and send it manually from the RM's `@apache.org` address to Use this script only after the vote has passed and the `[RESULT]` email has been sent manually. -It checks the passed RC source artifacts in the dev SVN, then uses `svnmucc` to -create the final release SVN directory, move the source tarball, detached -signature, and checksum there with RC-free file names, and remove the dev RC -folder in one SVN revision. +It checks the passed RC source artifacts in the dev SVN, regenerates and +verifies the final checksum sidecar with the RC-free source tarball name, then +uses `svnmucc` to create the final release SVN directory, move the source +tarball and detached signature there, upload the final checksum, and remove the +dev RC folder in one SVN revision. It then writes: diff --git a/tools/release-tools/tests/test-release-complete-checksum.sh b/tools/release-tools/tests/test-release-complete-checksum.sh new file mode 100644 index 00000000000000..c025e8c9f07768 --- /dev/null +++ b/tools/release-tools/tests/test-release-complete-checksum.sh @@ -0,0 +1,110 @@ +#!/usr/bin/env bash +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +set -euo pipefail + +ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +tmp="$(mktemp -d)" +trap 'rm -rf "$tmp"' EXIT + +cp "${ROOT}/04-release-complete.sh" "$tmp/" +cat > "$tmp/release.env" <<'EOF' +ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" &>/dev/null && pwd)" +VERSION="9.9.9" +RC="rc01" +TAG="${VERSION}-${RC}" +PKG_BASE="apache-doris-${TAG}-src" +RELEASE_PKG_BASE="apache-doris-${VERSION}-src" +WORK_DIR="${ROOT}/${TAG}" +DEV_SVN_BASE="https://dist.example.test/dev/doris" +DEV_SVN_DIR="${DEV_SVN_BASE}/${TAG}" +RELEASE_SVN_BASE="https://dist.example.test/release/doris" +RELEASE_SERIES="${VERSION%.*}" +RELEASE_SVN_DIR="${RELEASE_SVN_BASE}/${RELEASE_SERIES}/${VERSION}" +DOWNLOAD_PAGE_URL="https://doris.example.test/download/" +ANNOUNCE_RELEASE_NOTES_URL="https://doris.example.test/release-notes" +RELEASE_NOTES_URL="" +DEV_LIST="dev@example.test" +SIGNER_NAME="Release Manager" +EOF + +cat > "$tmp/svn" <<'EOF' +#!/usr/bin/env bash +set -euo pipefail +cmd="$1" +shift +case "$cmd" in + info) + url="${@: -1}" + [[ "$url" != "https://dist.example.test/release/doris/9.9/9.9.9" ]] + ;; + cat) + url="${@: -1}" + case "$url" in + *.tar.gz) + printf 'release artifact bytes\n' + ;; + *.sha512) + digest="$(printf 'release artifact bytes\n' | sha512sum | awk '{print $1}')" + printf '%s apache-doris-9.9.9-rc01-src.tar.gz\n' "$digest" + ;; + *) + echo "unexpected svn cat url: $url" >&2 + exit 1 + ;; + esac + ;; + *) + echo "unexpected svn command: $cmd" >&2 + exit 1 + ;; +esac +EOF +chmod +x "$tmp/svn" + +cat > "$tmp/svnmucc" <<'EOF' +#!/usr/bin/env bash +set -euo pipefail +printf '%s\n' "$*" > "$FAKE_SVNMUCC_LOG" +while (($#)); do + if [[ "$1" == "put" ]]; then + checksum_file="$2" + cp "$checksum_file" "$FAKE_FINAL_SHA512" + fi + shift +done +EOF +chmod +x "$tmp/svnmucc" + +export PATH="$tmp:$PATH" +export FAKE_SVNMUCC_LOG="$tmp/svnmucc.log" +export FAKE_FINAL_SHA512="$tmp/final.sha512" + +printf 'y\n' | bash "$tmp/04-release-complete.sh" >/dev/null + +if grep -q 'mv https://dist.example.test/dev/doris/9.9.9-rc01/apache-doris-9.9.9-rc01-src.tar.gz.sha512' "$FAKE_SVNMUCC_LOG"; then + echo "release completion must not move the RC checksum sidecar unchanged" >&2 + exit 1 +fi + +grep -q 'put ' "$FAKE_SVNMUCC_LOG" +grep -q 'apache-doris-9.9.9-src.tar.gz$' "$FAKE_FINAL_SHA512" +if grep -q 'apache-doris-9.9.9-rc01-src.tar.gz' "$FAKE_FINAL_SHA512"; then + echo "final checksum sidecar still references the RC tarball name" >&2 + exit 1 +fi From 3874c7701b9f46e0496f35162f13cb6696df0cfc Mon Sep 17 00:00:00 2001 From: morningman Date: Sun, 12 Jul 2026 13:53:03 +0800 Subject: [PATCH 4/8] [fix](release) Check svnmucc in release environment ### What problem does this PR solve? Issue Number: None Related PR: None Problem Summary: Step 04 of the release helper workflow requires svnmucc to publish final release artifacts, but 01-check-env.sh did not verify that svnmucc was available. A release manager could complete the preflight check and RC vote flow, then only discover the missing tool after the vote passed. This change adds svnmucc to the required tool check and adds a shell regression test for the required-tool list. ### Release note None ### Check List (For Author) - Test: Manual test - bash -n tools/release-tools/01-check-env.sh tools/release-tools/02-package-sign-upload.sh tools/release-tools/03-vote-mail.sh tools/release-tools/04-release-complete.sh tools/release-tools/tests/test-release-complete-checksum.sh tools/release-tools/tests/test-check-env-required-tools.sh - bash tools/release-tools/tests/test-check-env-required-tools.sh - bash tools/release-tools/tests/test-release-complete-checksum.sh - Behavior changed: No - Does this need documentation: No --- tools/release-tools/01-check-env.sh | 2 +- .../tests/test-check-env-required-tools.sh | 29 +++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 tools/release-tools/tests/test-check-env-required-tools.sh diff --git a/tools/release-tools/01-check-env.sh b/tools/release-tools/01-check-env.sh index c6e47048e916f2..431b7cfd10c8de 100755 --- a/tools/release-tools/01-check-env.sh +++ b/tools/release-tools/01-check-env.sh @@ -46,7 +46,7 @@ problems=0 echo "== Apache Doris ${TAG} - signing environment check ==" # 1. required tools -for t in git gpg svn sha512sum curl gzip; do +for t in git gpg svn svnmucc sha512sum curl gzip; do if command -v "$t" >/dev/null 2>&1; then ok "tool: $t"; else err "missing tool: $t"; problems=$((problems+1)); fi done diff --git a/tools/release-tools/tests/test-check-env-required-tools.sh b/tools/release-tools/tests/test-check-env-required-tools.sh new file mode 100644 index 00000000000000..cde2a1ee455bcf --- /dev/null +++ b/tools/release-tools/tests/test-check-env-required-tools.sh @@ -0,0 +1,29 @@ +#!/usr/bin/env bash +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +set -euo pipefail + +ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +required_tool_loop="$(awk '/^for t in /,/; do/' "${ROOT}/01-check-env.sh")" + +for tool in git gpg svn svnmucc sha512sum curl gzip; do + if ! grep -qw "$tool" <<<"$required_tool_loop"; then + echo "01-check-env.sh does not require tool: $tool" >&2 + exit 1 + fi +done From b0145e42eb13bf7821c1fb12b4aa16ea80db3e75 Mon Sep 17 00:00:00 2001 From: morningman Date: Sun, 12 Jul 2026 20:19:32 +0800 Subject: [PATCH 5/8] [fix](release) Verify voted RC before release publish ### What problem does this PR solve? Issue Number: None Related PR: None Problem Summary: Step 04 regenerated the final checksum from the dev SVN source tarball without first verifying that the tarball still matched the checksum and signature sidecars approved during the RC vote. If the dev SVN tarball changed after the vote while the sidecars remained unchanged, the script could publish changed bytes with a matching final checksum. This change downloads the RC tarball, checksum, and signature sidecars, verifies the tarball with sha512sum and gpg before generating the RC-free checksum, and extends the release-tool regression test to cover that verification flow. ### Release note None ### Check List (For Author) - Test: Manual test - bash -n tools/release-tools/01-check-env.sh tools/release-tools/02-package-sign-upload.sh tools/release-tools/03-vote-mail.sh tools/release-tools/04-release-complete.sh tools/release-tools/tests/test-release-complete-checksum.sh tools/release-tools/tests/test-check-env-required-tools.sh - bash tools/release-tools/tests/test-check-env-required-tools.sh - bash tools/release-tools/tests/test-release-complete-checksum.sh - Behavior changed: No - Does this need documentation: No --- tools/release-tools/04-release-complete.sh | 12 ++++++++-- tools/release-tools/README.md | 11 +++++----- .../tests/test-release-complete-checksum.sh | 22 +++++++++++++++++++ 3 files changed, 38 insertions(+), 7 deletions(-) diff --git a/tools/release-tools/04-release-complete.sh b/tools/release-tools/04-release-complete.sh index 70b71f7db55f4a..53a8b2536391e8 100755 --- a/tools/release-tools/04-release-complete.sh +++ b/tools/release-tools/04-release-complete.sh @@ -124,10 +124,11 @@ EOF } publish_to_release_svn() { - local src_tar src_asc src_sha512 dst_tar dst_asc dst_sha512 checksum_dir final_sha512_file + 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" @@ -160,13 +161,20 @@ publish_to_release_svn() { 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}/${dst_tar}" + 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 ---" diff --git a/tools/release-tools/README.md b/tools/release-tools/README.md index 8eaa4f556f0d0f..06f90ba1c254fb 100644 --- a/tools/release-tools/README.md +++ b/tools/release-tools/README.md @@ -236,11 +236,12 @@ Review the draft and send it manually from the RM's `@apache.org` address to Use this script only after the vote has passed and the `[RESULT]` email has been sent manually. -It checks the passed RC source artifacts in the dev SVN, regenerates and -verifies the final checksum sidecar with the RC-free source tarball name, then -uses `svnmucc` to create the final release SVN directory, move the source -tarball and detached signature there, upload the final checksum, and remove the -dev RC folder in one SVN revision. +It checks the passed RC source artifacts in the dev SVN, verifies the source +tarball against the RC checksum and detached signature that voters approved, +regenerates and verifies the final checksum sidecar with the RC-free source +tarball name, then uses `svnmucc` to create the final release SVN directory, +move the source tarball and detached signature there, upload the final checksum, +and remove the dev RC folder in one SVN revision. It then writes: diff --git a/tools/release-tools/tests/test-release-complete-checksum.sh b/tools/release-tools/tests/test-release-complete-checksum.sh index c025e8c9f07768..d88583bacaf2c7 100644 --- a/tools/release-tools/tests/test-release-complete-checksum.sh +++ b/tools/release-tools/tests/test-release-complete-checksum.sh @@ -55,6 +55,7 @@ case "$cmd" in ;; cat) url="${@: -1}" + printf '%s\n' "$url" >> "$FAKE_SVN_CAT_LOG" case "$url" in *.tar.gz) printf 'release artifact bytes\n' @@ -63,6 +64,9 @@ case "$cmd" in digest="$(printf 'release artifact bytes\n' | sha512sum | awk '{print $1}')" printf '%s apache-doris-9.9.9-rc01-src.tar.gz\n' "$digest" ;; + *.asc) + printf 'fake detached signature\n' + ;; *) echo "unexpected svn cat url: $url" >&2 exit 1 @@ -77,6 +81,18 @@ esac EOF chmod +x "$tmp/svn" +cat > "$tmp/gpg" <<'EOF' +#!/usr/bin/env bash +set -euo pipefail +printf '%s\n' "$*" > "$FAKE_GPG_LOG" +[[ "$1" == "--verify" ]] +[[ "$2" == "apache-doris-9.9.9-rc01-src.tar.gz.asc" ]] +[[ "$3" == "apache-doris-9.9.9-rc01-src.tar.gz" ]] +[[ -f "$2" ]] +[[ -f "$3" ]] +EOF +chmod +x "$tmp/gpg" + cat > "$tmp/svnmucc" <<'EOF' #!/usr/bin/env bash set -euo pipefail @@ -92,6 +108,8 @@ EOF chmod +x "$tmp/svnmucc" export PATH="$tmp:$PATH" +export FAKE_SVN_CAT_LOG="$tmp/svn-cat.log" +export FAKE_GPG_LOG="$tmp/gpg.log" export FAKE_SVNMUCC_LOG="$tmp/svnmucc.log" export FAKE_FINAL_SHA512="$tmp/final.sha512" @@ -102,6 +120,10 @@ if grep -q 'mv https://dist.example.test/dev/doris/9.9.9-rc01/apache-doris-9.9.9 exit 1 fi +grep -q 'apache-doris-9.9.9-rc01-src.tar.gz$' "$FAKE_SVN_CAT_LOG" +grep -q 'apache-doris-9.9.9-rc01-src.tar.gz.sha512$' "$FAKE_SVN_CAT_LOG" +grep -q 'apache-doris-9.9.9-rc01-src.tar.gz.asc$' "$FAKE_SVN_CAT_LOG" +grep -q -- '--verify apache-doris-9.9.9-rc01-src.tar.gz.asc apache-doris-9.9.9-rc01-src.tar.gz' "$FAKE_GPG_LOG" grep -q 'put ' "$FAKE_SVNMUCC_LOG" grep -q 'apache-doris-9.9.9-src.tar.gz$' "$FAKE_FINAL_SHA512" if grep -q 'apache-doris-9.9.9-rc01-src.tar.gz' "$FAKE_FINAL_SHA512"; then From b7555ebcf69671bde5805d89aeb7b284f2b0e5c4 Mon Sep 17 00:00:00 2001 From: morningman Date: Sun, 12 Jul 2026 20:22:47 +0800 Subject: [PATCH 6/8] [fix](release) Use series release SVN fallback ### What problem does this PR solve? Issue Number: None Related PR: None Problem Summary: Step 04 documented and configured final release artifacts under release/doris//, but its fallback for older or custom environments without RELEASE_SVN_DIR used release/doris/. That could silently target the wrong release SVN directory. This change derives RELEASE_SERIES from VERSION when it is not provided and uses release/doris// for the fallback. The release-completion regression test now omits RELEASE_SVN_DIR to cover this fallback path. ### Release note None ### Check List (For Author) - Test: Manual test - bash -n tools/release-tools/01-check-env.sh tools/release-tools/02-package-sign-upload.sh tools/release-tools/03-vote-mail.sh tools/release-tools/04-release-complete.sh tools/release-tools/tests/test-release-complete-checksum.sh tools/release-tools/tests/test-check-env-required-tools.sh - bash tools/release-tools/tests/test-check-env-required-tools.sh - bash tools/release-tools/tests/test-release-complete-checksum.sh - Behavior changed: No - Does this need documentation: No --- tools/release-tools/04-release-complete.sh | 3 ++- tools/release-tools/tests/test-release-complete-checksum.sh | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/tools/release-tools/04-release-complete.sh b/tools/release-tools/04-release-complete.sh index 53a8b2536391e8..cd43dbebbdb72c 100755 --- a/tools/release-tools/04-release-complete.sh +++ b/tools/release-tools/04-release-complete.sh @@ -60,7 +60,8 @@ svnmucc_auth=(--non-interactive --no-auth-cache) [[ -n "${ASF_PASSWORD:-}" ]] && svnmucc_auth+=(-p "$ASF_PASSWORD") RELEASE_PKG_BASE="${RELEASE_PKG_BASE:-apache-doris-${VERSION}-src}" -RELEASE_SVN_DIR="${RELEASE_SVN_DIR:-${RELEASE_SVN_BASE}/${VERSION}}" +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:-}" diff --git a/tools/release-tools/tests/test-release-complete-checksum.sh b/tools/release-tools/tests/test-release-complete-checksum.sh index d88583bacaf2c7..499c699599a7d2 100644 --- a/tools/release-tools/tests/test-release-complete-checksum.sh +++ b/tools/release-tools/tests/test-release-complete-checksum.sh @@ -35,7 +35,6 @@ DEV_SVN_BASE="https://dist.example.test/dev/doris" DEV_SVN_DIR="${DEV_SVN_BASE}/${TAG}" RELEASE_SVN_BASE="https://dist.example.test/release/doris" RELEASE_SERIES="${VERSION%.*}" -RELEASE_SVN_DIR="${RELEASE_SVN_BASE}/${RELEASE_SERIES}/${VERSION}" DOWNLOAD_PAGE_URL="https://doris.example.test/download/" ANNOUNCE_RELEASE_NOTES_URL="https://doris.example.test/release-notes" RELEASE_NOTES_URL="" @@ -124,6 +123,7 @@ grep -q 'apache-doris-9.9.9-rc01-src.tar.gz$' "$FAKE_SVN_CAT_LOG" grep -q 'apache-doris-9.9.9-rc01-src.tar.gz.sha512$' "$FAKE_SVN_CAT_LOG" grep -q 'apache-doris-9.9.9-rc01-src.tar.gz.asc$' "$FAKE_SVN_CAT_LOG" grep -q -- '--verify apache-doris-9.9.9-rc01-src.tar.gz.asc apache-doris-9.9.9-rc01-src.tar.gz' "$FAKE_GPG_LOG" +grep -q 'https://dist.example.test/release/doris/9.9/9.9.9/apache-doris-9.9.9-src.tar.gz' "$FAKE_SVNMUCC_LOG" grep -q 'put ' "$FAKE_SVNMUCC_LOG" grep -q 'apache-doris-9.9.9-src.tar.gz$' "$FAKE_FINAL_SHA512" if grep -q 'apache-doris-9.9.9-rc01-src.tar.gz' "$FAKE_FINAL_SHA512"; then From 745344deb3a2446225000ef4d56476999ba630a5 Mon Sep 17 00:00:00 2001 From: morningman Date: Mon, 13 Jul 2026 16:36:53 +0800 Subject: [PATCH 7/8] [fix](release) Handle release completion review comments ### What problem does this PR solve? Issue Number: None Related PR: #65488 Problem Summary: Release completion could fail for the first release in a new series because the script only created the final release SVN leaf directory and did not handle a missing series parent directory. The release-tool shell tests also had shebangs but were not executable and lacked a documented test runner, making the added coverage easy to skip. The README told release managers to send the announce email immediately after generating it, before explicitly verifying downloads.apache.org and the Doris download page propagation. This change creates the missing release SVN parent directory in the same svnmucc transaction when needed, adds an executable release-tool test runner, makes shell tests directly executable, and updates the post-publish announce guidance. ### Release note None ### Check List (For Author) - Test: Manual test - ./tools/release-tools/tests/run.sh - bash -n tools/release-tools/01-check-env.sh tools/release-tools/02-package-sign-upload.sh tools/release-tools/03-vote-mail.sh tools/release-tools/04-release-complete.sh tools/release-tools/tests/run.sh tools/release-tools/tests/test-check-env-required-tools.sh tools/release-tools/tests/test-release-complete-checksum.sh tools/release-tools/tests/test-readme-release-complete-guidance.sh - git diff --cached --check - Behavior changed: No - Does this need documentation: No --- tools/release-tools/04-release-complete.sh | 28 +++++++++--- tools/release-tools/README.md | 22 +++++++++- tools/release-tools/tests/run.sh | 26 +++++++++++ .../tests/test-check-env-required-tools.sh | 0 .../test-readme-release-complete-guidance.sh | 27 ++++++++++++ .../tests/test-release-complete-checksum.sh | 44 ++++++++++++++++--- 6 files changed, 132 insertions(+), 15 deletions(-) create mode 100755 tools/release-tools/tests/run.sh mode change 100644 => 100755 tools/release-tools/tests/test-check-env-required-tools.sh create mode 100755 tools/release-tools/tests/test-readme-release-complete-guidance.sh mode change 100644 => 100755 tools/release-tools/tests/test-release-complete-checksum.sh diff --git a/tools/release-tools/04-release-complete.sh b/tools/release-tools/04-release-complete.sh index cd43dbebbdb72c..f748ef804c2082 100755 --- a/tools/release-tools/04-release-complete.sh +++ b/tools/release-tools/04-release-complete.sh @@ -62,6 +62,7 @@ svnmucc_auth=(--non-interactive --no-auth-cache) 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}}" +RELEASE_SVN_PARENT_DIR="${RELEASE_SVN_PARENT_DIR:-${RELEASE_SVN_DIR%/*}}" DOWNLOAD_PAGE_URL="${DOWNLOAD_PAGE_URL:-https://doris.apache.org/download/}" ANNOUNCE_RELEASE_NOTES_URL="${ANNOUNCE_RELEASE_NOTES_URL:-}" @@ -125,7 +126,8 @@ EOF } 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 + local src_tar src_asc src_sha512 dst_tar dst_asc dst_sha512 checksum_dir src_tar_file final_sha512_file release_parent_missing + local -a svnmucc_ops require_tool svn require_tool svnmucc @@ -160,6 +162,13 @@ publish_to_release_svn() { 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 + release_parent_missing=0 + if svn info "${svn_auth[@]}" "$RELEASE_SVN_PARENT_DIR" >/dev/null 2>&1; then + ok "release SVN parent exists: ${RELEASE_SVN_PARENT_DIR}" + else + release_parent_missing=1 + warn "release SVN parent will be created: ${RELEASE_SVN_PARENT_DIR}" + fi checksum_dir="$(mktemp -d)" src_tar_file="${PKG_BASE}.tar.gz" @@ -179,24 +188,29 @@ publish_to_release_svn() { ok "final sha512 ok: ${dst_sha512}" echo "--- svnmucc operations ---" + svnmucc_ops=() + if [[ "$release_parent_missing" -eq 1 ]]; then + echo "mkdir ${RELEASE_SVN_PARENT_DIR}" + svnmucc_ops+=(mkdir "$RELEASE_SVN_PARENT_DIR") + fi echo "mkdir ${RELEASE_SVN_DIR}" + svnmucc_ops+=(mkdir "$RELEASE_SVN_DIR") echo "mv ${src_tar}" echo " -> ${RELEASE_SVN_DIR}/${dst_tar}" + svnmucc_ops+=(mv "$src_tar" "${RELEASE_SVN_DIR}/${dst_tar}") echo "mv ${src_asc}" echo " -> ${RELEASE_SVN_DIR}/${dst_asc}" + svnmucc_ops+=(mv "$src_asc" "${RELEASE_SVN_DIR}/${dst_asc}") echo "put ${final_sha512_file}" echo " -> ${RELEASE_SVN_DIR}/${dst_sha512}" + svnmucc_ops+=(put "$final_sha512_file" "${RELEASE_SVN_DIR}/${dst_sha512}") echo "rm ${DEV_SVN_DIR}" + svnmucc_ops+=(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}" \ - mv "$src_asc" "${RELEASE_SVN_DIR}/${dst_asc}" \ - put "$final_sha512_file" "${RELEASE_SVN_DIR}/${dst_sha512}" \ - rm "$DEV_SVN_DIR"; then + if ! svnmucc "${svnmucc_auth[@]}" -m "Release Doris ${VERSION}" "${svnmucc_ops[@]}"; then rm -rf "$checksum_dir" die "svnmucc release publish failed" fi diff --git a/tools/release-tools/README.md b/tools/release-tools/README.md index 06f90ba1c254fb..d82509c54ff993 100644 --- a/tools/release-tools/README.md +++ b/tools/release-tools/README.md @@ -115,7 +115,12 @@ 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. +3. Check that the new source artifacts are visible on `downloads.apache.org`. +4. Update the Doris download page and release metadata as needed, then check + that the public download page points at the new release. +5. Wait for the download and CDN propagation window. +6. Review the generated announce email in `WORK_DIR`. +7. Only after those checks pass, send the `[ANNOUNCE]` email manually. Use this command only when the release SVN step has already been done and you only need to regenerate the announce email: @@ -248,11 +253,22 @@ It then writes: - `announce-email.txt` - `announce-email.eml` -Review the announce draft and send it manually. +Before sending the announce email, check that the release is visible on +`downloads.apache.org`, update and verify the Doris download page, and wait for +the download and CDN propagation window. Only after those checks pass, send the +`[ANNOUNCE]` email manually. Use `./04-release-complete.sh --mail-only` to regenerate the announce email without touching SVN. +## Tests + +Run the release-tool shell tests from this directory: + +```bash +./tests/run.sh +``` + ## Manual work not automated The RM must still do these tasks manually: @@ -262,6 +278,8 @@ The RM must still do these tasks manually: - Send the `[VOTE]` email. - Upload convenience binaries, if the release includes them. - Tally the vote and send the `[RESULT]` email. +- Verify `downloads.apache.org` and the Doris download page before announcing. +- Wait for the download and CDN propagation window. - Send the `[ANNOUNCE]` email. - Publish Maven staging repositories, update the website and GitHub release notes, and clean up old release versions when applicable. diff --git a/tools/release-tools/tests/run.sh b/tools/release-tools/tests/run.sh new file mode 100755 index 00000000000000..fec52ed29385a1 --- /dev/null +++ b/tools/release-tools/tests/run.sh @@ -0,0 +1,26 @@ +#!/usr/bin/env bash +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +set -euo pipefail + +ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" + +for test_script in "${ROOT}"/tests/test-*.sh; do + echo "== ${test_script##*/} ==" + "$test_script" +done diff --git a/tools/release-tools/tests/test-check-env-required-tools.sh b/tools/release-tools/tests/test-check-env-required-tools.sh old mode 100644 new mode 100755 diff --git a/tools/release-tools/tests/test-readme-release-complete-guidance.sh b/tools/release-tools/tests/test-readme-release-complete-guidance.sh new file mode 100755 index 00000000000000..18597a15ddee62 --- /dev/null +++ b/tools/release-tools/tests/test-readme-release-complete-guidance.sh @@ -0,0 +1,27 @@ +#!/usr/bin/env bash +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +set -euo pipefail + +ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +readme="${ROOT}/README.md" + +grep -q 'downloads.apache.org' "$readme" +grep -q 'download page' "$readme" +grep -q 'propagation' "$readme" +grep -q 'Only after those checks pass, send the `\[ANNOUNCE\]` email' "$readme" diff --git a/tools/release-tools/tests/test-release-complete-checksum.sh b/tools/release-tools/tests/test-release-complete-checksum.sh old mode 100644 new mode 100755 index 499c699599a7d2..97234382bf2a3c --- a/tools/release-tools/tests/test-release-complete-checksum.sh +++ b/tools/release-tools/tests/test-release-complete-checksum.sh @@ -50,7 +50,11 @@ shift case "$cmd" in info) url="${@: -1}" - [[ "$url" != "https://dist.example.test/release/doris/9.9/9.9.9" ]] + case "$url" in + https://dist.example.test/release/doris/9.9|https://dist.example.test/release/doris/9.9/9.9.9) + exit 1 + ;; + esac ;; cat) url="${@: -1}" @@ -96,12 +100,39 @@ cat > "$tmp/svnmucc" <<'EOF' #!/usr/bin/env bash set -euo pipefail printf '%s\n' "$*" > "$FAKE_SVNMUCC_LOG" +series_dir_created=0 while (($#)); do - if [[ "$1" == "put" ]]; then - checksum_file="$2" - cp "$checksum_file" "$FAKE_FINAL_SHA512" - fi - shift + case "$1" in + mkdir) + if [[ "$2" == "https://dist.example.test/release/doris/9.9" ]]; then + series_dir_created=1 + elif [[ "$2" == "https://dist.example.test/release/doris/9.9/9.9.9" && "$series_dir_created" -eq 0 ]]; then + echo "release series directory must be created before release leaf directory" >&2 + exit 1 + fi + shift 2 + ;; + mv) + shift 3 + ;; + put) + checksum_file="$2" + cp "$checksum_file" "$FAKE_FINAL_SHA512" + shift 3 + ;; + rm) + shift 2 + ;; + -m|-u|-p) + shift 2 + ;; + --non-interactive|--no-auth-cache) + shift + ;; + *) + shift + ;; + esac done EOF chmod +x "$tmp/svnmucc" @@ -123,6 +154,7 @@ grep -q 'apache-doris-9.9.9-rc01-src.tar.gz$' "$FAKE_SVN_CAT_LOG" grep -q 'apache-doris-9.9.9-rc01-src.tar.gz.sha512$' "$FAKE_SVN_CAT_LOG" grep -q 'apache-doris-9.9.9-rc01-src.tar.gz.asc$' "$FAKE_SVN_CAT_LOG" grep -q -- '--verify apache-doris-9.9.9-rc01-src.tar.gz.asc apache-doris-9.9.9-rc01-src.tar.gz' "$FAKE_GPG_LOG" +grep -q 'mkdir https://dist.example.test/release/doris/9.9' "$FAKE_SVNMUCC_LOG" grep -q 'https://dist.example.test/release/doris/9.9/9.9.9/apache-doris-9.9.9-src.tar.gz' "$FAKE_SVNMUCC_LOG" grep -q 'put ' "$FAKE_SVNMUCC_LOG" grep -q 'apache-doris-9.9.9-src.tar.gz$' "$FAKE_FINAL_SHA512" From f23fd7c116c6c4c52c1b4f5e57245624f527c34f Mon Sep 17 00:00:00 2001 From: morningman Date: Mon, 13 Jul 2026 17:14:46 +0800 Subject: [PATCH 8/8] [fix](build) Clean release checksum temp directory ### What problem does this PR solve? Issue Number: None Related PR: None Problem Summary: Step 04 of the release tooling downloads the RC tarball, signature, and checksum into a mktemp directory before publishing artifacts to release SVN. The script only removed that directory on user cancellation at final confirmation, svnmucc failure, or successful publish. Because the script runs with set -e, failures while reading from SVN or verifying checksum/signature exited before those cleanup sites and left large release artifacts behind. Register an EXIT trap immediately after creating the checksum directory and clear it after the successful cleanup path. ### Release note None ### Check List (For Author) - Test: Manual test - tools/release-tools/tests/test-release-complete-checksum.sh - tools/release-tools/tests/run.sh - bash -n tools/release-tools/04-release-complete.sh tools/release-tools/tests/test-release-complete-checksum.sh - git diff --check -- tools/release-tools/04-release-complete.sh tools/release-tools/tests/test-release-complete-checksum.sh - Behavior changed: Yes. Release completion now removes the checksum temp directory when verification fails before final confirmation. - Does this need documentation: No --- tools/release-tools/04-release-complete.sh | 6 ++- .../tests/test-release-complete-checksum.sh | 37 ++++++++++++++++++- 2 files changed, 40 insertions(+), 3 deletions(-) diff --git a/tools/release-tools/04-release-complete.sh b/tools/release-tools/04-release-complete.sh index f748ef804c2082..84691d55a4c6e6 100755 --- a/tools/release-tools/04-release-complete.sh +++ b/tools/release-tools/04-release-complete.sh @@ -171,6 +171,8 @@ publish_to_release_svn() { fi checksum_dir="$(mktemp -d)" + trap 'rm -rf "$checksum_dir"' EXIT + 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}" @@ -208,13 +210,13 @@ publish_to_release_svn() { svnmucc_ops+=(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; } + confirm "FINAL confirm - publish release SVN and remove dev RC now?" || { warn "stopping before SVN commit."; exit 0; } if ! svnmucc "${svnmucc_auth[@]}" -m "Release Doris ${VERSION}" "${svnmucc_ops[@]}"; then - rm -rf "$checksum_dir" die "svnmucc release publish failed" fi rm -rf "$checksum_dir" + trap - EXIT ok "committed release artifacts: ${RELEASE_SVN_DIR}/" ok "removed dev RC folder: ${DEV_SVN_DIR}/" } diff --git a/tools/release-tools/tests/test-release-complete-checksum.sh b/tools/release-tools/tests/test-release-complete-checksum.sh index 97234382bf2a3c..0bde8c9ed31e69 100755 --- a/tools/release-tools/tests/test-release-complete-checksum.sh +++ b/tools/release-tools/tests/test-release-complete-checksum.sh @@ -64,7 +64,11 @@ case "$cmd" in printf 'release artifact bytes\n' ;; *.sha512) - digest="$(printf 'release artifact bytes\n' | sha512sum | awk '{print $1}')" + if [[ "${FAKE_BAD_SHA512:-0}" -eq 1 ]]; then + digest="00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" + else + digest="$(printf 'release artifact bytes\n' | sha512sum | awk '{print $1}')" + fi printf '%s apache-doris-9.9.9-rc01-src.tar.gz\n' "$digest" ;; *.asc) @@ -84,6 +88,17 @@ esac EOF chmod +x "$tmp/svn" +cat > "$tmp/mktemp" <<'EOF' +#!/usr/bin/env bash +set -euo pipefail +[[ "$1" == "-d" ]] +dir="${FAKE_MKTEMP_ROOT}/checksum-dir-${RANDOM}-${RANDOM}" +mkdir -p "$dir" +printf '%s\n' "$dir" >> "$FAKE_MKTEMP_LOG" +printf '%s\n' "$dir" +EOF +chmod +x "$tmp/mktemp" + cat > "$tmp/gpg" <<'EOF' #!/usr/bin/env bash set -euo pipefail @@ -142,6 +157,9 @@ export FAKE_SVN_CAT_LOG="$tmp/svn-cat.log" export FAKE_GPG_LOG="$tmp/gpg.log" export FAKE_SVNMUCC_LOG="$tmp/svnmucc.log" export FAKE_FINAL_SHA512="$tmp/final.sha512" +export FAKE_MKTEMP_ROOT="$tmp/mktemp-root" +export FAKE_MKTEMP_LOG="$tmp/mktemp.log" +mkdir -p "$FAKE_MKTEMP_ROOT" printf 'y\n' | bash "$tmp/04-release-complete.sh" >/dev/null @@ -162,3 +180,20 @@ if grep -q 'apache-doris-9.9.9-rc01-src.tar.gz' "$FAKE_FINAL_SHA512"; then echo "final checksum sidecar still references the RC tarball name" >&2 exit 1 fi + +success_checksum_dir="$(tail -n 1 "$FAKE_MKTEMP_LOG")" +if [[ -e "$success_checksum_dir" ]]; then + echo "checksum temp directory was not removed after successful publish: $success_checksum_dir" >&2 + exit 1 +fi + +if FAKE_BAD_SHA512=1 bash "$tmp/04-release-complete.sh" >/dev/null 2>&1; then + echo "release completion unexpectedly succeeded with a bad RC checksum" >&2 + exit 1 +fi + +failed_checksum_dir="$(tail -n 1 "$FAKE_MKTEMP_LOG")" +if [[ -e "$failed_checksum_dir" ]]; then + echo "checksum temp directory was not removed after checksum verification failure: $failed_checksum_dir" >&2 + exit 1 +fi