blob: 229f8347d43e9cc842e3771f09b839644decb7c1 [file] [log] [blame]
Eric Ballb31722a2026-06-09 18:07:26 -07001---
2# SPDX-FileCopyrightText: 2026 The Linux Foundation
3# SPDX-License-Identifier: Apache-2.0
4
5name: PyPI Publish
6description: "Build and publish Python packages to PyPI on SemVer release tags"
7
8inputs:
9 pypi-index:
10 description: "PyPI repository name to publish to"
11 required: false
12 default: "pypi"
13 pypi-username:
14 description: "PyPI username"
15 required: true
16 pypi-password:
17 description: "PyPI password or API token"
18 required: true
19 module-dirs:
20 description: "Pipe-separated list of directories containing Python modules to publish"
21 required: false
22 default: "."
23 prep-commands:
24 description: "Commands to run before building"
25 required: false
26 default: ""
27
28runs:
29 using: "composite"
30 steps:
31 - name: Get and verify SemVer release tag
32 id: tag-check
33 shell: bash
34 run: |
35 set -eu -o pipefail
36 TAG=$(git tag --points-at HEAD | head -n1 || true)
37 if [ -z "$TAG" ]; then
38 echo "No git tag on HEAD, skipping publish"
39 echo "is-release=false" >> "$GITHUB_OUTPUT"
40 exit 0
41 fi
42 # Match vX.Y.Z or X.Y.Z (SemVer release, no pre-release suffix)
43 if [[ "$TAG" =~ ^v?[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
44 echo "Found SemVer release tag: $TAG"
45 echo "is-release=true" >> "$GITHUB_OUTPUT"
46 echo "tag=$TAG" >> "$GITHUB_OUTPUT"
47 else
48 echo "Tag '$TAG' is not a SemVer release version, skipping publish"
49 echo "is-release=false" >> "$GITHUB_OUTPUT"
50 fi
51
52 - name: Run prep commands
53 if: steps.tag-check.outputs.is-release == 'true' && inputs.prep-commands != ''
54 shell: bash
55 run: |
56 set -eu -o pipefail
57 echo "Running prep commands..."
58 ${{ inputs.prep-commands }}
59
60 - name: Build and publish packages
61 if: steps.tag-check.outputs.is-release == 'true'
62 shell: bash
63 env:
64 TWINE_USERNAME: ${{ inputs.pypi-username }}
65 TWINE_PASSWORD: ${{ inputs.pypi-password }}
66 run: |
67 set -eu -o pipefail
68
69 echo "Installing build dependencies..."
70 pip install --upgrade pip setuptools wheel twine build
71
72 IFS='|' read -ra DIRS <<< "${{ inputs.module-dirs }}"
73 for dir in "${DIRS[@]}"; do
74 dir=$(echo "$dir" | xargs) # trim whitespace
75 echo "::group::Publishing module in: $dir"
76
77 if [ ! -f "$dir/setup.py" ]; then
78 echo "ERROR: setup.py not found in $dir"
79 exit 1
80 fi
81
82 echo "Building source distribution..."
83 cd "$dir"
84 python3 -m build
85
86 echo "Uploading to PyPI repository: ${{ inputs.pypi-index }}"
87 twine upload -r "${{ inputs.pypi-index }}" dist/*
88
89 cd "$GITHUB_WORKSPACE"
90 echo "::endgroup::"
91 done