# Publishing Kilit to PyPI

This guide explains how to publish Kilit to PyPI using GitHub Actions.

## Prerequisites

### 1. PyPI Account Setup

1. Create accounts on:
   - [PyPI](https://pypi.org/account/register/) (production)
   - [Test PyPI](https://test.pypi.org/account/register/) (testing)

2. Generate API tokens:
   - PyPI: https://pypi.org/manage/account/token/
   - Test PyPI: https://test.pypi.org/manage/account/token/

### 2. GitHub Secrets Setup

Add these secrets to your GitHub repository (Settings → Secrets and variables → Actions):

- `PYPI_API_TOKEN` - Your PyPI API token
- `TEST_PYPI_API_TOKEN` - Your Test PyPI API token

## Publishing Methods

### Method 1: Automatic Release (Recommended)

1. **Update version in `pyproject.toml`:**
   ```toml
   version = "0.1.0"  # Change to your new version
   ```

2. **Commit and push:**
   ```bash
   git add pyproject.toml
   git commit -m "Bump version to 0.1.0"
   git push
   ```

3. **Create a GitHub Release:**
   ```bash
   # Create and push a tag
   git tag v0.1.0
   git push origin v0.1.0
   
   # Or create release via GitHub UI:
   # Go to: Releases → Draft a new release
   # Tag: v0.1.0
   # Title: v0.1.0
   # Description: Release notes
   # Click: Publish release
   ```

4. **GitHub Actions will automatically:**
   - Build the package
   - Run tests
   - Publish to PyPI

### Method 2: Manual Workflow Dispatch

1. **Go to GitHub Actions:**
   - Navigate to: Actions → Publish to PyPI → Run workflow

2. **Choose options:**
   - Branch: `main`
   - Publish to Test PyPI: ✅ (for testing) or ❌ (for production)

3. **Click "Run workflow"**

### Method 3: Local Publishing (Not Recommended)

```bash
# Install build tools
pip install build twine

# Build package
python -m build

# Check package
twine check dist/*

# Upload to Test PyPI (testing)
twine upload --repository testpypi dist/*

# Upload to PyPI (production)
twine upload dist/*
```

## Version Numbering

Follow [Semantic Versioning](https://semver.org/):

- **MAJOR.MINOR.PATCH** (e.g., 1.2.3)
- **MAJOR**: Breaking changes
- **MINOR**: New features (backward compatible)
- **PATCH**: Bug fixes (backward compatible)

Examples:
- `0.1.0` - Initial release
- `0.1.1` - Bug fix
- `0.2.0` - New feature
- `1.0.0` - First stable release

## Pre-release Versions

For alpha/beta/rc releases:

```toml
version = "0.1.0a1"  # Alpha
version = "0.1.0b1"  # Beta
version = "0.1.0rc1" # Release Candidate
```

## Testing Before Release

### 1. Test Locally

```bash
# Install in development mode
pip install -e ".[dev,yaml]"

# Run tests
pytest

# Run linting
ruff check src/

# Check formatting
ruff format --check src/
```

### 2. Test on Test PyPI

```bash
# Publish to Test PyPI
twine upload --repository testpypi dist/*

# Install from Test PyPI
pip install --index-url https://test.pypi.org/simple/ kilit

# Test the installation
python -c "from kilit import Credentials; print('✅ Import successful')"
kilit --help
```

### 3. Test Installation

```bash
# Create a fresh virtual environment
python -m venv test-env
source test-env/bin/activate  # On Windows: test-env\Scripts\activate

# Install from Test PyPI
pip install --index-url https://test.pypi.org/simple/ kilit

# Test basic functionality
kilit init --path test.json.enc
kilit show --path test.json.enc --redact
```

## Release Checklist

Before publishing a new version:

- [ ] Update version in `pyproject.toml`
- [ ] Update `CHANGELOG.md` (if exists)
- [ ] Run all tests locally: `pytest`
- [ ] Run linting: `ruff check src/`
- [ ] Check formatting: `ruff format --check src/`
- [ ] Test package build: `python -m build`
- [ ] Test on Test PyPI first
- [ ] Update README if needed
- [ ] Commit all changes
- [ ] Create git tag: `git tag v0.1.0`
- [ ] Push tag: `git push origin v0.1.0`
- [ ] Create GitHub Release
- [ ] Verify package on PyPI
- [ ] Test installation: `pip install kilit`

## Troubleshooting

### "File already exists"

If you get this error, you've already published this version. You need to:
1. Increment the version number in `pyproject.toml`
2. Rebuild: `python -m build`
3. Upload again

### "Invalid distribution"

Check your package:
```bash
twine check dist/*
```

Fix any issues and rebuild.

### "Authentication failed"

Verify:
1. API token is correct
2. Token has upload permissions
3. GitHub secret is properly set

### Build fails

Common issues:
- Missing dependencies in `pyproject.toml`
- Syntax errors in Python files
- Missing `__init__.py` files

## Post-Release

After successful release:

1. **Verify on PyPI:**
   - Visit: https://pypi.org/project/kilit/
   - Check version, description, links

2. **Test installation:**
   ```bash
   pip install kilit
   kilit --version
   ```

3. **Update documentation:**
   - Update README with new features
   - Update examples if needed

4. **Announce:**
   - GitHub Discussions
   - Social media
   - Python community forums

## Continuous Deployment

The GitHub Actions workflow automatically:

1. **On every push to main:**
   - Runs tests on Python 3.10, 3.11, 3.12
   - Runs on Ubuntu, macOS, Windows
   - Checks code quality with Ruff

2. **On GitHub Release:**
   - Builds the package
   - Publishes to PyPI automatically

3. **On manual trigger:**
   - Allows testing on Test PyPI
   - Or direct publish to PyPI

## Security Notes

- **Never commit API tokens** to the repository
- Store tokens only in GitHub Secrets
- Use `__token__` as username for PyPI API tokens
- Rotate tokens periodically
- Use separate tokens for Test PyPI and PyPI

## Resources

- [PyPI Publishing Guide](https://packaging.python.org/tutorials/packaging-projects/)
- [GitHub Actions Documentation](https://docs.github.com/en/actions)
- [Semantic Versioning](https://semver.org/)
- [Python Packaging User Guide](https://packaging.python.org/)
