name: Publish to PyPI on: release: types: [published] permissions: contents: read jobs: # ── Job 1: Validate the version tag matches the package version ──────────── validate: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-python@v5 with: python-version: "3.12" - name: Check tag matches package version run: | PKG_VERSION=$(python -c "import re; content=open('contextzip/__init__.py').read(); print(re.search(r'__version__\s*=\s*[\"\'](.*?)[\"\']', content).group(1))") TOML_VERSION=$(python -c "import tomllib; print(tomllib.load(open('pyproject.toml','rb'))['project']['version'])") TAG_VERSION="${GITHUB_REF_NAME#v}" echo "Package version (__init__.py): $PKG_VERSION" echo "Package version (pyproject.toml): $TOML_VERSION" echo "Release tag: $TAG_VERSION" if [ "$PKG_VERSION" != "$TAG_VERSION" ] || [ "$TOML_VERSION" != "$TAG_VERSION" ]; then echo "Version mismatch — update __init__.py and/or pyproject.toml before releasing" exit 1 fi echo "Versions match" # ── Job 2: The full test suite must pass on every OS before a release ───── tests: uses: ./.github/workflows/tests.yml # ── Job 3: Build the distributions ──────────────────────────────────────── build: runs-on: ubuntu-latest needs: [validate, tests] steps: - uses: actions/checkout@v4 - uses: actions/setup-python@v5 with: python-version: "3.12" - name: Install build tool run: pip install build - name: Build wheel and sdist run: python -m build - name: Verify wheel contains entry_points.txt run: | python - << 'EOF' import zipfile, sys, os wheels = [f for f in os.listdir("dist") if f.endswith(".whl")] if not wheels: print("No wheel found in dist/"); sys.exit(1) with zipfile.ZipFile(f"dist/{wheels[0]}") as z: names = z.namelist() if not any("entry_points.txt" in n for n in names): print("entry_points.txt missing from wheel"); sys.exit(1) print(f"Wheel OK: {wheels[0]}") ep = [n for n in names if "entry_points" in n][0] print(z.read(ep).decode()) EOF - name: Upload distributions uses: actions/upload-artifact@v4 with: name: release-dists path: dist/ # ── Job 4: Publish to PyPI via Trusted Publishing (no token needed) ──────── publish: runs-on: ubuntu-latest needs: build permissions: id-token: write # required for trusted publishing environment: name: pypi url: https://pypi.org/project/contextzip/${{ github.event.release.tag_name }} steps: - name: Download distributions uses: actions/download-artifact@v4 with: name: release-dists path: dist/ - name: Publish to PyPI uses: pypa/gh-action-pypi-publish@release/v1 with: packages-dir: dist/