Publish π π¦ to TestPyPI workflow (paulrobello/parllama)
The Publish π π¦ to TestPyPI workflow from paulrobello/parllama, explained and optimized by Latchkey.
CI health: B - good
Point runs-on at Latchkey and get job timeouts, SHA-pinned actions, self-healing for flaky steps, and up to 58% lower cost, applied automatically.
What it does
This is the Publish π π¦ to TestPyPI workflow from the paulrobello/parllama 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: Publish π π¦ to TestPyPI
on:
workflow_dispatch:
inputs:
version:
description: 'Version to publish (optional - will auto-detect if not provided)'
required: false
type: string
jobs:
build:
name: Build distribution π¦
runs-on: ubuntu-latest
outputs:
version: ${{ steps.get_version.outputs.version }}
steps:
- uses: actions/checkout@v6
- name: Setup Python with uv
uses: ./.github/actions/setup-python-uv
- name: Validate version
id: get_version
uses: ./.github/actions/validate-version
with:
version-override: ${{ inputs.version }}
- name: Run tests and checks
run: |
make checkall
- name: Build package
run: make package
- name: Store the distribution packages
uses: actions/upload-artifact@v7
with:
name: python-package-distributions
path: dist/
publish-to-testpypi:
if: github.event_name == 'workflow_dispatch' # Only allow manual triggers
name: Publish π distribution π¦ to TestPyPI
runs-on: ubuntu-latest
needs: build
environment:
name: testpypi
url: https://test.pypi.org/p/parllama
permissions:
id-token: write # IMPORTANT: mandatory for trusted publishing
steps:
- name: Download all the dists
uses: actions/download-artifact@v8
with:
name: python-package-distributions
path: dist/
- name: Publish distribution π¦ to TestPyPI
uses: pypa/gh-action-pypi-publish@release/v1
with:
repository-url: https://test.pypi.org/legacy/
skip-existing: true
- name: Discord notification
if: always() && needs.build.result == 'success'
env:
DISCORD_WEBHOOK: ${{ secrets.DISCORD_WEBHOOK }}
uses: Ilshidur/action-discord@0.4.0
with:
args: 'β
Successfully published ${{ github.repository }} v${{ needs.build.outputs.version }} to TestPyPI! π§ͺ'
continue-on-error: true
- name: Discord notification - failure
if: failure()
env:
DISCORD_WEBHOOK: ${{ secrets.DISCORD_WEBHOOK }}
uses: Ilshidur/action-discord@0.4.0
with:
args: 'β Failed to publish ${{ github.repository }} v${{ needs.build.outputs.version }} to TestPyPI. Check the workflow logs for details.'
continue-on-error: true
# Global failure notification for any job failure
notify-failure:
runs-on: ubuntu-latest
needs: [build, publish-to-testpypi]
if: always() && contains(needs.*.result, 'failure')
steps:
- name: Discord notification - Workflow failure
env:
DISCORD_WEBHOOK: ${{ secrets.DISCORD_WEBHOOK }}
uses: Ilshidur/action-discord@0.4.0
with:
args: 'π₯ TestPyPI workflow FAILED for ${{ github.repository }}. Check logs for details!'
continue-on-error: true
The same workflow, on Latchkey
Removes redundant runs and caps runaway jobs. Added and changed lines are highlighted.
name: Publish π π¦ to TestPyPI on: workflow_dispatch: inputs: version: description: 'Version to publish (optional - will auto-detect if not provided)' required: false type: string jobs: build: timeout-minutes: 30 name: Build distribution π¦ runs-on: latchkey-small outputs: version: ${{ steps.get_version.outputs.version }} steps: - uses: actions/checkout@v6 - name: Setup Python with uv uses: ./.github/actions/setup-python-uv - name: Validate version id: get_version uses: ./.github/actions/validate-version with: version-override: ${{ inputs.version }} - name: Run tests and checks run: | make checkall - name: Build package run: make package - name: Store the distribution packages uses: actions/upload-artifact@v7 with: name: python-package-distributions path: dist/ publish-to-testpypi: timeout-minutes: 30 if: github.event_name == 'workflow_dispatch' # Only allow manual triggers name: Publish π distribution π¦ to TestPyPI runs-on: latchkey-small needs: build environment: name: testpypi url: https://test.pypi.org/p/parllama permissions: id-token: write # IMPORTANT: mandatory for trusted publishing steps: - name: Download all the dists uses: actions/download-artifact@v8 with: name: python-package-distributions path: dist/ - name: Publish distribution π¦ to TestPyPI uses: pypa/gh-action-pypi-publish@release/v1 with: repository-url: https://test.pypi.org/legacy/ skip-existing: true - name: Discord notification if: always() && needs.build.result == 'success' env: DISCORD_WEBHOOK: ${{ secrets.DISCORD_WEBHOOK }} uses: Ilshidur/action-discord@0.4.0 with: args: 'β Successfully published ${{ github.repository }} v${{ needs.build.outputs.version }} to TestPyPI! π§ͺ' continue-on-error: true - name: Discord notification - failure if: failure() env: DISCORD_WEBHOOK: ${{ secrets.DISCORD_WEBHOOK }} uses: Ilshidur/action-discord@0.4.0 with: args: 'β Failed to publish ${{ github.repository }} v${{ needs.build.outputs.version }} to TestPyPI. Check the workflow logs for details.' continue-on-error: true # Global failure notification for any job failure notify-failure: timeout-minutes: 30 runs-on: latchkey-small needs: [build, publish-to-testpypi] if: always() && contains(needs.*.result, 'failure') steps: - name: Discord notification - Workflow failure env: DISCORD_WEBHOOK: ${{ secrets.DISCORD_WEBHOOK }} uses: Ilshidur/action-discord@0.4.0 with: args: 'π₯ TestPyPI workflow FAILED for ${{ github.repository }}. Check logs for details!' continue-on-error: true
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. - Add a job timeout so a hung step cannot burn hours of runner time.
2 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.