Repository navigation
Release and Packaging
This guide details how releases are published to PyPI and how multi-platform standalone release packages are generated and distributed.
Espresso distributes packages in multiple formats to meet different user needs:
| Package Format | Target Platform | Requirements | Installation / Usage |
|---|---|---|---|
PyPI Wheel & sdist (espressoTUI) |
Universal | Python 3.10+ | pip install espressoTUI |
Universal Zipapp (espresso.pyz) |
Linux, macOS, BSD, Windows | Python 3.10+ | Zero installation. Just run ./espresso.pyz
|
Native Standalone Binary (espresso-linux-x86_64) |
Linux x86_64 | None (Self-contained) | chmod +x espresso-linux-x86_64 && ./espresso-linux-x86_64 |
Native Standalone Binary (espresso-macos-arm64) |
macOS Apple Silicon (M1/M2/M3) | None (Self-contained) | ./espresso-macos-arm64 |
Native Standalone Binary (espresso-macos-x86_64) |
macOS Intel | None (Self-contained) | ./espresso-macos-x86_64 |
Native Standalone Binary (espresso-windows-x86_64.exe) |
Windows x86_64 | None (Self-contained) | .\espresso-windows-x86_64.exe |
Espresso uses PyPI Trusted Publishing (OIDC), which eliminates the need to store long-lived API tokens in repository secrets.
- Log in to your account at pypi.org.
- Go to your project settings for
espressoTUI(or go to Account Settings -> Publishing if the package is newly registered). - Under Add a publisher, choose GitHub:
-
PyPI Project Name:
espressoTUI -
Owner:
kimusan -
Repository name:
espresso -
Workflow name:
release.yml -
Environment name:
pypi
-
PyPI Project Name:
- Click Add.
Once configured, GitHub Actions authenticates directly via short-lived OIDC tokens. Zero secrets required.
Espresso includes an interactive release script that runs tests, bumps the version, creates the chore commit, and creates the tag automatically:
# Preview changelog release notes ahead of time without making changes:
./scripts/release.py --preview-changelog patch
# Preview release pipeline (dry run)
./scripts/release.py --dry-run patch
# Release a patch (e.g. 0.2.0 -> 0.2.1)
./scripts/release.py patch
# Release a minor version (e.g. 0.2.0 -> 0.3.0)
./scripts/release.py minor
# Release an explicit version and automatically push:
./scripts/release.py --push 0.3.0
# Headless / plain CLI mode (for scripts or CI):
./scripts/release.py --cli patchThe script will:
- Verify git working directory is clean.
- Verify release tag is available.
- Ensure the full test suite passes.
- Update
src/espresso/__init__.py. - Parse git history and update
CHANGELOG.md(Keep a Changelog format with categorized Conventional Commits). - Create the git chore commit:
chore(release): bump version to vX.Y.Z. - Create the annotated git tag:
vX.Y.Z. - Prompt you to push (or print the exact push/rollback commands).
If you prefer running commands manually:
-
Bump Version: Update
__version__ = "X.Y.Z"insrc/espresso/__init__.py. -
Commit:
git commit -am "chore(release): bump version to vX.Y.Z" -
Tag:
git tag -a vX.Y.Z -m "Release vX.Y.Z" -
Push:
git push origin main git push origin vX.Y.Z
Once the tag is pushed to GitHub, the .github/workflows/release.yml pipeline triggers automatically:
- Tests: Validates all tests across Python 3.10, 3.11, 3.12, 3.13.
-
PyPI Build: Packages
.tar.gzand.whland validates withtwine check. -
Zipapp Build: Packages universal
espresso.pyz. - Binary Compilation: Builds standalone native executables for Linux (x86_64), macOS (Apple Silicon arm64), and Windows (.exe) via PyInstaller.
- PyPI Publish: Uploads packages to PyPI automatically.
-
GitHub Release: Attaches all distribution packages plus cryptographic
SHA256SUMSand formatted release notes to the GitHub release.
Maintainers can trigger a dry-run build at any time without uploading to PyPI:
- Navigate to Actions -> Release & Publish in the GitHub repository.
- Click Run workflow.
- Check the Dry run checkbox.
- The workflow will run tests, compile all packages, and verify their integrity without publishing to PyPI.
All GitHub releases include a SHA256SUMS manifest:
# Verify checksums on Linux / macOS:
sha256sum -c SHA256SUMS --ignore-missingEspresso TUI Documentation • Built with pure Python standard library • GitHub