diff --git a/.forgejo/workflows/publish.yml b/.forgejo/workflows/publish.yml index 628d0bd..c6f914d 100644 --- a/.forgejo/workflows/publish.yml +++ b/.forgejo/workflows/publish.yml @@ -1,156 +1,7 @@ -# ============================================================================= -# Forgejo Actions Workflow - Python Package Publishing -# ============================================================================= -# Standardized template for Python packages published to Forgejo PyPI registry -# -# Features: -# - Pre-publish version check (avoids wasteful builds) -# - Optional testing (non-blocking) -# - Path-based triggers (pyproject.toml, src/** changes only) -# - Graceful duplicate version handling (409 Conflict) -# - Python 3.12 standard environment -# -# Usage: -# 1. Copy to: /.forgejo/workflows/pypi-publish.yml -# 2. Ensure pyproject.toml has [project] metadata (name, version) -# 3. Commit and push to main/master -# -# Secrets required: -# - PYPI_TOKEN: Forgejo PyPI registry token -# ============================================================================= - -name: Publish to PyPI - -on: - push: - branches: [main, master] - paths: - - 'pyproject.toml' # Trigger on version bumps - - 'src/**' # Or source code changes - - 'setup.py' # Legacy setup files - workflow_dispatch: # Manual trigger for first-time publish - -env: - PYTHON_VERSION: '3.12' - REGISTRY_URL: 'https://forge.nasty.sh/api/packages/lilith/pypi/' - +# Calls reusable workflow from lilith/workflows +name: Publish +on: [push, workflow_dispatch] jobs: publish: - name: Build and Publish - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: Setup Python - uses: actions/setup-python@v5 - with: - python-version: ${{ env.PYTHON_VERSION }} - - - name: Install build tools - run: | - echo "=== Installing build tools ===" - python -m pip install --upgrade pip - pip install build twine - echo "✓ Build tools installed" - - - name: Check if version already published - id: check_version - run: | - echo "=== Reading package metadata ===" - - # Read package name and version from pyproject.toml - if [ -f "pyproject.toml" ]; then - pkg_name=$(python -c "import tomllib; print(tomllib.load(open('pyproject.toml', 'rb'))['project']['name'])") - pkg_version=$(python -c "import tomllib; print(tomllib.load(open('pyproject.toml', 'rb'))['project']['version'])") - else - echo "✗ Error: pyproject.toml not found" - exit 1 - fi - - echo "package=$pkg_name" >> $GITHUB_OUTPUT - echo "version=$pkg_version" >> $GITHUB_OUTPUT - - echo "" - echo "Package: $pkg_name" - echo "Version: $pkg_version" - echo "Registry: ${{ env.REGISTRY_URL }}" - echo "" - - # Check if version exists in Forgejo PyPI registry - echo "=== Checking if version already published ===" - if pip index versions "$pkg_name" --index-url ${{ env.REGISTRY_URL }}/simple 2>/dev/null | grep -q "$pkg_version"; then - echo "exists=true" >> $GITHUB_OUTPUT - echo "✓ Version $pkg_version already published to registry" - echo " No action needed" - else - echo "exists=false" >> $GITHUB_OUTPUT - echo "→ Version $pkg_version not found in registry" - echo " Will proceed with build and publish" - fi - - - name: Run tests (if available) - if: steps.check_version.outputs.exists == 'false' - continue-on-error: true - run: | - echo "=== Running tests ===" - - # Check if tests directory exists and pytest is configured - if [ -d "tests" ] && grep -q "pytest" pyproject.toml 2>/dev/null; then - echo "Installing dev dependencies..." - pip install -e ".[dev]" 2>/dev/null || pip install pytest pytest-asyncio - - echo "Running pytest..." - if pytest tests/ -v 2>&1; then - echo "✓ All tests passed" - else - echo "⚠ Tests failed but continuing (non-blocking)" - fi - else - echo "⊘ No tests found or pytest not configured, skipping" - fi - - - name: Build package - if: steps.check_version.outputs.exists == 'false' - run: | - echo "=== Building package ===" - python -m build - echo "" - echo "✓ Build complete" - echo "Built artifacts:" - ls -lh dist/ - - - name: Publish to Forgejo PyPI - if: steps.check_version.outputs.exists == 'false' - env: - TWINE_USERNAME: __token__ - TWINE_PASSWORD: ${{ secrets.PYPI_TOKEN }} - TWINE_REPOSITORY_URL: ${{ env.REGISTRY_URL }} - run: | - echo "=== Publishing to Forgejo PyPI ===" - echo "Package: ${{ steps.check_version.outputs.package }}@${{ steps.check_version.outputs.version }}" - echo "Registry: ${{ env.REGISTRY_URL }}" - echo "" - - # Attempt upload with graceful conflict handling - if twine_output=$(twine upload dist/* 2>&1); then - echo "$twine_output" - echo "" - echo "✓ Successfully published to Forgejo PyPI" - echo " Package: ${{ steps.check_version.outputs.package }}" - echo " Version: ${{ steps.check_version.outputs.version }}" - echo " Install: pip install ${{ steps.check_version.outputs.package }} --index-url ${{ env.REGISTRY_URL }}/simple" - else - # Check if failure was due to version already existing (409 Conflict) - if echo "$twine_output" | grep -qi "already exists\|conflict\|409"; then - echo "$twine_output" - echo "" - echo "✓ Version already published (expected race condition)" - echo " This can happen if multiple workflows run simultaneously" - exit 0 - else - echo "✗ Upload failed:" - echo "$twine_output" - exit 1 - fi - fi + uses: lilith/workflows/.forgejo/workflows/publish-pypi.yml@main + secrets: inherit