Spago2nix, any complete example to look at?

I’m trying to find a way to include a PureScript frontend in a project that uses Nix to build. On here I found references to both spago2nix and purs-nix and opted to try out the former first (the second being a flake put me off since I haven’t any knowledge of that yet). Setting up a dev environment with spago2nix was simple enough, but writing a derivation to be able to nix-build wasn’t.

I did write an issue asking for a more complete example in the project (issue #48) but I thought I’d ask here too in an attempt to widen the net.

Any suggestions or pointers will be much appreciated.

1 Like

I’m no Nix expert (even though I’d like to be one day!), but recently I got purs-tidy using spago2nix in easy-purescript-nix's derivation. I think that might be an okay place to start as it does the whole build cycle to compile and distribute an executable NodeJS script.

$ spago2nix generate 4 -- --config ./spago.dhall

This will give you a spago-packages.nix file you can import into your Nix project which will download and put the PureScript packages from their corresponding Git forge into your Nix store. The generated file also provides you some tools/functions for consuming those packages in your Nix derivation.

I’m not sure if you read some outdated text or just saw flake.nix in the repo (if it’s the former please do let me know), but purs-nix is compatible with nix stable as well :slightly_smiling_face:

Thanks, that got me a bit closer to the goal. I have to say though that your default.nix is much different from the instructions on the spago2nix site, I don’t think I’d ever have come up with that myself.

I ended up with the following

in stdenv.mkDerivation rec {
  pname = "my-frontend";
  src = lib.cleanSource ./.;
  version = "0.1";

  buildInputs = [
    spagoPkgs.installSpagoStyle
    spagoPkgs.buildSpagoStyle
    spagoPkgs.buildFromNixStore
    purescript
    spago
  ];

  unpackPhase = ''
    cp $src/{packages,spago}.dhall .
    cp -r $src/src .
    install-spago-style
  '';

  buildPhase = ''
    build-spago-style ./src/*.purs
    spago bundle-app --no-build --no-install
  '';

  installPhase = ''
    install -D -m644 ./index.js $out/srv/hu-frontend.js
  '';
}

It works fine locally but fails in CI with a slightly confusing error message when trying to bundle the app:

[error] Directory "/" is not accessible. Permissions {readable = True, writable = False, executable = False, searchable = True}
builder for '/nix/store/cv1xmms7j9mgsm08i0ydamjs00ah6yp5-my-frontend-0.1.drv' failed with exit code 1

I’m not sure what would make spago require more access to / than that. Am I missing something? Maybe there’s another way to bundle up an app?

I am aware that purs-nix is usable with nix stable as well. However, I’m not too hopeful that I’ll work out how to use it. The base is a flake and the instructions for setting it up seem geared towards getting a shell with tools while I want to set up a derivation that I can fit into my already existing project.

The main reason I built purs-nix actually was because I wanted an easy way to incorporate PureScript projects into bigger nix builds. The purs-nix command in the shell came later. For example, in purs-nix you can get the bundle for the module Main by simply using modules.Main.bundle {}. Perhaps I need to make this more clear in the README.

I’d be happy to help :slight_smile:

In my experience, spago doesn’t play very well with nix. I believe this error is caused by it trying to set up a global cache. There are flags to disable caching, I would try using them. If that doesn’t work you can set it so that it makes the cache inside the nix build I believe, but I can’t remember how off the top of my head.

edit (I read more): actually if you’re saying it works locally I might be wrong. When this happened to me it didn’t work locally. But maybe nix on you local machine has sandboxing turned off and on your CI it’s turned on?

1 Like

I went ahead and packaged purescript-tidy so people could compare the two approaches side by side. You can view it here.
Also, I now probably understand why you thought it was more oriented towards making a shell - For nix stable, I only give an example shell.nix. I’ll make a note to fix that :+1:
(also thanks to @toastal for exposing me to substituteInPlace)

General comments: While I like reading the version from the package.json, one of these packages at one time forgot to update their version in cabal file or package.json; as a result, I think kind of prefer overwriting the version from the git tag. This ruined my CI at one point, but I could be swayed either way though – it may not be what non-Nix users would expect. And with your merge request to easy-purescript-nix (regardless of it not being reviewed :frowning_face:), do we think maybe Flakes are a better endorsement in packaging? I kinda feel like manually updating pinned versions like this is tiresome and difficult to manage versus nix flake update.

Thanks @ursi , for providing a complete example.

I have to say though that I can’t follow it at all :disappointed: I’m not sure if it’s a result of purs-nix, but at a glance it’s really hard to see how to modify that example for another package.

1 Like

The comment about the global cache that @ursi made above was indeed correct. I added --global-cache skip to the arguments of spago bundle-app and now the CI service is happily building a bundle :smiley:

Thanks for all the help!

3 Likes

In case it helps, I have an example here lions-backend/default.nix at main · cideM/lions-backend · GitHub which builds a tiny PureScript snippet.