Skip to content
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
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

Check failure on line 122 in .github/workflows/release-pypi-flashinfer-cubin-wheel.yml

View workflow run for this annotation

GitHub Actions / .github/workflows/release-pypi-flashinfer-cubin-wheel.yml

Invalid workflow file

You have an error in your yaml syntax on line 122
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"