Skip to content

Use pixi to manage development conda environments#3044

Open
bouweandela wants to merge 24 commits intomainfrom
pixi
Open

Use pixi to manage development conda environments#3044
bouweandela wants to merge 24 commits intomainfrom
pixi

Conversation

@bouweandela
Copy link
Copy Markdown
Member

@bouweandela bouweandela commented Apr 17, 2026

Description

Switch to pixi for managing the development conda environments.

See ESMValGroup/ESMValTool#4407 for an extensive description and ESMValGroup/ESMValTool#3997 for further background.

Links to documentation:


Before you get started

Checklist

It is the responsibility of the author to make sure the pull request is ready to review. The icons indicate whether the item will be subject to the 🛠 Technical or 🧪 Scientific review.


To help with the number pull requests:

@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 17, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 96.15%. Comparing base (df77d1b) to head (112b87d).
⚠️ Report is 2 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #3044   +/-   ##
=======================================
  Coverage   96.15%   96.15%           
=======================================
  Files         270      270           
  Lines       15805    15805           
=======================================
  Hits        15198    15198           
  Misses        607      607           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@bouweandela bouweandela added the installation Installation problem label Apr 20, 2026
@bouweandela bouweandela marked this pull request as ready for review April 20, 2026 10:27
Copy link
Copy Markdown
Contributor

@valeriupredoi valeriupredoi left a comment

Choose a reason for hiding this comment

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

will be back 😁

Comment thread .github/workflows/run-tests.yml
Comment thread .github/workflows/run-tests.yml
Comment thread doc/quickstart/install.rst
Comment thread doc/conf.py
os.environ["ESMFMKFILE"] = f"{rtd_conda_prefix}/lib/esmf.mk"
os.environ["PROJ_DATA"] = f"{rtd_conda_prefix}/share/proj"
os.environ["PROJ_NETWORK"] = "OFF"

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.

I see the docs build nicely, so these can indeed be removed, but why are we removing them now - is it something to do with pixi?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Yes, as explained in the comment above, the conda environment used by the previous way of installing the environment on readthedocs was not activated. Pixi does not have this problem, so this code can be removed.

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.

I'd keep it somewhere somehow, just in case. I think the whole purge of conda-forge way of installing is a bit premature at this point in time, even if we have pixi in for end users- which is nice, I can already think of a few cases where pixi won't work, so I'd argue we still keep the old conda stashed somewhere, in case we have to use it. How, I need to think of that

Comment thread pyproject.toml
@valeriupredoi
Copy link
Copy Markdown
Contributor

hey @bouweandela a few points:

  • installing pixi from source via curl and install may be tricky for some systems, I think best bet is to point users to install it from conda-forge: though, having said that, my install + shell activation doesn't work:
(base) valeriu@valeriu-PORTEGE-Z30-C:~/ESMValCore$ pixi --version
pixi 0.67.0
(base) valeriu@valeriu-PORTEGE-Z30-C:~/ESMValCore$ pixi shell
 WARN Skipped running the post-link scripts because `run-post-link-scripts` = `false`
        - bin/.librsvg-pre-unlink.sh

To enable them, run:
	pixi config set --local run-post-link-scripts insecure

More info:
	https://pixi.sh/latest/reference/pixi_configuration/#run-post-link-scripts

WARNING: Did not detect successful shell initialization within 3 second(s).
         Please check on https://pixi.sh/latest/advanced/pixi_shell/#issues-with-pixi-shell for more tips.
er passphrase for /home/valeriu/.ssh/id_rsa_jasmin: 
Identity added: /home/valeriu/.ssh/id_rsa_jasmin (/home/valeriu/.ssh/id_rsa_jasmin)
Agent pid 963160
Enter passphrase for /home/valeriu/.ssh/id_rsa_cloud: 
valeriu@valeriu-PORTEGE-Z30-C:~/ESMValCore$ pixi config set --local run-post-link-scripts insecure
✅ Updated config at /home/valeriu/ESMValCore/.pixi/config.toml
valeriu@valeriu-PORTEGE-Z30-C:~/ESMValCore$ git status
On branch pixi
Your branch is up to date with 'origin/pixi'.

Untracked files:
  (use "git add <file>..." to include in what will be committed)
	.pixi/

nothing added to commit but untracked files present (use "git add" to track)
valeriu@valeriu-PORTEGE-Z30-C:~/ESMValCore$ pixi shell
WARNING: Did not detect successful shell initialization within 3 second(s).
         Please check on https://pixi.sh/latest/advanced/pixi_shell/#issues-with-pixi-shell for more tips.
er passphrase for /home/valeriu/.ssh/id_rsa_jasmin: 
Agent pid ...

Why is it putting .pixi dir in the source dir? I don't like that - can we add .pixi to gitignore then? Ideally I'd like it somewhere else anyway. And it starts sourcing my .bashrc - not liking that either. But more importantly, that shell never kicks in for me...

@valeriupredoi
Copy link
Copy Markdown
Contributor

valeriupredoi commented Apr 21, 2026

hey @bouweandela a few points:

* installing pixi from source via curl and install may be tricky for some systems, I think best bet is to point users to install it from conda-forge: though, having said that, my install + shell activation doesn't work:
(base) valeriu@valeriu-PORTEGE-Z30-C:~/ESMValCore$ pixi --version
pixi 0.67.0
(base) valeriu@valeriu-PORTEGE-Z30-C:~/ESMValCore$ pixi shell
 WARN Skipped running the post-link scripts because `run-post-link-scripts` = `false`
        - bin/.librsvg-pre-unlink.sh

To enable them, run:
	pixi config set --local run-post-link-scripts insecure

More info:
	https://pixi.sh/latest/reference/pixi_configuration/#run-post-link-scripts

WARNING: Did not detect successful shell initialization within 3 second(s).
         Please check on https://pixi.sh/latest/advanced/pixi_shell/#issues-with-pixi-shell for more tips.
er passphrase for /home/valeriu/.ssh/id_rsa_jasmin: 
Identity added: /home/valeriu/.ssh/id_rsa_jasmin (/home/valeriu/.ssh/id_rsa_jasmin)
Agent pid 963160
Enter passphrase for /home/valeriu/.ssh/id_rsa_cloud: 
valeriu@valeriu-PORTEGE-Z30-C:~/ESMValCore$ pixi config set --local run-post-link-scripts insecure
✅ Updated config at /home/valeriu/ESMValCore/.pixi/config.toml
valeriu@valeriu-PORTEGE-Z30-C:~/ESMValCore$ git status
On branch pixi
Your branch is up to date with 'origin/pixi'.

Untracked files:
  (use "git add <file>..." to include in what will be committed)
	.pixi/

nothing added to commit but untracked files present (use "git add" to track)
valeriu@valeriu-PORTEGE-Z30-C:~/ESMValCore$ pixi shell
WARNING: Did not detect successful shell initialization within 3 second(s).
         Please check on https://pixi.sh/latest/advanced/pixi_shell/#issues-with-pixi-shell for more tips.
er passphrase for /home/valeriu/.ssh/id_rsa_jasmin: 
Agent pid ...

Why is it putting .pixi dir in the source dir? I don't like that - can we add .pixi to gitignore then? Ideally I'd like it somewhere else anyway. And it starts sourcing my .bashrc - not liking that either. But more importantly, that shell never kicks in for me...

ah! It works now:

(ESMValCore) valeriu@valeriu-PORTEGE-Z30-C:~/ESMValCore$ esmvaltool version
Running esmvaltool executable from ESMValCore. No other command line utilities are available until ESMValTool is installed.
ESMValCore: 2.15.0.dev37+gb3905f59d

You gotta tell folks to not have anything that waits for a password in their .bashrc - that makes the shell init process wait more than the max 3 seconds.

@bouweandela
Copy link
Copy Markdown
Member Author

bouweandela commented Apr 22, 2026

Thanks for reviewing V!

ah! It works now:

I suspect you may have been on a different branch than the one from this pull request the first time you ran that command, because .pixi is added to .gitignore in this pull request. Does it work OK now?

And it starts sourcing my .bashrc - not liking that either.

As the name suggests, the command pixi shell starts a new shell. You could probably get around that by using the command pixi run with the --clean-env flag instead, e.g. pixi run --clean-env esmvaltool.

@valeriupredoi
Copy link
Copy Markdown
Contributor

(ESMValCore) valeriu@valeriu-PORTEGE-Z30-C:~/ESMValCore$ git status
On branch pixi
Your branch is up to date with 'origin/pixi'.

Untracked files:
  (use "git add <file>..." to include in what will be committed)
	.pixi/

nothing added to commit but untracked files present (use "git add" to track)
(ESMValCore) valeriu@valeriu-PORTEGE-Z30-C:~/ESMValCore$ vim .gitignore 
(ESMValCore) valeriu@valeriu-PORTEGE-Z30-C:~/ESMValCore$ git status
On branch pixi
Your branch is up to date with 'origin/pixi'.

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
	modified:   .gitignore

no changes added to commit (use "git add" and/or "git commit -a")

I put it in .gitignore correctly at the second call 😁

@valeriupredoi
Copy link
Copy Markdown
Contributor

note (am not sure how important it is) that a pip install -e .[develop] still works fine in a pixi shell - we still want to do that, for proper local development, but it does install some interesting packages that I've not seen before:

Successfully installed ESMValCore-2.15.0.dev38+gf8554ad53 httptools-0.7.1 uvloop-0.22.1 watchfiles-1.1.1 websockets-16.0

that don't show up in the pixi env:

(ESMValCore) valeriu@valeriu-PORTEGE-Z30-C:~/ESMValCore$ pixi list websockets
Error:   × No packages found in 'default' environment for 'linux-64' platform.

@bouweandela
Copy link
Copy Markdown
Member Author

It was already there, now you've added it a second time. Maybe it is because you ran pixi config set --local run-post-link-scripts insecure and that changed the file .pixi/config.toml which is versioned?

@valeriupredoi
Copy link
Copy Markdown
Contributor

It was already there, now you've added it a second time. Maybe it is because you ran pixi config set --local run-post-link-scripts insecure and that changed the file .pixi/config.toml which is versioned?

nope that was showing up as ungit before - leave it like that - twice is better 😁

@bouweandela
Copy link
Copy Markdown
Member Author

pip install -e .[develop] still works fine in a pixi shell - we still want to do that

There should be no need to do that

@valeriupredoi
Copy link
Copy Markdown
Contributor

As the name suggests, the command pixi shell starts a new shell. You could probably get around that by using the command pixi run with the --clean-env flag instead, e.g. pixi run --clean-env esmvaltool.

my point is that we need a bit of doc with this what you told me, or to tell folks not to have any shell init with passwords in their .bashrc otherwise pixi will moan

@valeriupredoi
Copy link
Copy Markdown
Contributor

pip install -e .[develop] still works fine in a pixi shell - we still want to do that

There should be no need to do that

it absolutely should be a need to do that when one wants to test if the package still builds well after changes to eg pyproject.toml or if you want to install the package in an eg module that will not load a pixi shell - think a central installation on an HPC

Comment thread doc/contributing.rst Outdated
@bouweandela
Copy link
Copy Markdown
Member Author

bouweandela commented Apr 22, 2026

After changes to pyproject.toml, one can test that things work as expected by e.g. running pixi lock or any of the other pixi commands, such as pixi shell or pixi run.

To create a module for an HPC, you will probably want to do the same as in the Dockerfile: clone the repo in the location where the module software should be, checkout the released version, create a pixi environment, and put the activation script (entrypoint without the esmvaltool command in the Dockerfile) somewhere it will be executed when the module is loaded.

@valeriupredoi
Copy link
Copy Markdown
Contributor

valeriupredoi commented Apr 22, 2026

To create a module for an HPC, you will probably want to do the same as in the Dockerfile: clone the repo in the location where the module software should be, checkout the released version, create a pixi environment, and put the activation script (entrypoint without the esmvaltool command in the Dockerfile) somewhere it will be executed when the module is loaded.

Not as straightforward as that: for one, Docker is not allowed on an HPC, two, Singularity comes with all manners of permission issues, and three -most important - a user will never have access to the pixi shell that an admin creates. forget about working with shells there, it's all paths to various bin dirs

@bouweandela
Copy link
Copy Markdown
Member Author

bouweandela commented Apr 22, 2026

Not as straightforward as that: for one, Docker is not allowed on an HPC, two, Singularity comes with all manners of permission issues, and three -most important -

I meant: "follow the same steps", not "use the container".. The steps are here:

RUN pixi install --frozen -e esmvalcore
RUN pixi shell-hook -e esmvalcore -s bash > /shell-hook
RUN echo "#!/bin/bash" > /app/entrypoint.sh
RUN cat /shell-hook >> /app/entrypoint.sh

Comment thread doc/quickstart/install.rst Outdated
@bouweandela
Copy link
Copy Markdown
Member Author

As the name suggests, the command pixi shell starts a new shell. You could probably get around that by using the command pixi run with the --clean-env flag instead, e.g. pixi run --clean-env esmvaltool.

my point is that we need a bit of doc with this what you told me

Added in 94f10e0

@valeriupredoi
Copy link
Copy Markdown
Contributor

Not as straightforward as that: for one, Docker is not allowed on an HPC, two, Singularity comes with all manners of permission issues, and three -most important -

I meant: "follow the same steps", not "use the container".. The steps are here:

RUN pixi install --frozen -e esmvalcore
RUN pixi shell-hook -e esmvalcore -s bash > /shell-hook
RUN echo "#!/bin/bash" > /app/entrypoint.sh
RUN cat /shell-hook >> /app/entrypoint.sh

just like Carroll Shelby told his chief mechanic that said she can come apart: one way to find out 😁 https://www.youtube.com/watch?v=5OfjrMWjrhs

@valeriupredoi
Copy link
Copy Markdown
Contributor

One thing I think you should mention is that people should not have multiple ESMValXXX dirs - and they have - lots of eg ESMValTool_something_somethingelse: since pixi is now local to the source code, and it's hefty ie ~2G for Core (prob 5G for Tool), disk space will soon start disappearing

@valeriupredoi
Copy link
Copy Markdown
Contributor

valeriupredoi commented Apr 22, 2026

One thing I think you should mention is that people should not have multiple ESMValXXX dirs - and they have - lots of eg ESMValTool_something_somethingelse: since pixi is now local to the source code, and it's hefty ie ~2G for Core (prob 5G for Tool), disk space will soon start disappearing

in this vein, how the heck does one create new named environments without duplicating the project ie the repo? Say I need an environment esmvalcore1 and another one esmvalcore2 that use the same base list of dependencies, but I want to further test in each of these?

@bouweandela
Copy link
Copy Markdown
Member Author

One thing I think you should mention is that people should not have multiple ESMValXXX dirs - and they have - lots of eg ESMValTool_something_somethingelse: since pixi is now local to the source code, and it's hefty ie ~2G for Core (prob 5G for Tool), disk space will soon start disappearing

Pixi avoids the problem by using hardlinks, so it only keeps one copy of a file, even if it's used in multiple places: https://pixi.prefix.dev/latest/workspace/environment/#de-duplication

@bouweandela
Copy link
Copy Markdown
Member Author

how the heck does one create new named environments without duplicating the project ie the repo?

Edit pyproject.toml, add the extra environment (plus any needed features) there and run pixi install -e name_of_environment: https://pixi.prefix.dev/latest/tutorials/multi_environment/

@valeriupredoi
Copy link
Copy Markdown
Contributor

One thing I think you should mention is that people should not have multiple ESMValXXX dirs - and they have - lots of eg ESMValTool_something_somethingelse: since pixi is now local to the source code, and it's hefty ie ~2G for Core (prob 5G for Tool), disk space will soon start disappearing

in this vein, how the heck does one create new named environments without duplicating the project ie the repo? Say I need an environment esmvalcore1 and another one esmvalcore2 that use the same base list of dependencies, but I want to further test in each of these?

ah! Found the solution - in pyproject.toml

[tool.pixi.environments]
default = { features = ["dev", "doc", "test"], solve-group = "default" }
esmvalcore = { solve-group = "default" }
# Environments for running tests with specific Python versions.
test-py312 = { features = ["py312", "test"], solve-group = "py312" }
test-py313 = { features = ["py313", "test"], solve-group = "py313" }
test-py314 = { features = ["py314", "test"], solve-group = "default" }
# Environment for testing R support
test-r = { features = ["test-r"], solve-group = "test-r" }

@valeriupredoi
Copy link
Copy Markdown
Contributor

valeriupredoi commented Apr 22, 2026

Ow man, you gonna get so many users (not technical ones, though) so confused with all these new procedures - they are still confused about using conda/mamba - pixi takes this one notch up the level of confusability. Pixi is a lot more under the hood technical than conda - I don't think our ESMValTool users will get used to it easily if they want to do the slightest bit of development, more than pixi shell and get cracking with diags after that

@valeriupredoi
Copy link
Copy Markdown
Contributor

we should think along these lines when we explain Pixi to our users (prob best to structure the docs too, or the UET in their Tutorial) - lifted from ChatGPT that makes a very solid point:

pixi is a lot more technical than conda, and I think non-technical users can struggle with it more than with conda, what do you think?

You’re not wrong—but it’s a bit more nuanced than “Pixi is harder.”

🧠 The core difference

  • Conda is designed to feel imperative:
    “run commands, get environment”

  • Pixi is more declarative:
    “define environment in a file, then use it”

That shift alone makes Pixi feel more “technical,” especially at first.


👍 Where Conda is easier for non-technical users

  • Very straightforward mental model:

    conda create -n myenv python=3.11
    conda activate myenv
  • No config file required

  • Immediate feedback, less abstraction

  • Widely taught (lots of tutorials, StackOverflow answers)

👉 For beginners or casual users, Conda is usually easier to start with.


🤔 Where Pixi feels harder

  • Requires understanding:

    • pixi.toml
    • features / environments
    • project-based workflow
  • Less “just run a command and go”

  • Errors can feel more “build-system-like” than user-friendly

👉 That does raise the barrier for non-technical users.


⚖️ But Pixi isn’t harder for no reason

Pixi is optimizing for things Conda struggles with:

  • Reproducibility (lockfiles that actually work reliably)
  • Project isolation (no mystery global envs)
  • Speed (much faster solves/installs)
  • Team workflows (commit pixi.toml and it just works)

So:

  • Conda = easier initial UX
  • Pixi = better long-term consistency

🎯 My honest take

  • For solo, non-technical users → Conda is usually the better fit
  • For teams, CI, reproducible research, dev workflows → Pixi quickly becomes nicer despite the learning curve

💡 Why Pixi feels more technical

It’s not just complexity—it’s where the complexity lives:

  • Conda hides complexity in commands and global state
  • Pixi exposes it in a config file

That’s great for engineers, but unfamiliar to beginners.


🧭 Practical compromise

A lot of people end up doing:

  • Use Conda for:

    • quick experiments
    • teaching
  • Use Pixi for:

    • projects that need to be shared/reproduced

@bouweandela
Copy link
Copy Markdown
Member Author

Learning something new is always hard, and learning a new technical skill is more annoying if it's not your main interest but rather something you want to get over with as quickly as possible with a minimal time investment. So yes, this will require some initial time investment and that may be frustrating to some, but I believe it will save our contributors time in the long run. No more waiting for solving environments will be an immediate time gain, and the much better reproducibility is very helpful when doing science.

While the observations above by ChatGPT above may be true in general, they are not for our project. Our contributors, at least the ones that want to change the dependencies, already need to understand two or more different configuration files: pyproject.toml for the Python dependencies and (multiple in the case of ESMValTool) environment.yml files for the conda-forge dependencies. Pixi simplifies that by making it possible to do all the configuration in a single file (pyproject.toml) with a single syntax.

One thing that we could do to make the transition easier is to do it at the upcoming workshop. Like that, we will be able to help out anyone who is there, either in person or online, immediately.

Copy link
Copy Markdown
Contributor

@valeriupredoi valeriupredoi left a comment

Choose a reason for hiding this comment

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

I agree with you, bud!

One thing that we could do to make the transition easier is to do it at the ESMValGroup/Community#273. Like that, we will be able to help out anyone who is there, either in person or online, immediately.

I think that's a good idea too! At any rate, very many thanks to you for doing this work, bud - excuse my constant nagging during the review process, I am always trying to find holes in the plot so we can fix them when we review, rather than when we have users barking at us 🐶

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

Labels

installation Installation problem

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants