feat: release versioning — workflow, VERSION file, RELEASE.md (Plan 14)
- VERSION: 0.1.0 (synced with pyproject.toml) - release.yml: tag-triggered pipeline (test → build → changelog → release) - RELEASE.md: semver scheme, hotfix/backport process Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,87 @@
|
||||
name: Release
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- "v*"
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
jobs:
|
||||
release:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Validate tag matches VERSION file
|
||||
run: |
|
||||
TAG_VERSION="${GITHUB_REF_NAME#v}"
|
||||
FILE_VERSION="$(cat VERSION | tr -d '[:space:]')"
|
||||
if [ "$TAG_VERSION" != "$FILE_VERSION" ]; then
|
||||
echo "::error::Tag $GITHUB_REF_NAME does not match VERSION file ($FILE_VERSION)"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: "3.12"
|
||||
|
||||
- name: Install Python dependencies
|
||||
run: pip install -e ".[dev]"
|
||||
|
||||
- name: Run tests
|
||||
run: pytest --tb=short -q
|
||||
|
||||
- name: Build Python package
|
||||
run: |
|
||||
pip install build
|
||||
python -m build
|
||||
|
||||
- name: Install PlatformIO
|
||||
run: pip install platformio
|
||||
|
||||
- name: Build firmware
|
||||
run: |
|
||||
cd firmware
|
||||
pio run
|
||||
mkdir -p ../release-artifacts
|
||||
cp /tmp/kl_pio_build/esp32s3_waveshare/.pio/build/esp32s3_waveshare/firmware.bin ../release-artifacts/ 2>/dev/null || \
|
||||
cp /tmp/kl_pio_build/esp32s3_waveshare/firmware.bin ../release-artifacts/ 2>/dev/null || \
|
||||
echo "::warning::Firmware binary not found at expected path, skipping artifact"
|
||||
|
||||
- name: Collect artifacts
|
||||
run: |
|
||||
mkdir -p release-artifacts
|
||||
cp dist/*.whl release-artifacts/ 2>/dev/null || true
|
||||
cp dist/*.tar.gz release-artifacts/ 2>/dev/null || true
|
||||
ls -la release-artifacts/
|
||||
|
||||
- name: Generate changelog
|
||||
id: changelog
|
||||
run: |
|
||||
# Find the previous tag
|
||||
PREV_TAG=$(git tag --sort=-v:refname | grep '^v' | head -2 | tail -1)
|
||||
if [ "$PREV_TAG" = "$GITHUB_REF_NAME" ] || [ -z "$PREV_TAG" ]; then
|
||||
# First release — show all commits
|
||||
echo "## What's Changed" > changelog.md
|
||||
git log --pretty=format:"- %s (%h)" >> changelog.md
|
||||
else
|
||||
echo "## What's Changed since $PREV_TAG" > changelog.md
|
||||
git log --pretty=format:"- %s (%h)" "$PREV_TAG".."$GITHUB_REF_NAME" >> changelog.md
|
||||
fi
|
||||
echo "" >> changelog.md
|
||||
echo "" >> changelog.md
|
||||
echo "**Full Changelog**: https://github.com/${{ github.repository }}/compare/${PREV_TAG:-initial}...${{ github.ref_name }}" >> changelog.md
|
||||
|
||||
- name: Create GitHub Release
|
||||
uses: softprops/action-gh-release@v2
|
||||
with:
|
||||
body_path: changelog.md
|
||||
files: release-artifacts/*
|
||||
generate_release_notes: false
|
||||
draft: false
|
||||
prerelease: ${{ contains(github.ref_name, '-rc') || contains(github.ref_name, '-alpha') || contains(github.ref_name, '-beta') }}
|
||||
+99
@@ -0,0 +1,99 @@
|
||||
# Release Process
|
||||
|
||||
## Versioning Scheme
|
||||
|
||||
Kill_LIFE follows [Semantic Versioning](https://semver.org/) (SemVer):
|
||||
|
||||
- **MAJOR** (X.0.0) — incompatible API changes, breaking firmware protocol changes
|
||||
- **MINOR** (0.X.0) — new features (MCP tools, firmware capabilities, new board support)
|
||||
- **PATCH** (0.0.X) — bug fixes, documentation, non-breaking improvements
|
||||
|
||||
Pre-release suffixes: `-alpha.N`, `-beta.N`, `-rc.N`
|
||||
|
||||
The canonical version lives in the `VERSION` file at the repository root.
|
||||
`pyproject.toml` must stay in sync.
|
||||
|
||||
## Creating a Release
|
||||
|
||||
1. **Prepare the release branch** (optional for patch releases):
|
||||
```bash
|
||||
git checkout -b release/0.2.0 main
|
||||
```
|
||||
|
||||
2. **Update the version**:
|
||||
```bash
|
||||
echo "0.2.0" > VERSION
|
||||
```
|
||||
Also update `pyproject.toml`:
|
||||
```toml
|
||||
version = "0.2.0"
|
||||
```
|
||||
|
||||
3. **Commit the version bump**:
|
||||
```bash
|
||||
git add VERSION pyproject.toml
|
||||
git commit -m "chore: bump version to 0.2.0"
|
||||
```
|
||||
|
||||
4. **Create an annotated tag**:
|
||||
```bash
|
||||
git tag -a v0.2.0 -m "Release 0.2.0 — short description of highlights"
|
||||
```
|
||||
|
||||
5. **Push the tag** (this triggers the release workflow):
|
||||
```bash
|
||||
git push origin main
|
||||
git push origin v0.2.0
|
||||
```
|
||||
|
||||
6. The GitHub Actions workflow will:
|
||||
- Validate the tag matches the `VERSION` file
|
||||
- Run tests
|
||||
- Build the Python package and firmware binary
|
||||
- Create a GitHub Release with auto-generated changelog
|
||||
- Attach build artifacts (`.whl`, `.tar.gz`, `firmware.bin`)
|
||||
|
||||
## Hotfix Process
|
||||
|
||||
For urgent fixes against a released version:
|
||||
|
||||
1. **Branch from the release tag**:
|
||||
```bash
|
||||
git checkout -b hotfix/0.1.1 v0.1.0
|
||||
```
|
||||
|
||||
2. **Apply the fix**, update `VERSION` to `0.1.1`, commit.
|
||||
|
||||
3. **Tag and push**:
|
||||
```bash
|
||||
git tag -a v0.1.1 -m "Hotfix 0.1.1 — description of fix"
|
||||
git push origin hotfix/0.1.1
|
||||
git push origin v0.1.1
|
||||
```
|
||||
|
||||
4. **Merge the hotfix back into main**:
|
||||
```bash
|
||||
git checkout main
|
||||
git merge hotfix/0.1.1
|
||||
```
|
||||
|
||||
## Backport Policy
|
||||
|
||||
- **Critical security fixes**: backported to the latest minor release branch.
|
||||
- **Bug fixes**: backported only if the affected version is still actively used on deployed hardware.
|
||||
- **Features**: never backported. Users should upgrade to the latest minor release.
|
||||
|
||||
Backport branches follow the naming convention `backport/<fix-description>-to-<version>`.
|
||||
|
||||
## Pre-releases
|
||||
|
||||
For testing before a stable release:
|
||||
|
||||
```bash
|
||||
echo "0.2.0-rc.1" > VERSION
|
||||
git tag -a v0.2.0-rc.1 -m "Release candidate 1 for 0.2.0"
|
||||
git push origin v0.2.0-rc.1
|
||||
```
|
||||
|
||||
Pre-releases are automatically marked as such on GitHub when the tag contains
|
||||
`-alpha`, `-beta`, or `-rc`.
|
||||
Reference in New Issue
Block a user