Manual Release to PyPI workflow (rsheftel/pandas_market_calendars)
The Manual Release to PyPI workflow from rsheftel/pandas_market_calendars, explained and optimized by Latchkey.
CI health: C - fair
Point runs-on at Latchkey and get caching, job timeouts, SHA-pinned actions, self-healing for flaky steps, and up to 58% lower cost, applied automatically.
What it does
This is the Manual Release to PyPI workflow from the rsheftel/pandas_market_calendars repository, a real project running GitHub Actions. It is shown here with attribution under its MIT license.
Below, Latchkey shows a faster, safer version produced by its optimization engine.
The workflow
name: Manual Release to PyPI
on:
workflow_dispatch:
permissions:
id-token: write # Required for Trusted Publishing OIDC
contents: write # Added: Enables pushing tags (and branches if needed)
jobs:
test-and-release:
runs-on: ubuntu-latest
strategy:
fail-fast: true
matrix:
os: [ ubuntu-latest, windows-latest, macos-latest ]
python-version: [ "3.10", "3.11", "3.12", "3.13", "3.14" ]
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
- name: Install uv
uses: astral-sh/setup-uv@v7 # Latest as of 2025; pin to specific tag if needed
with:
enable-cache: true # Optional: caches uv packages across runs for faster sync
# cache-dependency-glob: "uv.lock" # Invalidate on lockfile changes
- name: Install dependencies and project
run: uv sync --all-extras --dev
- name: Run tests
run: uv run pytest
- name: Extract package name and version from pyproject.toml
if: matrix.python-version == '3.14' && matrix.os == 'ubuntu-latest'
id: metadata
run: |
PACKAGE_NAME=$(uv run python -c "import tomllib; data = tomllib.load(open('pyproject.toml','rb')); print(data['project']['name'])")
VERSION=$(uv run python -c "import tomllib; data = tomllib.load(open('pyproject.toml','rb')); print(data['project']['version'])")
echo "package_name=$PACKAGE_NAME" >> $GITHUB_OUTPUT
echo "version=$VERSION" >> $GITHUB_OUTPUT
- name: Check if local version > current PyPI version
if: matrix.python-version == '3.14' && matrix.os == 'ubuntu-latest'
run: |
PACKAGE_NAME="${{ steps.metadata.outputs.package_name }}"
LOCAL_VERSION="${{ steps.metadata.outputs.version }}"
echo "Package name: $PACKAGE_NAME"
echo "Local version: $LOCAL_VERSION"
# Fetch latest version from PyPI JSON API
RESPONSE=$(curl -s -o /dev/null -w "%{http_code}" https://pypi.org/pypi/$PACKAGE_NAME/json)
if [ "$RESPONSE" -eq 404 ]; then
echo "Package not found on PyPI - assuming first release, proceeding."
exit 0
fi
if [ "$RESPONSE" -ne 200 ]; then
echo "Failed to query PyPI (HTTP $RESPONSE)"
exit 1
fi
PYPI_VERSION=$(curl -s https://pypi.org/pypi/$PACKAGE_NAME/json | jq -r '.info.version')
echo "Current PyPI version: $PYPI_VERSION"
# Compare versions using Python's packaging module
uv run python - <<EOF
from packaging.version import Version
local = Version("$LOCAL_VERSION")
pypi = Version("$PYPI_VERSION")
if local <= pypi:
raise SystemExit(f"Error: Local version {local} is not greater than PyPI version {pypi}")
print("Version check passed: $LOCAL_VERSION > $PYPI_VERSION")
EOF
- name: Tag the commit
if: matrix.python-version == '3.14' && matrix.os == 'ubuntu-latest'
run: |
git config user.name "github-actions"
git config user.email "github-actions@github.com"
git tag v${{ steps.metadata.outputs.version }}
git push origin v${{ steps.metadata.outputs.version }}
- name: Build package with uv
if: matrix.python-version == '3.14' && matrix.os == 'ubuntu-latest'
run: uv build
- name: Publish to PyPI using Trusted Publishing
if: matrix.python-version == '3.14' && matrix.os == 'ubuntu-latest'
run: uv publish
The same workflow, on Latchkey
Estimated ~20% faster on cache hits, plus fewer wasted runs and a safer supply chain. Added and changed lines are highlighted.
name: Manual Release to PyPI on: workflow_dispatch: permissions: id-token: write # Required for Trusted Publishing OIDC contents: write # Added: Enables pushing tags (and branches if needed) jobs: test-and-release: timeout-minutes: 30 runs-on: latchkey-small strategy: fail-fast: true matrix: os: [ ubuntu-latest, windows-latest, macos-latest ] python-version: [ "3.10", "3.11", "3.12", "3.13", "3.14" ] steps: - name: Checkout code uses: actions/checkout@v4 with: fetch-depth: 0 - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v5 with: cache: 'pip' python-version: ${{ matrix.python-version }} - name: Install uv uses: astral-sh/setup-uv@v7 # Latest as of 2025; pin to specific tag if needed with: enable-cache: true # Optional: caches uv packages across runs for faster sync # cache-dependency-glob: "uv.lock" # Invalidate on lockfile changes - name: Install dependencies and project run: uv sync --all-extras --dev - name: Run tests run: uv run pytest - name: Extract package name and version from pyproject.toml if: matrix.python-version == '3.14' && matrix.os == 'ubuntu-latest' id: metadata run: | PACKAGE_NAME=$(uv run python -c "import tomllib; data = tomllib.load(open('pyproject.toml','rb')); print(data['project']['name'])") VERSION=$(uv run python -c "import tomllib; data = tomllib.load(open('pyproject.toml','rb')); print(data['project']['version'])") echo "package_name=$PACKAGE_NAME" >> $GITHUB_OUTPUT echo "version=$VERSION" >> $GITHUB_OUTPUT - name: Check if local version > current PyPI version if: matrix.python-version == '3.14' && matrix.os == 'ubuntu-latest' run: | PACKAGE_NAME="${{ steps.metadata.outputs.package_name }}" LOCAL_VERSION="${{ steps.metadata.outputs.version }}" echo "Package name: $PACKAGE_NAME" echo "Local version: $LOCAL_VERSION" # Fetch latest version from PyPI JSON API RESPONSE=$(curl -s -o /dev/null -w "%{http_code}" https://pypi.org/pypi/$PACKAGE_NAME/json) if [ "$RESPONSE" -eq 404 ]; then echo "Package not found on PyPI - assuming first release, proceeding." exit 0 fi if [ "$RESPONSE" -ne 200 ]; then echo "Failed to query PyPI (HTTP $RESPONSE)" exit 1 fi PYPI_VERSION=$(curl -s https://pypi.org/pypi/$PACKAGE_NAME/json | jq -r '.info.version') echo "Current PyPI version: $PYPI_VERSION" # Compare versions using Python's packaging module uv run python - <<EOF from packaging.version import Version local = Version("$LOCAL_VERSION") pypi = Version("$PYPI_VERSION") if local <= pypi: raise SystemExit(f"Error: Local version {local} is not greater than PyPI version {pypi}") print("Version check passed: $LOCAL_VERSION > $PYPI_VERSION") EOF - name: Tag the commit if: matrix.python-version == '3.14' && matrix.os == 'ubuntu-latest' run: | git config user.name "github-actions" git config user.email "github-actions@github.com" git tag v${{ steps.metadata.outputs.version }} git push origin v${{ steps.metadata.outputs.version }} - name: Build package with uv if: matrix.python-version == '3.14' && matrix.os == 'ubuntu-latest' run: uv build - name: Publish to PyPI using Trusted Publishing if: matrix.python-version == '3.14' && matrix.os == 'ubuntu-latest' run: uv publish
What changed
- Run on Latchkey managed runners with one line (
runs-on), which apply the fixes below automatically and self-heal transient failures. This example useslatchkey-small; pick the runner size that fits the job. - Cache dependency installs on the setup step so they are served from cache.
- Add a job timeout so a hung step cannot burn hours of runner time.
1 third-party action is referenced by a movable tag. Pin it to the commit SHA (Latchkey resolves and applies this automatically) so a repointed tag cannot change what runs.
This workflow runs 1 job (15 with the matrix expanded) per trigger. On Latchkey the same minutes cost up to 58% less than GitHub-hosted, with zero queue time.