From 138efa88e8d7dde5146e0e38cb222ff3ab10b8c9 Mon Sep 17 00:00:00 2001 From: "Philipp A." Date: Tue, 4 Aug 2026 14:43:57 +0200 Subject: [PATCH 1/6] ci: run prek in GH actions --- .github/dependabot.yml | 22 ++++++-- .github/workflows/benchmark.yml | 10 ++-- .github/workflows/check-pr.yml | 18 ++++--- .github/workflows/ci.yml | 62 +++++++++++++--------- .github/workflows/publish.yml | 12 +++-- .pre-commit-config.yaml | 93 +++++++++++++++++++-------------- .vscode/settings.json | 5 +- ci/scripts/low-vers.py | 4 +- hatch.toml | 10 ++++ 9 files changed, 148 insertions(+), 88 deletions(-) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index afee4a5762..18fa22a4ca 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -1,14 +1,30 @@ version: 2 updates: - - package-ecosystem: github-actions + - package-ecosystem: pre-commit directory: / schedule: interval: weekly labels: - no milestone commit-message: - prefix: ci - - package-ecosystem: pip + prefix: test + cooldown: + default-days: 7 + groups: + pre-commit: + patterns: + - "*" + - package-ecosystem: github-actions directory: / schedule: interval: weekly + labels: + - no milestone + commit-message: + prefix: ci + cooldown: + default-days: 7 + groups: + actions-deps: + patterns: + - "*" diff --git a/.github/workflows/benchmark.yml b/.github/workflows/benchmark.yml index 21b8f96e50..ef28f89140 100644 --- a/.github/workflows/benchmark.yml +++ b/.github/workflows/benchmark.yml @@ -9,6 +9,8 @@ on: env: FORCE_COLOR: "1" +permissions: {} + jobs: benchmark: runs-on: ${{ matrix.os }} @@ -25,21 +27,21 @@ jobs: ASV_DIR: "./benchmarks" steps: - - uses: actions/checkout@v6 - with: { fetch-depth: 0 } # no blob:none so ASV can compare commits + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: { fetch-depth: 0, persist-credentials: false } # no blob:none so ASV can compare commits - name: Fetch main branch for `asv run`’s hash run: git fetch origin main:main if: ${{ github.ref_name != 'main' }} - name: Set up Python ${{ matrix.python }} - uses: actions/setup-python@v7 + uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0 with: python-version: ${{ matrix.python }} cache: 'pip' - name: Cache datasets - uses: actions/cache@v6 + uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 with: path: | ~/.cache diff --git a/.github/workflows/check-pr.yml b/.github/workflows/check-pr.yml index d93b3211dd..8498f8f7d5 100644 --- a/.github/workflows/check-pr.yml +++ b/.github/workflows/check-pr.yml @@ -20,19 +20,23 @@ on: # code change (e.g. this workflow) - synchronize +permissions: {} + jobs: # This job verifies that the milestone is present or not necessary # and determines if “check-relnotes” needs to be run. check-milestone: name: Check title, milestone, and labels runs-on: ubuntu-latest + permissions: + pull-requests: read # for amannn/action-semantic-pull-request steps: - name: Check if milestone or “no milestone” label is present - uses: flying-sheep/check@v1 + uses: flying-sheep/check@e10bb11109d1434ab16729bd988d78d65d47e163 # v1.0.5 with: success: ${{ github.event.pull_request.user.login == 'pre-commit-ci[bot]' || github.event.pull_request.milestone != null || contains(github.event.pull_request.labels.*.name, 'no milestone') }} - name: Check if the “Release notes” checkbox is checked and filled - uses: kaisugi/action-regex-match@v1.0.2 + uses: kaisugi/action-regex-match@d67cd689755dc47c5362609e0a6e2e1c93fa721b # v1.0.2 id: checked-relnotes with: text: ${{ github.event.pull_request.body }} @@ -40,7 +44,7 @@ jobs: flags: m - name: Check PR title id: check-title - uses: amannn/action-semantic-pull-request@v6 + uses: amannn/action-semantic-pull-request@48f256284bd46cdaab1048c3721360e808335d50 # v6.1.1 env: # Needs repo options: “Squash and merge” with commit message set to “PR title” GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} outputs: @@ -53,15 +57,15 @@ jobs: needs: check-milestone if: github.event.pull_request.user.login != 'pre-commit-ci[bot]' && needs.check-milestone.outputs.no-relnotes-reason == '' && !contains(fromJSON('["style","refactor","test","build","docs","ci"]'), needs.check-milestone.outputs.type) steps: - - uses: actions/checkout@v7 - with: { filter: 'blob:none', fetch-depth: 0 } + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: { filter: 'blob:none', fetch-depth: 0, persist-credentials: false } - name: Find out if a relevant release fragment is added - uses: dorny/paths-filter@v4 + uses: dorny/paths-filter@7b450fff21473bca461d4b92ce414b9d0420d706 # v4.0.2 id: changes with: filters: | # this is intentionally a string relnotes: 'docs/release-notes/${{ github.event.pull_request.number }}.${{ (contains(github.event.pull_request.title, '!') && 'breaking') || needs.check-milestone.outputs.type }}.md' - name: Check if a relevant release fragment is added - uses: flying-sheep/check@v1 + uses: flying-sheep/check@e10bb11109d1434ab16729bd988d78d65d47e163 # v1.0.5 with: success: ${{ steps.changes.outputs.relnotes }} diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ce4477ce87..3d5f661159 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -15,16 +15,24 @@ env: # so because leidenalg 0.10.0 has them, we pre-compile things: https://github.com/vtraag/leidenalg/issues/173 UV_COMPILE_BYTECODE: "1" +permissions: {} + jobs: get-environments: runs-on: ubuntu-latest outputs: envs: ${{ steps.get-envs.outputs.envs }} steps: - - uses: actions/checkout@v7 - with: { filter: 'blob:none', fetch-depth: 0 } - - uses: astral-sh/setup-uv@v9.0.0 - with: { enable-cache: false } + - &clone + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + fetch-depth: 0 + filter: blob:none + persist-credentials: false + - &setup-uv + uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0 + with: + enable-cache: true - id: get-envs run: | ENVS_JSON=$(NO_COLOR=1 uvx hatch env show --json | jq -c 'to_entries @@ -46,16 +54,13 @@ jobs: env: ${{ fromJSON(needs.get-environments.outputs.envs) }} permissions: id-token: write # for codecov OIDC + env: + UV_PYTHON: ${{ matrix.env.python }} steps: - - uses: actions/checkout@v7 - with: { filter: 'blob:none', fetch-depth: 0 } - - - uses: astral-sh/setup-uv@v9.0.0 - with: - python-version: ${{ matrix.env.python }} - + - *clone + - *setup-uv - name: Cache downloaded data - uses: actions/cache@v6 + uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 with: path: .pytest_cache/d/scanpy-data key: pytest @@ -83,7 +88,7 @@ jobs: - name: Upload coverage data if: ${{ !cancelled() && matrix.env.test-type == 'coverage' }} - uses: codecov/codecov-action@v6 + uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0 with: flags: ${{ matrix.env.name }} files: test-data/coverage.xml @@ -92,7 +97,7 @@ jobs: - name: Upload test results if: ${{ !cancelled() }} - uses: codecov/codecov-action@v6 + uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0 with: report_type: test_results flags: ${{ matrix.env.name }} @@ -102,7 +107,7 @@ jobs: - name: Publish debug artifacts if: ${{ !cancelled() }} - uses: actions/upload-artifact@v5 + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: debug-data-${{ matrix.env.name }} path: .pytest_cache/d/debug @@ -110,25 +115,34 @@ jobs: build: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v7 - with: { filter: 'blob:none', fetch-depth: 0 } - - uses: actions/setup-python@v7 - with: - python-version: "3.x" - - uses: astral-sh/setup-uv@v9.0.0 - with: - enable-cache: true + - *clone + - *setup-uv - run: uvx --from build pyproject-build --sdist --wheel . - run: uvx twine check dist/* + lint: + name: Pre-commit checks + runs-on: ubuntu-latest + permissions: {} + steps: + - *clone + - *setup-uv + - run: uv tool install hatch + - name: Run pre-commit hooks + run: uvx prek run --all-files --show-diff-on-failure --color=always + env: + SKIP: no-commit-to-branch + - uses: autofix-ci/action@c5b2d67aa2274e7b5a18224e8171550871fc7e4a # v1.3.4 + check: if: always() needs: - get-environments - test - build + - lint runs-on: ubuntu-latest steps: - - uses: re-actors/alls-green@release/v1 + - uses: re-actors/alls-green@05ac9388f0aebcb5727afa17fcccfecd6f8ec5fe # v1.2.2 with: jobs: ${{ toJSON(needs) }} diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index b818a646a4..2b6a46b4a6 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -14,12 +14,14 @@ jobs: permissions: id-token: write # to authenticate as Trusted Publisher to pypi.org steps: - - uses: actions/checkout@v7 - with: { filter: 'blob:none', fetch-depth: 0 } - - uses: actions/setup-python@v7 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: { filter: 'blob:none', fetch-depth: 0, persist-credentials: false } + - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0 with: python-version: "3.x" - - uses: astral-sh/setup-uv@v9.0.0 + - uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0 + with: + enable-cache: false - run: uvx --from build pyproject-build --sdist --wheel . - run: uvx twine check dist/* - - uses: pypa/gh-action-pypi-publish@release/v1 + - uses: pypa/gh-action-pypi-publish@dc37677b2e1c63e2034f94d8a5b11f265b73ba33 # v1.14.2 diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index a5a12b2a0f..586534e9ab 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,40 +1,55 @@ -ci: - autoupdate_commit_msg: "ci: pre-commit autoupdate" - repos: -- repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.16.1 - hooks: - - id: ruff-check - args: ["--fix"] - - id: ruff-format -- repo: https://github.com/flying-sheep/bibfmt - rev: v4.3.0 - hooks: - - id: bibfmt - args: - - --sort-by-bibkey - - --drop=abstract -- repo: https://github.com/biomejs/pre-commit - rev: v2.5.6 - hooks: - - id: biome-format -- repo: https://github.com/tox-dev/pyproject-fmt - rev: v2.26.0 - hooks: - - id: pyproject-fmt -- repo: https://github.com/pre-commit/pre-commit-hooks - rev: v6.0.0 - hooks: - - id: trailing-whitespace - exclude: tests/_data - - id: end-of-file-fixer - exclude: tests/_data - - id: check-added-large-files - - id: check-case-conflict - - id: check-toml - - id: check-yaml - - id: check-merge-conflict - - id: detect-private-key - - id: no-commit-to-branch - args: ["--branch=main"] +- repo: https://github.com/flying-sheep/bibfmt + rev: v4.3.0 + hooks: + - id: bibfmt + args: + - --sort-by-bibkey + - --drop=abstract + groups: [format] +- repo: https://github.com/biomejs/pre-commit + rev: v2.5.6 + hooks: + - id: biome-format + groups: [format] + exclude: ^\.cruft\.json$ # inconsistent indentation with cruft - file never to be modified manually. +- repo: https://github.com/tox-dev/pyproject-fmt + rev: v2.27.0 + hooks: + - id: pyproject-fmt + groups: [format] +- repo: https://github.com/astral-sh/ruff-pre-commit + rev: v0.16.1 + hooks: + - id: ruff-check + args: ["--fix"] + - id: ruff-format + groups: [format] +- repo: https://github.com/pre-commit/pre-commit-hooks + rev: v6.0.0 + hooks: + - id: detect-private-key + - id: check-ast + - id: check-added-large-files + - id: check-toml + - id: check-yaml + - id: end-of-file-fixer + groups: [format] + exclude: tests/_data + - id: mixed-line-ending + groups: [format] + args: [--fix=lf] + - id: trailing-whitespace + groups: [format] + exclude: tests/_data + - id: check-case-conflict + # Check that there are no merge conflicts (could be generated by template sync) + - id: check-merge-conflict + args: [--assume-in-merge] + - id: no-commit-to-branch + args: [--branch=main] +- repo: https://github.com/zizmorcore/zizmor-pre-commit + rev: v1.29.0 + hooks: + - id: zizmor + args: [--no-progress, --fix] diff --git a/.vscode/settings.json b/.vscode/settings.json index fc4da964e2..b0648f1990 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,5 +1,5 @@ { - "[python][toml][json][jsonc]": { + "[python][json][jsonc]": { "editor.formatOnSave": true, "editor.codeActionsOnSave": { "source.organizeImports": "explicit", @@ -9,9 +9,6 @@ "[python]": { "editor.defaultFormatter": "charliermarsh.ruff", }, - "[toml]": { - "editor.defaultFormatter": "tamasfe.even-better-toml", - }, "[json][jsonc]": { "editor.defaultFormatter": "biomejs.biome", }, diff --git a/ci/scripts/low-vers.py b/ci/scripts/low-vers.py index c8f52418bb..f88c9576fe 100755 --- a/ci/scripts/low-vers.py +++ b/ci/scripts/low-vers.py @@ -21,7 +21,7 @@ from packaging.version import Version if TYPE_CHECKING: - from collections.abc import Generator, Iterable, Sequence + from collections.abc import Generator, Iterable, Sequence from collections.abc import Set as AbstractSet from typing import Any, Self @@ -46,7 +46,7 @@ def min_dep(req: Requirement) -> Requirement: if not filter_specs: # TODO: handle markers return Requirement(f"{req_name}{req.specifier}") - min_version = Version("0.0.0.a1") + min_version = Version("0.0.0.a1") for spec in filter_specs: if spec.operator in {">", ">=", "~="}: min_version = max(min_version, Version(spec.version)) diff --git a/hatch.toml b/hatch.toml index e9c5d6cca7..59baac1e9a 100644 --- a/hatch.toml +++ b/hatch.toml @@ -15,6 +15,16 @@ scripts.create = "towncrier create {args}" scripts.build = "python3 ci/scripts/towncrier_automation.py {args}" scripts.clean = "git restore --source=HEAD --staged --worktree -- docs/release-notes" +[envs.hatch-check-fmt] +dependencies = [ "prek" ] +scripts.format-check = "echo 'try `hatch check fmt --fix`'; false" +scripts.format-fix = "prek run -a --group=format" + +[envs.hatch-check-code] +dependencies = [ "prek" ] +lint-check = "echo 'try `hatch check code --fix`'; false" +scripts.lint-fix = "prek run -a --no-group=format" + [envs.hatch-test] python = "3.14" default-args = [ ] From 90e42514247fa5d2a8c5bed7eef74c43f2a1cd68 Mon Sep 17 00:00:00 2001 From: "Philipp A." Date: Tue, 4 Aug 2026 14:48:39 +0200 Subject: [PATCH 2/6] fix: name --- .github/workflows/autofix.ci.yml | 148 +++++++++++++++++++++++++++++++ 1 file changed, 148 insertions(+) create mode 100644 .github/workflows/autofix.ci.yml diff --git a/.github/workflows/autofix.ci.yml b/.github/workflows/autofix.ci.yml new file mode 100644 index 0000000000..1018b5c679 --- /dev/null +++ b/.github/workflows/autofix.ci.yml @@ -0,0 +1,148 @@ +name: CI + +on: + push: + branches: + - main + - "[0-9]+.[0-9]+.x" + pull_request: + +env: + PYTEST_ADDOPTS: "-v --color=yes -n auto --internet-tests --junitxml=test-data/test-results.xml" + FORCE_COLOR: "1" + MPLBACKEND: agg + # It’s impossible to ignore SyntaxWarnings for a single module, + # so because leidenalg 0.10.0 has them, we pre-compile things: https://github.com/vtraag/leidenalg/issues/173 + UV_COMPILE_BYTECODE: "1" + +permissions: {} + +jobs: + get-environments: + runs-on: ubuntu-latest + outputs: + envs: ${{ steps.get-envs.outputs.envs }} + steps: + - &clone + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + fetch-depth: 0 + filter: blob:none + persist-credentials: false + - &setup-uv + uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0 + with: + enable-cache: true + - id: get-envs + run: | + ENVS_JSON=$(NO_COLOR=1 uvx hatch env show --json | jq -c 'to_entries + | map( + select(.key | startswith("hatch-test")) + | { + name: .key, + "test-type": (if (.key | test("pre|low-vers")) then "coverage" else null end), + python: .value.python + } + )') + echo "envs=${ENVS_JSON}" | tee $GITHUB_OUTPUT + + test: + needs: get-environments + runs-on: ubuntu-latest + strategy: + matrix: + env: ${{ fromJSON(needs.get-environments.outputs.envs) }} + permissions: + id-token: write # for codecov OIDC + env: + UV_PYTHON: ${{ matrix.env.python }} + steps: + - *clone + - *setup-uv + - name: Cache downloaded data + uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 + with: + path: .pytest_cache/d/scanpy-data + key: pytest + + - name: Install dependencies + run: | + echo "::group::Install hatch" + uv tool install hatch + echo "::endgroup::" + echo "::group::Create environment" + hatch -v env create ${{ matrix.env.name }} + echo "::endgroup::" + hatch run ${{ matrix.env.name }}:session-info scanpy anndata + + - name: Run tests + if: matrix.env.test-type == null + run: hatch run ${{ matrix.env.name }}:run + - name: Run tests (coverage) + if: matrix.env.test-type == 'coverage' + run: | + hatch run ${{ matrix.env.name }}:run-cov + hatch run ${{ matrix.env.name }}:cov-combine + hatch run ${{ matrix.env.name }}:coverage xml + hatch run ${{ matrix.env.name }}:cov-report + + - name: Upload coverage data + if: ${{ !cancelled() && matrix.env.test-type == 'coverage' }} + uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0 + with: + flags: ${{ matrix.env.name }} + files: test-data/coverage.xml + use_oidc: true + fail_ci_if_error: true + + - name: Upload test results + if: ${{ !cancelled() }} + uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0 + with: + report_type: test_results + flags: ${{ matrix.env.name }} + files: test-data/test-results.xml + use_oidc: true + fail_ci_if_error: true + + - name: Publish debug artifacts + if: ${{ !cancelled() }} + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: debug-data-${{ matrix.env.name }} + path: .pytest_cache/d/debug + + build: + runs-on: ubuntu-latest + steps: + - *clone + - *setup-uv + - run: uvx --from build pyproject-build --sdist --wheel . + - run: uvx twine check dist/* + + lint: + name: autofix.ci + runs-on: ubuntu-latest + permissions: {} + steps: + - *clone + - *setup-uv + - run: uv tool install hatch + - name: Run pre-commit hooks + run: uvx prek run --all-files --show-diff-on-failure --color=always + env: + SKIP: no-commit-to-branch + - uses: autofix-ci/action@c5b2d67aa2274e7b5a18224e8171550871fc7e4a # v1.3.4 + + check: + if: always() + needs: + - get-environments + - test + - build + - lint + runs-on: ubuntu-latest + steps: + - uses: re-actors/alls-green@05ac9388f0aebcb5727afa17fcccfecd6f8ec5fe # v1.2.2 + with: + jobs: ${{ toJSON(needs) }} From 8f39941dec2ab160f2223c76868b5b87452afaa7 Mon Sep 17 00:00:00 2001 From: "Philipp A." Date: Tue, 4 Aug 2026 14:49:43 +0200 Subject: [PATCH 3/6] actually autofix --- .github/workflows/autofix.ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/autofix.ci.yml b/.github/workflows/autofix.ci.yml index 1018b5c679..d435de4694 100644 --- a/.github/workflows/autofix.ci.yml +++ b/.github/workflows/autofix.ci.yml @@ -133,6 +133,7 @@ jobs: env: SKIP: no-commit-to-branch - uses: autofix-ci/action@c5b2d67aa2274e7b5a18224e8171550871fc7e4a # v1.3.4 + if: ${{ !cancelled() }} check: if: always() From e1f9feddecc21ab60d87738d90ece4dbb7f83df7 Mon Sep 17 00:00:00 2001 From: "Philipp A." Date: Tue, 4 Aug 2026 15:03:35 +0200 Subject: [PATCH 4/6] fix: whoops --- .github/workflows/autofix.ci.yml | 149 ------------------------------- .github/workflows/ci.yml | 1 + 2 files changed, 1 insertion(+), 149 deletions(-) delete mode 100644 .github/workflows/autofix.ci.yml diff --git a/.github/workflows/autofix.ci.yml b/.github/workflows/autofix.ci.yml deleted file mode 100644 index d435de4694..0000000000 --- a/.github/workflows/autofix.ci.yml +++ /dev/null @@ -1,149 +0,0 @@ -name: CI - -on: - push: - branches: - - main - - "[0-9]+.[0-9]+.x" - pull_request: - -env: - PYTEST_ADDOPTS: "-v --color=yes -n auto --internet-tests --junitxml=test-data/test-results.xml" - FORCE_COLOR: "1" - MPLBACKEND: agg - # It’s impossible to ignore SyntaxWarnings for a single module, - # so because leidenalg 0.10.0 has them, we pre-compile things: https://github.com/vtraag/leidenalg/issues/173 - UV_COMPILE_BYTECODE: "1" - -permissions: {} - -jobs: - get-environments: - runs-on: ubuntu-latest - outputs: - envs: ${{ steps.get-envs.outputs.envs }} - steps: - - &clone - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - with: - fetch-depth: 0 - filter: blob:none - persist-credentials: false - - &setup-uv - uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0 - with: - enable-cache: true - - id: get-envs - run: | - ENVS_JSON=$(NO_COLOR=1 uvx hatch env show --json | jq -c 'to_entries - | map( - select(.key | startswith("hatch-test")) - | { - name: .key, - "test-type": (if (.key | test("pre|low-vers")) then "coverage" else null end), - python: .value.python - } - )') - echo "envs=${ENVS_JSON}" | tee $GITHUB_OUTPUT - - test: - needs: get-environments - runs-on: ubuntu-latest - strategy: - matrix: - env: ${{ fromJSON(needs.get-environments.outputs.envs) }} - permissions: - id-token: write # for codecov OIDC - env: - UV_PYTHON: ${{ matrix.env.python }} - steps: - - *clone - - *setup-uv - - name: Cache downloaded data - uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 - with: - path: .pytest_cache/d/scanpy-data - key: pytest - - - name: Install dependencies - run: | - echo "::group::Install hatch" - uv tool install hatch - echo "::endgroup::" - echo "::group::Create environment" - hatch -v env create ${{ matrix.env.name }} - echo "::endgroup::" - hatch run ${{ matrix.env.name }}:session-info scanpy anndata - - - name: Run tests - if: matrix.env.test-type == null - run: hatch run ${{ matrix.env.name }}:run - - name: Run tests (coverage) - if: matrix.env.test-type == 'coverage' - run: | - hatch run ${{ matrix.env.name }}:run-cov - hatch run ${{ matrix.env.name }}:cov-combine - hatch run ${{ matrix.env.name }}:coverage xml - hatch run ${{ matrix.env.name }}:cov-report - - - name: Upload coverage data - if: ${{ !cancelled() && matrix.env.test-type == 'coverage' }} - uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0 - with: - flags: ${{ matrix.env.name }} - files: test-data/coverage.xml - use_oidc: true - fail_ci_if_error: true - - - name: Upload test results - if: ${{ !cancelled() }} - uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0 - with: - report_type: test_results - flags: ${{ matrix.env.name }} - files: test-data/test-results.xml - use_oidc: true - fail_ci_if_error: true - - - name: Publish debug artifacts - if: ${{ !cancelled() }} - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 - with: - name: debug-data-${{ matrix.env.name }} - path: .pytest_cache/d/debug - - build: - runs-on: ubuntu-latest - steps: - - *clone - - *setup-uv - - run: uvx --from build pyproject-build --sdist --wheel . - - run: uvx twine check dist/* - - lint: - name: autofix.ci - runs-on: ubuntu-latest - permissions: {} - steps: - - *clone - - *setup-uv - - run: uv tool install hatch - - name: Run pre-commit hooks - run: uvx prek run --all-files --show-diff-on-failure --color=always - env: - SKIP: no-commit-to-branch - - uses: autofix-ci/action@c5b2d67aa2274e7b5a18224e8171550871fc7e4a # v1.3.4 - if: ${{ !cancelled() }} - - check: - if: always() - needs: - - get-environments - - test - - build - - lint - runs-on: ubuntu-latest - steps: - - uses: re-actors/alls-green@05ac9388f0aebcb5727afa17fcccfecd6f8ec5fe # v1.2.2 - with: - jobs: ${{ toJSON(needs) }} diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3d5f661159..06f01f588e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -133,6 +133,7 @@ jobs: env: SKIP: no-commit-to-branch - uses: autofix-ci/action@c5b2d67aa2274e7b5a18224e8171550871fc7e4a # v1.3.4 + if: ${{ !cancelled() }} check: if: always() From d95319dbde0e5ef490c615e98b250feefbda7891 Mon Sep 17 00:00:00 2001 From: "Philipp A." Date: Tue, 4 Aug 2026 15:19:52 +0200 Subject: [PATCH 5/6] hm --- .github/workflows/ci.yml | 3 ++- .pre-commit-config.yaml | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 06f01f588e..ea2acca03c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -15,7 +15,8 @@ env: # so because leidenalg 0.10.0 has them, we pre-compile things: https://github.com/vtraag/leidenalg/issues/173 UV_COMPILE_BYTECODE: "1" -permissions: {} +permissions: + contents: read jobs: get-environments: diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 586534e9ab..8ffe492d9d 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -22,7 +22,7 @@ repos: rev: v0.16.1 hooks: - id: ruff-check - args: ["--fix"] + args: [--fix, --exit-non-zero-on-fix] - id: ruff-format groups: [format] - repo: https://github.com/pre-commit/pre-commit-hooks From 08653f798b17abe2ed9507a8a930bac19f0f8537 Mon Sep 17 00:00:00 2001 From: "autofix-ci[bot]" <114827586+autofix-ci[bot]@users.noreply.github.com> Date: Tue, 4 Aug 2026 14:24:46 +0000 Subject: [PATCH 6/6] [autofix.ci] apply automated fixes --- ci/scripts/low-vers.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ci/scripts/low-vers.py b/ci/scripts/low-vers.py index f88c9576fe..c8f52418bb 100755 --- a/ci/scripts/low-vers.py +++ b/ci/scripts/low-vers.py @@ -21,7 +21,7 @@ from packaging.version import Version if TYPE_CHECKING: - from collections.abc import Generator, Iterable, Sequence + from collections.abc import Generator, Iterable, Sequence from collections.abc import Set as AbstractSet from typing import Any, Self @@ -46,7 +46,7 @@ def min_dep(req: Requirement) -> Requirement: if not filter_specs: # TODO: handle markers return Requirement(f"{req_name}{req.specifier}") - min_version = Version("0.0.0.a1") + min_version = Version("0.0.0.a1") for spec in filter_specs: if spec.operator in {">", ">=", "~="}: min_version = max(min_version, Version(spec.version))