diff --git a/.asf.yaml b/.asf.yaml index 5ca12f6e9cf90f..70f2c884f1901e 100644 --- a/.asf.yaml +++ b/.asf.yaml @@ -25,7 +25,7 @@ github: - lakehouse - ai - agent - - elt + - observability - sql - snowflake - redshift diff --git a/.gitleaks.toml b/.gitleaks.toml index 8498a6e5184af9..7bc31857f9b1f5 100644 --- a/.gitleaks.toml +++ b/.gitleaks.toml @@ -27,6 +27,13 @@ regexTarget = "line" paths = ['''^fe/fe-filesystem/fe-filesystem-s3/src/test/java/org/apache/doris/filesystem/s3/S3ObjStorageTest\.java$'''] regexes = ['''(access_key|secret_key).*"(ak-|sk-|canonical|sess-tok)'''] +[[rules.allowlists]] +description = "Ignore the GPG signing-key fingerprint in the release-tools config template (a public key id, not a secret)" +condition = "AND" +regexTarget = "line" +paths = ['''^tools/release-tools/release\.env$'''] +regexes = ['''SIGNING_KEY="[A-F0-9]{40}"'''] + [[rules]] id = "private-key" diff --git a/tools/release-tools/01-check-env.sh b/tools/release-tools/01-check-env.sh new file mode 100755 index 00000000000000..c6e47048e916f2 --- /dev/null +++ b/tools/release-tools/01-check-env.sh @@ -0,0 +1,205 @@ +#!/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 01 - prepare / check the signing environment. +# Read-mostly. The only state-changing paths (import key / generate key / +# publish KEYS / edit gpg.conf) are opt-in and prompt before acting. +set -euo pipefail +HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +# shellcheck source=release.env +source "${HERE}/release.env" + +ok() { echo "[ OK ] $*"; } +warn() { echo "[WARN] $*"; } +err() { echo "[FAIL] $*"; } +die() { err "$*"; exit 1; } +confirm() { local a; read -r -p "$1 [y/N] " a; [[ "$a" == y || "$a" == Y ]]; } + +# does $1 (fingerprint) appear in a KEYS stream piped on stdin? +key_in_keys() { + local fpr="$1" kr ret=1; kr="$(mktemp -d)" + if gpg --homedir "$kr" --import >/dev/null 2>&1 && gpg --homedir "$kr" --list-keys "$fpr" >/dev/null 2>&1; then ret=0; fi + rm -rf "$kr"; return "$ret" +} + +# svn auth args (only added if exported) +svn_auth=(--non-interactive --no-auth-cache) +[[ -n "${ASF_USERNAME:-}" ]] && svn_auth+=(--username "$ASF_USERNAME") +[[ -n "${ASF_PASSWORD:-}" ]] && svn_auth+=(--password "$ASF_PASSWORD") + +problems=0 +echo "== Apache Doris ${TAG} - signing environment check ==" + +# 1. required tools +for t in git gpg svn 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 + +# 2. GPG_TTY (needed so the passphrase prompt can appear) +export GPG_TTY="$(tty || true)" +ok "GPG_TTY=${GPG_TTY:-}" + +# 3. gpg.conf SHA512 preference (Apache recommendation) +gpgconf_file="${GNUPGHOME:-$HOME/.gnupg}/gpg.conf" +if grep -q "cert-digest-algo SHA512" "$gpgconf_file" 2>/dev/null; then + ok "gpg.conf has SHA512 digest preferences" +else + warn "gpg.conf missing SHA512 preferences ($gpgconf_file)" + if confirm "Append recommended SHA512 lines to gpg.conf?"; then + { + echo "personal-digest-preferences SHA512" + echo "cert-digest-algo SHA512" + echo "default-preference-list SHA512 SHA384 SHA256 SHA224 AES256 AES192 AES CAST5 ZLIB BZIP2 ZIP Uncompressed" + } >> "$gpgconf_file" + ok "updated $gpgconf_file" + fi +fi + +# 4. resolve a usable secret key (one primary fpr per secret key) +list_secret_fprs() { + gpg --list-secret-keys --with-colons 2>/dev/null \ + | awk -F: '$1=="sec"{w=1} $1=="fpr"&&w{print $10; w=0}' +} +resolve_secret_key() { + if [[ -n "${SIGNING_KEY}" ]]; then + gpg --list-secret-keys "${SIGNING_KEY}" >/dev/null 2>&1 && { echo "${SIGNING_KEY}"; return 0; } + return 1 + fi + local fprs n; fprs="$(list_secret_fprs)"; n="$(printf '%s\n' "$fprs" | grep -c . || true)" + if [[ "$n" -eq 1 ]]; then printf '%s\n' "$fprs"; return 0 + elif [[ "$n" -gt 1 ]]; then return 2 + fi + return 1 +} + +import_key_from_file() { + local p; read -r -p "Path to exported secret key file (.asc/.gpg): " p + [[ -f "$p" ]] || die "no such file: $p" + gpg --import "$p" +} + +gen_key() { + local rn em + read -r -p "Real name (>=5 chars, e.g. morningman): " rn + read -r -p "Apache email (xxx@apache.org): " em + echo "Generating RSA-4096 sign key, no expiry. You'll be asked for a passphrase - REMEMBER IT." + gpg --quick-generate-key "${rn} (CODE SIGNING KEY) <${em}>" rsa4096 sign never +} + +# append the new public key to dev + release KEYS and commit (so voters can verify) +# append the key to the dev + release KEYS files and commit (append-only). +# idempotent: skips a repo whose KEYS already contains the key, so re-running +# after a partial failure won't duplicate the entry. +# caller is responsible for asking the user first. +publish_key_to_keys() { + local fpr="$1" spec name base wc + mkdir -p "${WORK_DIR}" + for spec in "dev=${DEV_SVN_BASE}" "release=${RELEASE_SVN_BASE}"; do + name="${spec%%=*}"; base="${spec#*=}" + wc="${WORK_DIR}/keys-${name}-$$" + rm -rf "$wc" # avoid stale working-copy collisions + echo ">> ${base}/KEYS" + svn checkout --depth files "${svn_auth[@]}" "$base" "$wc" + if key_in_keys "$fpr" < "$wc/KEYS"; then + ok "key already in ${name} KEYS - skip" + continue + fi + # append only - never rewrite existing KEYS content + { echo; gpg --list-sigs "$fpr"; gpg --armor --export "$fpr"; } >> "$wc/KEYS" + echo "--- appended to ${name}/KEYS (tail) ---"; tail -n 18 "$wc/KEYS" + svn commit "${svn_auth[@]}" -m "Add KEY for ${APACHE_ID}" "$wc" + ok "committed KEYS to ${base}" + done + warn "MANUAL: paste this fingerprint into https://id.apache.org (OpenPGP field):" + gpg --fingerprint "$fpr" | sed -n '2p' +} + +SIGNER="" +if SIGNER="$(resolve_secret_key)"; then + ok "signing key resolved: ${SIGNER}" +else + rc=$? + if [[ "$rc" -eq 2 ]]; then + err "multiple secret keys found - set SIGNING_KEY in release.env to choose one:" + gpg --list-secret-keys --keyid-format=long + problems=$((problems+1)) + else + warn "no usable secret key in this environment. Options:" + echo " 1) import an existing exported secret key from a file" + echo " 2) generate a NEW key here and publish it to the Doris KEYS files" + echo " 3) skip (you will sign on another machine)" + read -r -p "choose [1/2/3]: " choice + case "$choice" in + 1) import_key_from_file; SIGNER="$(resolve_secret_key || true)";; + 2) gen_key; SIGNER="$(resolve_secret_key || true)" + if [[ -n "$SIGNER" ]] && confirm "Publish this new key to dev+release KEYS now?"; then + publish_key_to_keys "$SIGNER" + fi;; + 3) warn "skipping local key; sign on another machine.";; + *) warn "no choice made.";; + esac + if [[ -n "$SIGNER" ]]; then ok "signing key resolved: ${SIGNER}"; else warn "still no signing key"; problems=$((problems+1)); fi + fi +fi + +# 5. is the signing key published in the live KEYS? + 6. test signature +if [[ -n "$SIGNER" ]]; then + fpr="$(gpg --list-keys --with-colons "$SIGNER" | awk -F: '/^fpr:/{print $10; exit}')" + ok "fingerprint: ${fpr}" + + if curl -fsSL "$KEYS_URL" 2>/dev/null | key_in_keys "$fpr"; then + ok "key is present in published KEYS" + else + warn "key NOT found in published KEYS ($KEYS_URL) - voters can't verify until it's published" + if confirm "Append this key to the Doris dev+release KEYS and commit now?"; then + publish_key_to_keys "$fpr" + if svn cat "${svn_auth[@]}" "${RELEASE_SVN_BASE}/KEYS" 2>/dev/null | key_in_keys "$fpr"; then + ok "key now in release SVN KEYS (downloads.apache.org mirror syncs in a few min)" + else + err "key still not in release SVN KEYS after commit - check output above" + problems=$((problems+1)) + fi + else + warn "skipped KEYS publish; key MUST be in published KEYS before the vote" + problems=$((problems+1)) + fi + fi + + tf="$(mktemp)"; echo "doris ${TAG} signing test" > "$tf" + if gpg -u "$SIGNER" --armor --detach-sign -o "$tf.asc" "$tf" >/dev/null 2>&1 \ + && gpg --verify "$tf.asc" "$tf" >/dev/null 2>&1; then + ok "test sign + verify succeeded (passphrase/agent working)" + else + err "test signing failed - check passphrase / GPG_TTY / pinentry"; problems=$((problems+1)) + fi + rm -f "$tf" "$tf.asc" +fi + +# 7. ASF SVN credentials +if [[ -n "${ASF_USERNAME:-}" && -n "${ASF_PASSWORD:-}" ]]; then + ok "ASF_USERNAME/ASF_PASSWORD present in env" +else + warn "ASF_USERNAME/ASF_PASSWORD not both set - needed for SVN upload (step 02) and KEYS publish" +fi + +echo +if [[ "$problems" -eq 0 ]]; then + ok "environment looks READY for ${TAG}" +else + err "${problems} problem(s) above - resolve before packaging"; exit 1 +fi diff --git a/tools/release-tools/02-package-sign-upload.sh b/tools/release-tools/02-package-sign-upload.sh new file mode 100755 index 00000000000000..8d6b20cc6416ba --- /dev/null +++ b/tools/release-tools/02-package-sign-upload.sh @@ -0,0 +1,109 @@ +#!/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 02 - package the source tarball, sign it, and upload to the Apache dev SVN. +# The SVN commit is outward-facing: it pauses twice for confirmation before commit. +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 ]]; } +export GPG_TTY="$(tty || true)" + +svn_auth=(--non-interactive --no-auth-cache) +[[ -n "${ASF_USERNAME:-}" ]] && svn_auth+=(--username "$ASF_USERNAME") +[[ -n "${ASF_PASSWORD:-}" ]] && svn_auth+=(--password "$ASF_PASSWORD") + +# resolve signer +if [[ -n "${SIGNING_KEY}" ]]; then + SIGNER="${SIGNING_KEY}" +else + SIGNER="$(gpg --list-secret-keys --with-colons 2>/dev/null | awk -F: '$1=="sec"{w=1} $1=="fpr"&&w{print $10; exit}')" +fi +[[ -n "$SIGNER" ]] || die "no signing key found; run ./01-check-env.sh first" +ok "signer: $SIGNER" + +# 1. verify the tag matches the apache remote (don't release a local-only tag) +cd "$REPO_DIR" +git rev-parse "$TAG" >/dev/null 2>&1 || die "local tag $TAG not found in $REPO_DIR" +local_tag="$(git rev-parse "$TAG")" +remote_tag="$(git ls-remote --tags "$GIT_REMOTE" "refs/tags/$TAG" | awk -v t="refs/tags/$TAG" '$2==t{print $1}')" +[[ -n "$remote_tag" ]] || die "tag $TAG not found on remote $GIT_REMOTE" +[[ "$local_tag" == "$remote_tag" ]] || die "tag mismatch: local=$local_tag $GIT_REMOTE=$remote_tag" +ok "tag $TAG matches $GIT_REMOTE" + +# 2. package via git archive from the tag +mkdir -p "$WORK_DIR" +art="$WORK_DIR/${PKG_BASE}.tar.gz" +echo "archiving $TAG -> $art" +git archive --format=tar --prefix="$ARCHIVE_PREFIX" "$TAG" | gzip > "$art" +ok "source tarball: $(du -h "$art" | cut -f1) $art" + +# 3. sign + checksum (inside WORK_DIR so the files reference bare basenames) +cd "$WORK_DIR" +f="${PKG_BASE}.tar.gz" +rm -f "$f.asc" "$f.sha512" +gpg -u "$SIGNER" --armor --output "$f.asc" --detach-sign "$f" +gpg --verify "$f.asc" "$f" +ok "signature ok: $f.asc" +sha512sum "$f" > "$f.sha512" +sha512sum --check "$f.sha512" +ok "sha512 ok: $f.sha512" +echo; ls -l "$f" "$f.asc" "$f.sha512"; echo + +# 4. sign + checksum the prebuilt binary tarballs. Sidecar files are written NEXT TO +# each binary (not in WORK_DIR) and are NOT uploaded here -- you upload them manually. +bin_count="${#BIN_FILES[@]}" +if [[ "$bin_count" -gt 0 ]]; then + echo "signing $bin_count binary artifact(s)..." + for bin in "${BIN_FILES[@]}"; do + [[ -f "$bin" ]] || die "binary artifact not found: $bin (check BIN_FILES in release.env)" + bdir="$(cd "$(dirname "$bin")" && pwd)" + bname="$(basename "$bin")" + ( + cd "$bdir" + rm -f "$bname.asc" "$bname.sha512" + gpg -u "$SIGNER" --armor --output "$bname.asc" --detach-sign "$bname" + gpg --verify "$bname.asc" "$bname" + sha512sum "$bname" > "$bname.sha512" + sha512sum --check "$bname.sha512" + ) + ok "binary signed: $bdir/$bname (+ .asc, .sha512)" + done + echo +fi + +# 5. upload to dev SVN (two confirmations; nothing public happens before them) +echo "Target dev SVN folder: ${DEV_SVN_DIR}/" +confirm "Checkout + add these 3 files for the above SVN URL?" || { warn "stopping before SVN."; exit 0; } +wc="$WORK_DIR/dev-svn" +rm -rf "$wc" +svn checkout --depth empty "${svn_auth[@]}" "$DEV_SVN_BASE" "$wc" +mkdir -p "$wc/$TAG" +cp "$f" "$f.asc" "$f.sha512" "$wc/$TAG/" +svn add "$wc/$TAG" +echo "--- svn status ---"; svn status "$wc"; echo +echo "Will commit the above to: ${DEV_SVN_DIR}/" +confirm "FINAL confirm - svn commit now?" || { warn "left staged (uncommitted) at $wc"; exit 0; } +svn commit "${svn_auth[@]}" -m "Add ${TAG}" "$wc" +ok "committed. Vote artifacts now at: ${DEV_SVN_DIR}/" +echo "Next: ./03-vote-mail.sh" diff --git a/tools/release-tools/03-vote-mail.sh b/tools/release-tools/03-vote-mail.sh new file mode 100755 index 00000000000000..025e154ea7a09e --- /dev/null +++ b/tools/release-tools/03-vote-mail.sh @@ -0,0 +1,111 @@ +#!/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 03 - generate the [VOTE] email draft for dev@doris.apache.org. +# Draft only: it writes a .txt and .eml; you send it from your @apache.org mail. +set -euo pipefail +HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +# shellcheck source=release.env +source "${HERE}/release.env" + +ok() { echo "[ OK ] $*"; } +die() { echo "[FAIL] $*" >&2; exit 1; } + +# release notes link (prompt if not preset) +rn="${RELEASE_NOTES_URL}" +if [[ -z "$rn" ]]; then read -r -p "Release Notes URL (the issue link): " rn; fi +[[ -n "$rn" ]] || die "release notes url required" + +# signer fingerprint +if [[ -n "${SIGNING_KEY}" ]]; then + SIGNER="${SIGNING_KEY}" +else + SIGNER="$(gpg --list-secret-keys --with-colons 2>/dev/null | awk -F: '$1=="sec"{w=1} $1=="fpr"&&w{print $10; exit}')" +fi +[[ -n "$SIGNER" ]] || die "no signing key found; run ./01-check-env.sh first" +FPR="$(gpg --list-keys --with-colons "$SIGNER" | awk -F: '/^fpr:/{print $10; exit}')" + +mkdir -p "$WORK_DIR" +subject="[VOTE] Release Apache Doris ${TAG}" +body_file="$WORK_DIR/vote-email.txt" +eml_file="$WORK_DIR/vote-email.eml" + +# Convenience-binary download section: derived from BIN_FILES, omitted when empty. +bin_section="" +if [[ "${#BIN_FILES[@]}" -gt 0 ]]; then + bin_section=$'\nThe convenience binaries can be downloaded here:\n' + for bin in "${BIN_FILES[@]}"; do + b="$(basename "$bin")" + bin_section+="${BIN_DOWNLOAD_BASE}/${b}"$'\n' + bin_section+="${BIN_DOWNLOAD_BASE}/${b}.asc"$'\n' + bin_section+="${BIN_DOWNLOAD_BASE}/${b}.sha512"$'\n' + done +fi + +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.)" diff --git a/tools/release-tools/README.md b/tools/release-tools/README.md new file mode 100644 index 00000000000000..20e34504d96ad5 --- /dev/null +++ b/tools/release-tools/README.md @@ -0,0 +1,99 @@ + + +# 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. + +## 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`. +- 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. + +--- + +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. + +## 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 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). + +## 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. + +## 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. diff --git a/tools/release-tools/release.env b/tools/release-tools/release.env new file mode 100644 index 00000000000000..024296f9b8fcf5 --- /dev/null +++ b/tools/release-tools/release.env @@ -0,0 +1,79 @@ +# 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. + +# Shared config for the Apache Doris release helper scripts. +# Edit values here; 01/02/03 all `source` this file. +# +# This release: 4.0.6-rc02 (tag already created & pushed to apache/doris) + +ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" &>/dev/null && pwd)" + +# --- Repo & version --- +REPO_DIR="${ROOT}/../../" +VERSION="4.0.6" +RC="rc02" +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. +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 + +# --- Work area (OUTSIDE the git repo: artifacts + svn checkouts live here) --- +WORK_DIR="${ROOT}/${TAG}" + +# --- Prebuilt binary artifacts (OPTIONAL; signed locally; uploaded MANUALLY by you) --- +# Step 02 writes a .asc signature and a .sha512 checksum NEXT TO each file listed here. +# These are NOT uploaded by the scripts and are NOT part of the source-only vote SVN; +# you upload the binaries together with their .asc/.sha512 yourself, wherever they go. +# Leave the list empty (the default) for the source-only flow. To also sign binaries, +# set absolute paths to your prebuilt binary tarballs, e.g.: +# BIN_FILES=( +# "${WORK_DIR}/apache-doris-${VERSION}-bin-x64.tar.gz" +# "${WORK_DIR}/apache-doris-${VERSION}-bin-x64-noavx2.tar.gz" +# "${WORK_DIR}/apache-doris-${VERSION}-bin-arm64.tar.gz" +# ) +BIN_FILES=() + +# Public download base for the convenience binaries advertised in the vote email. +# Step 03 lists each BIN_FILES basename under this URL (+ .asc / .sha512); +# when BIN_FILES is empty the email omits the convenience-binaries section. +BIN_DOWNLOAD_BASE="https://apache-doris-releases.oss-accelerate.aliyuncs.com" + +# --- Signer identity --- +APACHE_ID="morningman" +APACHE_EMAIL="morningman@apache.org" +SIGNER_NAME="Mingyu Chen" # display name used to sign the vote email +# Key passed to `gpg -u`. Leave EMPTY to auto-detect the only local secret key. +SIGNING_KEY="" # use `gpg --list-keys` to get + +# --- Apache dist SVN (vote artifacts are SOURCE-ONLY; no binaries) --- +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" +KEYS_URL="https://downloads.apache.org/doris/KEYS" + +# --- ASF credentials: export in your shell before running (NOT stored here) --- +# export ASF_USERNAME=morningman +# export ASF_PASSWORD='...' # Apache LDAP password + +# --- Vote email --- +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"