name: Python Package Release on: workflow_dispatch: workflow_call: inputs: version: description: Version to release required: true type: string concurrency: group: ${{ github.workflow }}-${{ github.ref }}-${{ github.event_name }} cancel-in-progress: true permissions: id-token: write pull-requests: write contents: read packages: write jobs: get-version: name: Determine Version if: (github.event_name == 'workflow_call' && inputs.version != '') || github.event_name == 'workflow_dispatch' runs-on: ubuntu-latest outputs: version: ${{ steps.version.outputs.version }} steps: - uses: actions/checkout@v6 with: fetch-depth: 0 - name: Get and validate version id: version shell: bash run: | if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then VERSION=$(git describe --tags --abbrev=0 2>/dev/null || echo "v0.1.0") echo "Using latest tag for manual trigger: $VERSION" elif [[ "${{ github.event_name }}" == "workflow_call" && -n "${{ inputs.version }}" ]]; then VERSION="${{ inputs.version }}" echo "Using provided version from workflow_call: $VERSION" else echo "Error: No version provided for workflow_call" exit 1 fi # Validate version format if [[ ! $VERSION =~ ^v[0-9]+\.[0-9]+\.[0-9]+.*$ ]]; then echo "Warning: Version $VERSION may not follow semantic versioning (vX.Y.Z)" fi echo "Final version: $VERSION" echo "version=$VERSION" >> $GITHUB_OUTPUT test: name: Run Tests if: (github.event_name == 'workflow_call' && inputs.version != '') || github.event_name == 'workflow_dispatch' needs: [get-version] runs-on: - self-hosted - X64 - Linux - 4c - aws steps: - uses: actions/checkout@v6 with: fetch-depth: 0 - uses: ./.github/actions/build_bindings_python with: target: x86_64-unknown-linux-gnu # No version means development build with tests linux: name: Build Linux Wheels if: (github.event_name == 'workflow_call' && inputs.version != '') || github.event_name == 'workflow_dispatch' needs: [get-version, test] runs-on: - self-hosted - "${{ matrix.runner }}" - Linux - 4c - aws strategy: fail-fast: false matrix: include: - { arch: x86_64, runner: X64 } - { arch: aarch64, runner: ARM64 } steps: - uses: actions/checkout@v6 with: fetch-depth: 0 - uses: ./.github/actions/build_bindings_python with: target: ${{ matrix.arch }}-unknown-linux-gnu version: ${{ needs.get-version.outputs.version }} - name: Upload Linux wheel uses: actions/upload-artifact@v7 with: name: python-linux-${{ matrix.arch }} path: src/bendpy/dist/*.whl retention-days: 7 macos: name: Build macOS Wheels if: (github.event_name == 'workflow_call' && inputs.version != '') || github.event_name == 'workflow_dispatch' needs: [get-version, test] runs-on: macos-latest continue-on-error: true strategy: matrix: target: [x86_64-apple-darwin, aarch64-apple-darwin] steps: - uses: actions/checkout@v6 with: fetch-depth: 0 - name: Install dependencies run: | # Install OpenSSL and necessary tools brew install openssl@3 # Use vendored OpenSSL to avoid cross-compilation issues echo "OPENSSL_STATIC=1" >> $GITHUB_ENV echo "OPENSSL_VENDORED=1" >> $GITHUB_ENV echo "PKG_CONFIG_ALLOW_CROSS=1" >> $GITHUB_ENV - uses: ./.github/actions/build_bindings_python with: target: ${{ matrix.target }} version: ${{ needs.get-version.outputs.version }} - name: Upload macOS wheel uses: actions/upload-artifact@v7 with: name: python-macos-${{ matrix.target }} path: src/bendpy/dist/*.whl retention-days: 7 publish: name: Publish to PyPI if: (github.event_name == 'workflow_call' && inputs.version != '') || github.event_name == 'workflow_dispatch' needs: [get-version, test, linux] runs-on: ubuntu-latest steps: - uses: actions/checkout@v6 - uses: actions/download-artifact@v8 with: pattern: python-* merge-multiple: true path: src/bendpy/dist continue-on-error: true - name: Show packages to publish run: | echo "Publishing packages for version: ${{ needs.get-version.outputs.version }}" echo "Packages found:" ls -la src/bendpy/dist/ || echo "No packages found" echo "Total packages: $(ls src/bendpy/dist/*.whl 2>/dev/null | wc -l)" - name: Publish to PyPI timeout-minutes: 10 run: | pip install twine echo "Publishing to PyPI..." if [ -n "$(find src/bendpy/dist -name "*.whl" 2>/dev/null)" ]; then twine upload --skip-existing --verbose src/bendpy/dist/*.whl else echo "No wheel files found to publish" exit 1 fi env: TWINE_USERNAME: __token__ TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }}