Skip to content

Commit 1547a07

Browse files
andrzejnovakclaude
andcommitted
feat: Setup automated PyPI publishing with GitHub Actions
Configure repository for PyPI publication with modern best practices: ## Package Structure - Move templates into package directory (mkdocs_header_dropdown/templates/) - Update plugin code to reference templates from package location - Ensure templates are properly included in distribution ## Configuration - Modernize pyproject.toml with SPDX license format - Add PyPI keywords for better discoverability - Add pyyaml dependency - Enhance project URLs (Issues, Documentation) - Support Python 3.7-3.12 - Create MANIFEST.in for proper source distribution ## GitHub Actions Workflows - Add CI workflow: Test on Python 3.8-3.12 across Ubuntu, macOS, Windows - Add CD workflow: Automated PyPI publishing on release - Use PyPI Trusted Publishing (no API tokens needed) - Leverage hynek/build-and-inspect-python-package for quality checks ## Documentation - Add PUBLISHING.md: Complete PyPI publishing guide - Add SETUP_SUMMARY.md: Overview of all changes - Add .github/RELEASE_CHECKLIST.md: Quick release reference - Add .github/workflows/README.md: Workflow documentation Inspired by scikit-hep/mplhep's modern packaging setup. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent f7f68eb commit 1547a07

File tree

12 files changed

+732
-5
lines changed

12 files changed

+732
-5
lines changed

.github/RELEASE_CHECKLIST.md

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
# Release Checklist
2+
3+
Quick reference for publishing a new release to PyPI.
4+
5+
## Pre-Release
6+
7+
- [ ] All tests passing on main branch
8+
- [ ] CHANGELOG.md updated with release notes
9+
- [ ] Version bumped in:
10+
- [ ] `pyproject.toml` (line 7)
11+
- [ ] `setup.py` (line 8)
12+
- [ ] Changes committed and pushed to main
13+
14+
## Release Process
15+
16+
### 1. Create Git Tag
17+
18+
```bash
19+
# Replace 0.1.0 with your version
20+
VERSION="0.1.0"
21+
git tag v${VERSION}
22+
git push origin v${VERSION}
23+
```
24+
25+
### 2. Create GitHub Release
26+
27+
**Option A: GitHub CLI**
28+
```bash
29+
gh release create v${VERSION} \
30+
--title "v${VERSION}" \
31+
--notes-file CHANGELOG.md
32+
```
33+
34+
**Option B: GitHub Web UI**
35+
1. Go to https://github.com/cms-cat/mkdocs-header-dropdown/releases/new
36+
2. Choose tag: `v0.1.0`
37+
3. Release title: `v0.1.0`
38+
4. Copy release notes from CHANGELOG.md
39+
5. Click "Publish release"
40+
41+
### 3. Verify Automatic Publishing
42+
43+
The CD workflow automatically:
44+
- ✅ Builds source and wheel distributions
45+
- ✅ Runs quality checks
46+
- ✅ Publishes to PyPI
47+
48+
Monitor progress:
49+
https://github.com/cms-cat/mkdocs-header-dropdown/actions/workflows/cd.yml
50+
51+
## Post-Release
52+
53+
- [ ] Verify package appears on PyPI: https://pypi.org/project/mkdocs-header-dropdown/
54+
- [ ] Test installation: `pip install mkdocs-header-dropdown==${VERSION}`
55+
- [ ] Verify plugin works in a test project
56+
- [ ] Update documentation if needed
57+
- [ ] Announce release (optional)
58+
59+
## First Release Only
60+
61+
Before the very first release, configure PyPI Trusted Publishing:
62+
63+
1. Go to https://pypi.org/manage/account/publishing/
64+
2. Add pending publisher:
65+
- **PyPI Project Name**: `mkdocs-header-dropdown`
66+
- **Owner**: `cms-cat`
67+
- **Repository**: `mkdocs-header-dropdown`
68+
- **Workflow**: `cd.yml`
69+
- **Environment**: `release`
70+
71+
## Troubleshooting
72+
73+
### Workflow Failed
74+
- Check Actions tab for error details
75+
- Common issues:
76+
- PyPI trusted publishing not configured
77+
- Version already exists on PyPI (bump version)
78+
- Build errors (test with `python -m build` locally)
79+
80+
### Package Not Appearing on PyPI
81+
- Verify the release was published (not just created as draft)
82+
- Check workflow completed successfully
83+
- Wait a few minutes for PyPI to index
84+
85+
### Import Errors After Installation
86+
- Verify templates included: `python -m zipfile -l dist/*.whl`
87+
- Check MANIFEST.in includes all necessary files
88+
89+
## Version Numbering
90+
91+
Follow [Semantic Versioning](https://semver.org/):
92+
93+
- **MAJOR** (X.0.0): Breaking changes
94+
- **MINOR** (0.X.0): New features (backward compatible)
95+
- **PATCH** (0.0.X): Bug fixes
96+
97+
Examples:
98+
- `0.1.0``0.1.1`: Bug fix
99+
- `0.1.0``0.2.0`: New feature
100+
- `0.9.0``1.0.0`: Stable release or breaking change
101+
102+
## Quick Commands
103+
104+
```bash
105+
# Check current version
106+
grep '^version = ' pyproject.toml
107+
108+
# Test build locally
109+
python -m build
110+
twine check dist/*
111+
112+
# Clean build artifacts
113+
rm -rf dist/ build/ *.egg-info
114+
115+
# View releases
116+
gh release list
117+
118+
# View workflow runs
119+
gh run list --workflow=cd.yml
120+
```
121+
122+
## Resources
123+
124+
- Full guide: `PUBLISHING.md`
125+
- Workflow details: `.github/workflows/README.md`
126+
- PyPI package: https://pypi.org/project/mkdocs-header-dropdown/
127+
- GitHub releases: https://github.com/cms-cat/mkdocs-header-dropdown/releases

.github/workflows/README.md

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
# GitHub Actions Workflows
2+
3+
This directory contains automated workflows for continuous integration and deployment.
4+
5+
## Workflows
6+
7+
### CI (Continuous Integration) - `ci.yml`
8+
9+
**Triggers:** Push to `main`, Pull Requests, Manual dispatch
10+
11+
**Purpose:** Test the package across multiple Python versions and operating systems.
12+
13+
**Jobs:**
14+
- **test**: Runs on Python 3.8-3.12 across Ubuntu, macOS, and Windows
15+
- Installs the package
16+
- Tests imports
17+
- Validates plugin registration with MkDocs
18+
19+
- **lint**: Code quality checks using ruff
20+
21+
### CD (Continuous Deployment) - `cd.yml`
22+
23+
**Triggers:** Push to `main`, Pull Requests, Releases, Manual dispatch
24+
25+
**Purpose:** Build distribution packages and publish to PyPI on releases.
26+
27+
**Jobs:**
28+
- **dist**: Builds and inspects the Python package using `hynek/build-and-inspect-python-package`
29+
- Runs on all triggers (for validation)
30+
- Creates source distribution (`.tar.gz`) and wheel (`.whl`)
31+
- Uploads as artifacts
32+
33+
- **publish**: Publishes to PyPI using trusted publishing
34+
- **Only runs on release events** (when you publish a GitHub release)
35+
- Uses PyPI's trusted publishing (no API tokens needed)
36+
- Requires the `release` environment
37+
- Downloads build artifacts from the `dist` job
38+
- Publishes to https://pypi.org/project/mkdocs-header-dropdown/
39+
40+
### Deploy Docs - `deploy-docs.yml`
41+
42+
**Purpose:** Deploys documentation site (existing workflow).
43+
44+
## Setup Required
45+
46+
### For CD Workflow (PyPI Publishing)
47+
48+
1. **Configure PyPI Trusted Publishing:**
49+
- Go to https://pypi.org/manage/account/publishing/
50+
- Add publisher for this repository
51+
- See `PUBLISHING.md` for detailed instructions
52+
53+
2. **Create GitHub Environment (optional but recommended):**
54+
- Repository Settings → Environments → New environment
55+
- Name it `release`
56+
- Add branch protection rules if desired
57+
58+
## Usage
59+
60+
### Running Tests
61+
62+
Tests run automatically on every push and PR. To manually trigger:
63+
64+
```bash
65+
# Via GitHub UI: Actions tab → CI → Run workflow
66+
# Or use GitHub CLI:
67+
gh workflow run ci.yml
68+
```
69+
70+
### Publishing a Release
71+
72+
1. Update version in `pyproject.toml` and `setup.py`
73+
2. Commit and push changes
74+
3. Create a git tag: `git tag v0.1.0 && git push origin v0.1.0`
75+
4. Create a GitHub release (via UI or `gh release create`)
76+
5. The CD workflow automatically publishes to PyPI
77+
78+
See `PUBLISHING.md` for complete instructions.
79+
80+
## Badges
81+
82+
Add these badges to your README:
83+
84+
```markdown
85+
[![CI](https://github.com/cms-cat/mkdocs-header-dropdown/actions/workflows/ci.yml/badge.svg)](https://github.com/cms-cat/mkdocs-header-dropdown/actions/workflows/ci.yml)
86+
[![CD](https://github.com/cms-cat/mkdocs-header-dropdown/actions/workflows/cd.yml/badge.svg)](https://github.com/cms-cat/mkdocs-header-dropdown/actions/workflows/cd.yml)
87+
[![PyPI](https://img.shields.io/pypi/v/mkdocs-header-dropdown)](https://pypi.org/project/mkdocs-header-dropdown/)
88+
[![Python Versions](https://img.shields.io/pypi/pyversions/mkdocs-header-dropdown)](https://pypi.org/project/mkdocs-header-dropdown/)
89+
```

.github/workflows/cd.yml

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
name: CD
2+
3+
on:
4+
workflow_dispatch:
5+
pull_request:
6+
push:
7+
branches:
8+
- main
9+
release:
10+
types:
11+
- published
12+
13+
jobs:
14+
dist:
15+
name: Build distribution
16+
runs-on: ubuntu-latest
17+
steps:
18+
- uses: actions/checkout@v4
19+
with:
20+
fetch-depth: 0
21+
22+
- uses: hynek/build-and-inspect-python-package@v2
23+
24+
publish:
25+
name: Publish to PyPI
26+
needs: [dist]
27+
environment:
28+
name: release
29+
url: https://pypi.org/project/mkdocs-header-dropdown/
30+
permissions:
31+
id-token: write # Required for trusted publishing
32+
runs-on: ubuntu-latest
33+
if: github.event_name == 'release' && github.event.action == 'published'
34+
steps:
35+
- uses: actions/download-artifact@v4
36+
with:
37+
name: Packages
38+
path: dist
39+
40+
- name: Publish to PyPI
41+
uses: pypa/gh-action-pypi-publish@release/v1

.github/workflows/ci.yml

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
name: CI
2+
3+
on:
4+
workflow_dispatch:
5+
push:
6+
branches:
7+
- main
8+
pull_request:
9+
10+
jobs:
11+
test:
12+
name: "🐍 ${{ matrix.python-version }} • ${{ matrix.os }}"
13+
runs-on: ${{ matrix.os }}
14+
strategy:
15+
fail-fast: false
16+
matrix:
17+
os: [ubuntu-latest]
18+
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"]
19+
include:
20+
- os: macos-latest
21+
python-version: "3.12"
22+
- os: windows-latest
23+
python-version: "3.12"
24+
25+
steps:
26+
- uses: actions/checkout@v4
27+
28+
- name: Set up Python ${{ matrix.python-version }}
29+
uses: actions/setup-python@v5
30+
with:
31+
python-version: ${{ matrix.python-version }}
32+
cache: 'pip'
33+
34+
- name: Install package
35+
run: |
36+
python -m pip install --upgrade pip
37+
pip install -e .
38+
39+
- name: Test import
40+
run: python -c "import mkdocs_header_dropdown; from mkdocs_header_dropdown.plugin import HeaderDropdownPlugin"
41+
42+
- name: Install test dependencies
43+
run: |
44+
pip install mkdocs>=1.4.0 mkdocs-material pyyaml
45+
46+
- name: Test plugin registration
47+
run: |
48+
python -c "from mkdocs.plugins import get_plugin_logger; print('Plugin system functional')"
49+
50+
lint:
51+
name: Lint code
52+
runs-on: ubuntu-latest
53+
steps:
54+
- uses: actions/checkout@v4
55+
56+
- name: Set up Python
57+
uses: actions/setup-python@v5
58+
with:
59+
python-version: "3.12"
60+
61+
- name: Install dependencies
62+
run: |
63+
python -m pip install --upgrade pip
64+
pip install ruff
65+
66+
- name: Lint with ruff
67+
run: ruff check mkdocs_header_dropdown/
68+
continue-on-error: true

MANIFEST.in

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
include README.md
2+
include LICENSE
3+
include CHANGELOG.md
4+
include QUICKSTART.md
5+
include USAGE.md
6+
include CONTRIBUTING.md
7+
recursive-include mkdocs_header_dropdown/templates *

0 commit comments

Comments
 (0)