Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 15 additions & 5 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ on:
branches:
- "*"

permissions: {}

concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
Expand All @@ -19,12 +21,14 @@ jobs:
runs-on: blacksmith-2vcpu-ubuntu-2404
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
persist-credentials: false
- name: Install uv and set Python version
uses: astral-sh/setup-uv@cec208311dfd045dd5311c1add060b2062131d57 # v8
with:
version: "0.11.2"
python-version: "3.13"
enable-cache: true
enable-cache: true # zizmor: ignore[cache-poisoning] CI-only, no artifacts published
- name: Install dependencies
run: uv sync --locked
- name: Run Ruff
Expand All @@ -34,13 +38,15 @@ jobs:
runs-on: blacksmith-2vcpu-ubuntu-2404
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
persist-credentials: false
- name: Install uv and set Python version
uses: astral-sh/setup-uv@cec208311dfd045dd5311c1add060b2062131d57 # v8
with:
version: "0.11.2"
python-version: "3.13"
enable-cache: true
- uses: actions/cache@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5
enable-cache: true # zizmor: ignore[cache-poisoning] CI-only, no artifacts published
- uses: actions/cache@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4 # zizmor: ignore[cache-poisoning]
name: Cache mypy cache
with:
path: ./.mypy_cache
Expand Down Expand Up @@ -73,12 +79,14 @@ jobs:
name: Unit tests on Python ${{ matrix.python-version }}
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
persist-credentials: false
- name: Install uv and set Python version
uses: astral-sh/setup-uv@cec208311dfd045dd5311c1add060b2062131d57 # v8
with:
version: "0.11.2"
python-version: ${{ matrix.python-version }}
enable-cache: true
enable-cache: true # zizmor: ignore[cache-poisoning] CI-only, no artifacts published

- name: Check Python version
run: python --version
Expand Down Expand Up @@ -134,12 +142,14 @@ jobs:
name: ${{ matrix.job_name }}
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
persist-credentials: false
- name: Install uv and set Python version
uses: astral-sh/setup-uv@cec208311dfd045dd5311c1add060b2062131d57 # v8
with:
version: "0.11.2"
python-version: "3.13"
enable-cache: true
enable-cache: true # zizmor: ignore[cache-poisoning] CI-only, no artifacts published
- name: Install the project dependencies
run: uv sync --locked
- name: Check uv Python version
Expand Down
5 changes: 3 additions & 2 deletions .github/workflows/claude-review-maintainer-prs.yml
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
name: Claude Review on Maintainer PRs

on:
pull_request_target:
pull_request:
types:
- opened
- ready_for_review

jobs:
comment:
if: github.event.pull_request.draft == false
# Only run on PRs that are not drafts and are from the same repository (i.e., not from forks)
if: github.event.pull_request.draft == false && github.event.pull_request.head.repo.full_name == github.repository
runs-on: ubuntu-latest
permissions:
issues: write
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/codeql.yml
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
persist-credentials: false

# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/dependabot-merge.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ permissions:
jobs:
dependabot:
runs-on: ubuntu-latest
if: ${{ github.actor == 'dependabot[bot]' }}
if: github.event.pull_request.user.id == 49699333 # dependabot[bot]
steps:
- name: Dependabot metadata
id: metadata
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/dependabot-rebase-stale.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ on:
- main
workflow_dispatch:

permissions: {}

jobs:
rebase-dependabot:
runs-on: ubuntu-latest
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/package-availability-check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ on:
- cron: "*/30 * * * *"
workflow_dispatch:

permissions: {}

jobs:
build:
runs-on: ubuntu-latest
Expand Down
78 changes: 50 additions & 28 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,32 +47,35 @@ jobs:
steps:
- name: Verify branch
run: |
if [ "${{ github.ref }}" != "refs/heads/main" ]; then
if [ "${GITHUB_REF}" != "refs/heads/main" ]; then
echo "❌ Error: Releases can only be triggered from main branch"
echo "Current ref: ${{ github.ref }}"
echo "Current ref: ${GITHUB_REF}"
exit 1
fi

- name: Confirm major release
if: ${{ inputs.version == 'major' || inputs.version == 'premajor' }}
run: |
if [ "${{ inputs.confirm_major }}" != "RELEASE MAJOR" ]; then
if [ "${INPUTS_CONFIRM_MAJOR}" != "RELEASE MAJOR" ]; then
echo "❌ For major/premajor releases, set confirm_major to RELEASE MAJOR"
exit 1
fi
env:
INPUTS_CONFIRM_MAJOR: ${{ inputs.confirm_major }}

- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
fetch-depth: 0
token: ${{ secrets.GH_ACCESS_TOKEN }}
persist-credentials: false

- name: Install uv and set Python version
uses: astral-sh/setup-uv@cec208311dfd045dd5311c1add060b2062131d57 # v8
with:
version: "0.11.2"
python-version: "3.12"
enable-cache: true
enable-cache: false

- name: Configure Git
env:
Expand All @@ -94,10 +97,10 @@ jobs:
- name: Calculate new version
id: new-version
run: |
current_version="${{ steps.current-version.outputs.version }}"
version_type="${{ inputs.version }}"
prerelease_type="${{ inputs.prerelease_type }}"
prerelease_increment="${{ inputs.prerelease_increment }}"
current_version="${STEPS_CURRENT_VERSION_OUTPUTS_VERSION}"
version_type="${INPUTS_VERSION}"
prerelease_type="${INPUTS_PRERELEASE_TYPE}"
prerelease_increment="${INPUTS_PRERELEASE_INCREMENT}"

# Extract base version (strip any pre-release suffix like a1, b2, rc1)
base_version=$(echo "$current_version" | sed -E 's/(a|b|rc)[0-9]+$//')
Expand Down Expand Up @@ -195,31 +198,42 @@ jobs:
echo "version=$new_version" >> $GITHUB_OUTPUT
echo "is_prerelease=$is_prerelease" >> $GITHUB_OUTPUT
echo "New version: $new_version (prerelease: $is_prerelease)"
env:
STEPS_CURRENT_VERSION_OUTPUTS_VERSION: ${{ steps.current-version.outputs.version }}
INPUTS_VERSION: ${{ inputs.version }}
INPUTS_PRERELEASE_TYPE: ${{ inputs.prerelease_type }}
INPUTS_PRERELEASE_INCREMENT: ${{ inputs.prerelease_increment }}

- name: Check if tag already exists
run: |
if git rev-parse "v${{ steps.new-version.outputs.version }}" >/dev/null 2>&1; then
echo "❌ Error: Tag v${{ steps.new-version.outputs.version }} already exists"
if git rev-parse "v${STEPS_NEW_VERSION_OUTPUTS_VERSION}" >/dev/null 2>&1; then
echo "❌ Error: Tag v${STEPS_NEW_VERSION_OUTPUTS_VERSION} already exists"
exit 1
fi
echo "✅ Tag v${{ steps.new-version.outputs.version }} does not exist"
echo "✅ Tag v${STEPS_NEW_VERSION_OUTPUTS_VERSION} does not exist"
env:
STEPS_NEW_VERSION_OUTPUTS_VERSION: ${{ steps.new-version.outputs.version }}

- name: Update version in pyproject.toml
run: |
uv version ${{ steps.new-version.outputs.version }}
uv version ${STEPS_NEW_VERSION_OUTPUTS_VERSION}
env:
STEPS_NEW_VERSION_OUTPUTS_VERSION: ${{ steps.new-version.outputs.version }}

- name: Verify version consistency
run: |
pyproject_version=$(uv version --short)

echo "pyproject.toml version: $pyproject_version"

if [ "$pyproject_version" != "${{ steps.new-version.outputs.version }}" ]; then
if [ "$pyproject_version" != "${STEPS_NEW_VERSION_OUTPUTS_VERSION}" ]; then
echo "❌ Error: Version in files doesn't match expected version"
exit 1
fi

echo "✅ Versions are consistent: $pyproject_version"
env:
STEPS_NEW_VERSION_OUTPUTS_VERSION: ${{ steps.new-version.outputs.version }}

- name: Build package
run: uv build --no-sources
Expand Down Expand Up @@ -250,14 +264,16 @@ jobs:
ls -lh dist/

# Verify the version in the built artifacts matches
expected_version="${{ steps.new-version.outputs.version }}"
expected_version="${STEPS_NEW_VERSION_OUTPUTS_VERSION}"
wheel_file=$(ls dist/*.whl | head -1)
if ! echo "$wheel_file" | grep -q "$expected_version"; then
echo "❌ Error: Wheel filename doesn't contain expected version $expected_version"
echo "Wheel file: $wheel_file"
exit 1
fi
echo "✅ Artifact version verified"
env:
STEPS_NEW_VERSION_OUTPUTS_VERSION: ${{ steps.new-version.outputs.version }}

- name: Smoke test wheel
run: |
Expand All @@ -270,32 +286,38 @@ jobs:
- name: Commit version changes
run: |
git add pyproject.toml uv.lock
git commit -m "chore: release v${{ steps.new-version.outputs.version }}"
git commit -m "chore: release v${STEPS_NEW_VERSION_OUTPUTS_VERSION}"
env:
STEPS_NEW_VERSION_OUTPUTS_VERSION: ${{ steps.new-version.outputs.version }}

- name: Create and push tag
id: push-tag
run: |
git tag "v${{ steps.new-version.outputs.version }}"
git tag "v${STEPS_NEW_VERSION_OUTPUTS_VERSION}"
git push origin main
git push origin "v${{ steps.new-version.outputs.version }}"
git push origin "v${STEPS_NEW_VERSION_OUTPUTS_VERSION}"
env:
STEPS_NEW_VERSION_OUTPUTS_VERSION: ${{ steps.new-version.outputs.version }}

- name: Publish to PyPI
id: publish-pypi
run: uv publish --trusted-publishing always

- name: Create GitHub Release
id: create-release
uses: softprops/action-gh-release@153bb8e04406b158c6c84fc1615b65b24149a1fe # v2
with:
tag_name: v${{ steps.new-version.outputs.version }}
name: v${{ steps.new-version.outputs.version }}
generate_release_notes: true
prerelease: ${{ steps.new-version.outputs.is_prerelease == 'true' }}
files: |
dist/*.whl
dist/*.tar.gz
run: |
prerelease_flag=""
if [ "${IS_PRERELEASE}" = "true" ]; then
prerelease_flag="--prerelease"
fi
gh release create "v${VERSION}" \
--title "v${VERSION}" \
--generate-notes \
$prerelease_flag \
dist/*.whl dist/*.tar.gz
env:
GITHUB_TOKEN: ${{ secrets.GH_ACCESS_TOKEN }}
GH_TOKEN: ${{ secrets.GH_ACCESS_TOKEN }}
VERSION: ${{ steps.new-version.outputs.version }}
IS_PRERELEASE: ${{ steps.new-version.outputs.is_prerelease }}

- name: Notify Slack on success
if: success()
Expand Down
32 changes: 32 additions & 0 deletions .github/workflows/zizmor.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
---
name: Check GitHub Actions

on:
workflow_dispatch:
push:
branches:
- "main"
merge_group:
pull_request:
branches:
- "main"

permissions: {}

jobs:
zizmor:
name: Check GitHub Actions security
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository
runs-on: ubuntu-latest
permissions:
security-events: write
contents: read
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
with:
persist-credentials: false
- name: Run zizmor
uses: zizmorcore/zizmor-action@b1d7e1fb5de872772f31590499237e7cce841e8e # v0.5.3
with:
advanced-security: true
Loading