Files
familiar/.gitea/workflows/ci.yml
T
LatteandClaude Opus 4.8 d76c8f87a8
CI / lint (pull_request) Successful in 51s
CI / test (pull_request) Successful in 59s
CI / lint (push) Successful in 52s
CI / publish (pull_request) Has been skipped
CI / test (push) Successful in 58s
CI / publish (push) Failing after 30s
ci: drop unsupported --skip-existing from twine upload
Gitea's PyPI registry rejects twine's --skip-existing flag
(UnsupportedConfiguration), which failed every publish run. Remove it and
instead tolerate an "already exists" conflict in the shell, so dev (unique
.devN versions) always publishes and a main re-run of an existing release
is treated as success rather than a hard failure.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-27 17:57:50 +02:00

94 lines
3.1 KiB
YAML

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:
contents: read # needed for checkout of the private repo
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: ${{ github.actor }}
TWINE_PASSWORD: ${{ secrets.PACKAGE_REGISTRY_TOKEN || secrets.GITHUB_TOKEN }}
run: |
# Gitea's PyPI registry does not support twine's --skip-existing, so
# we run a plain upload and tolerate an "already exists" conflict in
# the shell (dev versions are unique per run, so this only bites a
# main re-run of an already-published release).
set +e
out=$(uvx twine upload \
--repository-url "${{ github.server_url }}/api/packages/${{ github.repository_owner }}/pypi" \
--non-interactive \
--verbose \
dist/* 2>&1)
code=$?
echo "$out"
if [ $code -ne 0 ] && echo "$out" | grep -qiE "already exist|conflict|409"; then
echo "::notice::Version already published — treating as success."
exit 0
fi
exit $code