name: Reusable Python Package Publish # Builds a Python package with `python -m build` and uploads it to the Gitea PyPI registry with # twine. Intended to run only on version tags (v*), alongside python-checks, so a package is # never published without its tests passing. # # The caller gates this job on python-checks and on the tag ref, the same way docker-publish is # gated. The job itself additionally refuses to publish when the git tag does not match the # version declared in pyproject.toml, so a mistyped tag cannot ship the wrong version. on: workflow_call: inputs: package_name: # informational, used only in log output required: true type: string use_private_index: # build backends that need the in-house BB* packages to resolve build dependencies type: boolean default: false secrets: REGISTRY_USERNAME: { required: true } REGISTRY_PASSWORD: { required: true } PYPI_UPLOAD_URL: { required: true } PYPI_UPLOAD_USER: { required: true } PYPI_UPLOAD_PASSWORD: { required: true } jobs: publish: runs-on: docker container: image: gitea.tech-buddy.at/bitbuddydev/gitea_runner_python314:1.0.3 credentials: username: ${{ secrets.REGISTRY_USERNAME }} password: ${{ secrets.REGISTRY_PASSWORD }} steps: - name: Checkout uses: actions/checkout@v4 - name: Configure private package index if: ${{ inputs.use_private_index }} env: PRIVATE_INDEX_URL: ${{ secrets.PIP_EXTRA_INDEX_URL }} run: | if [ -z "$PRIVATE_INDEX_URL" ]; then echo "use_private_index=true but the PIP_EXTRA_INDEX_URL secret is empty or not set" exit 1 fi pip config --site set global.extra-index-url "$PRIVATE_INDEX_URL" - name: Verify the tag matches the package version shell: bash run: | set -euo pipefail if ! echo "${{ gitea.ref }}" | grep -q '^refs/tags/v'; then echo "This workflow only publishes on version tags (refs/tags/v*), got '${{ gitea.ref }}'" exit 1 fi TAG_VERSION="${{ gitea.ref_name }}" TAG_VERSION="${TAG_VERSION#v}" PROJECT_VERSION="$(python -c "import tomllib;print(tomllib.load(open('pyproject.toml','rb'))['project']['version'])")" echo "tag version : ${TAG_VERSION}" echo "pyproject version: ${PROJECT_VERSION}" if [ "${TAG_VERSION}" != "${PROJECT_VERSION}" ]; then echo "Tag v${TAG_VERSION} does not match the version ${PROJECT_VERSION} in pyproject.toml" echo "Bump the version in pyproject.toml and retag, so the published artifact matches the tag." exit 1 fi - name: Build the package shell: bash run: | set -euo pipefail python -m pip install --upgrade pip build twine python -m build echo "=== built artifacts for ${{ inputs.package_name }} ===" ls -1 dist - name: Check the artifacts run: python -m twine check dist/* - name: Upload to the package registry env: TWINE_USERNAME: ${{ secrets.PYPI_UPLOAD_USER }} TWINE_PASSWORD: ${{ secrets.PYPI_UPLOAD_PASSWORD }} run: | python -m twine upload --repository-url "${{ secrets.PYPI_UPLOAD_URL }}" dist/*