# Releasing

`fuggers-py` uses `setuptools_scm`, so supported release builds must be run from a normal git checkout (or tag checkout) with `.git` metadata present.

Do not cut release artifacts from an exported/copied source tree that no longer has SCM metadata attached. In that case `setuptools_scm` falls back to the configured development version, which is fine for scratch snapshots but not a publishing path.

## Local artifact validation from a normal checkout

```bash
python -m pip install --upgrade pip
python -m pip install -e ".[dev,engine,examples]"
pytest -q
pytest -q tests/validation tests/test_property_invariants.py tests/test_examples_smoke.py
ruff check src/fuggers_py tests/source_coverage.py tests/test_optional_dependencies.py tests/typing tools/run_release_ruff.py tests/packaging
python tools/run_release_ruff.py
mypy
python tests/source_coverage.py --pytest-args -q
PYTHONPATH=src pytest -q tests/test_examples_smoke.py
python -m build
python -m pip wheel . --no-deps -w /tmp/fuggers-pip-wheel-check
python -m twine check dist/*
python -m venv /tmp/fuggers-release-artifact-venv
/tmp/fuggers-release-artifact-venv/bin/pip install --upgrade pip
/tmp/fuggers-release-artifact-venv/bin/pip install dist/fuggers_py-*.whl
/tmp/fuggers-release-artifact-venv/bin/python -c "import fuggers_py; print(fuggers_py.__version__)"
```

Both `python -m build` and `python -m pip wheel . --no-deps -w <dir>` are supported from a normal git checkout and must produce the same version metadata. Treat any mismatch between editable install, built wheel, built sdist, pip-wheel output, and installed metadata as a release blocker.

For a stable release tag such as `v0.1.0`, the resolved version must be exactly `0.1.0`:

- no `.dev*`
- no `+local` suffix
- no `a`, `b`, or `rc` pre-release segment

## One-time PyPI Trusted Publisher setup

1. Make the GitHub repository public.
2. In the PyPI project settings for `fuggers-py`, add a GitHub Trusted Publisher with:
   - owner: `stanislawkubik`
   - repository: `fuggers-py`
   - workflow file: `release.yml`
3. Leave the GitHub environment field empty. The workflow does not use one.

## First public release

1. Ensure `main` is clean, ready, and CI is green.
2. In a clean release environment, run the checklist in `docs/private/release_checklist.md`.
3. Commit any final release-doc updates.
4. Optionally validate the exact stable tag locally before pushing:

```bash
git tag v0.1.0
EXPECTED_RELEASE_VERSION=0.1.0 pytest -q tests/test_packaging_version_consistency.py
git tag -d v0.1.0
```

5. Push the release tag:

```bash
git tag v0.1.0
git push origin main
git push origin v0.1.0
```

6. GitHub Actions runs `release.yml`, verifies the exact tagged version, builds the distributions, smoke-tests wheel and sdist install paths, and publishes to PyPI.

`setuptools_scm` maps the Git tag `v0.1.0` to the package version `0.1.0`.

## Subsequent releases

1. Update `CHANGELOG.md` as needed.
2. Rerun the release checklist.
3. Push the next tag, for example:

```bash
git tag v0.1.1
git push origin main
git push origin v0.1.1
```

No packaging-file edits should be required for later releases.
