Skip to content

Release Automation

This project ships with a lightweight release pipeline that runs whenever a Git tag that starts with v is pushed to GitHub. The workflow lives in .github/workflows/release.yml and takes care of version metadata, build validation, release creation, and optional package publication.

Tag-driven Version Management

  1. Create a conventional semantic version tag such as v0.5.0 and push it to GitHub:

    Terminal window
    git push origin v0.5.0
  2. The release workflow normalises the tag (for example v0.5.00.5.0) and runs scripts/sync_version.py to write that value into pyproject.toml and src/fair_platform/__init__.py before any build steps execute. The script can also be run locally if you ever need to verify or pre-populate version metadata:

    Terminal window
    python scripts/sync_version.py --version v0.5.0
  3. Version changes only exist within the workflow run; they are not committed back to the repository. The effective package version therefore always matches the tag that triggered the release, and developers are free to choose how they manage version bumps on long-lived branches.

Build and Release Flow

When a tag push kicks off the workflow it performs the following actions:

  1. Install the toolchain (Python 3.12, uv, and Bun)
  2. Install locked frontend dependencies (bun install --frozen-lockfile)
  3. Execute the project build pipeline via ./build.sh. This step performs the Bun/Vite frontend build, copies the assets into the Python package, and runs uv build to produce artifacts in dist/
  4. Publish a GitHub release with automatically generated notes and attach all build artifacts from dist/. Release notes are generated by GitHub and group commits by type (features, fixes, documentation, etc.) based on the merged PR titles and commit messages since the previous tag
  5. Mark the release as a prerelease when the tag contains a hyphen (for example v0.6.0-rc1). Plain semantic version tags such as v1.0.0 are treated as production releases

Publishing to PyPI

PyPI publication is opt-in. Set the PYPI_API_TOKEN repository secret to enable it. The workflow only attempts to publish when both of the following conditions are true:

  • The tag has no hyphen (e.g. v1.2.3)
  • PYPI_API_TOKEN is defined

Packages are uploaded from the dist/ directory using pypa/gh-action-pypi-publish. For pre-release tags or when the secret is absent, the workflow skips the PyPI step but still produces the GitHub release and attached assets.

If you need to publish to TestPyPI instead, add a similar step with its own secret (for example TEST_PYPI_API_TOKEN) and point it at the alternate repository URL. The existing step is a good template.

Local Dry Runs

You can rehearse the release process locally to ensure the build succeeds before pushing a tag:

Terminal window
python scripts/sync_version.py --version 0.0.0-dev
./build.sh

The script keeps version numbers aligned, while ./build.sh reproduces the same sequence of frontend and packaging steps that the workflow runs in CI. Clean the repository afterwards if you do not want to keep the temporary version change.