Skip to content
Latchkey

Publish to PyPI workflow (RUC-NLPIR/Arbor)

The Publish to PyPI workflow from RUC-NLPIR/Arbor, explained and optimized by Latchkey.

C

CI health: C - fair

Point runs-on at Latchkey and get run de-duplication, job timeouts, SHA-pinned actions, self-healing for flaky steps, and up to 58% lower cost, applied automatically.

Grade your own workflow free or run it on Latchkey →
Source: RUC-NLPIR/Arbor.github/workflows/publish.ymlLicense Apache-2.0View source

What it does

This is the Publish to PyPI workflow from the RUC-NLPIR/Arbor repository, a real project running GitHub Actions. It is shown here with attribution under its Apache-2.0 license.

Below, Latchkey shows a faster, safer version produced by its optimization engine.

The workflow

workflow (.yml)
name: Publish to PyPI

# Triggered when you push a version tag, e.g.:
#   git tag v0.2.0 && git push origin v0.2.0
# The tag value becomes the published version via setuptools-scm.
on:
  push:
    tags:
      - "v*"

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0  # full history + tags so setuptools-scm can read the version
      - uses: astral-sh/setup-uv@v5
      - name: Build sdist and wheel
        run: uv build
      - uses: actions/upload-artifact@v4
        with:
          name: dist
          path: dist/

  publish:
    needs: build
    runs-on: ubuntu-latest
    environment: pypi          # must match the environment in the PyPI trusted-publisher config
    permissions:
      id-token: write          # required for PyPI Trusted Publishing (OIDC); no token needed
    steps:
      - uses: actions/download-artifact@v4
        with:
          name: dist
          path: dist/
      - uses: pypa/gh-action-pypi-publish@release/v1

  github-release:
    needs: publish
    runs-on: ubuntu-latest
    permissions:
      contents: write          # required to create the GitHub Release
    steps:
      - uses: actions/download-artifact@v4
        with:
          name: dist
          path: dist/
      - name: Check whether a Release already exists for this tag
        id: check
        env:
          GH_TOKEN: ${{ github.token }}
        run: |
          # If you drafted the Release on the web before pushing the tag, it
          # already exists here and has your hand-written notes.
          if gh release view "${GITHUB_REF_NAME}" --repo "${GITHUB_REPOSITORY}" >/dev/null 2>&1; then
            echo "exists=true" >> "$GITHUB_OUTPUT"
          else
            echo "exists=false" >> "$GITHUB_OUTPUT"
          fi
      - name: Create or update GitHub Release
        uses: softprops/action-gh-release@v2
        with:
          # Auto-generate notes ONLY when this workflow is creating the Release
          # (i.e. you pushed a bare tag). If you already wrote notes on the web,
          # we leave them untouched and just attach the build artifacts.
          generate_release_notes: ${{ steps.check.outputs.exists == 'false' }}
          files: dist/*                  # attach the built wheel + sdist to the release

The same workflow, on Latchkey

Removes redundant runs and caps runaway jobs. Added and changed lines are highlighted.

name: Publish to PyPI
 
# Triggered when you push a version tag, e.g.:
#   git tag v0.2.0 && git push origin v0.2.0
# The tag value becomes the published version via setuptools-scm.
on:
  push:
    tags:
      - "v*"
 
concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true
 
jobs:
  build:
    timeout-minutes: 30
    runs-on: latchkey-small
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0  # full history + tags so setuptools-scm can read the version
      - uses: astral-sh/setup-uv@v5
      - name: Build sdist and wheel
        run: uv build
      - uses: actions/upload-artifact@v4
        with:
          name: dist
          path: dist/
 
  publish:
    timeout-minutes: 30
    needs: build
    runs-on: latchkey-small
    environment: pypi          # must match the environment in the PyPI trusted-publisher config
    permissions:
      id-token: write          # required for PyPI Trusted Publishing (OIDC); no token needed
    steps:
      - uses: actions/download-artifact@v4
        with:
          name: dist
          path: dist/
      - uses: pypa/gh-action-pypi-publish@release/v1
 
  github-release:
    timeout-minutes: 30
    needs: publish
    runs-on: latchkey-small
    permissions:
      contents: write          # required to create the GitHub Release
    steps:
      - uses: actions/download-artifact@v4
        with:
          name: dist
          path: dist/
      - name: Check whether a Release already exists for this tag
        id: check
        env:
          GH_TOKEN: ${{ github.token }}
        run: |
          # If you drafted the Release on the web before pushing the tag, it
          # already exists here and has your hand-written notes.
          if gh release view "${GITHUB_REF_NAME}" --repo "${GITHUB_REPOSITORY}" >/dev/null 2>&1; then
            echo "exists=true" >> "$GITHUB_OUTPUT"
          else
            echo "exists=false" >> "$GITHUB_OUTPUT"
          fi
      - name: Create or update GitHub Release
        uses: softprops/action-gh-release@v2
        with:
          # Auto-generate notes ONLY when this workflow is creating the Release
          # (i.e. you pushed a bare tag). If you already wrote notes on the web,
          # we leave them untouched and just attach the build artifacts.
          generate_release_notes: ${{ steps.check.outputs.exists == 'false' }}
          files: dist/*                  # attach the built wheel + sdist to the release
 

What changed

3 third-party actions are referenced by a movable tag. Pin them to the commit SHA (Latchkey resolves and applies this automatically) so a repointed tag cannot change what runs.

This workflow runs 3 jobs per trigger. On Latchkey the same minutes cost up to 58% less than GitHub-hosted, with zero queue time.

Actions used in this workflow