Skip to content

Commit dcc8135

Browse files
committed
docs: add comprehensive PyPI publishing setup guide
Complete guide for PyPI integration including: - Step-by-step token setup - Automated publishing workflow - Troubleshooting common issues - Security best practices - Manual publishing fallback Package verified: - Name 'adcp' is available on PyPI - Build succeeds (twine check passes) - Ready for first publish after token setup
1 parent 1abe866 commit dcc8135

File tree

1 file changed

+280
-0
lines changed

1 file changed

+280
-0
lines changed

PYPI_SETUP.md

Lines changed: 280 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,280 @@
1+
# PyPI Publishing Setup
2+
3+
This guide walks through setting up automated PyPI publishing for the `adcp` package.
4+
5+
## Quick Setup (5 minutes)
6+
7+
### Step 1: Create PyPI Account
8+
9+
If you don't have a PyPI account:
10+
11+
1. Go to https://pypi.org/account/register/
12+
2. Complete registration
13+
3. Verify your email
14+
15+
### Step 2: Generate API Token
16+
17+
1. Log in to PyPI
18+
2. Go to https://pypi.org/manage/account/token/
19+
3. Click **"Add API token"**
20+
4. Fill in:
21+
- **Token name**: `adcp-github-actions`
22+
- **Scope**: Select "Entire account" (for first publish)
23+
5. Click **"Add token"**
24+
6. **Copy the token immediately** (starts with `pypi-...`)
25+
- You can't view it again after closing the dialog!
26+
- Save it securely
27+
28+
### Step 3: Add Token to GitHub
29+
30+
1. Go to your GitHub repository: https://github.com/YOUR_ORG/adcp-client-python
31+
2. Navigate to **Settings → Secrets and variables → Actions**
32+
3. Click **"New repository secret"**
33+
4. Configure:
34+
- **Name**: `PYPI_API_TOKEN`
35+
- **Secret**: Paste your `pypi-...` token
36+
5. Click **"Add secret"**
37+
38+
### Step 4: Done! 🎉
39+
40+
That's it! Now when you merge a Release Please PR, the package will automatically publish to PyPI.
41+
42+
## How It Works
43+
44+
### Automated Publishing Flow
45+
46+
```mermaid
47+
graph LR
48+
A[Merge PR to main] --> B[Release Please]
49+
B --> C[Creates Release PR]
50+
C --> D[Merge Release PR]
51+
D --> E[GitHub Release]
52+
E --> F[Build Package]
53+
F --> G[Publish to PyPI]
54+
```
55+
56+
1. **Development**: Make changes using conventional commits
57+
2. **Release Please**: Automatically creates a release PR
58+
3. **Merge Release PR**: Triggers the workflow
59+
4. **Automatic Publishing**:
60+
- Builds the package (`python -m build`)
61+
- Publishes to PyPI (`twine upload`)
62+
- Creates GitHub release
63+
64+
### What Gets Published
65+
66+
The package includes:
67+
- `adcp` module with all source code
68+
- README.md as long description
69+
- LICENSE file
70+
- All dependencies from pyproject.toml
71+
72+
### Version Management
73+
74+
Versions are managed automatically by Release Please:
75+
- `feat:` commits → minor version bump (0.1.0 → 0.2.0)
76+
- `fix:` commits → patch version bump (0.1.0 → 0.1.1)
77+
- `feat!:` or `BREAKING CHANGE:` → major bump (pre-1.0: minor)
78+
79+
## Verification
80+
81+
### Check Package Built Correctly
82+
83+
```bash
84+
# Install build tools
85+
pip install build twine
86+
87+
# Build package
88+
python -m build
89+
90+
# Check with twine
91+
python -m twine check dist/*
92+
93+
# Should see: PASSED ✅
94+
```
95+
96+
### Test Installation After Publishing
97+
98+
```bash
99+
# In a fresh virtual environment
100+
pip install adcp
101+
102+
# Test import
103+
python -c "from adcp import ADCPClient; print('Success!')"
104+
```
105+
106+
### View on PyPI
107+
108+
After first publish, your package will be at:
109+
- https://pypi.org/project/adcp/
110+
111+
## Manual Publishing (Fallback)
112+
113+
If you need to publish manually (not recommended - use Release Please):
114+
115+
```bash
116+
# 1. Update version in pyproject.toml
117+
vim pyproject.toml
118+
119+
# 2. Clean old builds
120+
rm -rf dist/ build/ *.egg-info
121+
122+
# 3. Build
123+
python -m build
124+
125+
# 4. Check
126+
python -m twine check dist/*
127+
128+
# 5. Upload to PyPI
129+
python -m twine upload dist/*
130+
# Enter username: __token__
131+
# Enter password: pypi-... (your API token)
132+
```
133+
134+
## Security Best Practices
135+
136+
### ✅ Do
137+
138+
- Store API token in GitHub Secrets (never in code)
139+
- Use project-scoped tokens after first publish
140+
- Rotate tokens periodically
141+
- Use 2FA on your PyPI account
142+
- Review Release PRs before merging
143+
144+
### ❌ Don't
145+
146+
- Commit tokens to git
147+
- Share tokens in public channels
148+
- Use the same token across multiple projects
149+
- Manually publish if automation works
150+
- Skip reviewing release PRs
151+
152+
## Troubleshooting
153+
154+
### Package name already taken
155+
156+
**Error**: `The name 'adcp' is too similar to an existing project`
157+
158+
**Solution**:
159+
1. Check https://pypi.org/project/adcp/
160+
2. If taken, choose a different name in `pyproject.toml`:
161+
```toml
162+
name = "adcp-client" # or another unique name
163+
```
164+
165+
### Token invalid or expired
166+
167+
**Error**: `Invalid or non-existent authentication information`
168+
169+
**Solution**:
170+
1. Generate new token on PyPI
171+
2. Update `PYPI_API_TOKEN` secret in GitHub
172+
3. Re-run the workflow
173+
174+
### Build fails
175+
176+
**Error**: Package build errors
177+
178+
**Solution**:
179+
```bash
180+
# Test locally first
181+
python -m build
182+
183+
# Check for issues
184+
python -m twine check dist/*
185+
186+
# Review pyproject.toml for errors
187+
```
188+
189+
### First publish requires entire account scope
190+
191+
**Error**: `The user 'TOKEN' isn't allowed to upload to project 'adcp'`
192+
193+
**Why**: Project doesn't exist yet on PyPI
194+
195+
**Solution**: First token must have "Entire account" scope. After first successful publish:
196+
1. Create new token with project scope limited to `adcp`
197+
2. Update `PYPI_API_TOKEN` in GitHub Secrets
198+
199+
## Advanced Configuration
200+
201+
### TestPyPI (Optional)
202+
203+
Test publishing without affecting production:
204+
205+
1. Create TestPyPI account: https://test.pypi.org/
206+
2. Generate token on TestPyPI
207+
3. Add as `TEST_PYPI_API_TOKEN` secret
208+
4. Add workflow step:
209+
```yaml
210+
- name: Publish to TestPyPI
211+
env:
212+
TWINE_USERNAME: __token__
213+
TWINE_PASSWORD: ${{ secrets.TEST_PYPI_API_TOKEN }}
214+
TWINE_REPOSITORY_URL: https://test.pypi.org/legacy/
215+
run: twine upload dist/*
216+
```
217+
218+
### Custom PyPI Server
219+
220+
For private PyPI server:
221+
222+
```yaml
223+
- name: Publish to private PyPI
224+
env:
225+
TWINE_USERNAME: __token__
226+
TWINE_PASSWORD: ${{ secrets.PRIVATE_PYPI_TOKEN }}
227+
TWINE_REPOSITORY_URL: https://pypi.yourcompany.com
228+
run: twine upload dist/*
229+
```
230+
231+
## Monitoring
232+
233+
### Check Release Status
234+
235+
- **Workflow runs**: https://github.com/YOUR_ORG/adcp-client-python/actions
236+
- **Published releases**: https://github.com/YOUR_ORG/adcp-client-python/releases
237+
- **PyPI package**: https://pypi.org/project/adcp/
238+
- **Download stats**: https://pypistats.org/packages/adcp
239+
240+
### Email Notifications
241+
242+
PyPI will email you when:
243+
- New version is published
244+
- Project gets new maintainers
245+
- Security issues are found
246+
247+
## Resources
248+
249+
- [Python Packaging Guide](https://packaging.python.org/)
250+
- [PyPI Help](https://pypi.org/help/)
251+
- [Twine Documentation](https://twine.readthedocs.io/)
252+
- [Release Please](https://github.com/googleapis/release-please)
253+
- [Conventional Commits](https://www.conventionalcommits.org/)
254+
255+
## FAQ
256+
257+
**Q: How do I update package metadata after publishing?**
258+
A: Update `pyproject.toml` and publish a new version. Metadata for old versions can't be changed.
259+
260+
**Q: Can I delete a version after publishing?**
261+
A: You can hide versions, but not delete them. PyPI is immutable by design.
262+
263+
**Q: How do I add co-maintainers?**
264+
A: Go to https://pypi.org/manage/project/adcp/collaboration/ after first publish.
265+
266+
**Q: What if Release Please doesn't create a PR?**
267+
A: Ensure commits use conventional format (`feat:`, `fix:`, etc.)
268+
269+
**Q: How do I publish a pre-release?**
270+
A: Use pre-release version in `pyproject.toml`: `0.1.0a1`, `0.1.0b2`, `0.1.0rc1`
271+
272+
## Current Status
273+
274+
- ✅ Package name `adcp` is available on PyPI
275+
- ✅ Package builds successfully (`twine check` passes)
276+
- ✅ GitHub Actions workflow configured
277+
- ⏳ Waiting for `PYPI_API_TOKEN` secret
278+
- ⏳ Waiting for first release
279+
280+
**Next Step**: Add `PYPI_API_TOKEN` secret to GitHub, then merge to main!

0 commit comments

Comments
 (0)