diff --git a/.gitea/workflows/ci.yml b/.gitea/workflows/ci.yml new file mode 100644 index 0000000..32ca8df --- /dev/null +++ b/.gitea/workflows/ci.yml @@ -0,0 +1,80 @@ +name: CI + +# Lint + test on every PR and push to main/dev. +# On a push to main/dev (i.e. a merge), build the Python package and publish it +# to the Gitea PyPI registry — only if lint and tests pass first. +on: + pull_request: + branches: [main, dev] + push: + branches: [main, dev] + +jobs: + lint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: astral-sh/setup-uv@v5 + with: + enable-cache: true + - name: Install dependencies + run: uv sync --group dev + - name: Ruff (lint + format check) + run: | + uv run ruff check . + uv run ruff format --check . + + test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: astral-sh/setup-uv@v5 + with: + enable-cache: true + - name: Install dependencies + run: uv sync --group dev + - name: Run tests with coverage (fails under 80%) + run: uv run pytest + + publish: + # Only publish on a real merge into main or dev, never on PRs. + if: github.event_name == 'push' && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/dev') + needs: [lint, test] + runs-on: ubuntu-latest + permissions: + packages: write + steps: + - uses: actions/checkout@v4 + - uses: astral-sh/setup-uv@v5 + with: + enable-cache: true + + - name: Compute version + # main publishes the clean version from pyproject.toml. + # dev publishes a unique pre-release (X.Y.Z.devN) so merges never collide. + run: | + BASE=$(uv version --short) + if [ "${{ github.ref_name }}" = "dev" ]; then + VERSION="${BASE}.dev${{ github.run_number }}" + uv version "$VERSION" --no-sync + else + VERSION="$BASE" + fi + echo "Publishing version $VERSION" + echo "VERSION=$VERSION" >> "$GITHUB_ENV" + + - name: Build sdist + wheel + run: uv build + + - name: Publish to Gitea PyPI registry + env: + # The auto-provided token works for the same owner's package registry. + # Override with a PACKAGE_REGISTRY_TOKEN secret if your instance needs it. + TWINE_USERNAME: ${{ gitea.actor }} + TWINE_PASSWORD: ${{ secrets.PACKAGE_REGISTRY_TOKEN || secrets.GITHUB_TOKEN }} + run: | + uvx twine upload \ + --repository-url "${{ github.server_url }}/api/packages/${{ github.repository_owner }}/pypi" \ + --non-interactive \ + --skip-existing \ + dist/*