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 flashinfer-cubin wheel to PyPI | ||
| on: | ||
| workflow_dispatch: | ||
| inputs: | ||
| tag: | ||
| description: 'Tag (e.g., v1.2.3) to build and publish' | ||
| required: true | ||
| type: string | ||
| pull_request: | ||
| branches: | ||
| - main | ||
| jobs: | ||
| build-and-upload: | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - name: Validate tag format | ||
| run: | | ||
| if [[ ! "${{ inputs.tag }}" =~ ^v[0-9]+\.[0-9]+\.[0-9]+([a-z0-9]+)?$ ]]; then | ||
| echo "Error: Tag '${{ inputs.tag }}' does not match the expected format (e.g., v1.2.3 or v1.2.3.post1 or v1.2.3rc1)" | ||
| exit 1 | ||
| fi | ||
| echo "✓ Tag format is valid: ${{ inputs.tag }}" | ||
| - name: Check out tag | ||
| uses: actions/checkout@v4 | ||
| with: | ||
| ref: ${{ inputs.tag }} | ||
| submodules: true | ||
| - name: Set up Python | ||
| uses: actions/setup-python@v5 | ||
| with: | ||
| python-version: '3.10' | ||
| - name: Verify tag matches version.txt (CRITICAL) | ||
| run: | | ||
| # Extract version from tag (remove 'v' prefix) | ||
| TAG_VERSION="${{ inputs.tag }}" | ||
| TAG_VERSION="${TAG_VERSION#v}" | ||
| # Check version.txt FIRST - this is the source of truth | ||
| if [ ! -f "version.txt" ]; then | ||
| echo "Error: version.txt file not found!" | ||
| exit 1 | ||
| fi | ||
| VERSION_TXT=$(cat version.txt | tr -d '[:space:]') | ||
| if [ "$TAG_VERSION" != "$VERSION_TXT" ]; then | ||
| echo "❌ CRITICAL ERROR: version.txt does not match tag!" | ||
| echo " Tag version: $TAG_VERSION" | ||
| echo " version.txt: $VERSION_TXT" | ||
| echo "" | ||
| echo "Please update version.txt to match the release version before creating a release." | ||
| echo "The tag should be 'v$VERSION_TXT' (e.g., if version.txt contains '1.2.3', tag should be 'v1.2.3')" | ||
| exit 1 | ||
| fi | ||
| echo "✓ version.txt matches tag version: $VERSION_TXT" | ||
| - name: Install build dependencies | ||
| run: | | ||
| python -m pip install --upgrade pip | ||
| pip install build twine wheel | ||
| # Install dependencies required for building flashinfer-cubin | ||
| pip install setuptools>=61.0 requests filelock torch tqdm | ||
| - name: Build flashinfer-cubin wheel | ||
| run: | | ||
| echo "Building flashinfer-cubin wheel..." | ||
| cd flashinfer-cubin | ||
| # Clean any previous builds | ||
| rm -rf dist build *.egg-info | ||
| # Build the wheel using the build module for better isolation | ||
| python -m build --wheel | ||
| echo "✓ Build completed" | ||
| ls -lh dist/ | ||
| # Move the wheel to the root dist directory for consistency | ||
| mkdir -p ../dist | ||
| cp dist/*.whl ../dist/ | ||
| cd .. | ||
| - name: Check wheel contents | ||
| run: | | ||
| echo "Verifying wheel contents..." | ||
| # Create a temp directory to extract and check wheel | ||
| mkdir -p temp_wheel_check | ||
| cd temp_wheel_check | ||
| # Extract wheel (wheels are just zip files) | ||
| unzip -l ../dist/flashinfer_cubin*.whl | head -30 | ||
| echo "..." | ||
| # Check if cubins are included | ||
| unzip -l ../dist/flashinfer_cubin*.whl | grep -c "\.cubin" || true | ||
| cd .. | ||
| rm -rf temp_wheel_check | ||
| echo "✓ Wheel archive created successfully" | ||
| - name: Store build artifacts | ||
| uses: actions/upload-artifact@v4 | ||
| with: | ||
| name: python-package-distributions | ||
| path: dist/ | ||
| retention-days: 7 | ||
| - name: Test installation from wheel | ||
| run: | | ||
| echo "Testing installation from built wheel..." | ||
| python -m venv test-env | ||
| source test-env/bin/activate | ||
| # Install the wheel | ||
| pip install dist/flashinfer_cubin*.whl | ||
| # Test import and check for cubins | ||
| python -c " | ||
| import flashinfer_cubin | ||
| print(f'✓ Successfully imported flashinfer_cubin') | ||
| from pathlib import Path | ||
| import flashinfer_cubin | ||
| cubin_dir = Path(flashinfer_cubin.__file__).parent / 'cubins' | ||
| if cubin_dir.exists(): | ||
| cubins = list(cubin_dir.rglob('*.cubin')) | ||
| print(f'✓ Found {len(cubins)} cubin files in package') | ||
| else: | ||
| print('⚠ Warning: cubins directory not found in package') | ||
| " | ||
| deactivate | ||
| rm -rf test-env | ||
| - name: Check package with twine | ||
| run: | | ||
| echo "Running twine check..." | ||
| twine check dist/flashinfer_cubin*.whl | ||
| echo "✓ Package validation passed" | ||
| # - name: Upload to PyPI | ||
| # env: | ||
| # TWINE_USERNAME: __token__ | ||
| # TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }} | ||
| # run: | | ||
| # echo "Uploading flashinfer-cubin wheel to PyPI..." | ||
| # twine upload --verbose --non-interactive dist/flashinfer_cubin*.whl | ||
| # echo "✓ Successfully uploaded to PyPI" | ||