Skip to content

refactor: ci using pixi and ruff/flake8#472

Open
cmeesters wants to merge 19 commits into
mainfrom
refactor/ci_pixi
Open

refactor: ci using pixi and ruff/flake8#472
cmeesters wants to merge 19 commits into
mainfrom
refactor/ci_pixi

Conversation

@cmeesters

@cmeesters cmeesters commented Jun 17, 2026

Copy link
Copy Markdown
Member

the situation with black and python version mismatches on local and CI environments is not bearable any longer. Hence, the switch to a CI supporting pixi, ruff and flake8

Summary by CodeRabbit

Release Notes

  • Chores

    • Migrated CI formatting, linting, and testing to a unified pixi workflow.
    • Added pixi.toml to standardize environments and task commands.
    • Updated automated release publishing to build with python -m build and publish via PyPI.
  • Bug Fixes

    • Improved the error message when array job submission is effectively disabled due to a low array_limit.
  • Style / Tooling

    • Switched formatting/lint tooling to Ruff and updated related configuration.
    • Adjusted the throttler dependency lower bound.

@coderabbitai

coderabbitai Bot commented Jun 17, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

@cmeesters, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 55 minutes and 50 seconds. Learn how PR review limits work.

Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file).

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based credits.

🚦 How do rate limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan refill rate.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, the refill rate gradually slows as usage increases. The highest same-day bursts are limited more strictly.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 54028b05-2c34-43db-ab6b-135f3060bc6b

📥 Commits

Reviewing files that changed from the base of the PR and between f01b42c and 0e25162.

📒 Files selected for processing (1)
  • pyproject.toml

Walkthrough

Replaces Black and flake8 with Ruff for formatting and linting. Introduces pixi.toml defining project environments, dependencies, and task commands. Updates all three CI jobs to install pixi and use it for tooling. Loosens the throttler version lower bound. Adds setup.py.bck, a backup Cython build script. Modernizes release-please workflow from v4 to v5 with consolidated build-and-publish flow. Minor code cleanup in logging, assertions, and version constraint formatting.

Changes

Ruff + pixi toolchain migration

Layer / File(s) Summary
Ruff replaces Black/flake8 in project config
pyproject.toml, setup.cfg
Adds ruff dev dependency, removes black and flake8, loosens throttler lower bound from 1.2.3 to 1.2.2, replaces [tool.black] with [tool.ruff] (line length, target version, exclusions, lint ignores), and removes the flake8 configuration block from setup.cfg.
pixi.toml environment and task definitions
pixi.toml
Introduces pixi.toml with project metadata, channels/platforms, core dependencies (Python 3.11, ruff, pytest, coverage, snakemake), dev and conda_pkg feature variants, two environments, and task commands for format, lint, test, and coverage-report.
CI workflow updated to use pixi
.github/workflows/ci.yml
Upgrades actions/checkout to @v6 in all three jobs, adds prefix-dev/setup-pixi@v0 to formatting, linting, and testing jobs, replaces Poetry-based formatting/linting/testing with pixi run format --check ., pixi run lint, pixi run test, and pixi run coverage-report.

Build system and release workflow modernization

Layer / File(s) Summary
Cython extension build script
setup.py.bck
Adds a backup setuptools/Cython script that reads pyproject.toml metadata, scans all .py files in the plugin package, compiles them into a single snakemake_executor_plugin_slurm._core extension with -O3 and linetrace=True, and calls setup() with derived install_requires and classifiers.
Release-please workflow modernized to v5
.github/workflows/release-please.yml
Updates release-please-action from v4 to v5, consolidates build-and-publish into the same job with conditional checkout@v6 and setup-python@v6 steps, replaces Poetry-based publish with python -m build and pypa/gh-action-pypi-publish@release/v1 authenticated via PYPI_TOKEN.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • snakemake/snakemake-executor-plugin-slurm#460: Both PRs involve dependency-management updates and touches to upgrade_dependencies.py and pyproject.toml (this PR relaxes throttler and adjusts formatting, while PR #460 adds/adjusts dependency-relaxation tooling).

Poem

🐇 Hop hop, goodbye old Black and flake8 so slow,
Ruff leaps in with pixi in tow!
The release-please bounces to version five,
While Cython builds sparkle—the magic's alive.
One tool to format, one tool to lint,
The migration is done in a jiffy, not a squint! ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 40.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main changes: refactoring CI to use pixi instead of Poetry, and switching to ruff/flake8 for code quality checks.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch refactor/ci_pixi

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@cmeesters cmeesters marked this pull request as ready for review June 19, 2026 08:09

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🧹 Nitpick comments (1)
setup.py.bck (1)

36-36: ⚡ Quick win

Avoid clobbering externally provided CFLAGS.

Line 36 overwrites existing build flags from CI/users. Append -O3 instead of replacing to keep upstream build controls intact.

Proposed fix
-os.environ["CFLAGS"] = "-O3"
+os.environ["CFLAGS"] = f'{os.environ.get("CFLAGS", "").strip()} -O3'.strip()
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@setup.py.bck` at line 36, The assignment at line 36 where
os.environ["CFLAGS"] is set to "-O3" overwrites any existing CFLAGS value that
may have been set externally by CI or users. Instead of using direct assignment
with the equals operator, append the "-O3" flag to the existing CFLAGS
environment variable. Retrieve the current CFLAGS value (defaulting to an empty
string if not set) and concatenate it with "-O3" before reassigning it back to
os.environ["CFLAGS"].
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/ci.yml:
- Around line 31-32: The "Check code" step in the workflow is using `poetry run
lint` which is incompatible with the Pixi-based job configuration. Replace the
`poetry run lint` command in the run field of the "Check code" step with the
equivalent Pixi command to run the lint task directly, using the format `pixi
run lint` to maintain consistency with Pixi's task runner.

In `@pyproject.toml`:
- Around line 42-48: The ruff configuration has redundant settings for
tests/test_scontrol_parsing.py where the file is listed in extend-exclude (which
completely removes it from linting) and also has a per-file-ignores entry for
E501 that never gets applied because excluded files skip linting entirely.
Choose one strategy: either remove tests/test_scontrol_parsing.py from the
extend-exclude list and keep the per-file-ignores entry to lint the file with
E501 ignored, OR remove the per-file-ignores entry for that file from the
tool.ruff.lint.per-file-ignores section and keep it fully excluded.

In `@setup.py.bck`:
- Around line 22-33: The current approach of combining all Python files from the
base_dir into a single Extension named snakemake_executor_plugin_slurm._core
will make submodules like utils, accounts, and partitions non-importable,
breaking imports throughout the codebase and tests. Instead of iterating through
all .py files and combining them into one extension with py_files, create a
separate Extension object for each submodule in the list (e.g., one Extension
for snakemake_executor_plugin_slurm.utils, one for
snakemake_executor_plugin_slurm.accounts, etc.) with each submodule's
corresponding Python file. This preserves the submodule import structure that
the codebase depends on.
- Line 47: The install_requires parameter in setup.py is using
list(dependencies.keys()) which extracts only the package names and drops all
version constraints from the dependencies dictionary. This allows unconstrained
versions to be installed, breaking compatibility. Replace the
list(dependencies.keys()) call to preserve the full dependency specifications
including their version ranges, either by using the appropriate dictionary
values or by combining package names with their version constraints in the
proper format expected by install_requires.

---

Nitpick comments:
In `@setup.py.bck`:
- Line 36: The assignment at line 36 where os.environ["CFLAGS"] is set to "-O3"
overwrites any existing CFLAGS value that may have been set externally by CI or
users. Instead of using direct assignment with the equals operator, append the
"-O3" flag to the existing CFLAGS environment variable. Retrieve the current
CFLAGS value (defaulting to an empty string if not set) and concatenate it with
"-O3" before reassigning it back to os.environ["CFLAGS"].
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 9f5bbc66-a549-4082-bd88-0d2f7803dda6

📥 Commits

Reviewing files that changed from the base of the PR and between cdb97d5 and f4a13a8.

📒 Files selected for processing (5)
  • .github/workflows/ci.yml
  • pixi.toml
  • pyproject.toml
  • setup.cfg
  • setup.py.bck
💤 Files with no reviewable changes (1)
  • setup.cfg

Comment thread .github/workflows/ci.yml Outdated
Comment thread pyproject.toml Outdated
Comment thread setup.py.bck Outdated
Comment thread setup.py.bck Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
.github/workflows/ci.yml (1)

10-57: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Declare explicit least-privilege permissions for the workflow token.

No permissions: block is defined, so default token scopes apply. Add explicit minimal permissions to reduce blast radius and satisfy policy checks.

Suggested fix
 name: CI
+permissions:
+  contents: read
 
 on:
   push:

If any job later needs extra scopes, elevate only in that specific job.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/ci.yml around lines 10 - 57, The workflow lacks an
explicit permissions block, which means the default token scopes are being used.
Add a top-level permissions block at the workflow level (before the jobs
section) that declares minimal required permissions. Set contents to read since
the workflow only needs checkout access. If any individual job later requires
elevated permissions, those can be specified at the job level to override the
workflow-level defaults while keeping other jobs restricted.

Source: Linters/SAST tools

🧹 Nitpick comments (2)
.github/workflows/release-please.yml (2)

34-39: ⚖️ Poor tradeoff

Consider using PyPI Trusted Publishing for enhanced security.

The current token-based authentication works, but PyPI's Trusted Publishing (OIDC) provides stronger security by eliminating long-lived secrets. This requires one-time configuration on PyPI to trust this GitHub repository/workflow.

To enable trusted publishing, you would:

  1. Configure the publisher on PyPI for this package
  2. Simplify the publish step:
      - name: Publish to PyPI
        if: ${{ steps.release.outputs.release_created }}
        uses: pypa/gh-action-pypi-publish@release/v1
        # No credentials needed - uses OIDC

This is optional but recommended when feasible.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/release-please.yml around lines 34 - 39, In the "Publish
to PyPI" step using the pypa/gh-action-pypi-publish@release/v1 action, remove
the `user` and `password` fields (which currently use `__token__` and
`secrets.PYPI_TOKEN`). After removing these authentication parameters, configure
PyPI Trusted Publishing by creating a trusted publisher in your PyPI project
settings for this GitHub repository and workflow to enable OIDC-based
authentication. The action will automatically use OIDC once the publisher is
configured on PyPI.

Source: Linters/SAST tools


12-12: Consider pinning actions to commit SHAs for enhanced supply-chain security.

While the action versions used (actions/checkout@v6, actions/setup-python@v6, googleapis/release-please-action@v5, and pypa/gh-action-pypi-publish@release/v1) are valid and current, pinning to full commit SHAs instead of version tags provides stronger security guarantees against tag tampering or unexpected updates.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/release-please.yml at line 12, Replace the version tags in
all GitHub Actions with their full commit SHAs for enhanced security.
Specifically, update googleapis/release-please-action from `@v5` to its full
commit SHA, and also pin actions/checkout, actions/setup-python, and
pypa/gh-action-pypi-publish to their respective full commit SHAs instead of
using version tags. This prevents potential tag tampering and ensures
reproducible, secure builds by explicitly specifying the exact commit being
used.

Source: Linters/SAST tools

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/ci.yml:
- Line 17: Replace all three occurrences of the mutable tag
`prefix-dev/setup-pixi@v0` with an immutable commit SHA reference in the GitHub
Actions workflow file. Specifically, at the three locations where `uses:
prefix-dev/setup-pixi@v0` appears (lines 17, 29, and 50), change the tag from
`@v0` to `@<commit-sha>` where commit-sha is the full commit hash of a specific
release from the setup-pixi repository. This prevents action supply-chain drift
by pinning to an immutable commit digest rather than a mutable version tag.

In @.github/workflows/release-please.yml:
- Around line 18-21: Add the `persist-credentials: false` parameter to the
`actions/checkout@v6` step to disable credential persistence and prevent
potential credential leakage. This should be added as a new line in the `with`
section alongside the existing `fetch-depth: 0` parameter.

---

Outside diff comments:
In @.github/workflows/ci.yml:
- Around line 10-57: The workflow lacks an explicit permissions block, which
means the default token scopes are being used. Add a top-level permissions block
at the workflow level (before the jobs section) that declares minimal required
permissions. Set contents to read since the workflow only needs checkout access.
If any individual job later requires elevated permissions, those can be
specified at the job level to override the workflow-level defaults while keeping
other jobs restricted.

---

Nitpick comments:
In @.github/workflows/release-please.yml:
- Around line 34-39: In the "Publish to PyPI" step using the
pypa/gh-action-pypi-publish@release/v1 action, remove the `user` and `password`
fields (which currently use `__token__` and `secrets.PYPI_TOKEN`). After
removing these authentication parameters, configure PyPI Trusted Publishing by
creating a trusted publisher in your PyPI project settings for this GitHub
repository and workflow to enable OIDC-based authentication. The action will
automatically use OIDC once the publisher is configured on PyPI.
- Line 12: Replace the version tags in all GitHub Actions with their full commit
SHAs for enhanced security. Specifically, update
googleapis/release-please-action from `@v5` to its full commit SHA, and also pin
actions/checkout, actions/setup-python, and pypa/gh-action-pypi-publish to their
respective full commit SHAs instead of using version tags. This prevents
potential tag tampering and ensures reproducible, secure builds by explicitly
specifying the exact commit being used.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: f49d0fd9-2dcc-455a-85ee-64b0169c82da

📥 Commits

Reviewing files that changed from the base of the PR and between f4a13a8 and f01b42c.

📒 Files selected for processing (5)
  • .github/workflows/ci.yml
  • .github/workflows/release-please.yml
  • snakemake_executor_plugin_slurm/__init__.py
  • tests/tests.py
  • upgrade_dependencies.py
✅ Files skipped from review due to trivial changes (3)
  • upgrade_dependencies.py
  • tests/tests.py
  • snakemake_executor_plugin_slurm/init.py

Comment thread .github/workflows/ci.yml
Comment on lines +18 to +21
- uses: actions/checkout@v6
if: ${{ steps.release.outputs.release_created }}
with:
python-version: "3.11"
fetch-depth: 0

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Add persist-credentials: false to prevent credential persistence.

The checkout step should disable credential persistence to prevent potential credential leakage through artifacts or subsequent steps.

Proposed fix
       - uses: actions/checkout@v6
         if: ${{ steps.release.outputs.release_created }}
         with:
           fetch-depth: 0
+          persist-credentials: false
🧰 Tools
🪛 zizmor (1.25.2)

[warning] 18-21: credential persistence through GitHub Actions artifacts (artipacked): does not set persist-credentials: false

(artipacked)


[error] 18-18: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)

(unpinned-uses)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/release-please.yml around lines 18 - 21, Add the
`persist-credentials: false` parameter to the `actions/checkout@v6` step to
disable credential persistence and prevent potential credential leakage. This
should be added as a new line in the `with` section alongside the existing
`fetch-depth: 0` parameter.

Source: Linters/SAST tools

release-type: python
token: ${{ secrets.RELEASE_PLEASE_PR_CI_TOKEN }}

publish:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The separation into a release-please job and a publish job was actually a good thing. I would suggest to keep that, while still switching to pixi for the publish job.

Comment thread pixi.toml
@@ -0,0 +1,30 @@
[project]

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is no need for a spearate pixi.toml. Pixi works fine with a pyproject.toml (see the docs). Pixi specific sections are just added as [tool.pixi.*].

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants