Skip to content

Commit 7e0dacf

Browse files
committed
added version bumpting script
1 parent 0c9a590 commit 7e0dacf

5 files changed

Lines changed: 170 additions & 33 deletions

File tree

.github/RELEASE.md

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# Release Process
2+
3+
## Creating a Release
4+
5+
```bash
6+
python scripts/bump_version.py patch # or: minor, major
7+
git push && git push --tags
8+
```
9+
10+
Automation handles the rest: https://github.com/parameterlab/maseval/actions
11+
12+
---
13+
14+
## Troubleshooting
15+
16+
**Wrong version tagged?**
17+
18+
```bash
19+
git tag -d v0.1.2
20+
git push origin :refs/tags/v0.1.2
21+
# Then fix pyproject.toml and retry
22+
```
23+
24+
**Automation failed?**
25+
26+
```bash
27+
uv build && uv publish
28+
```
29+
30+
## Version Guide
31+
32+
- `patch`: Bug fixes (0.1.1 → 0.1.2)
33+
- `minor`: New features (0.1.1 → 0.2.0)
34+
- `major`: Breaking changes (0.1.1 → 1.0.0)

.github/workflows/publish.yml

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

.github/workflows/release.yml

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
name: Release to PyPI
2+
3+
on:
4+
push:
5+
tags:
6+
- "v*" # Triggers on version tags like v0.1.2
7+
8+
jobs:
9+
release:
10+
runs-on: ubuntu-latest
11+
permissions:
12+
contents: write
13+
id-token: write # Required for trusted publishing
14+
15+
steps:
16+
- uses: actions/checkout@v4
17+
18+
- name: Set up Python
19+
uses: actions/setup-python@v5
20+
with:
21+
python-version: "3.12"
22+
23+
- name: Install uv
24+
uses: astral-sh/setup-uv@v5
25+
26+
- name: Verify version matches tag
27+
run: |
28+
TAG_VERSION=${GITHUB_REF#refs/tags/v}
29+
PYPROJECT_VERSION=$(uv run python -c "import tomllib; print(tomllib.load(open('pyproject.toml', 'rb'))['project']['version'])")
30+
31+
if [ "$TAG_VERSION" != "$PYPROJECT_VERSION" ]; then
32+
echo "ERROR: Tag version ($TAG_VERSION) doesn't match pyproject.toml version ($PYPROJECT_VERSION)"
33+
exit 1
34+
fi
35+
echo "Version check passed: $TAG_VERSION"
36+
37+
- name: Build package
38+
run: |
39+
uv build
40+
41+
- name: Publish to PyPI
42+
uses: pypa/gh-action-pypi-publish@release/v1
43+
# Uses trusted publishing - no API token needed
44+
45+
- name: Create GitHub Release
46+
uses: softprops/action-gh-release@v1
47+
with:
48+
files: dist/*
49+
generate_release_notes: true

scripts/bump_version.py

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
#!/usr/bin/env python3
2+
"""
3+
Helper script to bump version and create git tag consistently.
4+
5+
Usage:
6+
python scripts/bump_version.py patch # 0.1.1 -> 0.1.2
7+
python scripts/bump_version.py minor # 0.1.1 -> 0.2.0
8+
python scripts/bump_version.py major # 0.1.1 -> 1.0.0
9+
"""
10+
11+
import argparse
12+
import re
13+
import subprocess
14+
from pathlib import Path
15+
16+
17+
def get_current_version(pyproject_path: Path) -> str:
18+
"""Extract version from pyproject.toml."""
19+
content = pyproject_path.read_text()
20+
match = re.search(r'^version\s*=\s*["\']([^"\']+)["\']', content, re.MULTILINE)
21+
if not match:
22+
raise ValueError("Could not find version in pyproject.toml")
23+
return match.group(1)
24+
25+
26+
def bump_version(version: str, part: str) -> str:
27+
"""Bump version according to semver."""
28+
major, minor, patch = map(int, version.split("."))
29+
30+
if part == "major":
31+
return f"{major + 1}.0.0"
32+
elif part == "minor":
33+
return f"{major}.{minor + 1}.0"
34+
elif part == "patch":
35+
return f"{major}.{minor}.{patch + 1}"
36+
else:
37+
raise ValueError(f"Invalid version part: {part}")
38+
39+
40+
def update_pyproject(pyproject_path: Path, old_version: str, new_version: str):
41+
"""Update version in pyproject.toml."""
42+
content = pyproject_path.read_text()
43+
new_content = re.sub(rf'^version\s*=\s*["\']({re.escape(old_version)})["\']', f'version = "{new_version}"', content, flags=re.MULTILINE)
44+
pyproject_path.write_text(new_content)
45+
46+
47+
def main():
48+
parser = argparse.ArgumentParser(description="Bump version and create git tag")
49+
parser.add_argument("part", choices=["major", "minor", "patch"], help="Version part to bump")
50+
parser.add_argument("--dry-run", action="store_true", help="Show what would be done")
51+
args = parser.parse_args()
52+
53+
# Get paths
54+
repo_root = Path(__file__).parent.parent
55+
pyproject_path = repo_root / "pyproject.toml"
56+
57+
# Get current version and calculate new version
58+
current_version = get_current_version(pyproject_path)
59+
new_version = bump_version(current_version, args.part)
60+
61+
print(f"Current version: {current_version}")
62+
print(f"New version: {new_version}")
63+
64+
if args.dry_run:
65+
print("\nDry run - no changes made")
66+
return
67+
68+
# Update pyproject.toml
69+
print(f"\nUpdating {pyproject_path}...")
70+
update_pyproject(pyproject_path, current_version, new_version)
71+
72+
# Commit and tag
73+
print("\nCreating git commit and tag...")
74+
subprocess.run(["git", "add", str(pyproject_path)], check=True)
75+
subprocess.run(["git", "commit", "-m", f"Bump version to {new_version}"], check=True)
76+
subprocess.run(["git", "tag", "-a", f"v{new_version}", "-m", f"Release v{new_version}"], check=True)
77+
78+
print(f"\nDone! Version bumped to {new_version}")
79+
print("\nNext steps:")
80+
print(" 1. Review the changes: git show")
81+
print(" 2. Push to GitHub: git push && git push --tags")
82+
print(" 3. GitHub Actions will handle PyPI release automatically")
83+
84+
85+
if __name__ == "__main__":
86+
main()

uv.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)