fix(ci): fix cargo-deb version, release artifact retry, Docker context #115
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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 }}" |