Skip to content
Open
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
31 changes: 25 additions & 6 deletions snakedeploy/scaffold_plugins/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,17 @@ def save_pyproject(pyproject):
# the python dependency should be in line with the dependencies
pyproject["project"]["requires-python"] = ">=3.11,<4.0"

# configure coverage
pyproject["tool"]["coverage"] = {
"report": {
"exclude_lines": [
"pass",
"\\.\\.\\.",
],
"fail_under": 90.0,
}
}
Comment on lines +68 to +77
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

pyproject["tool"] will raise KeyError if the initial pyproject.toml has no [tool] section.

At this point in execution the file hasn't been touched by any pixi command yet, so the [tool] key must already be present in the user's pyproject.toml. While pixi-generated manifests do include [tool.pixi], user-created files may not. The same fragility exists at line 103, but that executes after pixi has already modified the file.

🛡️ Proposed defensive fix
+        pyproject.setdefault("tool", {})
         pyproject["tool"]["coverage"] = {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@snakedeploy/scaffold_plugins/common.py` around lines 68 - 77,
pyproject["tool"] may not exist and will raise KeyError; before writing into
pyproject["tool"]["coverage"] (the block that sets "report" and "fail_under")
ensure pyproject has a "tool" dict by doing a safe default (e.g., if "tool" not
in pyproject: pyproject["tool"] = {}), then set pyproject["tool"]["coverage"] =
{ ... }; apply the same defensive check to the other place in this file that
directly accesses pyproject["tool"] so both spots guard against missing "tool".


save_pyproject(pyproject)

# add dependencies
Expand All @@ -79,8 +90,9 @@ def save_pyproject(pyproject):
"--feature",
"dev",
"ruff",
"coverage",
"pytest",
"pytest-cov",
"pyrefly",
Comment on lines +94 to +95
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

pyrefly is currently in early alpha — confirm stability expectations for scaffolded plugins.

Pyrefly is "currently under active development with known issues", and the announcement explicitly describes it as an alpha version. Every plugin generated by this scaffolding will adopt pyrefly as its type checker. If pyrefly introduces breaking CLI changes or produces noisy false positives in early plugin projects, it could be disruptive. Consider whether pinning a minimum version or noting the alpha status in generated documentation is warranted.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@snakedeploy/scaffold_plugins/common.py` around lines 94 - 95, The scaffold
currently includes "pyrefly" in the test/dev dependencies list (the string
"pyrefly"); update the scaffold to either pin pyrefly to a known working version
(e.g., "pyrefly>=X.Y.Z,<X+1.0.0") or remove it and instead add a clear note in
generated plugin docs/readme that pyrefly is alpha and optional; modify the
dependency list that contains "pytest-cov" and "pyrefly" accordingly and ensure
the generator code that writes README or templates emits the alpha-stability
warning so scaffolded plugins surface the risk to users.

"twine",
"build",
]
Expand All @@ -93,11 +105,19 @@ def save_pyproject(pyproject):
save_pyproject(pyproject)

sp.run(
["pixi", "task", "add", "--feature", "dev", "lint", "ruff check"],
["pixi", "task", "add", "--feature", "dev", "lint", "ruff check src tests"],
check=True,
)
sp.run(
["pixi", "task", "add", "--feature", "dev", "format", "ruff format src tests"],
check=True,
)
sp.run(
["pixi", "task", "add", "--feature", "dev", "typecheck", "pyrefly check src tests"],
check=True,
)
sp.run(
["pixi", "task", "add", "--feature", "dev", "format", "ruff format"],
["pixi", "task", "add", "--feature", "dev", "coverage-report", "coverage report -m"],
check=True,
)
Comment on lines +115 to +118
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Ruff S607 on line 116 is a false positive — no action required.

"pyrefly check" is a string argument passed to pixi task add, not a subprocess executable path. The process actually launched by sp.run is pixi itself (consistent with every other task-add call in this file). If ruff is run in CI and this causes a lint failure, suppressing it inline is the right fix:

🔇 Suppress false positive if needed
-        sp.run(
-            ["pixi", "task", "add", "--feature", "dev", "typecheck", "pyrefly check"],
+        sp.run(  # noqa: S607
+            ["pixi", "task", "add", "--feature", "dev", "typecheck", "pyrefly check"],
             check=True,
         )
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
sp.run(
["pixi", "task", "add", "--feature", "dev", "typecheck", "pyrefly check"],
check=True,
)
sp.run( # noqa: S607
["pixi", "task", "add", "--feature", "dev", "typecheck", "pyrefly check"],
check=True,
)
🧰 Tools
🪛 Ruff (0.15.1)

[error] 116-116: Starting a process with a partial executable path

(S607)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@snakedeploy/scaffold_plugins/common.py` around lines 115 - 118, Ruff S607 is
a false positive for the sp.run([... "pyrefly check"], ...) call; suppress it
inline by adding a noqa for S607 to the sp.run invocation (e.g., append a "#
noqa: S607" comment to the sp.run line or the statement) so the linter ignores
this specific warning while keeping the call unchanged.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

# First, find and check ci.yml.j2 for coverage references
fd "ci.yml.j2" --exec grep -n "coverage" {}

Repository: snakemake/snakedeploy

Length of output: 105


🏁 Script executed:

# Also search for any task-related references in common.py
fd "common.py" --path "*scaffold_plugins*" --exec wc -l {} \;

Repository: snakemake/snakedeploy

Length of output: 280


🏁 Script executed:

# Get a sense of what tasks are registered in common.py
fd "common.py" --path "*scaffold_plugins*" --exec grep -n "pixi.*task.*add" {} \;

Repository: snakemake/snakedeploy

Length of output: 280


🏁 Script executed:

# Find common.py in scaffold_plugins
find . -name "common.py" -path "*/scaffold_plugins/*"

Repository: snakemake/snakedeploy

Length of output: 105


🏁 Script executed:

# Read common.py to see all pixi task add calls
cat -n snakedeploy/scaffold_plugins/common.py | grep -A 2 "pixi.*task.*add"

Repository: snakemake/snakedeploy

Length of output: 626


🏁 Script executed:

# Get the full context around all pixi task add calls
rg "pixi.*task.*add" snakedeploy/scaffold_plugins/common.py -B 2 -A 2

Repository: snakemake/snakedeploy

Length of output: 611


🏁 Script executed:

# Also check the full line count and see the complete file structure
wc -l snakedeploy/scaffold_plugins/common.py

Repository: snakemake/snakedeploy

Length of output: 107


🏁 Script executed:

# Search for all task names being added, to get a complete list
rg "task.*add.*--feature" snakedeploy/scaffold_plugins/common.py | sed 's/.*--feature[^"]*"\([^"]*\)".*/\1/'

Repository: snakemake/snakedeploy

Length of output: 76


🏁 Script executed:

# Also check for test and check-build tasks
rg "(test|check-build|coverage)" snakedeploy/scaffold_plugins/common.py

Repository: snakemake/snakedeploy

Length of output: 574


🏁 Script executed:

# Read lines around task registrations to see the complete picture
sed -n '100,150p' snakedeploy/scaffold_plugins/common.py

Repository: snakemake/snakedeploy

Length of output: 1596


🏁 Script executed:

# Check if coverage-report task is added anywhere in the file
grep -n "coverage-report" snakedeploy/scaffold_plugins/common.py

Repository: snakemake/snakedeploy

Length of output: 133


🏁 Script executed:

# Let's check what ci.yml.j2 expects and the full context around coverage-report reference
sed -n '50,70p' snakedeploy/scaffold_plugins/templates/ci.yml.j2

Repository: snakemake/snakedeploy

Length of output: 156


🏁 Script executed:

# Find ci.yml.j2 file
find . -name "ci.yml.j2"

Repository: snakemake/snakedeploy

Length of output: 106


🏁 Script executed:

# Check the context around line 58 where coverage-report is referenced
sed -n '50,70p' ./snakedeploy/templates/plugins/ci.yml.j2

Repository: snakemake/snakedeploy

Length of output: 251


🏁 Script executed:

# Also check if there are any other coverage-report references
grep -n "coverage-report" ./snakedeploy/templates/plugins/ci.yml.j2

Repository: snakemake/snakedeploy

Length of output: 105


Remove the coverage-report task from ci.yml.j2 or register it in common.py.

The CI template (ci.yml.j2 line 58) references pixi run coverage-report, but common.py never registers this task via pixi task add. Coverage reporting is currently built into the test task (via --cov-report flags), but not exposed as a separate pixi task. This will cause the CI workflow to fail when attempting to run the non-existent coverage-report task.

Either add pixi task add coverage-report in common.py to expose the coverage output as a standalone task, or remove the coverage-report step from ci.yml.j2 if it's redundant with the test task.

🧰 Tools
🪛 Ruff (0.15.1)

[error] 116-116: Starting a process with a partial executable path

(S607)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@snakedeploy/scaffold_plugins/common.py` around lines 115 - 118, CI references
a pixi task named "coverage-report" but common.py doesn't register it, causing
the workflow to fail; either remove the coverage-report step from ci.yml.j2 or
register the task in common.py. To fix, add a pixi task registration in
common.py (similar to existing sp.run([... "pixi", "task", "add", ...]) calls)
that defines "coverage-report" and runs the pytest coverage reporting command
(the same flags used in the existing "test" task) so the CI step "pixi run
coverage-report" can execute; alternatively delete the "pixi run
coverage-report" step from ci.yml.j2 if you prefer to keep coverage only as part
of the "test" task.

Comment on lines 107 to 122
Copy link
Contributor

@coderabbitai coderabbitai bot Feb 22, 2026

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

CI failure: multiple lines exceed ruff's line-length limit.

The pipeline is failing because ruff format --check finds lines that need reformatting. Lines 108, 112, 116, and 120 all appear to exceed the 88-character default. The simplest fix is to run ruff format (or pixi run format) as the CI error message suggests, or break these into multi-line list form:

♻️ Proposed fix (multi-line style for all offending calls)
         sp.run(
-            ["pixi", "task", "add", "--feature", "dev", "lint", "ruff check src tests"],
+            [
+                "pixi",
+                "task",
+                "add",
+                "--feature",
+                "dev",
+                "lint",
+                "ruff check src tests",
+            ],
             check=True,
         )
         sp.run(
-            ["pixi", "task", "add", "--feature", "dev", "format", "ruff format src tests"],
+            [
+                "pixi",
+                "task",
+                "add",
+                "--feature",
+                "dev",
+                "format",
+                "ruff format src tests",
+            ],
             check=True,
         )
         sp.run(
-            ["pixi", "task", "add", "--feature", "dev", "typecheck", "pyrefly check src tests"],
+            [
+                "pixi",
+                "task",
+                "add",
+                "--feature",
+                "dev",
+                "typecheck",
+                "pyrefly check src tests",
+            ],
             check=True,
         )
         sp.run(
-            ["pixi", "task", "add", "--feature", "dev", "coverage-report", "coverage report -m"],
+            [
+                "pixi",
+                "task",
+                "add",
+                "--feature",
+                "dev",
+                "coverage-report",
+                "coverage report -m",
+            ],
             check=True,
         )

Note: The Ruff S607 warnings on these lines are false positives — the strings like "ruff check src tests" are arguments to pixi task add, not subprocess executable paths.

🧰 Tools
🪛 Ruff (0.15.1)

[error] 108-108: Starting a process with a partial executable path

(S607)


[error] 112-112: Starting a process with a partial executable path

(S607)


[error] 116-116: Starting a process with a partial executable path

(S607)


[error] 120-120: Starting a process with a partial executable path

(S607)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@snakedeploy/scaffold_plugins/common.py` around lines 107 - 122, Break the
long sp.run(...) calls so they don't exceed ruff's line-length: either run ruff
format (or `pixi run format`) to auto-fix, or manually rewrite each sp.run
invocation in common.py (the calls to sp.run that add pixi tasks for "lint",
"format", "typecheck", and "coverage-report") to use a multi-line list for the
arguments (e.g., put ["pixi", "task", "add", "--feature", "dev", "lint", "ruff
check src tests"] across several lines) so no line exceeds 88 chars; ensure you
preserve the exact argument order and quoting so the commands remain identical.

Choose a reason for hiding this comment

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

Should be fixed by #118.

Copy link
Contributor

Choose a reason for hiding this comment

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

@jonasfreimuth, thanks for the heads-up! I'll keep an eye on #118 to confirm the formatting is addressed there. Once that's merged (or cherry-picked into this branch), the ruff line-length violations should be resolved.

sp.run(
Expand All @@ -109,10 +129,10 @@ def save_pyproject(pyproject):
"dev",
"test",
"pytest "
f"--cov={package_name} "
f"--cov={package_name.replace('-', '_')} "
"--cov-report=xml:coverage-report/coverage.xml "
"--cov-report=term-missing "
"tests/tests.py",
"tests/test_plugin.py",
],
check=True,
)
Expand Down Expand Up @@ -157,7 +177,6 @@ def render_template(name, dest: Path):

(tests_path / "__init__.py").unlink(missing_ok=True)

render_template("setup.cfg.j2", Path("setup.cfg"))
render_template("release_please.yml.j2", workflows_path / "release-please.yml")
render_template("ci.yml.j2", workflows_path / "ci.yml")
render_template(
Expand Down
72 changes: 30 additions & 42 deletions snakedeploy/templates/plugins/ci.yml.j2
Original file line number Diff line number Diff line change
Expand Up @@ -6,65 +6,53 @@ on:
- main
pull_request:

env:
PYTHON_VERSION: 3.11

jobs:
linting:
format:
runs-on: ubuntu-latest
steps:
- name: Check out the code
uses: actions/checkout@v3
uses: actions/checkout@v6

- uses: actions/setup-python@v4
with:
python-version: {{ "${{ env.PYTHON_VERSION }}" }}
- name: Setup pixi
uses: prefix-dev/setup-pixi@v0

- name: Install poetry
run: pip install poetry
- name: Check formatting
run: pixi run format --check
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

git ls-files | grep -E "(ci\.yml|common\.py|pixi)" | head -20

Repository: snakemake/snakedeploy

Length of output: 143


🏁 Script executed:

find . -type f -name "*.py" -o -name "*.yml*" | grep -E "(ci|common|pixi)" | head -30

Repository: snakemake/snakedeploy

Length of output: 147


🏁 Script executed:

cat -n snakedeploy/templates/plugins/ci.yml.j2

Repository: snakemake/snakedeploy

Length of output: 1533


🏁 Script executed:

cat -n snakedeploy/scaffold_plugins/common.py

Repository: snakemake/snakedeploy

Length of output: 7298


🏁 Script executed:

find . -type f \( -name "pixi.toml" -o -name "pyproject.toml" \) | head -5

Repository: snakemake/snakedeploy

Length of output: 81


🏁 Script executed:

cat pyproject.toml

Repository: snakemake/snakedeploy

Length of output: 2054


🏁 Script executed:

# Search for any pixi documentation or examples in the repo
find . -type f \( -name "*.md" -o -name "*.txt" \) | xargs grep -l "pixi" 2>/dev/null | head -5

Repository: snakemake/snakedeploy

Length of output: 79


🏁 Script executed:

# Check CHANGELOG for any pixi-related information
cat CHANGELOG.md | grep -i pixi -A3 -B3 | head -50

Repository: snakemake/snakedeploy

Length of output: 439


🏁 Script executed:

# Search for how pixi tasks are used elsewhere in the codebase
rg "pixi run" --include="*.md" --include="*.yml" --include="*.yaml" --include="*.sh" -A2 -B2

Repository: snakemake/snakedeploy

Length of output: 506


🏁 Script executed:

# Search for how pixi tasks are used elsewhere in the codebase (corrected)
rg "pixi run" -A2 -B2

Repository: snakemake/snakedeploy

Length of output: 1658


🏁 Script executed:

# Search for pixi behavior documentation or comments
rg "pixi.*run.*-e|pixi.*environment" -A2 -B2

Repository: snakemake/snakedeploy

Length of output: 1068


🏁 Script executed:

# Check the release_please template to see how it handles environments
cat -n snakedeploy/templates/plugins/release_please.yml.j2

Repository: snakemake/snakedeploy

Length of output: 1546


🏁 Script executed:

# Search for any setup-pixi configuration with environments
rg "setup-pixi" -A5 -B5

Repository: snakemake/snakedeploy

Length of output: 3571


🌐 Web query:

pixi run task feature environment resolution default

💡 Result:

In Pixi, the environment used by pixi run is resolved roughly in this order:

  1. Per dependency in depends-on (highest precedence)
    If a task dependency is declared with an explicit environment, that dependency always runs in that environment—even if you pass --environment/-e on the CLI. [1]

  2. CLI --environment/-e <ENV>
    If you specify an environment on the command line, Pixi runs the task in that environment (unless overridden by rule #1 for dependencies). [2]

  3. Task-level default-environment
    A task can declare default-environment = "name"; Pixi uses that environment when you run the task, but it can still be overridden by -e (again, except for explicitly-environment-pinned dependencies). [1]

  4. Otherwise: the default environment
    If you don’t specify anything, Pixi runs in the default environment (and .pixi/envs/default is the conventional on-disk location). [3]

Notes on features ↔ environments:

  • An environment is defined as a collection of features in [environments]. [4]
  • Unless you opt out, the default feature is implicitly included in environments. (Dependencies in top-level [dependencies] are part of that default feature.) [4]
  • If a task is available in multiple environments, Pixi may prompt you to choose (or you can disambiguate with -e). [3]

Sources: Tasks & default-environment + dependency environment precedence [1]; pixi run CLI --environment option [2]; multi-environment behavior and selection [3]; manifest environment/feature rules [4].


🌐 Web query:

setup-pixi GitHub action environments parameter

💡 Result:

In prefix-dev/setup-pixi, the environments input lets you choose which Pixi environments to install (and cache) during the action run.

  • What to pass: one or more environment names (as defined in your pixi.toml / pyproject.toml [environments] table).
  • Format: space-separated list (YAML multiline >- is commonly used).
  • Default behavior: if you don’t set environments, the action installs/caches the default environment. Even if you later run another env with pixi run -e ..., caching/install done by the action is still for default unless you specify otherwise. [1] [2]

Examples:

# Install one env (e.g., in a matrix job)
- uses: prefix-dev/setup-pixi@v0.9.3
  with:
    environments: ${{ matrix.environment }}

[1]

# Install multiple envs in one job (space-separated)
- uses: prefix-dev/setup-pixi@v0.9.3
  with:
    environments: >-
      py311
      py312

[1] [2]


Add -e dev to all pixi run commands, or configure setup-pixi to install the dev environment.

Tasks (format, lint, typecheck, test) are registered only in the dev feature via --feature dev in common.py. By default, pixi run <task> executes in the default environment, which does not include the dev feature and therefore cannot find these tasks. Additionally, setup-pixi without explicit environments: dev only installs the default environment, meaning the dev environment won't even be available.

Use pixi run -e dev <task> to explicitly target the environment, or specify environments: dev in each setup-pixi step.

♻️ Suggested pattern for each job step
-      - name: Setup pixi
-        uses: prefix-dev/setup-pixi@v0
+      - name: Setup pixi
+        uses: prefix-dev/setup-pixi@v0
+        with:
+          environments: dev
-        run: pixi run format --check
+        run: pixi run -e dev format --check

Also applies to: 32, 44, 55

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@snakedeploy/templates/plugins/ci.yml.j2` at line 20, The CI step currently
runs "pixi run format --check" (and other pixi run invocations for lint,
typecheck, test) in the default environment which lacks the dev-feature tasks;
update each "pixi run ..." invocation to include the dev environment flag (e.g.
add "-e dev") or alternatively add "environments: dev" to the corresponding
"setup-pixi" steps so the dev environment is installed; search for the literal
"pixi run format --check" and other "pixi run" commands in the ci template
(ci.yml.j2) and make the change consistently across the steps referenced (lines
around the format/lint/typecheck/test steps).


- name: Determine dependencies
run: poetry lock
lint:
runs-on: ubuntu-latest
steps:
- name: Check out the code
uses: actions/checkout@v6

- uses: actions/setup-python@v4
with:
python-version: {{ "${{ env.PYTHON_VERSION }}" }}
cache: poetry
- name: Setup pixi
uses: prefix-dev/setup-pixi@v0

- name: Install Dependencies using Poetry
run: poetry install
- name: Check code
run: pixi run lint

- name: Check formatting
run: poetry run ruff format --check .

- name: Lint
run: poetry run ruff check .

testing:
typecheck:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3

- uses: actions/setup-python@v4
with:
python-version: {{ "${{ env.PYTHON_VERSION }}" }}
- name: Check out the code
uses: actions/checkout@v6

- name: Install poetry
run: pip install poetry
- name: Setup pixi
uses: prefix-dev/setup-pixi@v0

- name: Determine dependencies
run: poetry lock
- name: Check code
run: pixi run typecheck

- uses: actions/setup-python@v4
with:
python-version: {{ "${{ env.PYTHON_VERSION }}" }}
cache: poetry
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6

- name: Install dependencies
run: poetry install
- name: Setup pixi
uses: prefix-dev/setup-pixi@v0

- name: Run pytest
run: poetry run coverage run -m pytest
run: pixi run test -v

- name: Run Coverage
run: poetry run coverage report -m
run: pixi run coverage-report
7 changes: 0 additions & 7 deletions snakedeploy/templates/plugins/setup.cfg.j2

This file was deleted.

Loading