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).