Skip to content

release-on-tag-succeeded #454

release-on-tag-succeeded

release-on-tag-succeeded #454

# This workflow publishes the main AioHomematic package to PyPI when a GitHub Release is published,
# and also creates a separate "support-vX.Y.Z" release that contains only the aiohomematic_test_support
# folder as a ZIP PLUS an independently built support wheel/sdist (aiohomematic-support).
#
# Prereqs/assumptions:
# - Root pyproject.toml excludes aiohomematic_test_support from prod builds (wheel/sdist).
# - A minimal packaging setup exists at aiohomematic_test_support/{__init__.py, pyproject.toml}.
# - Trusted Publishing to PyPI is configured for this repository.
#
# Result:
# - Main Release tag: vX.Y.Z -> uploads to PyPI.
# - Support Release tag: support-vX.Y.Z -> attaches:
# * aiohomematic_test_support-vX.Y.Z.zip
# * aiohomematic_test_support-<version>-py3-none-any.whl
# * aiohomematic_test_support-<version>.tar.gz
name: "Release: Publish to PyPI"
on:
release:
types: [published]
repository_dispatch:
types: [release-on-tag-succeeded]
permissions:
contents: write # required to create tags/releases and upload assets
id-token: write # required for PyPI Trusted Publishing
concurrency:
group: python-publish-${{ github.event.release.tag_name || github.event.client_payload.tag || github.ref_name }}
cancel-in-progress: true
jobs:
# ==========================================================
# 1) MAIN BUILD JOB
# - Builds the production distributions from the repo root
# - Skips if the triggering tag already starts with "support-"
# ==========================================================
release-build:
if: ${{ github.repository_owner == 'SukramJ' && ((github.event_name == 'release' && !startsWith(github.event.release.tag_name, 'support-')) || (github.event_name == 'repository_dispatch' && !startsWith(github.event.client_payload.tag, 'support-'))) }}
runs-on: ubuntu-latest
name: Build Main Package (${{ github.event.release.tag_name || github.event.client_payload.tag }})
env:
TAG_NAME: ${{ github.event.release.tag_name || github.event.client_payload.tag }}
steps:
- name: Check out repository
uses: actions/checkout@v6
- name: Set up Python
uses: actions/setup-python@v6
with:
python-version: "3.13"
cache: 'pip'
cache-dependency-path: |
requirements.txt
requirements_test.txt
- name: Build distributions (prod)
run: |
python -m pip install --upgrade pip
python -m pip install build
# Optional: if your tests requirements are needed for build steps
if [ -f requirements_test.txt ]; then pip install -r requirements_test.txt; fi
python -m build
ls -l dist/
- name: Upload built distributions as artifact
uses: actions/upload-artifact@v6
with:
name: release-dists
path: dist/
# ==========================================================
# 2) PYPI PUBLISH JOB
# - Publishes the built distributions to PyPI (Trusted Publishing)
# ==========================================================
pypi-publish:
if: ${{ github.repository_owner == 'SukramJ' && ((github.event_name == 'release' && !startsWith(github.event.release.tag_name, 'support-')) || (github.event_name == 'repository_dispatch' && !startsWith(github.event.client_payload.tag, 'support-'))) }}
runs-on: ubuntu-latest
name: Publish to PyPI (${{ github.event.release.tag_name || github.event.client_payload.tag }})
needs: [release-build]
permissions:
id-token: write
contents: read
environment:
name: pypi
env:
TAG_NAME: ${{ github.event.release.tag_name || github.event.client_payload.tag }}
steps:
- name: Download built distributions
uses: actions/download-artifact@v7
with:
name: release-dists
path: dist/
- name: Publish to PyPI (Trusted Publishing)
uses: pypa/gh-action-pypi-publish@release/v1
with:
packages-dir: dist/
# ==========================================================
# 3) SUPPORT RELEASE JOB
# - Creates a separate support tag/release (support-vX.Y.Z)
# - Zips only aiohomematic_test_support/ and also builds a real support package
# ==========================================================
support-release:
if: ${{ github.repository_owner == 'SukramJ' && ((github.event_name == 'release' && !startsWith(github.event.release.tag_name, 'support-')) || (github.event_name == 'repository_dispatch' && !startsWith(github.event.client_payload.tag, 'support-'))) }}
runs-on: ubuntu-latest
name: Create Support Release (support-${{ github.event.release.tag_name || github.event.client_payload.tag }})
needs: [release-build]
permissions:
contents: write
id-token: write # <- REQUIRED for OIDC here too
env:
TAG_NAME: ${{ github.event.release.tag_name || github.event.client_payload.tag }}
steps:
- name: Checkout repository (full history for tags)
uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Set up Python
uses: actions/setup-python@v6
with:
python-version: "3.13"
cache: 'pip'
# Make a ZIP that contains a top-level 'aiohomematic_test_support/' folder WITHOUT touching your real package dir
- name: Create support-only ZIP (stage into temp folder)
run: |
set -euo pipefail
rm -rf support_zip_stage
mkdir -p support_zip_stage
rsync -a --delete aiohomematic_test_support/ support_zip_stage/aiohomematic_test_support/
# If you also want to include non-.py files (e.g. py.typed, data), they’re already copied by rsync
(cd support_zip_stage && zip -r "../aiohomematic_test_support-${TAG_NAME}.zip" aiohomematic_test_support)
ls -l "aiohomematic_test_support-${TAG_NAME}.zip"
- name: Compute support version from main tag
id: vparse
run: |
RAW="${TAG_NAME}" # e.g. v1.2.3
VER="${RAW#v}" # -> 1.2.3
echo "SUPPORT_VER=${VER}" >> "$GITHUB_OUTPUT"
# Ensure __init__.py exists in the real package dir and inject the version
- name: Inject version into aiohomematic_test_support/__init__.py
run: |
set -euo pipefail
VER="${{ steps.vparse.outputs.SUPPORT_VER }}"
if [ ! -f aiohomematic_test_support/__init__.py ]; then
echo '__version__ = "0.0.0"' > aiohomematic_test_support/__init__.py
echo "Created aiohomematic_test_support/__init__.py"
fi
python - <<'PY'
from pathlib import Path
import re
p = Path("aiohomematic_test_support/__init__.py")
txt = p.read_text(encoding="utf-8")
if "__version__" not in txt:
txt = '__version__ = "0.0.0"\n' + txt
txt = re.sub(r'__version__\s*=\s*".*?"', f'__version__ = "${{ steps.vparse.outputs.SUPPORT_VER }}"', txt)
p.write_text(txt, encoding="utf-8")
print("Injected version into", p)
PY
# Build wheel + sdist from the REAL package folder
- name: Build support package (wheel + sdist)
working-directory: aiohomematic_test_support
run: |
set -euo pipefail
python -m pip install --upgrade pip
python -m pip install build
python -m build
ls -l dist/
- name: Create & push support tag at the same commit
run: |
set -euo pipefail
SUPPORT_TAG="support-${TAG_NAME}"
if ! git rev-parse -q --verify "refs/tags/${SUPPORT_TAG}" >/dev/null; then
MAIN_SHA="$(git rev-list -n 1 "${TAG_NAME}")"
git tag "${SUPPORT_TAG}" "${MAIN_SHA}"
git push origin "${SUPPORT_TAG}"
fi
- name: Create/Update Support Release and upload assets
uses: softprops/action-gh-release@v2
with:
tag_name: support-${{ env.TAG_NAME }}
name: "AioHomematic Support ${{ env.TAG_NAME }}"
body: |
Support-only release for testing. Contains only the `aiohomematic_test_support` package.
This release is linked to main release ${{ env.TAG_NAME }}.
prerelease: true
files: |
aiohomematic_test_support-${{ env.TAG_NAME }}.zip
aiohomematic_test_support/dist/*.whl
aiohomematic_test_support/dist/*.tar.gz
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Publish support package to PyPI (OIDC Trusted Publishing)
uses: pypa/gh-action-pypi-publish@release/v1
with:
packages-dir: aiohomematic_test_support/dist/
skip-existing: true
verbose: true