name: CI on: push: branches: [main] tags: ["v*"] pull_request: branches: [main] workflow_dispatch: jobs: test: runs-on: ubuntu-latest permissions: contents: read actions: write strategy: matrix: python-version: ["3.13"] steps: - uses: actions/checkout@v4 - name: Enable uv from toolcache id: uv run: | uv_path="$(find /opt/hostedtoolcache/uv -maxdepth 4 -type f -name uv -perm -111 2>/dev/null | head -1)" if [ -n "$uv_path" ]; then dirname "$uv_path" >> "$GITHUB_PATH" echo "found=true" >> "$GITHUB_OUTPUT" else echo "uv not found in toolcache" fi - name: Install uv if: steps.uv.outputs.found != 'true' uses: astral-sh/setup-uv@v3 with: enable-cache: true - name: Cache Python toolchain uses: actions/cache@v4 with: path: /opt/hostedtoolcache/Python key: python-${{ matrix.python-version }}-${{ runner.os }} restore-keys: | python-${{ matrix.python-version }}- - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} - name: Install dependencies run: uv pip install --system -e ".[dev]" - name: Lint run: ruff check src/ tests/ - name: Format check run: ruff format --check src/ tests/ - name: Type check run: mypy src/ tests/ - name: Test with coverage run: pytest - name: Upload coverage report uses: actions/upload-artifact@v4 with: name: coverage path: coverage.xml build: needs: test runs-on: ubuntu-latest permissions: contents: read actions: write releases: write if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v') steps: - uses: actions/checkout@v4 - name: Enable uv from toolcache id: uv run: | uv_path="$(find /opt/hostedtoolcache/uv -maxdepth 4 -type f -name uv -perm -111 2>/dev/null | head -1)" if [ -n "$uv_path" ]; then dirname "$uv_path" >> "$GITHUB_PATH" echo "found=true" >> "$GITHUB_OUTPUT" else echo "uv not found in toolcache" fi - name: Install uv if: steps.uv.outputs.found != 'true' uses: astral-sh/setup-uv@v3 with: enable-cache: true - name: Cache Python toolchain uses: actions/cache@v4 with: path: /opt/hostedtoolcache/Python key: python-3.13-${{ runner.os }} restore-keys: | python-3.13- - name: Set up Python uses: actions/setup-python@v5 with: python-version: "3.13" - name: Build Debian package run: | sudo apt-get update -qq sudo apt-get install -y -qq build-essential debhelper dh-python python3-all python3-hatchling cd linux && dpkg-buildpackage -us -uc -b && cd .. mkdir -p dist-deb mv ./*.deb dist-deb/ - name: Build wheel run: uv build --wheel --out-dir dist - name: Upload wheel uses: actions/upload-artifact@v4 with: name: wheel path: dist/*.whl - name: Upload deb uses: actions/upload-artifact@v4 with: name: deb path: dist-deb/*.deb - name: Create Gitea release and upload assets env: GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }} run: | set -euo pipefail api="${{ github.server_url }}/api/v1" repo="${{ github.repository }}" tag="${{ github.ref_name }}" payload="{\"tag_name\":\"$tag\",\"name\":\"$tag\"}" out=$(curl -sS -X POST "$api/repos/$repo/releases" \ -H "Authorization: token $GITEA_TOKEN" \ -H "Content-Type: application/json" \ -d "$payload" || true) if ! printf '%s' "$out" | grep -q '"id"'; then out=$(curl -sS "$api/repos/$repo/releases/tags/$tag" \ -H "Authorization: token $GITEA_TOKEN") fi rid=$(printf '%s' "$out" | grep -o '"id":[0-9]*' | head -1 | cut -d: -f2) [ -n "$rid" ] || { echo "release id not found" >&2; exit 1; } for f in dist/*.whl dist-deb/*.deb; do [ -e "$f" ] || continue curl -fsS -X POST "$api/repos/$repo/releases/$rid/assets?name=$(basename "$f")" \ -H "Authorization: token $GITEA_TOKEN" \ --data-binary @"$f" echo "Uploaded $(basename "$f")" done