Skip to content

fix(ci): unblock v1.20.5 release matrix and client dispatch Refs #2706 #112

fix(ci): unblock v1.20.5 release matrix and client dispatch Refs #2706

fix(ci): unblock v1.20.5 release matrix and client dispatch Refs #2706 #112

Workflow file for this run

name: Publish Python Package to PyPI
on:
workflow_dispatch:
inputs:
version:
description: 'Version to publish (semantic version)'
required: true
type: string
dry_run:
description: 'Run in dry-run mode only'
required: false
type: boolean
default: true
repository:
description: 'PyPI repository (pypi or testpypi)'
required: false
type: choice
options:
- 'pypi'
- 'testpypi'
default: 'pypi'
push:
tags:
- 'v*'
- 'python-v*'
- 'pypi-v*'
permissions:
contents: write
packages: write
id-token: write # For PyPI trusted publishing
env:
CARGO_TERM_COLOR: always
RUST_BACKTRACE: 1
jobs:
validate:
name: Validate Python Package
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v6
- name: Set up Python
uses: actions/setup-python@v6
with:
python-version: "3.12"
- name: Install uv
uses: astral-sh/setup-uv@v7
with:
enable-cache: true
- name: Install Rust
uses: dtolnay/rust-toolchain@stable
- name: Validate package metadata
working-directory: crates/terraphim_automata_py
run: |
python -c "import tomllib; pkg = tomllib.load(open('pyproject.toml', 'rb')); print('Package name:', pkg['project']['name']); print('Version:', pkg['project']['version'])"
- name: Validate version format
run: |
if [[ "${{ github.event_name }}" == "push" && "${{ github.ref }}" == refs/tags/* ]]; then
VERSION=$(echo "${{ github.ref }}" | sed 's#refs/tags/python-v##; s#refs/tags/pypi-v##; s#refs/tags/v##')
if [[ ! "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
echo "Invalid version format: $VERSION"
exit 1
fi
echo "Version to publish: $VERSION"
fi
build:
name: Build Python Distributions
runs-on: ${{ matrix.os }}
needs: validate
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
python-version: ['3.9', '3.10', '3.11', '3.12']
include:
- os: ubuntu-latest
target: x86_64-unknown-linux-gnu
- os: windows-latest
target: x86_64-pc-windows-msvc
- os: macos-latest
target: aarch64-apple-darwin
macos-arch: arm64
steps:
- name: Checkout repository
uses: actions/checkout@v6
- name: Set up Python
uses: actions/setup-python@v6
with:
python-version: ${{ matrix.python-version }}
- name: Install Rust
uses: dtolnay/rust-toolchain@stable
with:
toolchain: stable
targets: ${{ matrix.target }}
- name: Install uv
uses: astral-sh/setup-uv@v7
with:
enable-cache: true
python-version: ${{ matrix.python-version }}
- name: Cache Cargo dependencies
uses: actions/cache@v4
with:
path: |
~/.cargo/registry/index/
~/.cargo/registry/cache/
~/.cargo/git/db/
target/
key: ${{ runner.os }}-cargo-${{ matrix.target }}-pypi-${{ hashFiles('**/Cargo.lock') }}
- name: Install Python build dependencies
working-directory: crates/terraphim_automata_py
run: |
uv pip install --system pip maturin pytest pytest-benchmark build
- name: Build wheel
uses: PyO3/maturin-action@v1
with:
working-directory: crates/terraphim_automata_py
args: --release --out dist --find-interpreter --target ${{ matrix.target }}
sccache: 'false'
manylinux: auto
- name: Upload wheel artifacts
uses: actions/upload-artifact@v5
with:
name: wheels-${{ matrix.os }}-py${{ matrix.python-version }}
path: crates/terraphim_automata_py/dist/*.whl
if-no-files-found: error
build-sdist:
name: Build Source Distribution
runs-on: ubuntu-latest
needs: validate
# Note: sdist build may fail due to maturin bug with workspace path dependencies
# Wheel builds are the primary artifacts, sdist is optional
continue-on-error: true
steps:
- name: Checkout repository
uses: actions/checkout@v6
- name: Set up Python
uses: actions/setup-python@v6
with:
python-version: "3.12"
- name: Install uv
uses: astral-sh/setup-uv@v7
with:
enable-cache: true
- name: Install Rust
uses: dtolnay/rust-toolchain@stable
- name: Build source distribution
uses: PyO3/maturin-action@v1
with:
working-directory: crates/terraphim_automata_py
command: sdist
args: --out dist
- name: Upload sdist artifact
uses: actions/upload-artifact@v5
with:
name: sdist
path: crates/terraphim_automata_py/dist/*.tar.gz
if-no-files-found: error
test:
name: Test Package
runs-on: ${{ matrix.os }}
needs: build
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
python-version: ['3.9', '3.10', '3.11', '3.12']
steps:
- name: Checkout repository
uses: actions/checkout@v6
- name: Set up Python
uses: actions/setup-python@v6
with:
python-version: ${{ matrix.python-version }}
- name: Install uv
uses: astral-sh/setup-uv@v7
with:
enable-cache: true
- name: Download test distributions
uses: actions/download-artifact@v4
with:
name: wheels-${{ matrix.os }}-py${{ matrix.python-version }}
path: ${{ github.workspace }}/dist
- name: Install test dependencies
working-directory: crates/terraphim_automata_py
run: |
uv pip install --system pytest pytest-benchmark pytest-cov black mypy ruff
uv pip install --system terraphim-automata --find-links=${{ github.workspace }}/dist
- name: Run tests
working-directory: crates/terraphim_automata_py
run: |
# Run Python tests
python -m pytest python/tests/ -v --cov=terraphim_automata --cov-report=term-missing
# Test basic import
python -c "import terraphim_automata; print('OK: Package imports successfully')"
publish-pypi:
name: Publish to PyPI
runs-on: ubuntu-latest
# Note: build-sdist is optional due to maturin bug, wheels are sufficient
needs: [build, test]
permissions:
id-token: write
steps:
- name: Checkout repository
uses: actions/checkout@v6
- name: Set up Python
uses: actions/setup-python@v6
with:
python-version: "3.12"
- name: Install uv
uses: astral-sh/setup-uv@v7
with:
enable-cache: true
- name: Install Rust
uses: dtolnay/rust-toolchain@stable
- name: Install 1Password CLI
uses: 1password/install-cli-action@v2
- name: Get PyPI token from 1Password (or use secret)
id: token
env:
OP_SERVICE_ACCOUNT_TOKEN: ${{ secrets.OP_SERVICE_ACCOUNT_TOKEN }}
run: |
TOKEN=""
if [[ -n "${OP_SERVICE_ACCOUNT_TOKEN}" ]]; then
TOKEN=$(op read "op://TerraphimPlatform/pypi.token/password" 2>/dev/null || true)
fi
if [[ -z "$TOKEN" ]]; then
echo "PyPI token not found in 1Password, using GitHub secret"
TOKEN="${{ secrets.PYPI_API_TOKEN }}"
fi
if [[ -z "$TOKEN" ]]; then
echo "No PyPI token available from 1Password or GitHub secrets"
exit 1
fi
echo "token=$TOKEN" >> $GITHUB_OUTPUT
- name: Determine version
id: version
run: |
VERSION="${{ inputs.version }}"
if [[ -z "$VERSION" ]]; then
# Extract version from tag
if [[ "${{ github.ref }}" == refs/tags/python-v* ]]; then
VERSION=${GITHUB_REF#refs/tags/python-v}
elif [[ "${{ github.ref }}" == refs/tags/pypi-v* ]]; then
VERSION=${GITHUB_REF#refs/tags/pypi-v}
elif [[ "${{ github.ref }}" == refs/tags/v* ]]; then
VERSION=${GITHUB_REF#refs/tags/v}
fi
fi
echo "version=$VERSION" >> $GITHUB_OUTPUT
echo "πŸ“¦ Publishing version: $VERSION"
- name: Download all artifacts
uses: actions/download-artifact@v4
with:
path: dist
- name: Make publish script executable
run: chmod +x ./scripts/publish-pypi.sh
- name: Collect distributions
run: |
mkdir -p crates/terraphim_automata_py/dist
find dist -name "*.whl" -exec cp {} crates/terraphim_automata_py/dist/ \; || true
find dist -name "*.tar.gz" -exec cp {} crates/terraphim_automata_py/dist/ \; || true
echo "πŸ“¦ Found distributions:"
ls -la crates/terraphim_automata_py/dist/
- name: Run publish script
env:
PYPI_TOKEN: ${{ steps.token.outputs.token }}
run: |
# Prepare script arguments
ARGS="--version ${{ steps.version.outputs.version }} --token $PYPI_TOKEN --use-existing-dist"
if [[ "${{ inputs.dry_run }}" == "true" ]]; then
ARGS="$ARGS --dry-run"
fi
if [[ "${{ inputs.repository }}" == "testpypi" ]]; then
ARGS="$ARGS --repository testpypi"
fi
# Run publish script
./scripts/publish-pypi.sh $ARGS
- name: Verify published packages
if: inputs.dry_run != 'true'
run: |
PACKAGE_NAME="terraphim-automata"
PACKAGE_VERSION="${{ steps.version.outputs.version }}"
# Try to install from PyPI (or TestPyPI)
if [[ "${{ inputs.repository }}" == "testpypi" ]]; then
python -m pip install --index-url https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple/ "$PACKAGE_NAME==$PACKAGE_VERSION" || echo "⚠️ Package not yet visible on TestPyPI"
else
python -m pip install "$PACKAGE_NAME==$PACKAGE_VERSION" || echo "⚠️ Package not yet visible on PyPI"
fi
echo "πŸ“Š Package verification complete"
- name: Create GitHub Release
if: startsWith(github.ref, 'refs/tags/') && inputs.dry_run != 'true'
uses: softprops/action-gh-release@v2
continue-on-error: true
with:
name: "terraphim-automata ${{ github.ref_name }}"
token: ${{ secrets.GITHUB_TOKEN }}
body: |
## Python Package Release
**Package**: `terraphim-automata`
**Version**: ${{ github.ref_name }}
**Repository**: ${{ inputs.repository }}
### πŸš€ Installation
```bash
pip install terraphim-automata
```
or for development:
```bash
pip install terraphim-automata[dev]
```
### ✨ Features
- **Fast Autocomplete**: Sub-millisecond prefix search
- **Knowledge Graph Integration**: Semantic connectivity analysis
- **Native Performance**: Rust backend with PyO3 bindings
- **Cross-Platform**: Linux, macOS, Windows support
- **Python 3.9+**: Modern Python support
### πŸ“Š Performance
- **Autocomplete Index**: ~749 bytes
- **Knowledge Graph**: ~856 bytes
- **Native Extension**: Optimized binary wheels
### πŸ”— Links
- [PyPI package](https://pypi.org/project/terraphim-automata)
- [Documentation](https://github.com/terraphim/terraphim-ai/tree/main/crates/terraphim_automata_py)
---
πŸ€– Generated on: $(date)
draft: false
prerelease: ${{ contains(github.ref, '-alpha') || contains(github.ref, '-beta') || contains(github.ref, '-rc') }}
- name: Notify completion
if: inputs.dry_run != 'true'
run: |
echo "πŸŽ‰ PyPI publishing workflow completed successfully!"
echo "πŸ“¦ Package: terrraphim-automata"
echo "πŸ“‹ Repository: ${{ inputs.repository }}"