Replies: 7 comments 3 replies
-
Hi Elio many thanks for this very valuable input (and for all the issues you opened, we were able to improve the package quite a lot thanks to you already!)
I feel that this is kinda already addressed in the readme. We don’t cover the Nix installation part nor how to build and run the environment, because strictly speaking rix is about generating Nix expressions. We will add some clarification though #225
Yes, but this will not be easy to do. There is a fundamental difference in how renv works vs Nix. I’m not sure we will be able to completely emulate renv’s functioning. renv is focused on package versions, while Nix provides a snapshot of the whole ecosystem at a point in time.
I think this needs clarification in the documentation. The way rix works now, users should not focus on package versions. The "pkg@version" syntax is there as a convenience and only for archived packages. But the implementation is not the best and it could be made more robust.
This definitely needs clarification in the documentation: #223
Nix environment get built in an isolated sandbox, but at run time, they have access to everything. Try for example
This is due to the above: lubridate was installed in the system library, even if you ran
I don’t think that having commands that are run interactively are good way to manage Nix environments.
Yes, we weren’t aware of this, but these older versions cannot be built using
Indeed, R 4.0.1 is not available: https://b-rodrigues.github.io/rix/reference/available_r.html
Here again, it is likely due to some interference with your current Rstudio. But it is still surprising though, I cannot reproduce this. Can you post the generated
It is likely that you have ggplot2 in your user/system library.
As above, this is very likely because ggplot2 is in the user library.
Did you call
Yeah, we need a way to warn the user, but it’s not always possible to know beforehand if the environment is going to build. It can happen that the package is simply broken on Nix’s side.
Yes, the snapshot model is the right way to look at it. But separate Nix environments are isolated from each other. I think a lot of the issues you had was because you already had an R user library and this one is accessible unless you call
That is a good point, we need to do some rephrasing. A graph could be useful to show what the ideal Nix workflow is.
Definitely! We need to think how to do that, maybe we could re-use renv::dependencies() to get everything.
Thanks, we’ll have to see what is possible, but there’s definitely more work needed! Many thanks once again for this review, it will greatly improve the package and hopefully the first-time experience of future new users! 😃 |
Beta Was this translation helpful? Give feedback.
-
# This file was generated by the {rix} R package v0.7.1 on 2024-06-28
# with following call:
# >rix(r_ver = "1e3deb3d8a86a870d925760db1a5adecc64d329d",
# > r_pkgs = NULL,
# > system_pkgs = NULL,
# > git_pkgs = NULL,
# > ide = "rstudio",
# > project_path = ".",
# > overwrite = TRUE,
# > print = TRUE)
# It uses nixpkgs' revision 1e3deb3d8a86a870d925760db1a5adecc64d329d for reproducibility purposes
# which will install R version latest.
# Report any issues to https://github.com/b-rodrigues/rix
let
pkgs = import (fetchTarball "https://github.com/NixOS/nixpkgs/archive/1e3deb3d8a86a870d925760db1a5adecc64d329d.tar.gz") {};
system_packages = builtins.attrValues {
inherit (pkgs)
R
glibcLocales
nix;
};
in
pkgs.mkShell {
LOCALE_ARCHIVE = if pkgs.system == "x86_64-linux" then "${pkgs.glibcLocales}/lib/locale/locale-archive" else "";
LANG = "en_US.UTF-8";
LC_ALL = "en_US.UTF-8";
LC_TIME = "en_US.UTF-8";
LC_MONETARY = "en_US.UTF-8";
LC_PAPER = "en_US.UTF-8";
LC_MEASUREMENT = "en_US.UTF-8";
buildInputs = [ system_packages ];
} This crashes RStudio even with the Also, running that with
I'm trying to reproduce. Building and now installing data.table inside nix and after successfully installing, now it's telling me that
I think the strong comparison with Docker + renv gave me the wrong idea. Things like "You can use rix and Nix to replace renv and Docker with one single tool" gave me the impression that they were fairly equivalent. Maybe it would be better to use a language that highlight the unique nix approach, something like "With renv you need to lock packages to specific versions, nix takes another approach, allowing you to define use snapshots of R and its package ecosystem".
Very likely. My suggestion would be to use |
Beta Was this translation helpful? Give feedback.
-
By using |
Beta Was this translation helpful? Give feedback.
-
Hi again @eliocamp many thanks once again for all your input. It did keep us busy! 😄 If you wish, you could give 0.8.0 a try we believe the experience should be smoother now! 👍 |
Beta Was this translation helpful? Give feedback.
-
I'm reading the documentation now and I think it's much more clear. I liked this line in particular:
This made things click much better for me. Nix doesn't generate a new environment, it adds stuff on top of your existing environment. Good stuff. |
Beta Was this translation helpful? Give feedback.
-
Hi Elio I'm curious, have you been using rix these past months? How has your experience been? |
Beta Was this translation helpful? Give feedback.
-
Not really. I haven't started a new project yet and I couldn't install nix on the HPC that I'm using now. |
Beta Was this translation helpful? Give feedback.
-
Chronicle
Documentation is very thorough. Vignettes are super useful. However they are a bit too verbose at the start. I would've preferred a quick start vignette with all the steps I need to get things running. Like
Right now I had to reach the "e" vignette, that I reached from a link in "c" to get an RStudio window running on nix.
Coming from renv, I feel that a migration tool would be absolutely fantastic. I see that this was mentioned in #5.
I tried to reproduce one of my projects environments recorded using renv to nix. This involved getting the R version, package versions and git information for those packages installed from git(hub). I found a few friction points. Nix requires the branch name, which is not recorded by renv (#209), and it cannot install current package versions if specified as "pkg@version" (#210). Eventually those two issues prevented me from being able to build the environment.
I decided to try something else and creating a barebones environment and installing packages there. My idea was to simulate how I usually work with a project with renv. Write code, explore data and add packages as I needed them. I then ran into the surprise that the environment wasn't as isolated as I though. Installing packages failed immediately because compilation was trying to use
ccache
, which I had activated in my local Makevars file. I was surprised that nix's R installation was reading those files, as I expected it to work more or less like a Docker container (#211).This seems like a weakness in terms of reproducibility. It means that potentially a lot of the user's environment is leaking into the nix installation.
I removed the
ccache
stuff from my Makevars and run nix shell again. This time I could install lubridate without problem. Then I shut down the shell and open it up again. Strangely, lubridate was still installed. Again, I had though that the nix environment would be like a Docker image, running from scratch every time. I was very surprised that this wasn't the case. This seems also like something that might impair reproducibilty. An user might feel confident that they are working in a reproducible environment when in reality they might have inadvertently installed a package interactively and thrown all reproducibility out the window without them knowing!I tried to rebuild the environment with
nix-buil
to get back to the "pure" environment, but that still had lubridate installed. Again, I had though thatnix-buil
would rebuild the whole environment and start from a blank slate. Apparently not! I deleted theresult
file and rannix-build
again; lubridate is still there.So at this point I'm not sure how to go back to the original environment. Maybe there should be a
rix::clear()
or something like that that.Created a new nix environment using a different r version (4.0.0 and 3.6.3).
nix-build
failed, however, with this error (#213):4.0.1 also failed with a different error (
Error in get_latest(r_ver) : The provided R version is likely wrong.
).Build with
r_ver = "latest"
andnix-build
succeeded, but when I started RStudio, it crashed because it couldn't fine GLIBC. (#214)R seemed to run fine, though.
At this point I realised that maybe lubridate kept creeping in because I was loading a project that used renv and it had been installed in the project library. Let's start fresh in an empty directory. Then install ggplot2. I close nix-shell, boot it up again, and ggplot2 is still there. re-run
nix-build
... ggplot2 is still there. So, again, how do I come back to my original environment if I install a package inside it?Let's try one last thing. Create a new folder and build the same nix config. I go into the shell and.. ggplot2 is still there! 😯 So if I build two projects with the same nix config, they share state?! That is very surprising. This would mean that if I start to work in two projects using the same base configuration, their libraries are shared! If I accidentally install a package in one project, I will affect both projects.
One thing I haven't tried is
rix::rix_init()
which apparently helps to isolate the projects. I run the command in the second project. Building and running the shell opens a session with ggplot2 still installed. Let's install data.table and see if it affects the original project. The package is still there after a rebuild; no surprise there. Run the original project... and data.table is there. So even withrix_init()
both projects are sharing the library.Summary
Ok, all of the above has been rambly and borderline incoherent because I was writing in sequence as I experienced things. So let's write some summary of all that mess.
First, I love that the package makes it so easy to create these nix incantations. Specify the R version, packages and whatnot and quickly boot up a working (and disposable) environment. When it works, it feels like magic. The potential of
with_nix()
is enormous, I think. Imagine being able to run arbitrary versions from particularly hard-to-install package from your R session without having to modify your whole setup. Awesome.But "when it works" is doing a bit of heavy lifting, because it seems that creating Frankenvirionments with arbitrary packages doesn't always work 100%. rix makes it easy to create any nix config, even if it's not really valid, like those that refused to "build" or the issues with RStudio and glibc. Those are probably bugs that can be ironed out in the future, though.
Specifically about nix, I have to admit that I'm more confused that before. I though that nix was roughly equivalent to using Docker + renv but that equivalence is clearly the wrong mental model. Unlike Docker, rix "environments" are not isolated, as they read and use configuration files and even whole applications from the local installation. Unlike Docker, they are not "memory-less", as packages installed "inside" nix carry over not only across sessions in the same project, but are shared between projects. This is also unlike renv. Also unlike renv, it doesn't seem to be prepared to pin specific package versions. Rather it seems that you're supposed to use a snapshot ("revision"? ) of the whole R ecosystem that is tied to an R version.
Part of my confusion might have to do with my own limitations and lack of knowledge, but I think that, while the package documentation goes into a lot of detail into some of the technical intricacies nix, it's missing a concise bird's-eye view and a concise description of the recommended workflow (the Docker and renv comparisons might even promote the wrong mental model). I think the Workflow section of the renv website is a good example. In just three paragraphs and a graph, it outlines the lifecycle of an renv project and the commands one needs to run to make (most) things work.
Nix also feels like a very complex and powerful system that has a lot of gotchas and potential foot-guns (losing reproducibilty by installing packages manually, for example). So I think for beginners (like me) it would be super helpful to have more safeguards and automation. Utilities to discover all needed dependencies of a project (like renv does) so I don't need to write them manually would be super useful. A function that sets up a project with all the recommended bells and whistles (like
rix_init()
) that automatically makes nix work as a fully isolated, project-specific environment. A function that actually re-builds the environment from zero and is able to rescue a fucked-up environment. Some way of warning the user when they try to install a package from inside nix (maybe a shim toinstall.packages
that warns/prevents installation, or changing the package library permissions to read-only, or even something that automatically adds a package to the nix expression when trying to install from inside nix).Beta Was this translation helpful? Give feedback.
All reactions