From 636fc88bcc5c7dfeefcf73e5f3896beff48f9b9c Mon Sep 17 00:00:00 2001 From: Thomas Isensee <26852629+thomasisensee@users.noreply.github.com> Date: Fri, 20 Mar 2026 13:30:34 +0100 Subject: [PATCH 1/3] ci: add pypi release workflow --- .github/workflows/release.yml | 126 ++++++++++++++++++++++++++++++++++ 1 file changed, 126 insertions(+) create mode 100644 .github/workflows/release.yml diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..c45b004 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,126 @@ +name: Release + +on: + workflow_dispatch: + inputs: + publish_target: + description: "Choose whether to build only, publish to TestPyPI, or publish to PyPI" + required: true + default: dry-run + type: choice + options: + - dry-run + - testpypi + - pypi + push: + tags: + - "v*" + +jobs: + build: + name: Build distribution artifacts + runs-on: ubuntu-latest + permissions: + contents: read + + steps: + - name: Checkout repository + uses: actions/checkout@v6 + + - name: Set up Python 3.14 + uses: actions/setup-python@v6 + with: + python-version: "3.14" + + - name: Verify release tag matches package version + if: ${{ github.event_name == 'push' || inputs.publish_target != 'dry-run' }} + run: | + python - <<'PY' + import os + import pathlib + import tomllib + + pyproject = pathlib.Path("pyproject.toml") + version = tomllib.loads(pyproject.read_text())["project"]["version"] + ref = os.environ["GITHUB_REF"] + expected_ref = f"refs/tags/v{version}" + + if ref != expected_ref: + raise SystemExit( + "Publishing requires running this workflow from the " + f"tag {expected_ref}, but GitHub provided {ref!r}." + ) + + print(f"Publishing from {ref}, matching project version {version}.") + PY + + - name: Install build and test dependencies + run: | + python -m pip install --upgrade pip build twine pytest + + - name: Build source and wheel distributions + run: | + python -m build + + - name: Check built distributions + run: | + python -m twine check dist/* + + - name: Install package from built wheel + run: | + python -m pip install --force-reinstall dist/*.whl + + - name: Run Python tests + run: | + python -m pytest + + - name: Upload built distributions + uses: actions/upload-artifact@v7 + with: + name: python-package-distributions + path: dist/* + if-no-files-found: error + + publish-testpypi: + name: Publish to TestPyPI + if: ${{ github.event_name == 'workflow_dispatch' && inputs.publish_target == 'testpypi' }} + needs: build + runs-on: ubuntu-latest + permissions: + id-token: write + environment: + name: testpypi + url: https://test.pypi.org/project/stitchmeta/ + + steps: + - name: Download built distributions + uses: actions/download-artifact@v8 + with: + name: python-package-distributions + path: dist/ + + - name: Publish distributions to TestPyPI + uses: pypa/gh-action-pypi-publish@release/v1 + with: + repository-url: https://test.pypi.org/legacy/ + + publish-pypi: + name: Publish to PyPI + if: ${{ github.event_name == 'push' || (github.event_name == 'workflow_dispatch' && inputs.publish_target == 'pypi') }} + needs: build + runs-on: ubuntu-latest + permissions: + id-token: write + environment: + name: pypi + url: https://pypi.org/project/stitchmeta/ + + steps: + - name: Download built distributions + uses: actions/download-artifact@v8 + with: + name: python-package-distributions + path: dist/ + + - name: Publish distributions to PyPI + uses: pypa/gh-action-pypi-publish@release/v1 From ee2a6033cfb26a8cbc784d203c525516a37d8f48 Mon Sep 17 00:00:00 2001 From: Thomas Isensee <26852629+thomasisensee@users.noreply.github.com> Date: Fri, 20 Mar 2026 14:18:38 +0100 Subject: [PATCH 2/3] ci: add github release on pushes --- .github/workflows/release.yml | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index c45b004..1acfafa 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -124,3 +124,24 @@ jobs: - name: Publish distributions to PyPI uses: pypa/gh-action-pypi-publish@release/v1 + + github-release: + name: Create GitHub Release + if: ${{ github.event_name == 'push' }} + needs: [build, publish-pypi] + runs-on: ubuntu-latest + permissions: + contents: write + + steps: + - name: Download built distributions + uses: actions/download-artifact@v8 + with: + name: python-package-distributions + path: dist/ + + - name: Create GitHub Release + uses: softprops/action-gh-release@v2 + with: + generate_release_notes: true + files: dist/* From 9e20c4b856aa254d15ef8447019c25bdfffe2410 Mon Sep 17 00:00:00 2001 From: Thomas Isensee <26852629+thomasisensee@users.noreply.github.com> Date: Fri, 20 Mar 2026 14:21:26 +0100 Subject: [PATCH 3/3] ci: pypi publish only on tag pushes --- .github/workflows/release.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 1acfafa..96e6273 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -11,7 +11,6 @@ on: options: - dry-run - testpypi - - pypi push: tags: - "v*" @@ -33,7 +32,7 @@ jobs: python-version: "3.14" - name: Verify release tag matches package version - if: ${{ github.event_name == 'push' || inputs.publish_target != 'dry-run' }} + if: ${{ github.event_name == 'push' || inputs.publish_target == 'testpypi' }} run: | python - <<'PY' import os @@ -106,7 +105,7 @@ jobs: publish-pypi: name: Publish to PyPI - if: ${{ github.event_name == 'push' || (github.event_name == 'workflow_dispatch' && inputs.publish_target == 'pypi') }} + if: ${{ github.event_name == 'push' }} needs: build runs-on: ubuntu-latest permissions: