This guide will help you quickly set up and publish your packages to PyPI.
- GitHub repository with the workflows
- PyPI account (https://pypi.org/account/register/)
- TestPyPI account (https://test.pypi.org/account/register/) - optional but recommended
- Visit https://pypi.org/manage/account/token/
- Click "Add API token"
- Fill in:
- Token name:
GitHub Actions - NetDriver - Scope:
Entire account(or select specific project after first upload)
- Token name:
- Click "Add token"
- Copy the token (starts with
pypi-...) - you won't see it again!
- Visit https://test.pypi.org/manage/account/token/
- Follow same steps as above
- Copy the token
-
Go to your GitHub repository
-
Navigate to: Settings → Secrets and variables → Actions
-
Click "New repository secret"
-
Add two secrets:
Secret 1:
- Name:
PYPI_API_TOKEN - Secret: Paste your PyPI token
Secret 2:
- Name:
TEST_PYPI_API_TOKEN - Secret: Paste your TestPyPI token
- Name:
The publish-pypi.yml workflow uses a pre-built Docker image for faster execution.
Build the image:
- Go to Actions → "Build CI Image"
- Click "Run workflow"
- Select branch:
master - Click "Run workflow"
Or build locally:
docker build -t ghcr.io/opensecflow/netdriver/python-uv:3.12 -f .github/Dockerfile.ci .
docker push ghcr.io/opensecflow/netdriver/python-uv:3.12Note: This only needs to be done once. The image will be cached and reused.
Before publishing to production PyPI, test with TestPyPI:
- Go to Actions → "Publish to PyPI"
- Click "Run workflow"
- Select:
- Branch:
master - Environment:
testpypi - Projects:
all
- Branch:
- Click "Run workflow"
-
Check your packages:
-
Test installation:
pip install --index-url https://test.pypi.org/simple/ netdriver-agent
- Go to Actions → "Publish to PyPI"
- Click "Run workflow"
- Select:
- Branch:
master - Environment:
pypi(NOT testpypi!) - Projects:
all
- Branch:
- Click "Run workflow"
# 1. Update version numbers
sed -i 's/^version = ".*"/version = "0.3.1"/' packages/agent/pyproject.toml
sed -i 's/^version = ".*"/version = "0.3.1"/' packages/simunet/pyproject.toml
# 2. Commit changes
git add packages/*/pyproject.toml
git commit -m "chore: bump version to 0.3.1"
git push
# 3. Create and push tag (without 'v' prefix)
git tag 0.3.1
git push origin 0.3.1Note: Both 0.3.1 and v0.3.1 tag formats are supported.
The release.yml workflow will automatically:
- ✅ Create a GitHub Release
- ✅ Build both packages
- ✅ Publish to PyPI
- ✅ Attach wheel files to the release
-
Check on PyPI:
-
Test installation:
pip install netdriver-agent pip install netdriver-simunet
Solution: Check that GitHub secrets are correctly configured
# Verify secrets exist in: Settings → Secrets and variables → Actions
# Should see:
# - PYPI_API_TOKEN
# - TEST_PYPI_API_TOKENSolution: Version already exists on PyPI. Bump the version:
# Manually update version in pyproject.toml files
sed -i 's/^version = ".*"/version = "0.3.2"/' packages/agent/pyproject.toml
sed -i 's/^version = ".*"/version = "0.3.2"/' packages/simunet/pyproject.toml
# Then rebuild and publishSolution: Build the CI Docker image first
# Go to Actions → "Build CI Image" → Run workflowOr check the image name matches: ghcr.io/opensecflow/netdriver/python-uv:3.12
Solution: Check build output - Polylith path warnings are normal, verify wheel contents:
unzip -l packages/agent/dist/netdriver_agent-*.whl✅ DO:
- Keep version numbers in sync across
packages/agent/pyproject.tomlandpackages/simunet/pyproject.toml - Use semantic versioning:
MAJOR.MINOR.PATCH - Test on TestPyPI before production
❌ DON'T:
- Publish the same version twice
- Skip testing on TestPyPI
- Use local version identifiers for production (e.g.,
0.3.0+local)
- Develop features on branches
- Test locally:
uv build --directory packages/agent - Create PR and verify build test passes
- Merge to master
- Test on TestPyPI
- Tag and release to production PyPI
- 🔒 Never commit tokens to repository
- 🔒 Use scoped tokens when possible
- 🔒 Rotate tokens regularly
- 🔒 Use GitHub environments for additional approval gates
- Set up automated testing before publishing
- Configure GitHub environments for approval workflows
- Set up branch protection rules
- Consider using PyPI Trusted Publishers (no tokens needed!)
- 📖 Full documentation:
.github/workflows/README.md - 🐛 Report issues: https://github.com/OpenSecFlow/netdriver/issues
- 📝 PyPI Help: https://pypi.org/help/
- 🎯 GitHub Actions: https://docs.github.com/en/actions