From 6534a87c282c22eabff28a316ac65e55230716ab Mon Sep 17 00:00:00 2001 From: safishamsi Date: Sat, 18 Jul 2026 22:23:13 +0100 Subject: [PATCH] ci: add PyPI trusted-publishing workflow (publish.yml) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Publishes graphifyy to PyPI via GitHub OIDC on a published Release — no API token. Builds sdist+wheel with uv, guards that the package version matches the release tag, twine-checks, then uploads via pypa/gh-action-pypi-publish with id-token: write and the `pypi` environment. Requires a matching GitHub trusted publisher configured on PyPI (Owner Graphify-Labs, repo graphify, workflow publish.yml, environment pypi). Co-Authored-By: Claude Opus 4.8 (1M context) --- .github/workflows/publish.yml | 55 +++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 .github/workflows/publish.yml diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml new file mode 100644 index 000000000..9e868c96e --- /dev/null +++ b/.github/workflows/publish.yml @@ -0,0 +1,55 @@ +name: Publish to PyPI + +# Publishes graphifyy to PyPI via OpenID Connect (trusted publishing) — no API +# token or password. Fires when a GitHub Release is published (i.e. after +# `gh release create ... --latest`), builds the sdist + wheel, guards that the +# package version matches the release tag, then uploads with an OIDC token. +# +# One-time PyPI setup (Manage project -> Publishing -> Add a GitHub publisher): +# Owner: Graphify-Labs +# Repository: graphify +# Workflow name: publish.yml +# Environment name: pypi +on: + release: + types: [published] + # Manual re-run escape hatch (still requires the release tag to be checked out). + workflow_dispatch: + +permissions: + contents: read + +jobs: + publish: + name: Build and publish graphifyy + runs-on: ubuntu-latest + environment: + name: pypi + url: https://pypi.org/project/graphifyy/ + permissions: + id-token: write # REQUIRED: mint the OIDC token PyPI verifies. Nothing else. + steps: + - uses: actions/checkout@v4 + + - name: Install uv + uses: astral-sh/setup-uv@v6 + + - name: Build sdist + wheel + run: uv build --sdist --wheel + + - name: Guard — package version must match the release tag + if: github.event_name == 'release' + run: | + VERSION=$(grep -m1 '^version = ' pyproject.toml | sed -E 's/^version = "(.*)"/\1/') + TAG="${GITHUB_REF_NAME#v}" + echo "pyproject version: $VERSION | release tag: $TAG" + if [ "$VERSION" != "$TAG" ]; then + echo "::error::pyproject version ($VERSION) does not match release tag ($TAG); refusing to publish." + exit 1 + fi + + - name: Twine metadata check + run: uvx twine check dist/* + + - name: Publish to PyPI (trusted publishing) + uses: pypa/gh-action-pypi-publish@release/v1