Skip to content

Commit 36fd6a1

Browse files
committed
modernize release setup with hatchling
1 parent d2965e7 commit 36fd6a1

File tree

6 files changed

+388
-28
lines changed

6 files changed

+388
-28
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,4 @@ example/*-outfile.txt
1212
requirements-mxdev.txt
1313
.venv/
1414
dist/
15+
src/mxdev/_version.py

.pre-commit-config.yaml

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,6 @@ repos:
2828
# - id: flake8
2929
# additional_dependencies:
3030
# - flake8-docstrings
31-
- repo: https://github.com/mgedmin/check-manifest
32-
rev: "0.49"
33-
hooks:
34-
- id: check-manifest
3531
# - repo: https://github.com/Lucas-C/pre-commit-hooks-safety
3632
# rev: v1.2.4
3733
# hooks:

MANIFEST.in

Lines changed: 0 additions & 10 deletions
This file was deleted.

RELEASE.md

Lines changed: 321 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,321 @@
1+
# Release Process
2+
3+
This document describes the release process for mxdev.
4+
5+
## Overview
6+
7+
mxdev uses **automated versioning from git tags** via `hatch-vcs`. The version number is automatically derived from git tags during build time, eliminating the need for manual version bumps in code.
8+
9+
## Release Workflow
10+
11+
### Prerequisites
12+
13+
- Commit access to the repository
14+
- PyPI publishing permissions (handled via GitHub Actions)
15+
- All tests passing on main branch
16+
17+
### Step-by-Step Release Process
18+
19+
#### 1. Ensure main branch is ready
20+
21+
```bash
22+
# Make sure you're on main and up to date
23+
git checkout main
24+
git pull origin main
25+
26+
# Verify all tests pass
27+
uvx --with tox-uv tox
28+
29+
# Check current status
30+
git status # Should be clean
31+
```
32+
33+
#### 2. Review changes since last release
34+
35+
```bash
36+
# See what's changed since last tag
37+
git log $(git describe --tags --abbrev=0)..HEAD --oneline
38+
39+
# Or view in GitHub
40+
# https://github.com/mxstack/mxdev/compare/v4.1.0...main
41+
```
42+
43+
#### 3. Update CHANGES.md
44+
45+
Edit [CHANGES.md](CHANGES.md) to document the changes in this release:
46+
47+
```markdown
48+
## 4.2.0 (2025-10-20)
49+
50+
### Features
51+
52+
- Added new feature X
53+
- Improved Y performance
54+
55+
### Bug Fixes
56+
57+
- Fixed issue with Z
58+
59+
### Internal
60+
61+
- Migrated to hatchling build backend
62+
```
63+
64+
Commit the changes:
65+
66+
```bash
67+
git add CHANGES.md
68+
git commit -m "Prepare release 4.2.0"
69+
git push origin main
70+
```
71+
72+
#### 4. Create GitHub Release
73+
74+
1. Go to https://github.com/mxstack/mxdev/releases/new
75+
2. Click "Choose a tag" and type the new version: `v4.2.0` (with `v` prefix!)
76+
3. Click "Create new tag: v4.2.0 on publish"
77+
4. Set release title: `v4.2.0` or `Version 4.2.0`
78+
5. Copy relevant section from CHANGES.md into release description
79+
6. Click "Publish release"
80+
81+
**The GitHub Actions workflow will automatically:**
82+
- Run all tests across Python 3.8-3.12 on Ubuntu, Windows, macOS
83+
- Build the package with version `4.2.0` (from the tag)
84+
- Publish to PyPI if tests pass
85+
86+
#### 5. Monitor the release
87+
88+
1. Watch the GitHub Actions workflow: https://github.com/mxstack/mxdev/actions
89+
2. Verify tests pass (usually ~5-10 minutes)
90+
3. Check PyPI once published: https://pypi.org/project/mxdev/
91+
92+
#### 6. Post-release steps
93+
94+
The workflow automatically runs `make postrelease` which handles:
95+
- Creating post-release version bump commit
96+
- Any other zest.releaser configured tasks
97+
98+
Verify and pull the changes:
99+
100+
```bash
101+
git pull origin main
102+
```
103+
104+
## Version Numbering
105+
106+
mxdev follows [Semantic Versioning](https://semver.org/):
107+
108+
- **MAJOR.MINOR.PATCH** (e.g., `4.2.1`)
109+
- **MAJOR**: Breaking changes, incompatible API changes
110+
- **MINOR**: New features, backwards-compatible
111+
- **PATCH**: Bug fixes, backwards-compatible
112+
113+
### Version Format in Git Tags
114+
115+
- Git tags: `vMAJOR.MINOR.PATCH` (e.g., `v4.2.0`)
116+
- Package version: `MAJOR.MINOR.PATCH` (e.g., `4.2.0`)
117+
118+
The `v` prefix in tags is **required** and automatically stripped by hatch-vcs.
119+
120+
## Development Versions
121+
122+
Between releases, development builds automatically get versions like:
123+
124+
```
125+
4.2.0.dev3+g1234abc
126+
```
127+
128+
Where:
129+
- `4.2.0` = Next release version (from last tag)
130+
- `dev3` = 3 commits since last tag
131+
- `g1234abc` = Git commit hash
132+
133+
This happens automatically via `hatch-vcs` - no manual intervention needed.
134+
135+
## Emergency Hotfix Release
136+
137+
For urgent fixes to a released version:
138+
139+
1. Create a branch from the tag:
140+
```bash
141+
git checkout -b hotfix-4.2.1 v4.2.0
142+
```
143+
144+
2. Make and commit the fix:
145+
```bash
146+
# Make changes
147+
git add .
148+
git commit -m "Fix critical bug X"
149+
git push origin hotfix-4.2.1
150+
```
151+
152+
3. Create pull request to main
153+
154+
4. After merge, follow normal release process with version `v4.2.1`
155+
156+
## Testing a Release (TestPyPI)
157+
158+
To test the release process without publishing to production PyPI:
159+
160+
### 1. Build locally from a tag
161+
162+
```bash
163+
# Create a test tag
164+
git tag v4.2.0-rc1
165+
166+
# Build the package
167+
python -m build
168+
169+
# Check the version in built artifacts
170+
unzip -p dist/mxdev-*.whl mxdev/_version.py
171+
# Should show: __version__ = "4.2.0rc1"
172+
173+
# Clean up test tag
174+
git tag -d v4.2.0-rc1
175+
```
176+
177+
### 2. Upload to TestPyPI (maintainers only)
178+
179+
```bash
180+
# Install twine if needed
181+
pip install twine
182+
183+
# Upload to TestPyPI
184+
twine upload --repository testpypi dist/*
185+
186+
# Test installation from TestPyPI
187+
pip install --index-url https://test.pypi.org/simple/ mxdev
188+
```
189+
190+
## Release Checklist
191+
192+
Use this checklist for each release:
193+
194+
- [ ] All tests passing on main branch
195+
- [ ] CHANGES.md updated with release notes
196+
- [ ] Changes committed and pushed to main
197+
- [ ] GitHub release created with correct tag (format: `vX.Y.Z`)
198+
- [ ] GitHub Actions workflow completed successfully
199+
- [ ] Package visible on PyPI with correct version
200+
- [ ] Post-release changes pulled from main
201+
- [ ] Release announced (if applicable)
202+
203+
## Troubleshooting
204+
205+
### Build fails with "version not found"
206+
207+
**Cause:** Building outside of a git repository or without tags.
208+
209+
**Solution:** Ensure you're in a git checkout with tags fetched:
210+
```bash
211+
git fetch --tags
212+
python -m build
213+
```
214+
215+
### Version is wrong in built package
216+
217+
**Cause:** Uncommitted changes or wrong tag checked out.
218+
219+
**Solution:** Ensure clean checkout at the tagged commit:
220+
```bash
221+
git checkout v4.2.0
222+
git status # Should show "HEAD detached at v4.2.0"
223+
python -m build
224+
```
225+
226+
### CI fails to publish to PyPI
227+
228+
**Cause:** Usually authentication issues or PyPI permissions.
229+
230+
**Solution:**
231+
1. Check GitHub Actions workflow logs
232+
2. Verify PyPI trusted publisher configuration
233+
3. Contact repository maintainers
234+
235+
### README doesn't render correctly on PyPI
236+
237+
**Cause:** Markdown formatting issue or missing files.
238+
239+
**Solution:**
240+
1. Test locally: `python -m build && twine check dist/*`
241+
2. Upload to TestPyPI first
242+
3. Fix formatting in README.md, CONTRIBUTING.md, CHANGES.md, or LICENSE.md
243+
244+
## Maintainer Notes
245+
246+
### PyPI Trusted Publisher Setup
247+
248+
This project uses GitHub Actions OIDC for PyPI publishing (no API tokens needed).
249+
250+
Configuration in PyPI:
251+
- Publisher: GitHub
252+
- Owner: mxstack
253+
- Repository: mxdev
254+
- Workflow: release.yaml
255+
- Environment: release
256+
257+
### GitHub Release Environment
258+
259+
The `release` environment in GitHub requires:
260+
- Approval from maintainers (optional, can be configured)
261+
- Runs only on release events
262+
263+
### Makefile Integration
264+
265+
The release workflow uses `make postrelease` which calls zest.releaser.
266+
267+
To customize behavior, edit the Makefile variables:
268+
```makefile
269+
ZEST_RELEASER_POSTRELEASE_OPTIONS=--no-input
270+
```
271+
272+
## Alternative: Manual Release (Not Recommended)
273+
274+
For emergency situations where GitHub Actions is unavailable:
275+
276+
```bash
277+
# 1. Checkout the tag
278+
git checkout v4.2.0
279+
280+
# 2. Build
281+
python -m build
282+
283+
# 3. Upload (requires PyPI credentials)
284+
twine upload dist/*
285+
```
286+
287+
**Note:** This bypasses CI checks and is not recommended for normal releases.
288+
289+
## Version Management Tools
290+
291+
### Checking current version
292+
293+
```bash
294+
# From git tags
295+
git describe --tags
296+
297+
# From installed package
298+
python -c "import mxdev; print(mxdev.__version__)"
299+
300+
# From built package
301+
python -m build
302+
unzip -p dist/mxdev-*.whl mxdev/_version.py
303+
```
304+
305+
### Listing all releases
306+
307+
```bash
308+
# Git tags
309+
git tag --list 'v*' --sort=-version:refname | head
310+
311+
# PyPI releases
312+
pip index versions mxdev
313+
```
314+
315+
## Further Reading
316+
317+
- [Semantic Versioning](https://semver.org/)
318+
- [hatch-vcs Documentation](https://github.com/ofek/hatch-vcs)
319+
- [GitHub Releases](https://docs.github.com/en/repositories/releasing-projects-on-github)
320+
- [PyPI Trusted Publishers](https://docs.pypi.org/trusted-publishers/)
321+
- [Python Packaging Guide](https://packaging.python.org/)

0 commit comments

Comments
 (0)