name: Release on: push: tags: - "v*" permissions: contents: write jobs: checks: runs-on: ubuntu-latest strategy: fail-fast: false matrix: python-version: ["3.12", "3.13", "3.14"] steps: - uses: actions/checkout@v4 - name: Install uv uses: astral-sh/setup-uv@v7 with: python-version: ${{ matrix.python-version }} enable-cache: true - name: Install dependencies run: uv sync --locked - name: Run release checks run: | uv run ruff check src/ tests/ uv run ruff format --check src/ tests/ uv run mypy src/ uv run pytest --tb=short -q release: runs-on: ubuntu-latest needs: checks steps: - uses: actions/checkout@v4 with: fetch-depth: 0 - name: Install uv uses: astral-sh/setup-uv@v7 with: python-version: "3.12" enable-cache: true - name: Install dependencies run: uv sync --locked - name: Validate release version run: | package_version="$(grep '^version = ' pyproject.toml | cut -d '"' -f 2)" module_version="$(grep '^__version__ = ' src/rp/__init__.py | cut -d '"' -f 2)" expected_tag="v${package_version}" if [ "$package_version" != "$module_version" ]; then printf 'Version mismatch: pyproject.toml=%s src/rp/__init__.py=%s\n' "$package_version" "$module_version" exit 1 fi if [ "${{ github.ref_name }}" != "$expected_tag" ]; then printf 'Tag %s does not match package version %s\n' "${{ github.ref_name }}" "$expected_tag" exit 1 fi - name: Build release artifacts run: | rm -rf dist uv build cd dist sha256sum *.tar.gz *.whl > SHA256SUMS - name: Generate release notes run: | tag="${{ github.ref_name }}" release_target="${tag}^" previous_tag="$(git tag --list 'v*' --sort=-version:refname | awk -v tag="$tag" '$0 == tag { found = 1; next } found { print; exit }')" if ! git rev-parse --verify "$release_target" >/dev/null 2>&1; then release_target="$tag" fi { printf '# %s\n\n' "$tag" if [ -n "$previous_tag" ]; then printf '## Changes since %s\n\n' "$previous_tag" git log --no-merges --pretty='- %s (%h)' "${previous_tag}..${release_target}" else printf '## Changes\n\n' git log --no-merges --pretty='- %s (%h)' "$release_target" fi } > release-notes.md - name: Create GitHub release if: ${{ github.server_url == 'https://github.com' }} uses: softprops/action-gh-release@v2 with: name: ${{ github.ref_name }} tag_name: ${{ github.ref_name }} body_path: release-notes.md files: | dist/*.tar.gz dist/*.whl dist/SHA256SUMS - name: Create Gitea release if: ${{ github.server_url == 'https://gitea.yunxiao.xyz' }} uses: akkuman/gitea-release-action@v1 env: NODE_OPTIONS: --experimental-fetch with: server_url: https://gitea.yunxiao.xyz token: ${{ secrets.RELEASE_TOKEN_GITEA }} name: ${{ github.ref_name }} tag_name: ${{ github.ref_name }} body_path: release-notes.md files: | dist/*.tar.gz dist/*.whl dist/SHA256SUMS