Complete package deployment configuration for PyPI publishing:
- Add MANIFEST.in to control package distribution
- Include LICENSE, README, requirements files
- Include docs/ and examples/ directories
- Include type stub marker (py.typed)
- Exclude test files and development artifacts
- Fix dependency specification
- Add pydantic[email] for email validation support
- Required for User model EmailStr fields
- Update both requirements.txt and pyproject.toml
- Create comprehensive deployment documentation
- docs/deployment.md - Complete PyPI publishing guide
- Pre-deployment checklist
- Build and test procedures
- PyPI upload instructions
- Troubleshooting guide
- CI/CD automation examples
- DEPLOYMENT_READY.md - Deployment status summary
- What's included in distributions
- Verification test results
- Quick deployment steps
- PyPI vs Gitea comparison
Package is now 100% ready for PyPI deployment:
✅ Builds successfully (sdist + wheel)
✅ Installs correctly with all dependencies
✅ Imports work without errors
✅ All files properly included
✅ Complete documentation provided
Testing:
- Successfully built wikijs_python_sdk-0.1.0.tar.gz (134 KB)
- Successfully built wikijs_python_sdk-0.1.0-py3-none-any.whl (66 KB)
- Verified installation and imports work correctly
- All dependencies resolve properly
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
534 lines
11 KiB
Markdown
534 lines
11 KiB
Markdown
# Deployment Guide - Publishing py-wikijs to PyPI
|
|
|
|
**Last Updated**: October 2025
|
|
**Target Audience**: Maintainers and release managers
|
|
|
|
---
|
|
|
|
## 📋 Overview
|
|
|
|
This guide covers how to build, test, and publish the `wikijs-python-sdk` package to PyPI (Python Package Index).
|
|
|
|
---
|
|
|
|
## ✅ Pre-Deployment Checklist
|
|
|
|
### 1. Code Quality
|
|
- [ ] All tests pass (`pytest`)
|
|
- [ ] Code coverage ≥85% (`pytest --cov`)
|
|
- [ ] Linting passes (`black`, `flake8`, `mypy`)
|
|
- [ ] Security scan passes (`bandit`)
|
|
- [ ] No critical bugs in issue tracker
|
|
|
|
### 2. Documentation
|
|
- [ ] README.md is up to date
|
|
- [ ] CHANGELOG.md has release notes
|
|
- [ ] API documentation is current
|
|
- [ ] Examples are tested and working
|
|
- [ ] Compatibility guide is accurate
|
|
|
|
### 3. Version Management
|
|
- [ ] Version bumped in `wikijs/version.py`
|
|
- [ ] CHANGELOG.md updated with new version
|
|
- [ ] Git tag created for release
|
|
- [ ] No uncommitted changes
|
|
|
|
### 4. Legal & Metadata
|
|
- [ ] LICENSE file present (MIT)
|
|
- [ ] setup.py metadata correct
|
|
- [ ] pyproject.toml metadata correct
|
|
- [ ] Author information accurate
|
|
|
|
---
|
|
|
|
## 🔧 Prerequisites
|
|
|
|
### Required Tools
|
|
|
|
```bash
|
|
# Install build and publishing tools
|
|
pip install --upgrade pip
|
|
pip install build twine
|
|
```
|
|
|
|
### PyPI Account Setup
|
|
|
|
1. **Create PyPI Account**: https://pypi.org/account/register/
|
|
2. **Create API Token**:
|
|
- Go to https://pypi.org/manage/account/
|
|
- Click "Add API token"
|
|
- Name: `wikijs-python-sdk-upload`
|
|
- Scope: Entire account (or specific project after first upload)
|
|
3. **Save Token Securely**: Store in password manager or environment variable
|
|
|
|
### Configure PyPI Credentials
|
|
|
|
**Option 1: Using .pypirc file** (Recommended for local development)
|
|
|
|
```bash
|
|
# Create ~/.pypirc
|
|
cat > ~/.pypirc << 'EOF'
|
|
[distutils]
|
|
index-servers =
|
|
pypi
|
|
testpypi
|
|
|
|
[pypi]
|
|
username = __token__
|
|
password = pypi-AgEIcHlwaS5vcmc...YOUR-TOKEN-HERE...
|
|
|
|
[testpypi]
|
|
repository = https://test.pypi.org/legacy/
|
|
username = __token__
|
|
password = pypi-AgENdGVzdC5weXBp...YOUR-TEST-TOKEN-HERE...
|
|
EOF
|
|
|
|
chmod 600 ~/.pypirc
|
|
```
|
|
|
|
**Option 2: Using environment variables** (Recommended for CI/CD)
|
|
|
|
```bash
|
|
export TWINE_USERNAME=__token__
|
|
export TWINE_PASSWORD=pypi-AgEIcHlwaS5vcmc...YOUR-TOKEN-HERE...
|
|
```
|
|
|
|
---
|
|
|
|
## 📦 Building the Package
|
|
|
|
### 1. Clean Previous Builds
|
|
|
|
```bash
|
|
# Remove old build artifacts
|
|
rm -rf build/ dist/ *.egg-info wikijs_python_sdk.egg-info
|
|
|
|
# Verify clean state
|
|
git status
|
|
```
|
|
|
|
### 2. Update Version
|
|
|
|
```bash
|
|
# Edit wikijs/version.py
|
|
__version__ = "0.2.0" # Update version number
|
|
__version_info__ = (0, 2, 0)
|
|
```
|
|
|
|
### 3. Update CHANGELOG
|
|
|
|
```markdown
|
|
# Edit docs/CHANGELOG.md
|
|
|
|
## [0.2.0] - 2025-10-XX
|
|
|
|
### Added
|
|
- New feature descriptions
|
|
- API additions
|
|
|
|
### Changed
|
|
- Modified functionality
|
|
|
|
### Fixed
|
|
- Bug fixes
|
|
```
|
|
|
|
### 4. Build Distributions
|
|
|
|
```bash
|
|
# Build both source distribution (sdist) and wheel
|
|
python -m build
|
|
|
|
# This creates:
|
|
# - dist/wikijs_python_sdk-X.Y.Z.tar.gz (source distribution)
|
|
# - dist/wikijs_python_sdk-X.Y.Z-py3-none-any.whl (wheel)
|
|
```
|
|
|
|
### 5. Verify Build Contents
|
|
|
|
```bash
|
|
# Check source distribution contents
|
|
tar -tzf dist/wikijs_python_sdk-*.tar.gz | head -30
|
|
|
|
# Check wheel contents
|
|
python -m zipfile -l dist/wikijs_python_sdk-*-py3-none-any.whl | head -30
|
|
|
|
# Verify required files are included:
|
|
# - LICENSE
|
|
# - README.md
|
|
# - requirements.txt
|
|
# - docs/
|
|
# - examples/
|
|
# - wikijs/ (all source code)
|
|
# - wikijs/py.typed (type stub marker)
|
|
```
|
|
|
|
---
|
|
|
|
## 🧪 Testing the Package
|
|
|
|
### 1. Validate Package Metadata
|
|
|
|
```bash
|
|
# Check package metadata for errors
|
|
python -m twine check dist/*
|
|
|
|
# Should show:
|
|
# Checking dist/wikijs_python_sdk-X.Y.Z.tar.gz: PASSED
|
|
# Checking dist/wikijs_python_sdk-X.Y.Z-py3-none-any.whl: PASSED
|
|
```
|
|
|
|
### 2. Test Local Installation
|
|
|
|
```bash
|
|
# Create a test virtual environment
|
|
python -m venv test-env
|
|
source test-env/bin/activate # On Windows: test-env\Scripts\activate
|
|
|
|
# Install from wheel
|
|
pip install dist/wikijs_python_sdk-*-py3-none-any.whl
|
|
|
|
# Test import
|
|
python -c "from wikijs import WikiJSClient, __version__; print(f'Version: {__version__}')"
|
|
|
|
# Test basic functionality
|
|
python << 'EOF'
|
|
from wikijs import WikiJSClient
|
|
from wikijs.models import PageCreate
|
|
|
|
# This should not error (will fail at connection, which is expected)
|
|
try:
|
|
client = WikiJSClient('https://example.com', auth='test-key')
|
|
print("✅ Client instantiation successful")
|
|
except Exception as e:
|
|
print(f"❌ Error: {e}")
|
|
EOF
|
|
|
|
# Cleanup
|
|
deactivate
|
|
rm -rf test-env
|
|
```
|
|
|
|
### 3. Test on TestPyPI (Optional but Recommended)
|
|
|
|
```bash
|
|
# Upload to TestPyPI first
|
|
python -m twine upload --repository testpypi dist/*
|
|
|
|
# Install from TestPyPI
|
|
pip install --index-url https://test.pypi.org/simple/ \
|
|
--extra-index-url https://pypi.org/simple/ \
|
|
wikijs-python-sdk
|
|
|
|
# Test the installation
|
|
python -c "from wikijs import WikiJSClient; print('TestPyPI install successful')"
|
|
```
|
|
|
|
---
|
|
|
|
## 🚀 Publishing to PyPI
|
|
|
|
### 1. Final Pre-Publish Checks
|
|
|
|
```bash
|
|
# Ensure you're on the main branch
|
|
git checkout main
|
|
|
|
# Ensure everything is committed
|
|
git status
|
|
|
|
# Tag the release
|
|
git tag v0.2.0
|
|
git push origin v0.2.0
|
|
```
|
|
|
|
### 2. Upload to PyPI
|
|
|
|
```bash
|
|
# Upload to production PyPI
|
|
python -m twine upload dist/*
|
|
|
|
# You'll see output like:
|
|
# Uploading distributions to https://upload.pypi.org/legacy/
|
|
# Uploading wikijs_python_sdk-0.2.0-py3-none-any.whl
|
|
# Uploading wikijs_python_sdk-0.2.0.tar.gz
|
|
# View at:
|
|
# https://pypi.org/project/wikijs-python-sdk/0.2.0/
|
|
```
|
|
|
|
### 3. Verify Publication
|
|
|
|
```bash
|
|
# Visit PyPI page
|
|
# https://pypi.org/project/wikijs-python-sdk/
|
|
|
|
# Test installation from PyPI
|
|
pip install wikijs-python-sdk
|
|
|
|
# Verify version
|
|
python -c "from wikijs import __version__; print(__version__)"
|
|
```
|
|
|
|
---
|
|
|
|
## 🔄 Post-Publication Tasks
|
|
|
|
### 1. Update Documentation
|
|
|
|
- [ ] Update README.md installation instructions
|
|
- [ ] Update GitHub releases page
|
|
- [ ] Announce release in community channels
|
|
- [ ] Update project status badges
|
|
|
|
### 2. Git Housekeeping
|
|
|
|
```bash
|
|
# Create GitHub release
|
|
# Go to: https://github.com/l3ocho/py-wikijs/releases/new
|
|
# - Tag version: v0.2.0
|
|
# - Release title: v0.2.0 - Release Name
|
|
# - Description: Copy from CHANGELOG.md
|
|
# - Attach dist/ files
|
|
|
|
# Merge release branch if applicable
|
|
git checkout main
|
|
git merge release/v0.2.0
|
|
git push origin main
|
|
```
|
|
|
|
### 3. Prepare for Next Development Cycle
|
|
|
|
```bash
|
|
# Bump to next development version
|
|
# Edit wikijs/version.py
|
|
__version__ = "0.3.0-dev"
|
|
|
|
git add wikijs/version.py
|
|
git commit -m "chore: bump version to 0.3.0-dev"
|
|
git push
|
|
```
|
|
|
|
---
|
|
|
|
## 🐛 Troubleshooting
|
|
|
|
### Build Failures
|
|
|
|
**Problem**: `FileNotFoundError: requirements.txt`
|
|
|
|
```bash
|
|
# Solution: Ensure MANIFEST.in includes requirements.txt
|
|
# Check MANIFEST.in contents:
|
|
cat MANIFEST.in
|
|
```
|
|
|
|
**Problem**: Missing documentation in package
|
|
|
|
```bash
|
|
# Solution: Update MANIFEST.in to include docs
|
|
recursive-include docs *.md
|
|
```
|
|
|
|
### Upload Failures
|
|
|
|
**Problem**: `403 Forbidden - Invalid or non-existent authentication information`
|
|
|
|
```bash
|
|
# Solution: Check your API token
|
|
# 1. Verify token is correct in ~/.pypirc
|
|
# 2. Ensure token has upload permissions
|
|
# 3. Try using environment variables instead
|
|
export TWINE_USERNAME=__token__
|
|
export TWINE_PASSWORD=your-token-here
|
|
python -m twine upload dist/*
|
|
```
|
|
|
|
**Problem**: `400 File already exists`
|
|
|
|
```bash
|
|
# Solution: You cannot re-upload the same version
|
|
# 1. Increment version in wikijs/version.py
|
|
# 2. Rebuild: python -m build
|
|
# 3. Upload again: python -m twine upload dist/*
|
|
```
|
|
|
|
**Problem**: Package name already taken
|
|
|
|
```bash
|
|
# Solution: Choose a different package name
|
|
# 1. Update name in setup.py and pyproject.toml
|
|
# 2. Rebuild package
|
|
# Note: wikijs-python-sdk is our chosen name
|
|
```
|
|
|
|
### Installation Issues
|
|
|
|
**Problem**: `ModuleNotFoundError` after install
|
|
|
|
```bash
|
|
# Solution: Check dependencies are installed
|
|
pip show wikijs-python-sdk
|
|
pip install wikijs-python-sdk[all] # Install all optional deps
|
|
```
|
|
|
|
**Problem**: Import errors with type hints
|
|
|
|
```bash
|
|
# Solution: Ensure py.typed file is in package
|
|
# Check if included: python -m zipfile -l dist/*.whl | grep py.typed
|
|
```
|
|
|
|
---
|
|
|
|
## 📊 Package Statistics
|
|
|
|
### Size Guidelines
|
|
|
|
- **Wheel**: Should be < 100 KB for SDK
|
|
- **Source**: Should be < 200 KB including docs
|
|
- **Total dependencies**: Keep minimal
|
|
|
|
```bash
|
|
# Check package sizes
|
|
ls -lh dist/
|
|
|
|
# Check dependency tree
|
|
pip install pipdeptree
|
|
pipdeptree -p wikijs-python-sdk
|
|
```
|
|
|
|
### Download Stats
|
|
|
|
After publication, monitor package metrics:
|
|
|
|
- **PyPI Stats**: https://pypistats.org/packages/wikijs-python-sdk
|
|
- **GitHub Stats**: Stars, forks, watchers
|
|
- **Issue Tracker**: Open issues, response time
|
|
|
|
---
|
|
|
|
## 🔐 Security Best Practices
|
|
|
|
### 1. Protect API Tokens
|
|
|
|
- Never commit tokens to git
|
|
- Use `.gitignore` for `.pypirc`
|
|
- Rotate tokens periodically
|
|
- Use scoped tokens (project-specific)
|
|
|
|
### 2. Package Security
|
|
|
|
```bash
|
|
# Run security scan before publishing
|
|
pip install safety
|
|
safety check --file requirements.txt
|
|
|
|
# Scan for vulnerabilities
|
|
bandit -r wikijs/
|
|
```
|
|
|
|
### 3. Signing Releases (Optional)
|
|
|
|
```bash
|
|
# Sign the release with GPG
|
|
gpg --detach-sign -a dist/wikijs_python_sdk-0.2.0.tar.gz
|
|
|
|
# Upload signatures
|
|
python -m twine upload dist/* --sign
|
|
```
|
|
|
|
---
|
|
|
|
## 📝 Checklist Summary
|
|
|
|
### Pre-Release
|
|
- [ ] Tests pass
|
|
- [ ] Version bumped
|
|
- [ ] CHANGELOG updated
|
|
- [ ] Documentation current
|
|
|
|
### Build
|
|
- [ ] Clean build environment
|
|
- [ ] Build succeeds
|
|
- [ ] Package validated
|
|
- [ ] Local test passes
|
|
|
|
### Publish
|
|
- [ ] TestPyPI upload (optional)
|
|
- [ ] PyPI upload
|
|
- [ ] Installation verified
|
|
- [ ] Package page checked
|
|
|
|
### Post-Release
|
|
- [ ] Git tag created
|
|
- [ ] GitHub release published
|
|
- [ ] Documentation updated
|
|
- [ ] Community notified
|
|
|
|
---
|
|
|
|
## 📞 Support
|
|
|
|
### Resources
|
|
- **PyPI Help**: https://pypi.org/help/
|
|
- **Packaging Guide**: https://packaging.python.org/
|
|
- **Twine Docs**: https://twine.readthedocs.io/
|
|
|
|
### Getting Help
|
|
- PyPI Support: https://pypi.org/help/#feedback
|
|
- GitHub Issues: https://github.com/l3ocho/py-wikijs/issues
|
|
- Packaging Discourse: https://discuss.python.org/c/packaging/
|
|
|
|
---
|
|
|
|
## 🎓 Additional Notes
|
|
|
|
### Automated Publishing (CI/CD)
|
|
|
|
For automated releases via GitHub Actions:
|
|
|
|
```yaml
|
|
# .github/workflows/publish.yml
|
|
name: Publish to PyPI
|
|
|
|
on:
|
|
release:
|
|
types: [published]
|
|
|
|
jobs:
|
|
pypi-publish:
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@v3
|
|
- uses: actions/setup-python@v4
|
|
with:
|
|
python-version: '3.10'
|
|
- name: Install dependencies
|
|
run: |
|
|
pip install build twine
|
|
- name: Build package
|
|
run: python -m build
|
|
- name: Publish to PyPI
|
|
env:
|
|
TWINE_USERNAME: __token__
|
|
TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }}
|
|
run: twine upload dist/*
|
|
```
|
|
|
|
### Alternative: Using Trusted Publishing
|
|
|
|
Modern approach (no API tokens needed):
|
|
|
|
1. Configure trusted publisher on PyPI
|
|
2. Use OIDC token from GitHub Actions
|
|
3. More secure, no secrets needed
|
|
|
|
See: https://docs.pypi.org/trusted-publishers/
|
|
|
|
---
|
|
|
|
**Last Updated**: October 2025
|
|
**Maintainer**: leomiranda
|
|
|
|
For questions about deployment, open an issue on GitHub.
|