Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
159 changes: 159 additions & 0 deletions .github/RELEASE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
# Release Process

This document describes the process for releasing a new version of nmcli.

## Current Release Flow (Phase 1: GitHub Release)

Currently, only GitHub Release automation is implemented. PyPI publishing automation will be added in the future.

## Pre-Release Checklist

- [ ] All tests pass (`python -m pytest tests`)
- [ ] Type checking passes (`python -m mypy nmcli`)
- [ ] Lint checks pass (`python -m pylint nmcli`)
- [ ] README.md Change Log is updated
- [ ] README.md API documentation is up to date
- [ ] README.md Compatibility table is up to date

## Release Steps

### 1. Determine Version Number

Follow semantic versioning:
- **MAJOR**: Incompatible API changes
- **MINOR**: Backwards-compatible functionality additions
- **PATCH**: Backwards-compatible bug fixes

Example: Current `1.6.0` → Next `1.7.0` (for feature additions)

### 2. Update pyproject.toml Version

```toml
[project]
version = "1.7.0" # ← Update this
```

### 3. Update README.md Change Log

Add the new version's changes to the "Change Log" section in README.md:

```markdown
### 1.7.0

- Added support for `connection.show_all` with active filtering
- Added support for `device.up` and `device.down` commands
- Added support for `general.reload` with configuration flags
```

### 4. Commit Changes

```bash
git add pyproject.toml README.md
git commit -m "Release v1.7.0"
```

### 5. Create and Push Tag

```bash
# Push to main branch
git push origin main

# Create tag
git tag v1.7.0

# Push tag (this triggers GitHub Actions)
git push origin v1.7.0
```

### 6. Verify GitHub Actions Completion

1. Check workflow execution status at https://github.com/ushiboy/nmcli/actions
2. Verify all tests pass
3. Verify build succeeds

### 7. Edit and Publish Draft Release

1. Go to https://github.com/ushiboy/nmcli/releases
2. Open the auto-created draft release
3. Edit release notes:
- Review auto-generated content
- Add main changes as bullet points in the "What's Changed" section
- Clean up commit history if needed
4. Click "Publish release" to publish

### 8. Manual PyPI Publishing (Current)

PyPI publishing is currently done manually:

```bash
# Build (requires Python 3.10+)
python -m build

# Upload to PyPI
twine upload dist/nmcli-1.7.0*
```

## Troubleshooting

### Tag and Version Mismatch Error

```
Error: Package version (1.6.0) does not match tag version (1.7.0)
```

**Cause**: Forgot to update version in pyproject.toml

**Solution**:
1. Delete tag: `git tag -d v1.7.0 && git push origin :v1.7.0`
2. Fix pyproject.toml and commit
3. Create and push tag again

### Test Failures

**Solution**:
1. Delete tag (see above)
2. Fix tests and commit
3. Create and push tag again

### Build Failures

Recommended to verify locally before tagging:

```bash
# Clean build verification
rm -rf dist/
python -m build

# Check generated files
ls -lh dist/
```

## Future Extension (Phase 2: PyPI Auto-Publishing)

The following will be added in the future:

1. **PyPI Trusted Publishers Setup**
- Register GitHub repository as a trusted publisher on PyPI
- No token management needed, more secure

2. **Workflow Extension**
- Automatically publish to PyPI after GitHub Release
- Or make PyPI publishing optional at draft stage

3. **TestPyPI Validation**
- Validate on TestPyPI before production release

## Release Checklist

Before releasing, verify:

- [ ] Updated pyproject.toml version
- [ ] Updated README.md Change Log
- [ ] All tests pass locally
- [ ] Committed changes
- [ ] Pushed to main
- [ ] Created and pushed tag
- [ ] Verified GitHub Actions completion
- [ ] Edited draft release
- [ ] Published release
- [ ] (Current) Manually uploaded to PyPI
98 changes: 98 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
name: Release

on:
push:
tags:
- 'v*.*.*'

permissions:
contents: write

jobs:
# Run tests first to ensure quality
test:
runs-on: ${{ matrix.os }}
strategy:
matrix:
include:
- python-version: '3.7'
os: ubuntu-22.04
- python-version: '3.8'
os: ubuntu-latest
- python-version: '3.9'
os: ubuntu-latest
- python-version: '3.10'
os: ubuntu-latest
- python-version: '3.11'
os: ubuntu-latest
- python-version: '3.12'
os: ubuntu-latest
- python-version: '3.13'
os: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
python -m pip install -U pip
pip install -r develop-requirements.txt
- name: Check mypy
run: python -m mypy nmcli
- name: Check lint
run: python -m pylint nmcli
- name: Run unit tests
run: python -m pytest tests

# Build and create release after tests pass
build-and-release:
needs: test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.10'

- name: Install build dependencies
run: |
python -m pip install -U pip
pip install build

- name: Build package
run: python -m build

- name: Extract version from tag
id: version
run: echo "version=${GITHUB_REF#refs/tags/v}" >> $GITHUB_OUTPUT

- name: Verify version matches
run: |
PKG_VERSION=$(grep '^version = ' pyproject.toml | cut -d '"' -f 2)
TAG_VERSION="${{ steps.version.outputs.version }}"
if [ "$PKG_VERSION" != "$TAG_VERSION" ]; then
echo "Error: Package version ($PKG_VERSION) does not match tag version ($TAG_VERSION)"
exit 1
fi

- name: Create GitHub Release
uses: softprops/action-gh-release@v2
with:
# Auto-generate release notes (editable after creation)
generate_release_notes: true
# Create as draft (publish after manual review)
draft: true
# Attach build artifacts
files: |
dist/*.whl
dist/*.tar.gz
# Release body template (shown before auto-generated notes)
body: |
## What's Changed

<!-- Add main changes as bullet points here -->

**Full Changelog**: https://github.com/${{ github.repository }}/compare/v${{ steps.version.outputs.version }}...v${{ steps.version.outputs.version }}