diff --git a/.github/workflows/format.yml b/.github/workflows/format.yml index a226ae0..95450e5 100644 --- a/.github/workflows/format.yml +++ b/.github/workflows/format.yml @@ -1,23 +1,61 @@ -name: pre-commit-format +name: pre-commit (PR only on changed files) on: - push: - branches: [main] pull_request: - branches: [main] + types: [opened, synchronize, reopened] jobs: - pre_commit_checks: + detect_changes: runs-on: ubuntu-latest + outputs: + changed: ${{ steps.changed_files.outputs.changed }} + steps: - - uses: actions/checkout@v3 + - name: Checkout full history + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Detect changed files + id: changed_files + run: | + git fetch origin ${{ github.base_ref }} + CHANGED_FILES=$(git diff --name-only origin/${{ github.base_ref }}...HEAD) + + { + echo "changed<> "$GITHUB_OUTPUT" + + - name: Show changed files + run: | + echo "Changed files:" + echo "${{ steps.changed_files.outputs.changed }}" + + precommit: + needs: detect_changes + runs-on: ubuntu-latest + if: ${{ needs.detect_changes.outputs.changed != '' }} + + steps: + - name: Checkout PR branch + uses: actions/checkout@v4 with: fetch-depth: 0 ref: ${{ github.head_ref }} - - uses: actions/setup-python@v4 + - name: Set up Python + uses: actions/setup-python@v5 with: - python-version: '3.10' + python-version: "3.12" + + - name: Install pre-commit + run: pip install pre-commit - - run: pip install pre-commit - - run: pre-commit run --all-files + - name: Run pre-commit (CI check-only stage) on changed files + env: + CHANGED_FILES: ${{ needs.detect_changes.outputs.changed }} + run: | + mapfile -t files <<< "$CHANGED_FILES" + pre-commit run --hook-stage manual --files "${files[@]}" --show-diff-on-failure diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 3d846cf..b69e80a 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,28 +1,61 @@ +default_stages: [pre-commit] + repos: - repo: https://github.com/pre-commit/pre-commit-hooks rev: v6.0.0 hooks: + # These are safe to run in both local & CI (they don't require "fix vs check" split) - id: check-added-large-files + stages: [pre-commit, manual] - id: check-yaml + stages: [pre-commit, manual] - id: check-toml + stages: [pre-commit, manual] + - id: check-merge-conflict + stages: [pre-commit, manual] + + # These modify files. Run locally only (pre-commit stage). - id: end-of-file-fixer - - id: name-tests-test - args: [--pytest-test-first] + stages: [pre-commit] - id: trailing-whitespace - - id: check-merge-conflict + stages: [pre-commit] + - repo: https://github.com/tox-dev/pyproject-fmt rev: v2.15.2 hooks: - id: pyproject-fmt + stages: [pre-commit] # modifies -> local only + - repo: https://github.com/abravalheri/validate-pyproject rev: v0.25 hooks: - id: validate-pyproject + stages: [pre-commit, manual] + - repo: https://github.com/astral-sh/ruff-pre-commit rev: v0.15.0 hooks: - # Run the formatter. + # -------------------------- + # LOCAL AUTOFIX (developers) + # -------------------------- + - id: ruff-check + name: ruff-check (fix) + args: [--fix, --unsafe-fixes] + stages: [pre-commit] + - id: ruff-format - # Run the linter. + name: ruff-format (write) + stages: [pre-commit] + + # -------------------------- + # CI CHECK-ONLY (no writes) + # -------------------------- - id: ruff-check - args: [--fix,--unsafe-fixes] + name: ruff-check (ci) + args: [--output-format=github] + stages: [manual] + + - id: ruff-format + name: ruff-format (ci) + args: [--check, --diff] + stages: [manual]