|
| 1 | +# Publishing toon_format to PyPI |
| 2 | + |
| 3 | +This guide explains how to publish the toon_format package to PyPI (Python Package Index). |
| 4 | + |
| 5 | +## Prerequisites |
| 6 | + |
| 7 | +### 1. PyPI Accounts |
| 8 | + |
| 9 | +Create accounts on both platforms: |
| 10 | + |
| 11 | +- **TestPyPI** (for testing): https://test.pypi.org/account/register/ |
| 12 | +- **PyPI** (production): https://pypi.org/account/register/ |
| 13 | + |
| 14 | +### 2. GitHub Environments |
| 15 | + |
| 16 | +The publish workflow uses GitHub environments with trusted publishing (no API tokens needed!). |
| 17 | + |
| 18 | +#### Set up environments in GitHub: |
| 19 | + |
| 20 | +1. Go to your repository Settings > Environments |
| 21 | +2. Create two environments: |
| 22 | + - `testpypi` - for TestPyPI releases |
| 23 | + - `pypi` - for production PyPI releases |
| 24 | +3. For each environment, configure: |
| 25 | + - **Deployment protection rules** (optional but recommended): |
| 26 | + - Required reviewers (for production releases) |
| 27 | + - Wait timer (optional delay before deployment) |
| 28 | + |
| 29 | +#### Configure Trusted Publishers: |
| 30 | + |
| 31 | +**For TestPyPI:** |
| 32 | +1. Log in to https://test.pypi.org |
| 33 | +2. Go to Account Settings > Publishing |
| 34 | +3. Add a new pending publisher: |
| 35 | + - PyPI Project Name: `toon_format` |
| 36 | + - Owner: `toon-format` |
| 37 | + - Repository: `toon-python` |
| 38 | + - Workflow: `publish.yml` |
| 39 | + - Environment: `testpypi` |
| 40 | + |
| 41 | +**For PyPI:** |
| 42 | +1. Log in to https://pypi.org |
| 43 | +2. Go to Account Settings > Publishing |
| 44 | +3. Add a new pending publisher: |
| 45 | + - PyPI Project Name: `toon_format` |
| 46 | + - Owner: `toon-format` |
| 47 | + - Repository: `toon-python` |
| 48 | + - Workflow: `publish.yml` |
| 49 | + - Environment: `pypi` |
| 50 | + |
| 51 | +> Note: After the first successful publish, the project will be registered and future publishes will use the same trusted publisher configuration. |
| 52 | +
|
| 53 | +## Release Process |
| 54 | + |
| 55 | +### Step 1: Prepare the Release |
| 56 | + |
| 57 | +1. **Update version number** in two places: |
| 58 | + - `pyproject.toml` (line 3): `version = "X.Y.Z"` |
| 59 | + - `src/toon_format/__init__.py` (line 28): `__version__ = "X.Y.Z"` |
| 60 | + |
| 61 | +2. **Update changelog** (if exists) or create release notes |
| 62 | + |
| 63 | +3. **Run tests locally**: |
| 64 | + ```bash |
| 65 | + uv run pytest |
| 66 | + uv run ruff check . |
| 67 | + uv run mypy src/toon_format |
| 68 | + ``` |
| 69 | + |
| 70 | +4. **Build and test locally**: |
| 71 | + ```bash |
| 72 | + # Clean previous builds |
| 73 | + rm -rf dist/ build/ *.egg-info |
| 74 | + |
| 75 | + # Build the package |
| 76 | + python -m build |
| 77 | + |
| 78 | + # Verify the package contents |
| 79 | + python -m zipfile -l dist/toon_format-X.Y.Z-py3-none-any.whl |
| 80 | + |
| 81 | + # Test installation in a clean environment |
| 82 | + python -m venv test_env |
| 83 | + test_env/bin/pip install dist/toon_format-X.Y.Z-py3-none-any.whl |
| 84 | + test_env/bin/python -c "import toon_format; print(toon_format.__version__)" |
| 85 | + rm -rf test_env |
| 86 | + ``` |
| 87 | + |
| 88 | +### Step 2: Commit and Tag |
| 89 | + |
| 90 | +1. **Commit version changes**: |
| 91 | + ```bash |
| 92 | + git add pyproject.toml src/toon_format/__init__.py |
| 93 | + git commit -m "Bump version to X.Y.Z" |
| 94 | + ``` |
| 95 | + |
| 96 | +2. **Create and push tag**: |
| 97 | + ```bash |
| 98 | + git tag -a vX.Y.Z -m "Release version X.Y.Z" |
| 99 | + git push origin main |
| 100 | + git push origin vX.Y.Z |
| 101 | + ``` |
| 102 | + |
| 103 | +### Step 3: Test on TestPyPI (Recommended) |
| 104 | + |
| 105 | +Before publishing to production PyPI, test on TestPyPI: |
| 106 | + |
| 107 | +1. Go to GitHub Actions: https://github.com/toon-format/toon-python/actions |
| 108 | +2. Select the "Publish to PyPI" workflow |
| 109 | +3. Click "Run workflow" |
| 110 | +4. Select branch: `main` (or the tag `vX.Y.Z`) |
| 111 | +5. Click "Run workflow" |
| 112 | + - Note: Manual workflow dispatch automatically publishes to TestPyPI |
| 113 | + |
| 114 | +6. **Verify the TestPyPI upload**: |
| 115 | + - Check the package: https://test.pypi.org/project/toon_format/ |
| 116 | + - Test installation: |
| 117 | + ```bash |
| 118 | + pip install --index-url https://test.pypi.org/simple/ toon_format |
| 119 | + ``` |
| 120 | + |
| 121 | +### Step 4: Publish to PyPI |
| 122 | + |
| 123 | +**Automatic (via GitHub Release)** |
| 124 | + |
| 125 | +1. Go to https://github.com/toon-format/toon-python/releases/new |
| 126 | +2. Select the tag you created: `vX.Y.Z` |
| 127 | +3. Release title: `Version X.Y.Z` |
| 128 | +4. Description: Add release notes and changelog |
| 129 | +5. Click "Publish release" |
| 130 | +6. The GitHub Action will automatically build and publish to PyPI |
| 131 | + |
| 132 | +### Step 5: Verify the Release |
| 133 | + |
| 134 | +1. **Check PyPI**: https://pypi.org/project/toon_format/ |
| 135 | +2. **Test installation**: |
| 136 | + ```bash |
| 137 | + pip install toon_format |
| 138 | + python -c "import toon_format; print(toon_format.__version__)" |
| 139 | + ``` |
| 140 | +3. **Update README badge** (optional): |
| 141 | + ```markdown |
| 142 | + [](https://pypi.org/project/toon_format/) |
| 143 | + ``` |
| 144 | + |
| 145 | +## Troubleshooting |
| 146 | + |
| 147 | +### Build fails with "metadata missing" |
| 148 | + |
| 149 | +This is usually a configuration issue in `pyproject.toml`. Verify: |
| 150 | +- All required fields are present (name, version, description, etc.) |
| 151 | +- Project URLs are properly formatted |
| 152 | +- Author email is valid |
| 153 | + |
| 154 | +### Trusted publishing fails |
| 155 | + |
| 156 | +If the trusted publisher configuration fails: |
| 157 | +1. Verify the environment name matches exactly |
| 158 | +2. Check that the repository owner and name are correct |
| 159 | +3. Ensure the workflow file path is correct (`publish.yml`) |
| 160 | +4. Make sure the PyPI project name is available or already claimed by you |
| 161 | + |
| 162 | +### Package already exists on PyPI |
| 163 | + |
| 164 | +PyPI doesn't allow overwriting published versions. You must: |
| 165 | +1. Increment the version number |
| 166 | +2. Create a new tag |
| 167 | +3. Publish the new version |
| 168 | +
|
| 169 | +## Version Numbering |
| 170 | +
|
| 171 | +Follow [Semantic Versioning](https://semver.org/): |
| 172 | +
|
| 173 | +- **MAJOR version** (X.0.0): Incompatible API changes |
| 174 | +- **MINOR version** (0.X.0): New functionality, backward compatible |
| 175 | +- **PATCH version** (0.0.X): Bug fixes, backward compatible |
| 176 | +
|
| 177 | +### Agreed Roadmap (from Discussion #18): |
| 178 | +
|
| 179 | +- **0.8.x** - Initial code set, tests, documentation, migration from toon-llm |
| 180 | +- **0.9.x** - Serializer, spec compliance, publishing to PyPI (test and prod) |
| 181 | +- **1.0.0-rc.x** - Production readiness candidates |
| 182 | +- **1.0.0** - Official stable release 🎉 |
| 183 | +
|
| 184 | +Examples: |
| 185 | +- `0.9.0-beta.1` - First beta release for testing |
| 186 | +- `0.9.0-beta.2` - Second beta with fixes |
| 187 | +- `0.9.0` - First minor release with new features |
| 188 | +- `1.0.0-rc.1` - Release candidate |
| 189 | +- `1.0.0` - First stable release |
| 190 | +
|
| 191 | +## Checklist |
| 192 | +
|
| 193 | +Before each release, verify: |
| 194 | +
|
| 195 | +- [ ] All tests pass (`uv run pytest`) |
| 196 | +- [ ] Linting passes (`uv run ruff check .`) |
| 197 | +- [ ] Type checking passes (`uv run mypy src/toon_format`) |
| 198 | +- [ ] Version updated in `pyproject.toml` and `src/toon_format/__init__.py` |
| 199 | +- [ ] Changes committed and pushed to `main` |
| 200 | +- [ ] Git tag created and pushed |
| 201 | +- [ ] Package tested on TestPyPI (optional but recommended) |
| 202 | +- [ ] GitHub Release created |
| 203 | +- [ ] Package verified on PyPI |
| 204 | +- [ ] Installation tested from PyPI |
| 205 | +
|
| 206 | +## References |
| 207 | +
|
| 208 | +- [Python Packaging Guide](https://packaging.python.org/) |
| 209 | +- [PyPI Help](https://pypi.org/help/) |
| 210 | +- [Trusted Publishing Guide](https://docs.pypi.org/trusted-publishers/) |
| 211 | +- [GitHub Actions Publishing](https://packaging.python.org/guides/publishing-package-distribution-releases-using-github-actions-ci-cd-workflows/) |
| 212 | +- [TOON Format Specification](https://github.com/toon-format/spec) |
0 commit comments