example GitHub workflow for for building Spago statically#882
example GitHub workflow for for building Spago statically#882cdepillabout wants to merge 2 commits intomasterfrom
Conversation
|
@f-f This PR is a rough proof-of-concept of adding a GitHub Action job for building Spago statically. Currently, this PR just adds One thing to notice is that building the statically-linked |
|
@cdepillabout this looks amazing! ❤️ I have only one question: what would we do when upgrading Haskell dependencies? |
| nixpkgs-src = builtins.fetchTarball { | ||
| # This is one of the last commits from https://github.com/NixOS/nixpkgs/pull/169513. | ||
| # This commit is used because it is for the `haskell-updates` branch. | ||
| # Hydra builds a GHC for static linking on this branch, so we can get | ||
| # most dependencies from the NixOS cache. | ||
| url = "https://github.com/NixOS/nixpkgs/archive/999a0e87f9b1792e229c53602e80bda6dd52c105.tar.gz"; | ||
| sha256 = "1p0vgmdz884gld4p2zcdy7g0w7xznc4kxj80wf5pk2qdxicbnscy"; | ||
| }; |
There was a problem hiding this comment.
One problem with building from Nixpkgs like this is that we get the Haskell package versions in whatever commit of Nixpkgs we use. So with the above commit, we are building with mainly LTS-19, while the stack.yaml in this repo is still LTS-18.
While this discrepancy doesn't seem to cause any big problems now, it is at least unfortunate that we're not using the same exact package versions.
(haskell.nix has tools for generating a Haskell package set using versions from a stack.yaml and Stackage resolver, but haskell.nix comes with its own set of problems.)
There was a problem hiding this comment.
This is somewhat concerning - new lts versions might break behaviour (it has happened in the past), and we wouldn't notice this happening since we don't run tests for this binary.
So I'd like to at least be on the same lts and compiler version, even if the versions of the packages are slightly different.
Would it make sense to generate the package versions in the stack.yaml from the ones in Nixpkgs? (and of course check that they match in CI)
This would mean depending on whatever versions of packages coming from Nixpkgs, which is not the best (because we introduce a dependency) but it's pretty alright in the end. I assume we would/could tolerate some overrides in case we need them for the build to work.
There was a problem hiding this comment.
That's a good point, and a good reason for us to make sure we use the same package versions.
Would it make sense to generate the package versions in the stack.yaml from the ones in Nixpkgs? (and of course check that they match in CI)
I think this would make sense, although I don't know of any sort of tool that is able to generate a stack.yaml from a given Nixpkgs commit. I'm not sure how difficult it would be to write something like this.
For now, it would probably be the easiest to just manually keep the Nixpkgs Haskell package set and the resolver from the stack.yaml file the same. This PR uses Nixpkgs at commit NixOS/nixpkgs@999a0e8, which is included in PR NixOS/nixpkgs#169513. At the top of that PR, you can see there is a commit bumping the Nixpkgs Haskell stuff to LTS-19.4.
So maybe I could take a stab at bumping spago to LTS-19.4 (possibly in this PR, or a separate PR). Then we'd be using the same LTS version and GHC version in both stack.yaml and the Nixpkgs Haskell package set.
This would mean depending on whatever versions of packages coming from Nixpkgs, which is not the best (because we introduce a dependency) but it's pretty alright in the end.
I agree this is somewhat unfortunate. Ideally there would be a tool that could generate a Nixpkgs Haskell package set from a stack.yaml file, but we don't currently have something like that. (There used to be a tool https://github.com/input-output-hk/stack2nix that would do this, but it hasn't been maintained over the last few years.)
I assume we would/could tolerate some overrides in case we need them for the build to work.
Yeah, the Nixpkgs Haskell side is somewhat flexible, and it should be possible to add any overrides that we may need. I'd of course be happy to help out with this.
| spagoDrvFromCabal2nix = | ||
| final.haskell.lib.overrideCabal | ||
| (hfinal.callCabal2nix "spago" src {}) | ||
| (drv: { | ||
| doCheck = false; | ||
| postUnpack = (drv.postUnpack or "") + '' | ||
| # Spago includes the following two files directly into the binary | ||
| # with Template Haskell. They are fetched at build-time from the | ||
| # `purescript-docs-search` repo above. If they cannot be fetched at | ||
| # build-time, they are pulled in from the `templates/` directory in | ||
| # the spago source. | ||
| # | ||
| # However, they are not actually available in the spago source, so they | ||
| # need to fetched with nix and put in the correct place. | ||
| # https://github.com/spacchetti/spago/issues/510 | ||
| cp ${docsSearchApp_0_0_10} "$sourceRoot/templates/docs-search-app-0.0.10.js" | ||
| cp ${docsSearchApp_0_0_11} "$sourceRoot/templates/docs-search-app-0.0.11.js" | ||
| cp ${purescriptDocsSearch_0_0_10} "$sourceRoot/templates/purescript-docs-search-0.0.10" | ||
| cp ${purescriptDocsSearch_0_0_11} "$sourceRoot/templates/purescript-docs-search-0.0.11" | ||
|
|
||
| # For some weird reason, on Darwin, the open(2) call to embed these files | ||
| # requires write permissions. The easiest resolution is just to permit that | ||
| # (doesn't cause any harm on other systems). | ||
| chmod u+w \ | ||
| "$sourceRoot/templates/docs-search-app-0.0.10.js" \ | ||
| "$sourceRoot/templates/purescript-docs-search-0.0.10" \ | ||
| "$sourceRoot/templates/docs-search-app-0.0.11.js" \ | ||
| "$sourceRoot/templates/purescript-docs-search-0.0.11" | ||
| ''; | ||
| }); | ||
| in | ||
| final.haskell.lib.compose.generateOptparseApplicativeCompletion | ||
| "spago" | ||
| spagoDrvFromCabal2nix; |
There was a problem hiding this comment.
These overrides are basically taken directly from Nixpkgs.
In my opinion, this is basically the biggest problem. A few months ago, there was a PR that got static-linking working pretty reliably in Nixpkgs for Haskell executables: NixOS/nixpkgs#162374. With this PR, most Haskell executables can be built statically (at least with GHC-9). It seems like there are now enough people interesting in static-linking and cross-compilation in Nixpkgs that the Musl-related infrastructure is pretty solid. We also have some checks in our CI to make sure that statically-linking Haskell executables is working. This gives us Musl-built GHCs for static linking from the NixOS cache, so end users (or the However, the bigger problem is what do to when upgrading Haskell dependencies. The Haskell packages in Nixpkgs are generally set as the latest LTS release. There are times when this matches the LTS release that Spago is using, but sometimes Spago lags behind. In the past, this hasn't seemed to prove a big problem maintaining Spago in Nixpkgs, but like I said above, it would be unfortunate for non-Nix-using contributors to be faced with these kinds of errors. My suggestion would be to move forward with this PR as-is, but keep an eye out for these types of problems in the future. If the Nix-related stuff seems to be turning away too many contributors (or taking up too much of our time fixing things), then we could always consider removing it. |
| final.haskell.lib.overrideCabal | ||
| (hfinal.callCabal2nix "spago" src {}) | ||
| (drv: { | ||
| doCheck = false; |
There was a problem hiding this comment.
Since spago uses the network during tests, I've had to disable the tests here.
We end up not really testing this Nix-built spago binary, which is unfortunate. We could potentially add some simple tests to the build.yaml CI file, like running spago version, spago init, spago build, etc.
There was a problem hiding this comment.
We do have plans to be able to tolerate network loss - in that case we would refactor the test suite to be able to function without network (and introduce a section that explicitly exercises the network parts). That's some work though, so I think for now it might be easier to concentrate on matching the dependencies
|
I'll close this as we're about to switch to a PureScript-based Spago. |
Description of the change
wip
Checklist:
READMEP.S.: the above checks are not compulsory to get a change merged, so you may skip them. However, taking care of them will result in less work for the maintainers and will be much appreciated 😊