Skip to content
Latchkey

Publish Wheel package to PyPI workflow (nyu-mlab/iot-inspector-client)

The Publish Wheel package to PyPI workflow from nyu-mlab/iot-inspector-client, explained and optimized by Latchkey.

B

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.

Grade your own workflow free or run it on Latchkey →
Source: nyu-mlab/iot-inspector-client.github/workflows/create_release.ymlLicense Apache-2.0View source

What it does

This is the Publish Wheel package to PyPI workflow from the nyu-mlab/iot-inspector-client 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 Wheel package to PyPI

on:
  workflow_dispatch:
    inputs:
      bump_type:
        type: choice
        required: true
        default: patch
        options:
          - patch
          - minor
          - major
        description: "Select the type of version bump for the release"
  #push:
  #  branches:
  #    - master

# Set no permissions by default. This is the most secure practice.
# We will grant specific permissions to each job that needs them.
permissions: {}

jobs:
  create_release:
    runs-on: ubuntu-latest
    permissions:
      contents: read
    outputs:
      v-version: ${{ steps.version.outputs.v-version }}
    steps:
      - name: Get next version
        uses: reecetech/version-increment@2024.10.1
        id: version
        with:
          release_branch: master
          use_api: true
          increment: ${{ github.event.inputs.bump_type || 'patch' }}

  build:
    runs-on: ${{ matrix.os }}
    permissions:
      contents: read
    needs: [create_release]
    strategy:
      fail-fast: false
      matrix:
        os: [ macos-latest, ubuntu-latest, windows-latest ]

    steps:
    - name: Checkout project sources
      uses: actions/checkout@v5

    - name: Create wheel file
      if: runner.os == 'Linux'
      run: |
        python3 -m pip install --upgrade pip
        python3 -m pip install setuptools wheel build setuptools_scm
        PRETEND_VERSION=${{ needs.create_release.outputs.v-version }} python3 -m build --wheel .

    - name: Store the IoT Inspector Python wheel
      if: runner.os == 'Linux'
      uses: actions/upload-artifact@v5
      with:
        name: iot-inspector
        path: dist/*.whl
        if-no-files-found: error

    - name: Install NSIS
      if: runner.os == 'Windows'
      uses: negrutiu/nsis-install@v2

    - name: Create Windows IoT Inspector launcher
      if: runner.os == 'Windows'
      shell: pwsh
      run: |
        makensis iot-inspector.nsi

    - name: Store the IoT Inspector executable
      if: runner.os == 'Windows'
      uses: actions/upload-artifact@v5
      with:
        name: iot-exe
        path: ./*.exe
        if-no-files-found: error

  publish-to-pypi:
    name: Publish Python 🐍 distribution πŸ“¦ to PyPI
    if: github.repository == 'nyu-mlab/iot-inspector-client'
    needs: [create_release, build]
    runs-on: ubuntu-latest
    environment:
      name: pypi
      url: https://pypi.org/p/iot-inspector  # Replace <package-name> with your PyPI project name
    permissions:
      id-token: write  # IMPORTANT: mandatory for trusted publishing
      contents: write  # Required for creating releases

    steps:
      - name: Download the wheel file
        uses: actions/download-artifact@v5
        with:
          name: iot-inspector
          path: dist/

      - name: Publish distribution πŸ“¦ to PyPI
        uses: pypa/gh-action-pypi-publish@release/v1
        with:
          verbose: true

      - name: Download all the IoT Inspector executable
        uses: actions/download-artifact@v5
        with:
          name: iot-exe
          path: dist/

      - name: Upload wheel package to release
        uses: softprops/action-gh-release@v2
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          tag_name: ${{ needs.create_release.outputs.v-version }}
          draft: false
          generate_release_notes: true
          prerelease: false
          files: |
            dist/*.whl

The same workflow, on Latchkey

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

name: Publish Wheel package to PyPI
 
on:
  workflow_dispatch:
    inputs:
      bump_type:
        type: choice
        required: true
        default: patch
        options:
          - patch
          - minor
          - major
        description: "Select the type of version bump for the release"
  #push:
  #  branches:
  #    - master
 
# Set no permissions by default. This is the most secure practice.
# We will grant specific permissions to each job that needs them.
permissions: {}
 
jobs:
  create_release:
    timeout-minutes: 30
    runs-on: latchkey-small
    permissions:
      contents: read
    outputs:
      v-version: ${{ steps.version.outputs.v-version }}
    steps:
      - name: Get next version
        uses: reecetech/version-increment@2024.10.1
        id: version
        with:
          release_branch: master
          use_api: true
          increment: ${{ github.event.inputs.bump_type || 'patch' }}
 
  build:
    timeout-minutes: 30
    runs-on: ${{ matrix.os }}
    permissions:
      contents: read
    needs: [create_release]
    strategy:
      fail-fast: false
      matrix:
        os: [ macos-latest, ubuntu-latest, windows-latest ]
 
    steps:
    - name: Checkout project sources
      uses: actions/checkout@v5
 
    - name: Create wheel file
      if: runner.os == 'Linux'
      run: |
        python3 -m pip install --upgrade pip
        python3 -m pip install setuptools wheel build setuptools_scm
        PRETEND_VERSION=${{ needs.create_release.outputs.v-version }} python3 -m build --wheel .
 
    - name: Store the IoT Inspector Python wheel
      if: runner.os == 'Linux'
      uses: actions/upload-artifact@v5
      with:
        name: iot-inspector
        path: dist/*.whl
        if-no-files-found: error
 
    - name: Install NSIS
      if: runner.os == 'Windows'
      uses: negrutiu/nsis-install@v2
 
    - name: Create Windows IoT Inspector launcher
      if: runner.os == 'Windows'
      shell: pwsh
      run: |
        makensis iot-inspector.nsi
 
    - name: Store the IoT Inspector executable
      if: runner.os == 'Windows'
      uses: actions/upload-artifact@v5
      with:
        name: iot-exe
        path: ./*.exe
        if-no-files-found: error
 
  publish-to-pypi:
    timeout-minutes: 30
    name: Publish Python 🐍 distribution πŸ“¦ to PyPI
    if: github.repository == 'nyu-mlab/iot-inspector-client'
    needs: [create_release, build]
    runs-on: latchkey-small
    environment:
      name: pypi
      url: https://pypi.org/p/iot-inspector  # Replace <package-name> with your PyPI project name
    permissions:
      id-token: write  # IMPORTANT: mandatory for trusted publishing
      contents: write  # Required for creating releases
 
    steps:
      - name: Download the wheel file
        uses: actions/download-artifact@v5
        with:
          name: iot-inspector
          path: dist/
 
      - name: Publish distribution πŸ“¦ to PyPI
        uses: pypa/gh-action-pypi-publish@release/v1
        with:
          verbose: true
 
      - name: Download all the IoT Inspector executable
        uses: actions/download-artifact@v5
        with:
          name: iot-exe
          path: dist/
 
      - name: Upload wheel package to release
        uses: softprops/action-gh-release@v2
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          tag_name: ${{ needs.create_release.outputs.v-version }}
          draft: false
          generate_release_notes: true
          prerelease: false
          files: |
            dist/*.whl
 

What changed

4 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.

What Latchkey heals here

This workflow has steps that commonly fail on transient issues (network, registries, flaky browsers). On Latchkey managed runners they are detected, retried, and self-healed instead of failing your build:

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

Actions used in this workflow