|
| 1 | +# Release Guide for easy-drone |
| 2 | + |
| 3 | +This guide explains how to publish the easy-drone package to PyPI using GitHub Actions. |
| 4 | + |
| 5 | +## Prerequisites |
| 6 | + |
| 7 | +### 1. PyPI Account Setup |
| 8 | + |
| 9 | +1. Create accounts on: |
| 10 | + - [PyPI](https://pypi.org/account/register/) (for production releases) |
| 11 | + - [Test PyPI](https://test.pypi.org/account/register/) (for testing) |
| 12 | + |
| 13 | +2. Create API tokens: |
| 14 | + - **PyPI**: Go to [Account Settings → API Tokens](https://pypi.org/manage/account/token/) |
| 15 | + - **Test PyPI**: Go to [Account Settings → API Tokens](https://test.pypi.org/manage/account/token/) |
| 16 | + - Create a token with "Upload packages" scope |
| 17 | + - Save the tokens securely (they're only shown once!) |
| 18 | + |
| 19 | +### 2. GitHub Secrets Setup |
| 20 | + |
| 21 | +Add the following secrets to your GitHub repository: |
| 22 | + |
| 23 | +1. Go to your repository → Settings → Secrets and variables → Actions |
| 24 | +2. Add two secrets: |
| 25 | + - `PYPI_API_TOKEN`: Your PyPI API token |
| 26 | + - `TEST_PYPI_API_TOKEN`: Your Test PyPI API token |
| 27 | + |
| 28 | +**How to add:** |
| 29 | +- Click "New repository secret" |
| 30 | +- Name: `PYPI_API_TOKEN` |
| 31 | +- Value: `pypi-...` (your full token starting with `pypi-`) |
| 32 | +- Click "Add secret" |
| 33 | + |
| 34 | +## Workflows |
| 35 | + |
| 36 | +The project includes three GitHub Actions workflows: |
| 37 | + |
| 38 | +### 1. Test Workflow (`test.yml`) |
| 39 | +**Trigger**: Push or PR to main/master/develop branches |
| 40 | + |
| 41 | +**What it does**: |
| 42 | +- Tests installation on Ubuntu, macOS, and Windows |
| 43 | +- Tests Python versions 3.8, 3.9, 3.10, 3.11, 3.12 |
| 44 | +- Verifies imports work correctly |
| 45 | +- Runs verification script |
| 46 | +- Builds package and checks it with twine |
| 47 | + |
| 48 | +### 2. Lint Workflow (`lint.yml`) |
| 49 | +**Trigger**: Push or PR to main/master/develop branches |
| 50 | + |
| 51 | +**What it does**: |
| 52 | +- Checks code formatting with black |
| 53 | +- Checks import sorting with isort |
| 54 | +- Runs flake8 linting |
| 55 | +- All checks continue on error (non-blocking) |
| 56 | + |
| 57 | +### 3. Publish Workflow (`publish.yml`) |
| 58 | +**Trigger**: |
| 59 | +- Automatically on GitHub Release |
| 60 | +- Manually via workflow_dispatch |
| 61 | + |
| 62 | +**What it does**: |
| 63 | +- Builds the package (wheel and source distribution) |
| 64 | +- Checks package with twine |
| 65 | +- Publishes to PyPI or Test PyPI |
| 66 | + |
| 67 | +## Release Process |
| 68 | + |
| 69 | +### Option 1: Automatic Release (Recommended) |
| 70 | + |
| 71 | +#### Step 1: Update Version |
| 72 | +Edit `setup.py` and `pyproject.toml`: |
| 73 | +```python |
| 74 | +version="0.1.1" # Increment version |
| 75 | +``` |
| 76 | + |
| 77 | +#### Step 2: Commit and Push |
| 78 | +```bash |
| 79 | +git add setup.py pyproject.toml |
| 80 | +git commit -m "Bump version to 0.1.1" |
| 81 | +git push origin main |
| 82 | +``` |
| 83 | + |
| 84 | +#### Step 3: Create GitHub Release |
| 85 | +1. Go to your repository → Releases → "Draft a new release" |
| 86 | +2. Click "Choose a tag" → Type new tag (e.g., `v0.1.1`) → "Create new tag" |
| 87 | +3. Release title: `v0.1.1` or `Release 0.1.1` |
| 88 | +4. Description: List changes, new features, bug fixes |
| 89 | +5. Click "Publish release" |
| 90 | + |
| 91 | +**The workflow will automatically**: |
| 92 | +- Build the package |
| 93 | +- Publish to PyPI |
| 94 | +- Make it available via `pip install easy-drone` |
| 95 | + |
| 96 | +### Option 2: Manual Testing with Test PyPI |
| 97 | + |
| 98 | +Use this to test the release process before publishing to production PyPI. |
| 99 | + |
| 100 | +#### Step 1: Manual Workflow Trigger |
| 101 | +1. Go to Actions → "Publish to PyPI" workflow |
| 102 | +2. Click "Run workflow" |
| 103 | +3. Select branch (usually `main`) |
| 104 | +4. Choose "testpypi" from dropdown |
| 105 | +5. Click "Run workflow" |
| 106 | + |
| 107 | +#### Step 2: Test Installation |
| 108 | +```bash |
| 109 | +# Install from Test PyPI |
| 110 | +pip install --index-url https://test.pypi.org/simple/ \ |
| 111 | + --extra-index-url https://pypi.org/simple/ \ |
| 112 | + easy-drone |
| 113 | + |
| 114 | +# Test it works |
| 115 | +python -c "from gz_transport import Node; print('Success!')" |
| 116 | +``` |
| 117 | + |
| 118 | +#### Step 3: If successful, publish to PyPI |
| 119 | +1. Run workflow again |
| 120 | +2. Choose "pypi" from dropdown |
| 121 | +3. Or create a GitHub Release (automatic) |
| 122 | + |
| 123 | +## Version Numbering |
| 124 | + |
| 125 | +Follow [Semantic Versioning](https://semver.org/): |
| 126 | +- `MAJOR.MINOR.PATCH` (e.g., `1.2.3`) |
| 127 | +- **MAJOR**: Incompatible API changes |
| 128 | +- **MINOR**: New features, backward compatible |
| 129 | +- **PATCH**: Bug fixes, backward compatible |
| 130 | + |
| 131 | +Examples: |
| 132 | +- `0.1.0` → `0.1.1`: Bug fix |
| 133 | +- `0.1.0` → `0.2.0`: New feature |
| 134 | +- `0.9.0` → `1.0.0`: First stable release |
| 135 | + |
| 136 | +## Checklist Before Release |
| 137 | + |
| 138 | +- [ ] Version updated in `setup.py` and `pyproject.toml` |
| 139 | +- [ ] `CHANGES.md` or changelog updated |
| 140 | +- [ ] All tests passing (check Actions tab) |
| 141 | +- [ ] Documentation updated if needed |
| 142 | +- [ ] Committed and pushed to main branch |
| 143 | +- [ ] Created GitHub release with tag |
| 144 | + |
| 145 | +## Common Issues |
| 146 | + |
| 147 | +### Issue: "Invalid or expired token" |
| 148 | +**Solution**: Generate a new API token on PyPI and update GitHub secret |
| 149 | + |
| 150 | +### Issue: "File already exists" |
| 151 | +**Solution**: You've already published this version. Increment version number. |
| 152 | + |
| 153 | +### Issue: "Workflow fails to publish" |
| 154 | +**Solution**: |
| 155 | +- Check GitHub Actions logs |
| 156 | +- Verify secrets are set correctly |
| 157 | +- Ensure version in setup.py matches tag (without 'v' prefix) |
| 158 | + |
| 159 | +### Issue: "Package not found after publishing" |
| 160 | +**Solution**: |
| 161 | +- Wait 5-10 minutes for PyPI to index |
| 162 | +- Check [https://pypi.org/project/easy-drone/](https://pypi.org/project/easy-drone/) |
| 163 | + |
| 164 | +## After Publishing |
| 165 | + |
| 166 | +### Update Installation Instructions |
| 167 | +Users can now install with: |
| 168 | +```bash |
| 169 | +pip install easy-drone |
| 170 | + |
| 171 | +# With optional features |
| 172 | +pip install easy-drone[zenoh] |
| 173 | +pip install easy-drone[yolo] |
| 174 | +pip install easy-drone[all] |
| 175 | +``` |
| 176 | + |
| 177 | +### Announce Release |
| 178 | +- Update README badges (if any) |
| 179 | +- Post announcement (social media, forums, etc.) |
| 180 | +- Notify users of changes |
| 181 | + |
| 182 | +## Workflow Files |
| 183 | + |
| 184 | +The workflows are located in `.github/workflows/`: |
| 185 | +- `publish.yml` - Publishing to PyPI |
| 186 | +- `test.yml` - Testing and verification |
| 187 | +- `lint.yml` - Code quality checks |
| 188 | + |
| 189 | +## Security Notes |
| 190 | + |
| 191 | +- **Never** commit API tokens to the repository |
| 192 | +- Use GitHub Secrets for all sensitive data |
| 193 | +- Tokens should have minimal required permissions |
| 194 | +- Rotate tokens periodically |
| 195 | +- Use trusted publishing when possible (PyPI supports this) |
| 196 | + |
| 197 | +## Trusted Publishing (Advanced) |
| 198 | + |
| 199 | +For even more security, you can set up [Trusted Publishing](https://docs.pypi.org/trusted-publishers/) which doesn't require API tokens. The workflow already supports this with the `id-token: write` permission. |
| 200 | + |
| 201 | +## Support |
| 202 | + |
| 203 | +For issues with: |
| 204 | +- **GitHub Actions**: Check the Actions tab for logs |
| 205 | +- **PyPI Publishing**: See [PyPI Help](https://pypi.org/help/) |
| 206 | +- **Package Issues**: Open an issue on GitHub |
| 207 | + |
| 208 | +--- |
| 209 | + |
| 210 | +**Happy Releasing!** 🚀 |
| 211 | + |
0 commit comments