This guide explains how to publish the package to PyPI using GitHub Actions automation.
This repository uses GitHub Actions to:
- Run tests automatically on every push and pull request
- Publish to PyPI automatically when you create a GitHub release
Modern PyPI uses "Trusted Publishers" instead of API tokens. This is more secure and doesn't require storing secrets.
-
Go to PyPI: https://pypi.org/manage/account/publishing/
-
Add a new publisher:
- PyPI Project Name:
generic-llm-api-client - Owner:
RISE-UNIBAS - Repository name:
generic_llm_api_client - Workflow name:
publish.yml - Environment name:
pypi
- PyPI Project Name:
-
Click "Add"
That's it! No API tokens needed. GitHub Actions will authenticate automatically using OIDC.
- Go to https://codecov.io/ and sign in with GitHub
- Enable the
RISE-UNIBAS/generic_llm_api_clientrepository - Get your Codecov token
- Add it as a GitHub secret:
- Go to:
https://github.com/RISE-UNIBAS/generic_llm_api_client/settings/secrets/actions - Click "New repository secret"
- Name:
CODECOV_TOKEN - Value: Your Codecov token
- Click "Add secret"
- Go to:
The test workflow (.github/workflows/tests.yml) runs automatically on:
- Every push to
main,master, ordevelopbranches - Every pull request
- ✅ Tests on 3 operating systems: Ubuntu, Windows, macOS
- ✅ Tests on 4 Python versions: 3.9, 3.10, 3.11, 3.12
- ✅ Runs unit tests only (no API calls, no cost)
- ✅ Generates coverage reports
- ✅ Checks code formatting (black)
- ✅ Runs linting (ruff)
Go to: https://github.com/RISE-UNIBAS/generic_llm_api_client/actions
Each commit will show a green checkmark ✅ or red X ❌.
Publishing happens automatically when you create a GitHub release:
-
Update version in
pyproject.toml:version = "0.1.1" # Increment version number
-
Commit and push:
git add pyproject.toml git commit -m "Bump version to 0.1.1" git push -
Create a GitHub Release:
Option A: Via GitHub UI
- Go to: https://github.com/RISE-UNIBAS/generic_llm_api_client/releases/new
- Tag:
v0.1.1(must match pyproject.toml version) - Release title:
v0.1.1orVersion 0.1.1 - Description: List changes (see example below)
- Click "Publish release"
Option B: Via GitHub CLI
gh release create v0.1.1 \ --title "v0.1.1" \ --notes "## Changes - Added support for feature X - Fixed bug Y - Improved Z"
-
Wait for automation (1-2 minutes):
- GitHub Actions builds the package
- Publishes to PyPI
- Uploads signed artifacts to GitHub release
-
Verify on PyPI:
If you need to publish manually for some reason:
# 1. Install build tools
pip install build twine
# 2. Clean old builds
rm -rf dist/ build/ *.egg-info
# 3. Build the package
python -m build
# 4. Upload to PyPI (requires PyPI API token)
twine upload dist/*Follow Semantic Versioning:
- Major (1.0.0): Breaking changes
- Minor (0.2.0): New features, backward compatible
- Patch (0.1.1): Bug fixes, backward compatible
# Bug fix release
version = "0.1.1"
# New feature release
version = "0.2.0"
# Breaking change (when ready for v1)
version = "1.0.0"Before creating a release:
# Run unit tests
pytest
# Run with coverage
pytest --cov=ai_client --cov-report=term-missing
# Optionally: Run integration tests
pytest -m integrationEdit pyproject.toml:
version = "0.1.1" # Increment appropriatelyCreate/update CHANGELOG.md with release notes:
## [0.1.1] - 2025-10-28
### Added
- Support for OpenRouter and sciCORE providers
### Fixed
- Image MIME type detection for all providers
- Gemini client compatibility with google-genai 1.46.0
### Changed
- Improved error messages in integration testsgit add pyproject.toml CHANGELOG.md
git commit -m "Bump version to 0.1.1"
git pushgh release create v0.1.1 \
--title "v0.1.1" \
--notes-file CHANGELOG.mdWatch: https://github.com/RISE-UNIBAS/generic_llm_api_client/actions
You should see:
- ✅ Build distribution
- ✅ Publish to PyPI
- ✅ Upload artifacts to release
Check: https://pypi.org/project/generic-llm-api-client/
Test installation:
pip install --upgrade generic-llm-api-clientProblem: PyPI rejects the publish because settings don't match.
Solution: Check that PyPI trusted publisher settings match exactly:
- Repository owner:
RISE-UNIBAS - Repository name:
generic_llm_api_client - Workflow:
publish.yml - Environment:
pypi
Problem: You're trying to publish a version that's already on PyPI.
Solution: You can't overwrite PyPI versions. Increment the version number:
version = "0.1.2" # New versionProblem: Tests pass on your machine but fail on GitHub Actions.
Possible causes:
- Missing dependency in
pyproject.toml - OS-specific issue (test on Linux if you develop on Windows)
- Python version incompatibility
Solution: Check the GitHub Actions logs to see what failed.
If GitHub Actions fails and you need to publish immediately:
# Get a PyPI API token from https://pypi.org/manage/account/token/
export TWINE_USERNAME=__token__
export TWINE_PASSWORD=pypi-...your-token...
python -m build
twine upload dist/*# Make sure you're on main
git checkout main
git pull
# Then create release
gh release create v0.1.1Bad:
v0.1.1
Bug fixes
Good:
v0.1.1 - Improved Provider Support
## Changes
- Added OpenRouter and sciCORE integration tests
- Fixed image MIME type detection for PNG files across all providers
- Updated Gemini client for google-genai 1.46.0 compatibility
## Bug Fixes
- Fixed Claude client rejecting PNG images (was expecting JPEG)
- Fixed finish_reason enum parsing in Gemini responses
Always run tests before creating a release:
pytestDocument all changes in CHANGELOG.md before releasing.
Automated workflow:
- Update version in
pyproject.toml - Commit and push
- Create GitHub release (tag must be
v{version}) - Wait 1-2 minutes
- Package is on PyPI! 🎉
Key URLs:
- Repository: https://github.com/RISE-UNIBAS/generic_llm_api_client
- Actions: https://github.com/RISE-UNIBAS/generic_llm_api_client/actions
- PyPI: https://pypi.org/project/generic-llm-api-client/
- Releases: https://github.com/RISE-UNIBAS/generic_llm_api_client/releases
For questions, open an issue: https://github.com/RISE-UNIBAS/generic_llm_api_client/issues