Tuist and Nix

As I read throughout the Nix documentation and pills, I keep thinking about how Tuist could leverage its functional and deterministic way of setting environments to improve the experience of developing apps for Apple platforms.

Deterministic environments running “tuist up”

The first idea that popped in my mind is using it from “tuist up” to set up the environment rather than delegating the installation to Homebrew. Homebrew is widely used in the community, but it does a poor at ensuring environments are reproducible and that installations don’t break when transitive dependencies are updates (e.g. macOS upgrades). Tuist up could install Nix, and use it to install packages defined in the Setup.swift file. The definition for the packages would be in our own repository of definitions, some of which could be contributed upstream to the official packages repository. It’d contain the definition for packages like Carthage, Swiflint, or SwiftGen. Thanks to this, all the developers will be using the same version of the tools and therefore getting consistent results when working on their projects. If we go down this path, we could deprecate Homebrew as a valid up task and and document how to contribute adding more packages to Tuist’s channel.

tuist-env delegating to Nix

The second idea is using Nix to manage installations of Tuist.
This is something that we are currently doing implicitly with tuist-env. When users run tuist, they are actually running tuist-env, which takes care of installing and calling the right version of Tuist. With the adoption of Nix we could take a different approach where we’d activate the right version of Tuist when cd’ing into directories. tuist-env would just be a user-friendly interface to Tuist.

Although tuist-env has served its purpose well, I’ve never been fully convinced of its implicit approach being a good idea. I implemented it because I didn’t want the user-experience to be worsened by using Homebrew, but after using Nix, I really feel it’s time to delegate that task and rather focus on Tuist.

I’m curious about your thoughts on this and if you think those are sensible ideas that we could adopt. As always, this is with the aim of making things deterministic and simple for the users.

My 2 cents on this… In my my experience, it is pretty complicated to install nix on macOS (at least Catalina). So if Tuist users, who are probably all macOS users, have to go through the hassle of solving the nix installation, I think that’d have a pretty negative impact on the user experience.

This is great idea, with Nix cocoapods could be served with ruby and Gems setup etc.
But I have similar concerns as @romain.
Nix is working on solution for the Catalina issue, maybe it’s good idea to wait until they make the installation easier.

Agree. It’d worse the experience if developers had to install it themselves, but the ideas is for Tuist to manage the installation. They’d never interact with Nix directly; they’d do it through Tuist, which would act as a proxy.

This is great idea, with Nix cocoapods could be served with ruby and Gems setup etc.

Exactly. No more issues caused by developers using different Ruby versions or struggling to install the right Ruby version in their environments.

Nix is working on solution for the Catalina issue, maybe it’s good idea to wait until they make the installation easier.

At Shopify that’s the script that we used and we have no issues so far. What the script does is using a mounted volume as a Nix store instead of using a folder in the system’s directory. Once enabled, Nix works as always.

This is a great idea @pepibumur!. Having interface in Setup.swift for interacting with a deterministic package manager would make preparing a stable dev environment a piece of cake :cake:
I don’t see anything holding us up in that regard. If we decide to handle Nix installation in Tuist, only thing I am concerned with (besides the installation of Nix as has been raised above) is how we would handle different version of Nix itself? Do we always depend on the latest/currently-installed version (and let user update nix by themselves if they desire)? Follow-up question: do we only take care of the installation of Nix or do we want to also update Nix for the user? I am not sure how much the Nix versions differ (I have started using it only recently) but I feel like it’s something to look into it.

Delegating Nix to tuist-env would save us a lot of logic. But maybe it’d make sense to first try it out in Setup.swift and see if we stumble upon any issues. But if all goes well, I don’t see why we could not get rid of tuist-env.

We could handle updates too. The good thing is that Nix release cadence is typically months, and they don’t seem to be breaking.

Delegating Nix to tuist-env would save us a lot of logic. But maybe it’d make sense to first try it out in Setup.swift and see if we stumble upon any issues. But if all goes well, I don’t see why we could not get rid of tuist-env .

Agree. I’d start with the Setup.swift and if the experiment works well, I’d then adopt it from tuist-env.