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

guanmingchiu pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/mahout.git


The following commit(s) were added to refs/heads/main by this push:
     new e670407a5 Update release docs and scripts (#964)
e670407a5 is described below

commit e670407a580e0e35224094e217e3f3ca245d07ee
Author: Guan-Ming (Wesley) Chiu <[email protected]>
AuthorDate: Thu Jan 29 00:06:39 2026 +0800

    Update release docs and scripts (#964)
    
    * Update release docs and scripts
    
    * Add email template
    
    * Add branch strategy
---
 .gitignore               |   3 +
 dev/generate-rc-issue.sh |  57 +++++++++++++++++++
 dev/rc-email-template.md |  60 ++++++++++++++++++++
 dev/release.md           | 143 +++++++++++++++++++++++++++++++++++++++++------
 4 files changed, 245 insertions(+), 18 deletions(-)

diff --git a/.gitignore b/.gitignore
index de41e2269..070a8c4b2 100644
--- a/.gitignore
+++ b/.gitignore
@@ -52,3 +52,6 @@ __pycache__/
 
 # Testing and type checking (project uses these)
 .pytest_cache/
+
+# pypi
+.pypirc
diff --git a/dev/generate-rc-issue.sh b/dev/generate-rc-issue.sh
new file mode 100755
index 000000000..b5525121c
--- /dev/null
+++ b/dev/generate-rc-issue.sh
@@ -0,0 +1,57 @@
+#!/bin/bash
+# Generate RC Testing Issue for Apache Mahout
+# Usage: ./generate-rc-issue.sh <qumat_version> <qdp_version> [milestone_name]
+# Example: ./generate-rc-issue.sh 0.5.0rc1 0.1.0rc1 "Qumat 0.5.0"
+
+QUMAT_VERSION=${1:-"0.5.0rc1"}
+QDP_VERSION=${2:-"0.1.0rc1"}
+MILESTONE=${3:-"Qumat 0.5.0"}
+
+cat << EOF
+# Testing Apache Mahout Qumat 0.5.0rc1
+We kindly request all contributors to help test the Release Candidate for 
[qumat ${QUMAT_VERSION}](https://pypi.org/project/qumat/${QUMAT_VERSION}/) and 
[qumat-qdp ${QDP_VERSION}](https://pypi.org/project/qumat-qdp/${QDP_VERSION}/).
+
+## Requirements
+
+- Python 3.10, 3.11, or 3.12
+- **For QDP extension**: Linux with NVIDIA GPU and CUDA
+
+## Installation
+
+\`\`\`bash
+# Core package
+pip install --pre "qumat==${QUMAT_VERSION}"
+
+# With QDP extension
+pip install --pre "qumat[qdp]==${QUMAT_VERSION}"
+\`\`\`
+
+## Changes to Test
+
+EOF
+
+# Get merged PRs from milestone with PR URL
+gh pr list --repo apache/mahout --state merged --search 
"milestone:\"${MILESTONE}\"" --limit 500 --json number,title,author \
+  --jq '.[] | "- [ ] [\(.title) 
(#\(.number))](https://github.com/apache/mahout/pull/\(.number)): 
@\(.author.login)"' 2>/dev/null
+
+cat << EOF
+
+## Compatibility
+
+- [ ] Python 3.10
+- [ ] Python 3.11
+- [ ] Python 3.12
+
+EOF
+
+echo -n "Thanks to all who contributed to the release: "
+gh pr list --repo apache/mahout --state merged --search 
"milestone:\"${MILESTONE}\"" --limit 500 --json author \
+  --jq '.[].author.login' 2>/dev/null | sort -u | sed 's/^/@/' | tr '\n' ' '
+
+cat << EOF
+
+
+### Committer
+
+- [ ] I acknowledge that I am a maintainer/committer of the Apache Mahout 
project.
+EOF
diff --git a/dev/rc-email-template.md b/dev/rc-email-template.md
new file mode 100644
index 000000000..441e0a067
--- /dev/null
+++ b/dev/rc-email-template.md
@@ -0,0 +1,60 @@
+# RC Announcement Email Template
+
+Send this to `[email protected]` when cutting a release candidate.
+
+---
+
+**Subject:** [ANNOUNCE] Qumat {VERSION} RC{N} - Cutting Release Candidate
+
+---
+
+Hi all,
+
+The main features for Qumat {VERSION} have reached a good stopping point, and
+I'm ready to start the release process. As the Release Manager for this
+release, I'm planning to cut RC{N} on {DATE} at {TIME} (UTC+8).
+
+Milestone: https://github.com/apache/mahout/milestone/{MILESTONE_NUMBER}
+
+Please let me know if there are any blockers or concerns before I proceed.
+
+Thanks,
+{YOUR_NAME}
+
+---
+
+# RC Voting Email Template
+
+Send this to `[email protected]` after the RC has been published to PyPI.
+
+---
+
+**Subject:** [VOTE] Release Mahout qumat {QUMAT_VERSION}rc{N} and qumat-qdp 
{QDP_VERSION}rc{N}
+
+---
+
+Hi all,
+
+I have created a release candidate for Mahout qumat {QUMAT_VERSION}rc{N} and 
qumat-qdp {QDP_VERSION}rc{N}.
+
+PyPI
+- qumat: https://pypi.org/project/qumat/{QUMAT_VERSION}rc{N}/
+- qumat-qdp: https://pypi.org/project/qumat-qdp/{QDP_VERSION}rc{N}/
+GitHub Tag 
https://github.com/apache/mahout/releases/tag/mahout-qumat-{QUMAT_VERSION}-RC{N}
+Changelog https://github.com/apache/mahout/issues/{ISSUE_NUMBER}
+
+To test the release candidate:
+
+```bash
+pip install --pre "qumat=={QUMAT_VERSION}rc{N}"
+pip install --pre "qumat-qdp=={QDP_VERSION}rc{N}"
+```
+
+Please vote on the release. The vote will be open for at least 72 hours.
+
+[ ] +1 Release these packages as Apache Mahout qumat {QUMAT_VERSION} and 
qumat-qdp {QDP_VERSION}
+[ ] +0 No opinion
+[ ] -1 Do not release (please provide reason)
+
+Thanks,
+{YOUR_NAME}
diff --git a/dev/release.md b/dev/release.md
index cde6f0616..003b124a0 100644
--- a/dev/release.md
+++ b/dev/release.md
@@ -12,6 +12,64 @@ This document describes the process for releasing `qumat` 
and `qumat-qdp`. The p
 
 ---
 
+## Branching Strategy
+
+We follow the Airflow-style release branching model:
+
+```
+main ────●────●────●────●────●──→ (development continues)
+                   │
+                   ├── mahout-qumat-0.5.0-RC1 (tag)
+                   │
+                   └── v0.5-stable (branch) ──●──→ RC2 ──→ v0.5.0 ──→ v0.5.1
+```
+
+### Create Stable Branch
+
+When ready to cut a release, create a stable branch from `main`:
+
+```bash
+git checkout main
+git pull upstream main
+git checkout -b v0.5-stable
+git push -u upstream v0.5-stable
+```
+
+### Tag Release Candidates
+
+Tag RCs on the stable branch:
+
+```bash
+git checkout v0.5-stable
+git tag -a mahout-qumat-0.5.0-RC1 -m "Release Candidate 1 for qumat 0.5.0"
+git push upstream mahout-qumat-0.5.0-RC1
+```
+
+### Cherry-pick Bug Fixes
+
+If bugs are found during RC testing:
+
+1. **Fix on `main` first** (keeps main up-to-date):
+   ```bash
+   git checkout main
+   # ... fix and commit ...
+   git push upstream main
+   ```
+
+2. **Cherry-pick to stable branch**:
+   ```bash
+   # Using cherry-picker tool (auto-creates PR)
+   uvx cherry-picker <commit-hash> v0.5-stable
+   ```
+
+3. **Tag new RC**:
+   ```bash
+   git tag -a mahout-qumat-0.5.0-RC2 -m "Release Candidate 2 for qumat 0.5.0"
+   git push upstream mahout-qumat-0.5.0-RC2
+   ```
+
+---
+
 ## Phase 1: Community Pre-Release (RC Preparation)
 
 The goal of this phase is to ensure the release candidate is stable and ready 
for a formal vote.
@@ -23,41 +81,90 @@ The goal of this phase is to ensure the release candidate 
is stable and ready fo
 Update version numbers and build the artifacts locally.
 
 **Update Versions to RC:**
-Ensure the version includes the `rc` suffix (e.g., `1.0.0rc1`):
--   `qumat/pyproject.toml`
--   `qdp/qdp-python/pyproject.toml`
--   `qdp/Cargo.toml` (if releasing Rust core)
+Ensure the version includes the `rc` suffix (e.g., `0.5.0rc1`):
+-   `pyproject.toml` — set `version = "0.5.0rc1"`
+-   `qdp/Cargo.toml` — set `version = "0.1.0-rc1"`
 
 **Build:**
 ```bash
-# For Qumat
-cd qumat && python -m build
+# Build Qumat (pure Python — one wheel for all Python versions)
+uv build
 
-# For Qumat-QDP
-cd qdp/qdp-python && maturin build --release
+# Build Qumat-QDP (native Rust — one wheel per Python version)
+cd qdp/qdp-python
+uv tool run maturin build --release --interpreter python3.10
+uv tool run maturin build --release --interpreter python3.11
+uv tool run maturin build --release --interpreter python3.12
 ```
 
-**Important:** Store these build artifacts safely. They will be used for both 
PyPI upload and ATR submission.
+**Output locations:**
+-   `dist/qumat-0.5.0rc1-py3-none-any.whl`
+-   `dist/qumat-0.5.0rc1.tar.gz`
+-   `qdp/target/wheels/qumat_qdp-0.1.0rc1-cp3XX-*.whl`
 
 ### 1.3 Upload to PyPI (RC Version)
-Upload the generated artifacts to **PyPI** as a Release Candidate.
 
+**Configure `.pypirc`:**
+Create a `.pypirc` file with your API token (from 
https://pypi.org/manage/account/token/):
+```ini
+[testpypi]
+username = __token__
+password = pypi-xxxxx
+
+[pypi]
+username = __token__
+password = pypi-xxxxx
+```
+
+**Upload to TestPyPI first (recommended):**
 ```bash
 # Upload Qumat
-cd qumat
-twine upload dist/*
+uv tool run twine upload --repository testpypi --config-file .pypirc dist/*
 
 # Upload Qumat-QDP
-cd qdp/qdp-python
-twine upload target/wheels/*
+uv tool run twine upload --repository testpypi --config-file .pypirc 
qdp/target/wheels/qumat_qdp-<version>-cp31{0,1,2}-*.whl
 ```
 
-*Note: This makes the RC available on the official PyPI for easy testing with 
`pip install --pre qumat==1.0.0rc1`.*
+**Test install from TestPyPI:**
+```bash
+uv venv && source .venv/bin/activate
+uv pip install \
+  --index-url https://test.pypi.org/simple/ \
+  --extra-index-url https://pypi.org/simple/ \
+  --index-strategy unsafe-best-match \
+  qumat==0.5.0rc1 qumat-qdp==0.1.0rc1
+pytest testing/
+```
+
+**Upload to PyPI:**
+```bash
+# Upload Qumat
+uv tool run twine upload --repository pypi --config-file .pypirc dist/*
+
+# Upload Qumat-QDP (exclude Python versions outside requires-python)
+uv tool run twine upload --repository pypi --config-file .pypirc 
qdp/target/wheels/qumat_qdp-<version>-cp31{0,1,2}-*.whl
+```
+
+*Note: This makes the RC available on PyPI for testing with `pip install --pre 
qumat==0.5.0rc1`.*
 
 ### 1.4 Open Testing Issue
-Open a GitHub Issue titled **"Testing Qumat <Version> RC1"**.
--   List the installation commands (e.g., `pip install --pre qumat`).
--   Track feedback, reported bugs, and verification results.
+Use the script to generate the RC testing issue:
+
+```bash
+# Generate issue content (dry run)
+./dev/generate-rc-issue.sh 0.5.0rc1 0.1.0rc1 "Qumat 0.5.0"
+
+# Create GitHub issue directly
+./dev/generate-rc-issue.sh 0.5.0rc1 0.1.0rc1 "Qumat 0.5.0" | \
+  gh issue create --repo apache/mahout \
+    --title "Status of testing Apache Mahout Qumat 0.5.0rc1" \
+    --body-file -
+```
+
+The script generates an issue with:
+-   Installation commands
+-   All PRs from the milestone with checkboxes
+-   Contributor mentions for testing
 
 ### 1.5 Community Testing & Closure
 -   Allow a testing interval (e.g., 3-5 days).

Reply via email to