From a57743e3a3f12a71b8f633bf8b7df91fc2368e1b Mon Sep 17 00:00:00 2001 From: Manfred Riem Date: Wed, 10 Jun 2026 08:19:59 -0500 Subject: [PATCH] feat: add PyPI publishing workflow and readme metadata - Add readme = "README.md" to pyproject.toml for PyPI project description - Add manual publish-pypi.yml workflow using trusted publishers (OIDC) - Update release.yml install instructions to prefer PyPI The publish workflow is manually triggered after a release, checks out the specified tag, verifies version consistency, builds with uv, and publishes using trusted publishing (no API tokens required). Prerequisites before first use: - Take ownership of the specify-cli PyPI project (#2908) - Create a 'pypi' environment in repo settings - Configure trusted publisher on PyPI for this repo/workflow Closes #2908 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .github/workflows/publish-pypi.yml | 70 ++++++++++++++++++++++++++++++ .github/workflows/release.yml | 8 +++- pyproject.toml | 1 + 3 files changed, 78 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/publish-pypi.yml diff --git a/.github/workflows/publish-pypi.yml b/.github/workflows/publish-pypi.yml new file mode 100644 index 000000000..e5d8ac28f --- /dev/null +++ b/.github/workflows/publish-pypi.yml @@ -0,0 +1,70 @@ +name: Publish to PyPI + +on: + workflow_dispatch: + inputs: + tag: + description: 'Release tag to publish (e.g., v0.10.1)' + required: true + type: string + +permissions: + contents: read + +jobs: + build: + runs-on: ubuntu-latest + steps: + - name: Checkout release tag + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 + with: + ref: ${{ inputs.tag }} + + - name: Verify tag is a release + run: | + TAG="${{ inputs.tag }}" + if [[ ! "$TAG" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then + echo "Error: '$TAG' is not a valid release tag (expected vX.Y.Z)" + exit 1 + fi + + - name: Verify tag matches package version + run: | + TAG_VERSION="${{ inputs.tag }}" + TAG_VERSION="${TAG_VERSION#v}" + PROJECT_VERSION="$(python3 -c 'import tomllib; print(tomllib.load(open("pyproject.toml","rb"))["project"]["version"])')" + if [[ "$TAG_VERSION" != "$PROJECT_VERSION" ]]; then + echo "Error: Tag version ($TAG_VERSION) does not match pyproject.toml version ($PROJECT_VERSION)" + exit 1 + fi + + - name: Install uv + uses: astral-sh/setup-uv@0c5e2b8115b80b4c7c5ddf6ffdd634974642d182 # v5 + + - name: Build package + run: uv build + + - name: Upload build artifacts + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 + with: + name: dist + path: dist/ + + publish: + needs: build + runs-on: ubuntu-latest + environment: pypi + permissions: + id-token: write + steps: + - name: Download build artifacts + uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4 + with: + name: dist + path: dist/ + + - name: Install uv + uses: astral-sh/setup-uv@0c5e2b8115b80b4c7c5ddf6ffdd634974642d182 # v5 + + - name: Publish to PyPI + run: uv publish --trusted-publishing always diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index b35bc30ec..7b5683881 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -66,10 +66,16 @@ jobs: ## Install \`\`\`bash - uv tool install specify-cli --from git+https://github.com/github/spec-kit.git@${VERSION} + uv tool install specify-cli@latest specify init my-project \`\`\` + Or install from source: + + \`\`\`bash + uv tool install specify-cli --from git+https://github.com/github/spec-kit.git@${VERSION} + \`\`\` + NOTES_EOF echo "## What's Changed" >> release_notes.md diff --git a/pyproject.toml b/pyproject.toml index f8bdc23f9..463d8d856 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,6 +2,7 @@ name = "specify-cli" version = "0.10.2.dev0" description = "Specify CLI, part of GitHub Spec Kit. A tool to bootstrap your projects for Spec-Driven Development (SDD)." +readme = "README.md" requires-python = ">=3.11" dependencies = [ "typer>=0.24.0",