Skip to content

ci: bump actions/upload-artifact from 4 to 7 #84

ci: bump actions/upload-artifact from 4 to 7

ci: bump actions/upload-artifact from 4 to 7 #84

Workflow file for this run

# CI pipeline for the Convert Python SDK (Story 5.1, qs-02 / qs-03 / qs-09).
#
# Job graph (fail-fast lint/type-check before the matrix):
# pr-title (PR-only, independent)
# lint -> type-check -> test (15-cell matrix) -> build
# \-> bounds-check (lower/upper)
#
# All dependency resolution uses `uv` (never `pip install -e .`).
#
# WORKFLOW-NAME COUPLING (LOAD-BEARING): the `name: CI` below must match
# release.yml's `workflow_run.workflows` value EXACTLY ("CI"). Renaming either
# side silently breaks releases — `workflow_run` would never fire. release.yml
# carries the mirror comment.
name: CI
on:
push:
branches: [main]
pull_request:
# Cancel superseded runs on the same ref to keep the matrix under the merge ceiling.
concurrency:
group: ci-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
env:
# Pin the uv version for reproducible CI resolution.
UV_VERSION: "0.10.11"
jobs:
pr-title:
name: PR title (Conventional Commits)
runs-on: ubuntu-latest
if: github.event_name == 'pull_request'
steps:
- name: Validate PR title
env:
PR_TITLE: ${{ github.event.pull_request.title }}
run: |
# Dependency-free Conventional Commits check (squash-merge-only repo:
# the squash commit subject is the PR title).
if ! echo "$PR_TITLE" | grep -qE '^(feat|fix|docs|test|refactor|perf|build|ci|chore)(\(.+\))?!?: .+'; then
echo "::error::PR title must follow Conventional Commits: '$PR_TITLE'"
echo "Expected: <type>(<scope>)?!?: <description>"
echo "Allowed types: feat, fix, docs, test, refactor, perf, build, ci, chore"
exit 1
fi
echo "PR title OK: $PR_TITLE"
lint:
name: Ruff lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install uv
uses: astral-sh/setup-uv@d4b2f3b6ecc6e67c4457f6d3e41ec42d3d0fcb86 # v5
with:
version: ${{ env.UV_VERSION }}
enable-cache: true
- name: Set up Python
run: uv python install 3.13
- name: Sync dev environment
run: uv sync --group dev
- name: Ruff lint
run: uv run ruff check src tests scripts demo
type-check:
name: mypy --strict
runs-on: ubuntu-latest
needs: lint
steps:
- uses: actions/checkout@v4
- name: Install uv
uses: astral-sh/setup-uv@d4b2f3b6ecc6e67c4457f6d3e41ec42d3d0fcb86 # v5
with:
version: ${{ env.UV_VERSION }}
enable-cache: true
- name: Set up Python
run: uv python install 3.13
- name: Sync dev environment
run: uv sync --group dev
- name: Check generated .pyi header markers
run: uv run python scripts/check_generated_pyi_header.py
- name: mypy strict
run: uv run mypy --strict
- name: mypy strict (serving_config contract probe)
run: uv run mypy --strict typecheck/serving_config_contract.py
test:
name: test (py${{ matrix.python-version }} / ${{ matrix.os }})
runs-on: ${{ matrix.os }}
needs: type-check
strategy:
fail-fast: false
matrix:
# 15-cell matrix: Python 3.9-3.13 x {ubuntu, macos, windows} (qs-02).
# Do NOT trim cells — NFR22 mandates the full CPython matrix.
os: [ubuntu-latest, macos-latest, windows-latest]
python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"]
steps:
- uses: actions/checkout@v4
- name: Install uv
uses: astral-sh/setup-uv@d4b2f3b6ecc6e67c4457f6d3e41ec42d3d0fcb86 # v5
with:
version: ${{ env.UV_VERSION }}
enable-cache: true
- name: Set up Python
run: uv python install ${{ matrix.python-version }}
- name: Sync dev environment
run: uv sync --group dev --python ${{ matrix.python-version }}
- name: Run tests with coverage (project floor 85%)
run: >-
uv run pytest -p no:cacheprovider
--cov=convert_sdk --cov-report=term-missing --cov-fail-under=85
- name: Enforce evaluation/ coverage floor (95%)
run: >-
uv run coverage report
--include='*/convert_sdk/evaluation/*' --fail-under=95
bounds-check:
name: bounds-check (${{ matrix.bound }})
runs-on: ubuntu-latest
needs: type-check
strategy:
fail-fast: false
matrix:
# Lower bound: oldest declared deps (httpx==0.28.0) on the oldest Python.
# Upper bound: newest compatible deps on the newest Python (qs-09).
include:
- bound: lower
python-version: "3.9"
- bound: upper
python-version: "3.13"
steps:
- uses: actions/checkout@v4
- name: Install uv
uses: astral-sh/setup-uv@d4b2f3b6ecc6e67c4457f6d3e41ec42d3d0fcb86 # v5
with:
version: ${{ env.UV_VERSION }}
enable-cache: true
- name: Set up Python
run: uv python install ${{ matrix.python-version }}
- name: Sync dev environment (lower bound — apply override constraints)
if: matrix.bound == 'lower'
run: >-
uv sync --group dev --python ${{ matrix.python-version }}
--resolution lowest-direct
- name: Pin runtime deps to declared lower bounds
if: matrix.bound == 'lower'
run: uv pip install --constraint ci/lower-bounds-overrides.txt httpx
- name: Sync dev environment (upper bound — newest compatible)
if: matrix.bound == 'upper'
run: >-
uv sync --group dev --python ${{ matrix.python-version }}
--upgrade
- name: Run unit + integration suite (parity covered elsewhere)
run: >-
uv run pytest -p no:cacheprovider --ignore=tests/parity
build:
name: build (wheel + sdist)
runs-on: ubuntu-latest
needs: test
steps:
- uses: actions/checkout@v4
- name: Install uv
uses: astral-sh/setup-uv@d4b2f3b6ecc6e67c4457f6d3e41ec42d3d0fcb86 # v5
with:
version: ${{ env.UV_VERSION }}
enable-cache: true
- name: Set up Python
run: uv python install 3.13
- name: Build distributions
run: uv build
# Keep this twine version equal to the one release.yml's pinned
# pypa/gh-action-pypi-publish ships, or publish can reject a build CI
# accepted. Both move together.
- name: twine check (same twine the publish action runs)
run: uv run --with twine==7.0.0 twine check dist/*
- name: Upload distribution artifacts
uses: actions/upload-artifact@v7
with:
name: dist
path: dist/*
if-no-files-found: error