Skip to content

Fixing CIs

Fixing CIs #2

name: Release Python SDK

Check failure on line 1 in .github/workflows/release-python-sdk.yml

View workflow run for this annotation

GitHub Actions / .github/workflows/release-python-sdk.yml

Invalid workflow file

(Line: 147, Col: 14): Unrecognized function: 'substring'. Located at position 37 within expression: startsWith(github.ref_name, 'v') && substring(github.ref_name, 1) || github.ref_name
on:
release:
types: [published]
permissions:
contents: read
id-token: write
jobs:
test:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Install uv
uses: astral-sh/setup-uv@v2
- name: Install dev dependencies with uv
working-directory: python-sdk
run: |
uv sync --group dev
- name: Install python-sdk package (editable)
working-directory: python-sdk
run: |
uv pip install -e .
- name: Run tests with pytest and coverage
working-directory: python-sdk
run: |
uv run pytest --cov=exospherehost --cov-report=xml --cov-report=term-missing -v --junitxml=pytest-report.xml
- name: Upload coverage reports to Codecov
uses: codecov/codecov-action@v5
with:
token: ${{ secrets.CODECOV_TOKEN }}
slug: exospherehost/exospherehost
files: python-sdk/coverage.xml
flags: python-sdk-unittests
name: python-sdk-coverage-report
fail_ci_if_error: true
- name: Upload test results
uses: actions/upload-artifact@v4
if: always()
with:
name: python-sdk-test-results
path: python-sdk/pytest-report.xml
retention-days: 30
publish:
runs-on: ubuntu-latest
needs: test
defaults:
run:
working-directory: python-sdk
if: github.repository == 'exospherehost/exospherehost'
steps:
- uses: actions/checkout@v4
- uses: astral-sh/setup-uv@v6
name: Install uv
- run: uv python install
- run: uv sync --locked --dev
- name: Update version to release tag
run: |
# Extract version from tag (remove 'v' or 'V' prefix if present)
RELEASE_VERSION="${{ github.ref_name }}"
# Handle empty or invalid tags
if [[ -z "$RELEASE_VERSION" ]]; then
echo "ERROR: Release tag is empty"
exit 1
fi
# Remove 'v' or 'V' prefix (case insensitive)
if [[ $RELEASE_VERSION =~ ^[vV] ]]; then
RELEASE_VERSION="${RELEASE_VERSION#?}" # Remove first character
fi
# Validate the extracted version is not empty
if [[ -z "$RELEASE_VERSION" ]]; then
echo "ERROR: Invalid tag format - version part is empty"
exit 1
fi
# Update the version file
echo "version = \"$RELEASE_VERSION\"" > exospherehost/_version.py
echo "Updated version to $RELEASE_VERSION for release"
- name: Verify version format
run: |
uv run python -c "
import sys
sys.path.append('.')
from exospherehost._version import version
import re
# Check if version matches semantic versioning pattern
if not re.match(r'^\d+\.\d+\.\d+$', version):
print(f'ERROR: Version {version} does not match semantic versioning pattern (x.y.z)')
sys.exit(1)
# Ensure it's not a beta version (should not contain 'b')
if 'b' in version:
print(f'ERROR: Release version {version} contains beta indicator. Release versions should not be beta.')
sys.exit(1)
print(f'Version {version} is valid for release publishing')
"
- name: Generate requirements file for SBOM
run: |
uv export --locked --format=requirements-txt --output-file=requirements.txt
echo "Generated requirements.txt for SBOM creation from lockfile"
- name: Install SBOM generation tools
run: |
uv tool install cyclonedx-bom
uv tool install pip-audit
- name: Generate SBOM with CycloneDX
run: |
uv tool run cyclonedx-py requirements --format json --output-file sbom-cyclonedx.json requirements.txt
uv tool run cyclonedx-py requirements --format xml --output-file sbom-cyclonedx.xml requirements.txt
echo "Generated CycloneDX SBOM in JSON and XML formats"
- name: Generate vulnerability report with pip-audit
run: |
uv tool run pip-audit --format json --output vulnerability-report.json --requirement requirements.txt || true
echo "Generated vulnerability report (non-blocking)"
- name: Create SBOM summary
run: |
echo "## Software Bill of Materials (SBOM)" > sbom-summary.md
echo "" >> sbom-summary.md
echo "This release includes the following supply chain security artifacts:" >> sbom-summary.md
echo "" >> sbom-summary.md
echo "- **Provenance**: Cryptographic proof of build integrity using GitHub's OIDC tokens" >> sbom-summary.md
echo "- **SBOM**: Complete dependency inventory in CycloneDX format" >> sbom-summary.md
echo "- **Vulnerability Report**: Security scan results for all dependencies" >> sbom-summary.md
echo "" >> sbom-summary.md
echo "### Dependencies Count:" >> sbom-summary.md
echo "- Direct dependencies: $(grep -c '^[^#]' requirements.txt || echo '0')" >> sbom-summary.md
echo "- Total dependencies (including transitive): $(wc -l < requirements.txt)" >> sbom-summary.md
echo "" >> sbom-summary.md
echo "### Verification:" >> sbom-summary.md
echo "You can verify this package's provenance on PyPI using:" >> sbom-summary.md
echo '```bash' >> sbom-summary.md
echo 'pip install sigstore' >> sbom-summary.md
echo 'python -m sigstore verify --bundle <bundle-file> exospherehost==${{ startsWith(github.ref_name, 'v') && substring(github.ref_name, 1) || github.ref_name }}' >> sbom-summary.md
echo '```' >> sbom-summary.md
- run: uv build
- name: Publish to PyPI with provenance
run: uv publish --provenance
- name: Upload SBOM artifacts
uses: actions/upload-artifact@v4
with:
name: sbom-artifacts-${{ github.ref_name }}
path: |
python-sdk/sbom-cyclonedx.json
python-sdk/sbom-cyclonedx.xml
python-sdk/requirements.txt
python-sdk/vulnerability-report.json
python-sdk/sbom-summary.md
retention-days: 90
- name: Add SBOM to release assets
uses: softprops/action-gh-release@v2
if: startsWith(github.ref, 'refs/tags/')
with:
files: |
python-sdk/sbom-cyclonedx.json
python-sdk/sbom-cyclonedx.xml
python-sdk/sbom-summary.md
python-sdk/vulnerability-report.json
body_path: python-sdk/sbom-summary.md
append_body: true