netlify / build-image

This is the build image used for running automated builds
MIT License
496 stars 196 forks source link

Add Nix support #617

Open lambdadog opened 3 years ago

lambdadog commented 3 years ago

Essentially a follow-up on #187.

To reiterate the reasoning there (and shared in #251 when the Nix PR came up), Nix would be able to "wear several hats" for Netlify's build image.

It allows essentially infinite flexibility in builds, although it would largely be a power-user build tool in comparison to most of Netlify's other offerings. On the other hand, a well-designed Nix build would be able to afford a high level of granularity in rebuilding unchanged code.

It also addresses the issue with extending Netlify's build image further (and manually) for specific static site generators, instead leaving that ability in the hands of the user. It would be a drastic action, but you could likely remove every single dependency added to the build image and alternatively support it with Nix instead and lose no performance, except for power users who currently have to find their own (likely not performance-sensitive) workarounds in the first place.

Thorough caching support would have to interlink with Netlify's own internal infrastructure, so I'd personally be uncomfortable writing up a PR without consulting with Netlify employees to ensure solid caching -- to lack it would certainly increase build times -- but Nix support would frankly put Netlify head and tail ahead of every other JAMStack provider I'm aware of in the field of user flexibility.

edrex commented 2 years ago

Specifically, nix's new flakes support. Look for flake.nix which specifies all dependencies and how to build. See https://github.com/numtide/nix-unstable-installer#github-actions

I see flake.nix emerging as an alternative to docker for repeatable builds across languages.

sagikazarmark commented 2 years ago

I'd also love to see this. Flakes make portable build environments so much easier.

nomeata commented 2 years ago

Until there is official support, are there workarounds? Can I install nix as part of the netlify build command?

justinas commented 2 years ago

See nix-netlify-poc for a workaround using nix-portable. @nomeata

edrex commented 2 years ago

@justinas 404 priv?

justinas commented 2 years ago

@justinas 404 priv?

Sorry! Yup, just made the repo public.

nomeata commented 2 years ago

Neat! I guess the next step might be to add the nix store directory to what's cached by netlify somehow?

edrex commented 2 years ago

Maybe via a JS build plugin wrapper? Also, it looks like the cache dir is .netlify/cache/.

nomeata commented 2 years ago

Playing with the nix-portable work-around, and it’s neat that it works! With my page’s build dependencies, I spend 6min downloading stuff every time, that’s not great. Now hooking it up to a remote builder (nixbuild.net) to see if that gets it into a better shape, although I still observe a 4min delay where it presumably downloads nixpks and evaluates my build.

nomeata commented 2 years ago

Maybe simply export NP_LOCATION="$PWD/.netlify/cache" is enough? Trying that right now.

Or maybe not. Trying to use https://github.com/jakejarvis/netlify-plugin-cache. This requires me to add a packages.json file to the repo, really?

nomeata commented 2 years ago

Sigh, that doesn't work neither, it seems. I have

export NP_LOCATION="$PWD/.cache"

and

[[plugins]]
package = "netlify-plugin-cache"
  [plugins.inputs]
  paths = [".cache"]

but I get

11:17:56 PM: Attempted to cache: .cache ... but failed. :(
11:17:56 PM: Try setting the 'paths' input appropriately in your netlify.toml configuration.
11:17:56 PM: More details: https://jrvs.io/netlify-cache-usage

without further indication what went wrong.

edrex commented 2 years ago

maybe it's too big or something along those lines.

nomeata commented 2 years ago

It’s not thaaat big in my small test. Maybe dead symlinks are an issue, or stuff like that.

It’s probably too much of an hack anyways, even if it worked. If only using a remote builder would work without downloading all build dependencies first…