From 184d7a8b99e2ff0e071fd2d4d50e1682c6522cbb Mon Sep 17 00:00:00 2001 From: Marnik Bercx Date: Wed, 22 Apr 2026 08:54:37 +0200 Subject: [PATCH] =?UTF-8?q?=F0=9F=90=9B=20Conda:=20Let=20activated=20envs?= =?UTF-8?q?=20win=20over=20`~/.local/bin`=20on=20PATH?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The `~/.local/bin` symlinks are meant as a convenience layer so that unpackaged binaries from each code env are reachable without activating anything, but they were shadowing the real env binaries after `workon`: (koopmans) max@qmobile:~$ which pw.x /home/max/.local/bin/pw.x (koopmans) max@qmobile:~$ echo $PATH /home/max/.local/bin:/home/max/.conda/envs/koopmans/bin:... The cause is ordering in `~/.bashrc`. The previous symlink task wrote an `export PATH="$HOME/.local/bin:$PATH"` block at end-of-file via `blockinfile` (default position), which runs AFTER the miniforge-managed `conda initialize` block. So conda would correctly swap in the env's `bin/` on activation, but the later `~/.local/bin` export then re- prepended itself and won every lookup. For binaries that are symlinks into the env this was a no-op; for binaries that exist in the env but NOT as symlinks (e.g. anything not listed in `bin_patterns`) it still looked right; but for anything symlinked from a DIFFERENT env it was wrong — `workon koopmans` still resolved `pw.x` to the `qespresso` env. Here we extract the `~/.local/bin` setup into a dedicated `local/tasks/setup-local-bin.yml` and run it from `playbook-build-dev.yml` once, before the conda install. The export block now uses `insertbefore: BOF` so it lands at the top of `.bashrc`, to be sure it lands before the conda init block that miniforge appends later in the file. After a login shell initialises, `conda activate` prepends the env bin and wins over `~/.local/bin`. Also drop the directory-create and block-management steps from `conda-env-install.yml`, since the base layer now guarantees both — the task is reduced to the symlink loop, which is the part that is actually per-env. --- local/tasks/conda-env-install.yml | 11 ----------- local/tasks/setup-local-bin.yml | 23 +++++++++++++++++++++++ playbook-build-dev.yml | 4 ++++ 3 files changed, 27 insertions(+), 11 deletions(-) create mode 100644 local/tasks/setup-local-bin.yml diff --git a/local/tasks/conda-env-install.yml b/local/tasks/conda-env-install.yml index 9b4c0e2..980d447 100644 --- a/local/tasks/conda-env-install.yml +++ b/local/tasks/conda-env-install.yml @@ -20,17 +20,6 @@ become_user: "{{ vm_user }}" when: bin_patterns is defined and bin_patterns | length > 0 block: - - name: "Create ~/.local/bin" - ansible.builtin.file: - path: "/home/{{ vm_user }}/.local/bin" - state: directory - mode: "0755" - - name: "Add ~/.local/bin to PATH in .bashrc" - ansible.builtin.blockinfile: - path: "/home/{{ vm_user }}/.bashrc" - marker: "## {mark} ANSIBLE MANAGED BLOCK (~/.local/bin)" - block: | - export PATH="$HOME/.local/bin:$PATH" - name: "Find binaries matching patterns" ansible.builtin.find: paths: "/home/{{ vm_user }}/.conda/envs/{{ conda_env }}/bin" diff --git a/local/tasks/setup-local-bin.yml b/local/tasks/setup-local-bin.yml new file mode 100644 index 0000000..9677cdd --- /dev/null +++ b/local/tasks/setup-local-bin.yml @@ -0,0 +1,23 @@ +--- +# Create ~/.local/bin and prepend it to PATH in .bashrc. +# The export is inserted at BOF so conda init (appended later by the miniforge +# installer) ends up AFTER it in .bashrc, letting conda env activation prepend +# its own bin/ and win on PATH resolution. + +- name: "Create ~/.local/bin" + become: true + become_user: "{{ vm_user }}" + ansible.builtin.file: + path: "/home/{{ vm_user }}/.local/bin" + state: directory + mode: "0755" + +- name: "Add ~/.local/bin to PATH in .bashrc" + become: true + become_user: "{{ vm_user }}" + ansible.builtin.blockinfile: + path: "/home/{{ vm_user }}/.bashrc" + marker: "## {mark} ANSIBLE MANAGED BLOCK (~/.local/bin)" + insertbefore: BOF + block: | + export PATH="$HOME/.local/bin:$PATH" diff --git a/playbook-build-dev.yml b/playbook-build-dev.yml index e4aba8e..8f22ead 100644 --- a/playbook-build-dev.yml +++ b/playbook-build-dev.yml @@ -122,6 +122,10 @@ ansible.builtin.import_role: name: marvel-nccr.slurm + - name: "Setup ~/.local/bin on PATH" + tags: [local-bin] + ansible.builtin.import_tasks: local/tasks/setup-local-bin.yml + - name: Install conda+mamba tags: [conda] ansible.builtin.import_role: