Skip to content

Commit 81d4fa1

Browse files
authored
Merge pull request #24 from baselinrhq/bwaite/versioning
Adding version management
2 parents 11453e6 + 162d56e commit 81d4fa1

File tree

8 files changed

+398
-4
lines changed

8 files changed

+398
-4
lines changed

.github/workflows/release.yml

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
name: Release
2+
3+
on:
4+
push:
5+
tags:
6+
- 'v*.*.*' # Triggers on tags like v0.1.1, v0.2.0, v1.0.0
7+
8+
permissions:
9+
contents: write
10+
id-token: write # Required for PyPI trusted publishing
11+
12+
jobs:
13+
build-and-publish:
14+
runs-on: ubuntu-latest
15+
steps:
16+
- name: Checkout
17+
uses: actions/checkout@v4
18+
with:
19+
fetch-depth: 0 # Required for setuptools-scm to work correctly
20+
21+
- name: Set up Python
22+
uses: actions/setup-python@v5
23+
with:
24+
python-version: '3.12'
25+
26+
- name: Install build dependencies
27+
run: |
28+
python -m pip install --upgrade pip
29+
pip install build twine setuptools wheel setuptools-scm[toml]
30+
31+
- name: Extract version from tag
32+
id: version
33+
run: |
34+
TAG_NAME=${GITHUB_REF#refs/tags/}
35+
# Remove 'v' prefix if present for version
36+
VERSION=${TAG_NAME#v}
37+
echo "version=$VERSION" >> $GITHUB_OUTPUT
38+
echo "Building version: $VERSION"
39+
40+
- name: Build package
41+
run: python -m build
42+
env:
43+
SETUPTOOLS_SCM_PRETEND_VERSION: ${{ steps.version.outputs.version }}
44+
45+
- name: Verify package
46+
run: |
47+
python -m twine check dist/*
48+
49+
- name: Publish to PyPI
50+
uses: pypa/gh-action-pypi-publish@release/v1
51+
# Uses PyPI trusted publishing - no API token needed!
52+
# Make sure to enable trusted publishing in PyPI project settings
53+
54+
- name: Extract tag name
55+
id: tag
56+
run: |
57+
TAG_NAME=${GITHUB_REF#refs/tags/}
58+
echo "tag_name=$TAG_NAME" >> $GITHUB_OUTPUT
59+
# Remove 'v' prefix if present for release name
60+
RELEASE_NAME=${TAG_NAME#v}
61+
echo "release_name=$RELEASE_NAME" >> $GITHUB_OUTPUT
62+
63+
- name: Create GitHub Release
64+
uses: softprops/action-gh-release@v1
65+
with:
66+
name: Release ${{ steps.tag.outputs.release_name }}
67+
body: |
68+
## Release ${{ steps.tag.outputs.release_name }}
69+
70+
This release was automatically created from tag `${{ steps.tag.outputs.tag_name }}`.
71+
72+
### Installation
73+
74+
```bash
75+
pip install baselinr==${{ steps.tag.outputs.release_name }}
76+
```
77+
78+
### What's Changed
79+
80+
See the [full changelog](https://github.com/${{ github.repository }}/compare/${{ steps.tag.outputs.tag_name }}^...${{ steps.tag.outputs.tag_name }}) for details.
81+
82+
draft: false
83+
prerelease: false
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
name: Version Check
2+
3+
on:
4+
pull_request:
5+
types: [opened, synchronize, reopened]
6+
7+
permissions:
8+
contents: read
9+
pull-requests: write # Required to comment on PRs
10+
11+
jobs:
12+
check-version:
13+
runs-on: ubuntu-latest
14+
steps:
15+
- name: Checkout
16+
uses: actions/checkout@v4
17+
with:
18+
fetch-depth: 0
19+
20+
- name: Set up Python
21+
uses: actions/setup-python@v5
22+
with:
23+
python-version: '3.12'
24+
25+
- name: Install setuptools-scm
26+
run: |
27+
python -m pip install --upgrade pip
28+
pip install setuptools-scm[toml]
29+
30+
- name: Check version can be determined
31+
run: |
32+
cd baselinr
33+
python -c "from setuptools_scm import get_version; print(f'Version: {get_version()}')"
34+
continue-on-error: true
35+
36+
- name: Get current version
37+
id: current
38+
run: |
39+
cd baselinr
40+
VERSION=$(python -c "from setuptools_scm import get_version; print(get_version())" 2>/dev/null || echo "0.1.0.dev0")
41+
echo "version=$VERSION" >> $GITHUB_OUTPUT
42+
echo "Current version: $VERSION"
43+
44+
- name: Comment version info
45+
uses: actions/github-script@v7
46+
if: github.event_name == 'pull_request'
47+
with:
48+
script: |
49+
const version = '${{ steps.current.outputs.version }}';
50+
github.rest.issues.createComment({
51+
issue_number: context.issue.number,
52+
owner: context.repo.owner,
53+
repo: context.repo.repo,
54+
body: `📦 **Version Check**: Current version would be \`${version}\`\n\nThis is determined from git tags using setuptools-scm. When this PR is merged and a release tag is created, the version will be set automatically.`
55+
});

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,3 +75,6 @@ tmp/
7575
temp/
7676
*.tmp
7777

78+
# Auto-generated version file
79+
baselinr/baselinr/_version.py
80+

CONTRIBUTING.md

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,117 @@ Use conventional commit prefixes:
204204
- `style:` - Code style changes (formatting)
205205
- `chore:` - Maintenance tasks
206206

207+
## Release Process
208+
209+
Baselinr uses [Semantic Versioning](https://semver.org/) (SemVer) with automated releases via GitHub Actions and PyPI.
210+
211+
### Version Numbering
212+
213+
Versions follow the format `MAJOR.MINOR.PATCH`:
214+
215+
- **PATCH** (`0.1.0``0.1.1`): Bug fixes, patches, minor improvements
216+
- **MINOR** (`0.1.0``0.2.0`): New features, enhancements (non-breaking)
217+
- **MAJOR** (`0.1.0``1.0.0`): Breaking changes, major API changes
218+
219+
While in `0.x.y`, breaking changes may bump MINOR instead of MAJOR.
220+
221+
### Automated Versioning
222+
223+
Version numbers are automatically generated from git tags using `setuptools-scm`. The version is:
224+
- Read from the latest git tag (e.g., `v0.1.0` → version `0.1.0`)
225+
- Auto-generated for development installs (e.g., `0.1.0.dev5+gabc123`)
226+
- Stored in `baselinr/baselinr/_version.py` (auto-generated, do not edit)
227+
228+
### Creating a Release
229+
230+
1. **Prepare your release**:
231+
- Ensure all tests pass: `make test`
232+
- Update CHANGELOG.md (if maintained) or review recent commits
233+
- Determine the appropriate version bump (patch/minor/major)
234+
235+
2. **Create and push a git tag**:
236+
```bash
237+
# Patch release (bug fixes)
238+
git tag v0.1.1
239+
git push origin v0.1.1
240+
241+
# Minor release (new features)
242+
git tag v0.2.0
243+
git push origin v0.2.0
244+
245+
# Major release (breaking changes)
246+
git tag v1.0.0
247+
git push origin v1.0.0
248+
```
249+
250+
3. **Automated release process**:
251+
- GitHub Actions automatically:
252+
- Builds the package using the tag
253+
- Runs package verification checks
254+
- Publishes to PyPI (if trusted publishing is configured)
255+
- Creates a GitHub Release with release notes
256+
257+
4. **Verify the release**:
258+
- Check PyPI: https://pypi.org/project/baselinr/
259+
- Check GitHub Releases: https://github.com/baselinrhq/baselinr/releases
260+
- Test installation: `pip install baselinr==<version>`
261+
262+
### Release Workflow
263+
264+
The release process is fully automated via `.github/workflows/release.yml`:
265+
266+
- **Trigger**: Pushing a tag matching `v*.*.*` (e.g., `v0.1.1`)
267+
- **Build**: Creates source distribution and wheel
268+
- **Publish**: Uploads to PyPI using trusted publishing
269+
- **Release**: Creates a GitHub Release with changelog
270+
271+
### PyPI Trusted Publishing Setup
272+
273+
To enable automated PyPI publishing:
274+
275+
1. Go to PyPI → Your project → Settings → Manage API tokens
276+
2. Enable "Trusted publishing" for your GitHub repository
277+
3. Add the repository: `baselinrhq/baselinr`
278+
4. Save the configuration
279+
280+
Once enabled, releases will automatically publish to PyPI without requiring API tokens.
281+
282+
### Development Releases
283+
284+
For development/testing before a full release:
285+
286+
1. Create a pre-release tag: `v0.1.1-rc1` or `v0.2.0-alpha1`
287+
2. These will be published to PyPI with the full tag as the version
288+
3. Users can install with: `pip install baselinr==0.1.1rc1`
289+
290+
### Rapid Release Workflow
291+
292+
When pushing PRs rapidly:
293+
294+
- **Daily releases**: Use patch versions (`0.1.1`, `0.1.2`, `0.1.3`, ...)
295+
- **Weekly feature releases**: Use minor versions (`0.2.0`, `0.3.0`, ...)
296+
- **Major milestones**: Use major versions (`1.0.0`, `2.0.0`, ...)
297+
298+
You can release as frequently as needed - each tag triggers a new release automatically.
299+
300+
### Manual Release (if needed)
301+
302+
If you need to manually build and publish:
303+
304+
```bash
305+
# Install build tools
306+
pip install build twine setuptools-scm
307+
308+
# Build package
309+
python -m build
310+
311+
# Verify package
312+
python -m twine check dist/*
313+
314+
# Publish to PyPI (requires PyPI credentials)
315+
python -m twine upload dist/*
316+
```
317+
207318
## Questions?
208319

209320
- Check existing [issues](https://github.com/baselinrhq/baselinr/issues)

RELEASE.md

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
# Release Guide
2+
3+
Quick reference guide for creating releases of Baselinr.
4+
5+
## Quick Start
6+
7+
1. **Tag and push**:
8+
```bash
9+
git tag v0.1.1 # Use appropriate version (patch/minor/major)
10+
git push origin v0.1.1
11+
```
12+
13+
2. **Wait for automation**: GitHub Actions will automatically:
14+
- Build the package
15+
- Publish to PyPI
16+
- Create a GitHub Release
17+
18+
## Version Numbering
19+
20+
Follow [Semantic Versioning](https://semver.org/):
21+
22+
- **PATCH** (`0.1.0``0.1.1`): Bug fixes, patches
23+
- **MINOR** (`0.1.0``0.2.0`): New features (non-breaking)
24+
- **MAJOR** (`0.1.0``1.0.0`): Breaking changes
25+
26+
## Release Checklist
27+
28+
Before creating a release tag:
29+
30+
- [ ] All tests pass: `make test`
31+
- [ ] Code is formatted: `make format`
32+
- [ ] Linting passes: `make lint`
33+
- [ ] Documentation is up to date
34+
- [ ] CHANGELOG updated (if maintained)
35+
- [ ] Version number determined (patch/minor/major)
36+
37+
## Creating the Tag
38+
39+
```bash
40+
# Patch release (bug fixes)
41+
git tag v0.1.1
42+
git push origin v0.1.1
43+
44+
# Minor release (new features)
45+
git tag v0.2.0
46+
git push origin v0.2.0
47+
48+
# Major release (breaking changes)
49+
git tag v1.0.0
50+
git push origin v1.0.0
51+
```
52+
53+
## Verify Release
54+
55+
After pushing the tag, check:
56+
57+
1. **GitHub Actions**: https://github.com/baselinrhq/baselinr/actions
58+
- Look for "Release" workflow to complete successfully
59+
60+
2. **PyPI**: https://pypi.org/project/baselinr/
61+
- Verify new version appears
62+
- Test installation: `pip install baselinr==<version>`
63+
64+
3. **GitHub Releases**: https://github.com/baselinrhq/baselinr/releases
65+
- Verify release notes were created
66+
67+
## Troubleshooting
68+
69+
### Release workflow failed
70+
71+
- Check GitHub Actions logs for errors
72+
- Verify PyPI trusted publishing is configured
73+
- Ensure tag format matches `v*.*.*` (e.g., `v0.1.1`)
74+
75+
### Version not appearing on PyPI
76+
77+
- Check PyPI project settings → Trusted publishing
78+
- Verify repository is linked: `baselinrhq/baselinr`
79+
- Check GitHub Actions logs for PyPI publish step
80+
81+
### Version is wrong
82+
83+
- Ensure git tags exist: `git tag`
84+
- Verify setuptools-scm is installed: `pip install setuptools-scm`
85+
- Check tag format matches SemVer: `v0.1.1` not `0.1.1` (note the `v` prefix)
86+
87+
## Development Version
88+
89+
To check the current development version:
90+
91+
```bash
92+
cd baselinr
93+
python -c "from setuptools_scm import get_version; print(get_version())"
94+
```
95+
96+
This will show something like `0.1.0.dev5+gabc123` if no release tag exists.
97+
98+
## Manual Release (If Needed)
99+
100+
If you need to manually publish:
101+
102+
```bash
103+
# Install build tools
104+
pip install build twine setuptools-scm
105+
106+
# Build package
107+
python -m build
108+
109+
# Verify package
110+
python -m twine check dist/*
111+
112+
# Publish to PyPI (requires credentials)
113+
python -m twine upload dist/*
114+
```
115+
116+
## Rapid Release Strategy
117+
118+
For rapid development with frequent releases:
119+
120+
- **Daily releases**: Use patch versions (`0.1.1`, `0.1.2`, `0.1.3`, ...)
121+
- **Weekly feature releases**: Use minor versions (`0.2.0`, `0.3.0`, ...)
122+
- **Major milestones**: Use major versions (`1.0.0`, `2.0.0`, ...)
123+
124+
You can release as frequently as needed - each tag triggers an automated release.
125+

0 commit comments

Comments
 (0)