# Publishing Guide

This guide walks you through publishing `upgrade-policy-optimizer` to GitHub and PyPI.

## Prerequisites

1. **GitHub account** with repository access
2. **PyPI account** - Create one at https://pypi.org/account/register/
3. **API token** for PyPI - Generate at https://pypi.org/manage/account/token/
4. **Build tools** installed:

   **Using uv (recommended if you use uv):**

   ```bash
   uv tool install build twine
   ```

   **Or using pip:**

   ```bash
   pip install build twine
   ```

## Step 1: Prepare Your Repository

### 1.1 Commit All Changes

```bash
# Check what needs to be committed
git status

# Add all changes
git add .

# Commit with a descriptive message
git commit -m "Prepare for initial release v0.1.0"
```

### 1.2 Verify Package Configuration

Ensure `pyproject.toml` has correct metadata:

- ✅ Package name: `upgrade-policy-optimizer`
- ✅ Author email (currently `eduard@example.com` - update if needed)
- ✅ GitHub URLs are correct
- ✅ License is MIT

### 1.3 Run Final Checks

```bash
# Run tests
pytest

# Check code quality
black --check src/ tests/ examples/
ruff check src/ tests/ examples/
mypy src/

# Build locally to verify
python -m build
```

## Step 2: Publish to GitHub

### 2.1 Push Code to GitHub

```bash
# Push main/master branch
git push origin main
# or
git push origin master

# Push tags (important for setuptools_scm)
git push origin --tags
```

### 2.2 Create GitHub Release (Optional but Recommended)

1. Go to: https://github.com/eonof/upgrade-policy-optimizer/releases/new
2. **Tag**: Select `v0.1.0` (or create new tag)
3. **Title**: `v0.1.0 - Initial Release`
4. **Description**: Copy from your CHANGELOG or describe what's new
5. **Attach files**: Upload `dist/*.whl` and `dist/*.tar.gz` (after building)
6. Click **Publish release**

## Step 3: Publish to PyPI

### 3.1 Build Distribution Packages

```bash
# Clean previous builds
rm -rf dist/ build/ *.egg-info

# Build source distribution and wheel
# Using uv tool:
uv tool run --from build pyproject-build
# Or using standard Python:
python -m build

# Verify what was built
ls -lh dist/
# Should see:
# - upgrade_policy_optimizer-0.1.0-py3-none-any.whl
# - upgrade_policy_optimizer-0.1.0.tar.gz
```

### 3.2 Test Upload to TestPyPI (Recommended First Step)

TestPyPI is a test version of PyPI. Always test here first!

```bash
# Create account at https://test.pypi.org/account/register/
# Generate API token at https://test.pypi.org/manage/account/token/

# Upload to TestPyPI
# Using uv tool:
uv tool run --from twine twine upload --repository testpypi dist/*
# Or using standard twine:
twine upload --repository testpypi dist/*

# Test installation from TestPyPI
pip install --index-url https://test.pypi.org/simple/ upgrade-policy-optimizer
```

### 3.3 Upload to Production PyPI

Once TestPyPI upload works:

```bash
# Upload to production PyPI
# Using uv tool:
uv tool run --from twine twine upload dist/*
# Or using standard twine:
twine upload dist/*

# You'll be prompted for:
# - Username: __token__
# - Password: <your PyPI API token>
```

**Alternative: Use environment variables**

```bash
export TWINE_USERNAME=__token__
export TWINE_PASSWORD=pypi-<your-token-here>
twine upload dist/*
```

### 3.4 Verify Installation

```bash
# Wait a few minutes for PyPI to process, then test
pip install upgrade-policy-optimizer

# Verify it works
python -c "from upo import __version__; print(__version__)"
python -m upo.cli --version
```

## Step 4: Post-Publication Checklist

- [ ] Package appears on PyPI: https://pypi.org/project/upgrade-policy-optimizer/
- [ ] Can install with `pip install upgrade-policy-optimizer`
- [ ] GitHub release created (if desired)
- [ ] Update README with installation instructions if needed
- [ ] Share on social media / relevant communities

## Future Releases

For subsequent releases:

```bash
# 1. Make your changes and commit
git add .
git commit -m "Add feature X"

# 2. Create new version tag
git tag v0.2.0

# 3. Push code and tags
git push origin main
git push origin v0.2.0

# 4. Build and publish
python -m build
twine upload dist/*
```

## Troubleshooting

### "Package already exists" error

- You can't re-upload the same version
- Either bump the version (create new tag) or delete the old version on PyPI (if you have permissions)

### "Invalid version" error

- Check your git tag format: should be `v0.1.0` or `0.1.0`
- setuptools_scm reads tags starting with `v` or numbers

### Version shows as "0.0.0.dev0"

- Make sure you have a git tag: `git tag v0.1.0`
- Make sure tag is pushed: `git push origin v0.1.0`
- Rebuild: `python -m build`

### Build fails

- Ensure setuptools-scm is installed: `pip install setuptools-scm`
- Check you're in a git repository: `git status`

## Security Best Practices

1. **Never commit API tokens** - Use environment variables or `~/.pypirc`
2. **Use API tokens, not passwords** - More secure and revocable
3. **Test on TestPyPI first** - Catch issues before production
4. **Enable 2FA on PyPI** - Protect your account

## Additional Resources

- [PyPI Packaging Guide](https://packaging.python.org/en/latest/guides/distributing-packages-using-setuptools/)
- [setuptools_scm Documentation](https://github.com/pypa/setuptools_scm)
- [Twine Documentation](https://twine.readthedocs.io/)
