ci: publish to PyPI via trusted publishing; build version images on release (#417)
* ci: publish to PyPI via trusted publishing; build version images on release * ci: pin publish actions to commit SHAs; extend version guard to docker and manual dispatch * ci: disable setup-uv cache in the publish workflow
This commit is contained in:
@@ -3,7 +3,10 @@ name: Docker
|
||||
on:
|
||||
push:
|
||||
branches: ["main"]
|
||||
tags: ["v*"]
|
||||
# Version images build when a GitHub Release is published — the same event
|
||||
# that triggers the PyPI upload (publish.yml), so the two channels stay in sync.
|
||||
release:
|
||||
types: [published]
|
||||
pull_request:
|
||||
paths:
|
||||
- "Dockerfile"
|
||||
@@ -32,6 +35,19 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1
|
||||
|
||||
# Same guard as publish.yml — a release whose tag mismatches pyproject
|
||||
# must not publish versioned images either.
|
||||
- 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 images."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- uses: docker/setup-qemu-action@c7c53464625b32c7a7e944ae62b3e17d2b600130 # v3.7.0
|
||||
- uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3.12.0
|
||||
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
name: Publish to PyPI
|
||||
|
||||
# Publishes EvoScientist to PyPI via OpenID Connect (trusted publishing) — no
|
||||
# API token or password involved. Fires when a GitHub Release is published
|
||||
# (i.e. after `gh release create vX.Y.Z`), builds the sdist + wheel, guards
|
||||
# that the package version matches the release tag, then uploads with a
|
||||
# short-lived OIDC token.
|
||||
#
|
||||
# One-time PyPI setup (Manage project -> Publishing -> Add a new publisher):
|
||||
# Owner: EvoScientist
|
||||
# Repository: EvoScientist
|
||||
# Workflow name: publish.yml
|
||||
# Environment name: pypi
|
||||
on:
|
||||
release:
|
||||
types: [published]
|
||||
# Manual re-run escape hatch — dispatch it from the release tag; the version
|
||||
# guard rejects any non-tag ref.
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
publish:
|
||||
name: Build and publish to PyPI
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 15
|
||||
environment:
|
||||
name: pypi
|
||||
url: https://pypi.org/project/EvoScientist/
|
||||
permissions:
|
||||
id-token: write # required to mint the OIDC token PyPI verifies
|
||||
steps:
|
||||
# Actions in this job are pinned to full commit SHAs (like docker.yml):
|
||||
# it holds id-token: write and PyPI publishing authority.
|
||||
- uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5.0.1
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
|
||||
with:
|
||||
python-version: "3.11"
|
||||
# No shared cache in the publishing job — build from clean sources only.
|
||||
enable-cache: false
|
||||
|
||||
- name: Build sdist + wheel
|
||||
run: uv build
|
||||
|
||||
- name: Guard — package version must match the release tag
|
||||
run: |
|
||||
if [ "${GITHUB_REF_TYPE}" != "tag" ]; then
|
||||
echo "::error::This workflow must run from a version tag (got ${GITHUB_REF_TYPE} '${GITHUB_REF_NAME}'); dispatch it from the release tag."
|
||||
exit 1
|
||||
fi
|
||||
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@dc37677b2e1c63e2034f94d8a5b11f265b73ba33 # v1.14.2
|
||||
Reference in New Issue
Block a user