chore(release): v0.1.1 #2
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Release | |
| # On every tag matching `vX.Y.Z`: | |
| # 1. validate the tag matches pyproject.toml version | |
| # 2. build sdist + wheel | |
| # 3. publish to PyPI via OIDC trusted publishing | |
| # 4. create a GitHub Release with notes from CHANGELOG.md and dist/* attached | |
| # | |
| # PyPI auth (pick one): | |
| # | |
| # 1. Trusted publishing (active) — no token needed. Configured at | |
| # https://pypi.org/manage/project/decepticons/settings/publishing/ | |
| # with workflow `release.yml` and environment `pypi`. | |
| # | |
| # 2. API token fallback — uncomment `password:` in the publish step and add | |
| # `PYPI_API_TOKEN` as a repository secret. | |
| on: | |
| push: | |
| tags: | |
| - "v*" | |
| workflow_dispatch: | |
| permissions: | |
| contents: read | |
| jobs: | |
| build: | |
| name: Build sdist + wheel | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - uses: actions/setup-python@v5 | |
| with: | |
| python-version: "3.12" | |
| - name: Verify tag matches pyproject version | |
| run: | | |
| TAG="${GITHUB_REF#refs/tags/v}" | |
| PYPROJECT="$(grep -E '^version = ' pyproject.toml | sed -E 's/version = "(.+)"/\1/')" | |
| if [ "$TAG" != "$PYPROJECT" ]; then | |
| echo "::error::tag v${TAG} does not match pyproject version ${PYPROJECT}" | |
| exit 1 | |
| fi | |
| echo "tag v${TAG} matches pyproject version ${PYPROJECT}" | |
| - name: Install build tools | |
| run: python -m pip install --upgrade pip build twine | |
| - name: Build distributions | |
| run: python -m build | |
| - name: Verify metadata | |
| run: python -m twine check dist/* | |
| - name: Smoke install | |
| run: | | |
| TAG="${GITHUB_REF#refs/tags/v}" | |
| python -m venv /tmp/smoke | |
| /tmp/smoke/bin/pip install --quiet dist/*.whl | |
| INSTALLED="$(/tmp/smoke/bin/python -c 'import decepticons; print(decepticons.__version__)')" | |
| if [ "$INSTALLED" != "$TAG" ]; then | |
| echo "::error::installed wheel reports __version__=${INSTALLED} but tag is v${TAG}" | |
| exit 1 | |
| fi | |
| echo "smoke OK: decepticons.__version__ = ${INSTALLED}" | |
| - uses: actions/upload-artifact@v4 | |
| with: | |
| name: dist | |
| path: dist/ | |
| publish: | |
| name: Publish to PyPI | |
| needs: build | |
| runs-on: ubuntu-latest | |
| environment: | |
| name: pypi | |
| url: https://pypi.org/p/decepticons | |
| permissions: | |
| id-token: write | |
| steps: | |
| - uses: actions/download-artifact@v4 | |
| with: | |
| name: dist | |
| path: dist/ | |
| - name: Publish | |
| uses: pypa/gh-action-pypi-publish@release/v1 | |
| # with: | |
| # password: ${{ secrets.PYPI_API_TOKEN }} | |
| github-release: | |
| name: Create GitHub Release | |
| needs: publish | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: write | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - uses: actions/download-artifact@v4 | |
| with: | |
| name: dist | |
| path: dist/ | |
| - name: Extract release notes from CHANGELOG | |
| id: notes | |
| run: | | |
| VERSION="${GITHUB_REF#refs/tags/v}" | |
| # Pull the section between `## [VERSION]` and the next `## [` heading. | |
| awk -v v="$VERSION" ' | |
| $0 ~ "^## \\[" v "\\]" { found=1; next } | |
| found && /^## \[/ { exit } | |
| found { print } | |
| ' CHANGELOG.md > release-notes.md | |
| if [ ! -s release-notes.md ]; then | |
| echo "warning: no CHANGELOG entry found for v${VERSION} — release notes will be empty" | |
| fi | |
| echo "version=${VERSION}" >> "$GITHUB_OUTPUT" | |
| - name: Create release | |
| uses: softprops/action-gh-release@v2 | |
| with: | |
| tag_name: ${{ github.ref_name }} | |
| name: v${{ steps.notes.outputs.version }} | |
| body_path: release-notes.md | |
| files: dist/* | |
| fail_on_unmatched_files: true |