diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..707f53c --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,63 @@ +name: Release + +# Triggers on either: +# - pushing a tag matching v*.*.* (e.g. v1.1.0) +# - publishing a GitHub Release manually from the UI +# +# Builds an sdist + wheel from pyproject.toml and attaches them to the +# Release for that tag. The Release itself can be created manually or +# automatically by `softprops/action-gh-release` if it doesn't exist yet. + +on: + push: + tags: + - "v*.*.*" + release: + types: [published] + +permissions: + contents: write # needed to upload assets to the Release + +jobs: + build-and-attach: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-python@v5 + with: + python-version: "3.12" + + - name: Verify tag matches pyproject version + run: | + TAG="${GITHUB_REF_NAME#v}" + PROJECT_VERSION=$(python -c "import tomllib; print(tomllib.loads(open('pyproject.toml','rb').read().decode())['project']['version'])") + echo "Tag version: $TAG" + echo "Project version: $PROJECT_VERSION" + if [ "$TAG" != "$PROJECT_VERSION" ]; then + echo "::error::Tag $GITHUB_REF_NAME does not match pyproject version $PROJECT_VERSION. Bump version in pyproject.toml before tagging." + exit 1 + fi + + - name: Build sdist and wheel + run: | + python -m pip install --upgrade pip build + python -m build + + - name: List build artifacts + run: ls -la dist/ + + - name: Upload artifacts to workflow run + uses: actions/upload-artifact@v4 + with: + name: dist-${{ github.ref_name }} + path: dist/ + + - name: Attach to GitHub Release + uses: softprops/action-gh-release@v2 + with: + files: dist/* + fail_on_unmatched_files: true + # If the Release for this tag doesn't already exist, this action + # will create one. Body / title can be edited in the UI after. + generate_release_notes: true diff --git a/CHANGELOG.md b/CHANGELOG.md index ad667b6..2e3a74a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Issue and pull request templates under `.github/`. - Dependabot configuration for weekly dependency and Actions updates. - `.env.example` documenting the supported environment variables. +- Release automation workflow (`.github/workflows/release.yml`): on + pushing a `v*.*.*` tag, builds the sdist and wheel from + `pyproject.toml` and attaches them to the GitHub Release. Verifies the + tag matches the project version to prevent mismatched artifacts. - CodeQL workflow (`.github/workflows/codeql.yml`) running GitHub's `security-and-quality` Python query suite on every push, PR, and weekly. Findings surface under the repo's Security tab.