mirror of
https://github.com/ZGCA-Forge/Elevator.git
synced 2025-12-14 13:04:41 +00:00
259 lines
7.9 KiB
YAML
259 lines
7.9 KiB
YAML
# This workflow will upload a Python Package to PyPI when a release is created
|
|
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python#publishing-to-package-registries
|
|
|
|
# This workflow uses actions that are not certified by GitHub.
|
|
# They are provided by a third-party and are governed by
|
|
# separate terms of service, privacy policy, and support
|
|
# documentation.
|
|
|
|
name: Upload PyPI package
|
|
|
|
on:
|
|
release:
|
|
types: [published, edited]
|
|
workflow_dispatch:
|
|
inputs:
|
|
test_pypi:
|
|
description: "Publish to Test PyPI instead of PyPI"
|
|
required: false
|
|
default: false
|
|
type: boolean
|
|
|
|
permissions:
|
|
contents: read
|
|
|
|
jobs:
|
|
# Step 1: Code formatting and pre-commit validation (fast failure)
|
|
code-format:
|
|
name: Code formatting and pre-commit validation
|
|
runs-on: ubuntu-latest
|
|
|
|
steps:
|
|
- uses: actions/checkout@v5
|
|
|
|
- name: Set up Python
|
|
uses: actions/setup-python@v6
|
|
with:
|
|
python-version: "3.10" # Use minimum version for consistency
|
|
|
|
- name: Install dependencies
|
|
run: |
|
|
python -m pip install --upgrade pip
|
|
pip install -e .[dev]
|
|
|
|
- name: Run pre-commit hooks
|
|
uses: pre-commit/action@v3.0.1
|
|
with:
|
|
extra_args: --all-files
|
|
|
|
# Step 2: Basic build and test with minimum Python version (3.10)
|
|
basic-build:
|
|
name: Basic build (Python 3.10, Ubuntu)
|
|
runs-on: ubuntu-latest
|
|
needs: [code-format] # Only run after code formatting passes
|
|
|
|
steps:
|
|
- uses: actions/checkout@v5
|
|
|
|
- name: Set up Python 3.10
|
|
uses: actions/setup-python@v6
|
|
with:
|
|
python-version: "3.10"
|
|
|
|
- name: Cache pip dependencies
|
|
uses: actions/cache@v4
|
|
with:
|
|
path: ~/.cache/pip
|
|
key: ubuntu-pip-3.10-${{ hashFiles('**/pyproject.toml') }}
|
|
restore-keys: |
|
|
ubuntu-pip-3.10-
|
|
|
|
- name: Install dependencies
|
|
run: |
|
|
python -m pip install --upgrade pip
|
|
python -m pip install pytest
|
|
pip install -e .[dev]
|
|
|
|
- name: Test with pytest
|
|
run: |
|
|
pytest -v
|
|
|
|
# Step 3: Security scan
|
|
security:
|
|
name: Security scan
|
|
runs-on: ubuntu-latest
|
|
needs: [basic-build] # Run in parallel with other tests after basic build
|
|
|
|
steps:
|
|
- uses: actions/checkout@v5
|
|
|
|
- name: Run Safety CLI to check for vulnerabilities
|
|
uses: pyupio/safety-action@v1
|
|
with:
|
|
api-key: ${{ secrets.SAFETY_CHECK }}
|
|
output-format: json
|
|
args: --detailed-output --output-format json
|
|
continue-on-error: true
|
|
|
|
- name: Upload security reports
|
|
uses: actions/upload-artifact@v4
|
|
with:
|
|
name: security-reports
|
|
path: |
|
|
safety-report.json
|
|
if: always()
|
|
|
|
release-build:
|
|
name: Build release distributions
|
|
runs-on: ubuntu-latest
|
|
needs: [basic-build]
|
|
|
|
steps:
|
|
- uses: actions/checkout@v5
|
|
|
|
- name: Set up Python
|
|
uses: actions/setup-python@v6
|
|
with:
|
|
python-version: "3.10" # Use minimum version for consistency
|
|
|
|
- name: Install build dependencies
|
|
run: |
|
|
python -m pip install --upgrade pip
|
|
python -m pip install build twine
|
|
|
|
- name: Verify version consistency
|
|
if: github.event_name == 'release' && (github.event.action == 'published' || (github.event.action == 'edited' && !github.event.release.prerelease))
|
|
run: |
|
|
# Install package first
|
|
pip install -e .
|
|
|
|
# Get package version (fail fast if not available)
|
|
VERSION=$(python -c "import elevator_saga; print(elevator_saga.__version__)")
|
|
|
|
# Handle both v0.0.3 and 0.0.3 tag formats
|
|
RAW_TAG="${GITHUB_REF#refs/tags/}"
|
|
if [[ "$RAW_TAG" == v* ]]; then
|
|
TAG_VERSION="${RAW_TAG#v}"
|
|
else
|
|
TAG_VERSION="$RAW_TAG"
|
|
fi
|
|
|
|
echo "Package version: $VERSION"
|
|
echo "Tag version: $TAG_VERSION"
|
|
|
|
if [ "$VERSION" != "$TAG_VERSION" ]; then
|
|
echo "❌ Version mismatch: package=$VERSION, tag=$TAG_VERSION"
|
|
echo "Please ensure the package version matches the git tag"
|
|
exit 1
|
|
fi
|
|
|
|
echo "✅ Version verification passed: $VERSION"
|
|
|
|
- name: Build release distributions
|
|
run: |
|
|
python -m build
|
|
|
|
- name: Check package
|
|
run: |
|
|
twine check dist/*
|
|
|
|
- name: Upload distributions
|
|
uses: actions/upload-artifact@v4
|
|
with:
|
|
name: release-dists
|
|
path: dist/
|
|
|
|
pypi-publish:
|
|
name: Publish to PyPI
|
|
runs-on: ubuntu-latest
|
|
needs:
|
|
- release-build
|
|
if: github.event_name == 'release' && !github.event.release.prerelease && github.event.inputs.test_pypi != 'true' && (github.event.action == 'published' || github.event.action == 'edited')
|
|
permissions:
|
|
# IMPORTANT: this permission is mandatory for trusted publishing
|
|
id-token: write
|
|
|
|
# Note: For enhanced security, consider configuring deployment environments
|
|
# in your GitHub repository settings with protection rules
|
|
|
|
steps:
|
|
- name: Retrieve release distributions
|
|
uses: actions/download-artifact@v5
|
|
with:
|
|
name: release-dists
|
|
path: dist/
|
|
|
|
- name: Publish release distributions to PyPI
|
|
uses: pypa/gh-action-pypi-publish@release/v1
|
|
|
|
test-pypi-publish:
|
|
name: Publish to Test PyPI
|
|
runs-on: ubuntu-latest
|
|
needs:
|
|
- release-build
|
|
if: github.event.inputs.test_pypi == 'true' || (github.event_name == 'release' && github.event.release.prerelease && (github.event.action == 'published' || github.event.action == 'edited'))
|
|
permissions:
|
|
# IMPORTANT: this permission is mandatory for trusted publishing
|
|
id-token: write
|
|
|
|
# Note: For enhanced security, consider configuring deployment environments
|
|
# in your GitHub repository settings with protection rules
|
|
|
|
steps:
|
|
- name: Retrieve release distributions
|
|
uses: actions/download-artifact@v5
|
|
with:
|
|
name: release-dists
|
|
path: dist/
|
|
|
|
- name: Publish release distributions to Test PyPI
|
|
uses: pypa/gh-action-pypi-publish@release/v1
|
|
with:
|
|
repository-url: https://test.pypi.org/legacy/
|
|
|
|
create-github-release-assets:
|
|
name: Add assets to GitHub release
|
|
runs-on: ubuntu-latest
|
|
needs: release-build
|
|
if: github.event_name == 'release' && (github.event.action == 'published' || github.event.action == 'edited')
|
|
permissions:
|
|
contents: write # Need write access to upload release assets
|
|
|
|
steps:
|
|
- name: Retrieve release distributions
|
|
uses: actions/download-artifact@v5
|
|
with:
|
|
name: release-dists
|
|
path: dist/
|
|
|
|
- name: Upload release assets
|
|
uses: softprops/action-gh-release@v2
|
|
with:
|
|
files: dist/*
|
|
env:
|
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
|
|
post-publish:
|
|
name: Post-publish tasks
|
|
runs-on: ubuntu-latest
|
|
needs: [pypi-publish, test-pypi-publish]
|
|
if: always() && (needs.pypi-publish.result == 'success' || needs.test-pypi-publish.result == 'success')
|
|
|
|
steps:
|
|
- uses: actions/checkout@v5
|
|
|
|
- name: Create deployment summary
|
|
run: |
|
|
echo "## Deployment Summary" >> $GITHUB_STEP_SUMMARY
|
|
echo "| Item | Status |" >> $GITHUB_STEP_SUMMARY
|
|
echo "|------|--------|" >> $GITHUB_STEP_SUMMARY
|
|
|
|
if [ "${{ needs.pypi-publish.result }}" = "success" ]; then
|
|
echo "| PyPI | Published |" >> $GITHUB_STEP_SUMMARY
|
|
elif [ "${{ needs.test-pypi-publish.result }}" = "success" ]; then
|
|
echo "| Test PyPI | Published |" >> $GITHUB_STEP_SUMMARY
|
|
fi
|
|
|
|
echo "| GitHub Release | Assets uploaded |" >> $GITHUB_STEP_SUMMARY
|
|
echo "| Version | ${{ github.event.release.tag_name || 'test' }} |" >> $GITHUB_STEP_SUMMARY
|