spease
spease

Reputation: 766

How best to create a resource-only package in nix?

For integration testing, I have to fetch some resources. My thinking is that it might work well to have an integration test data package. What I'm doing right now looks roughly like this:

pkgs.stdenv.mkDerivation {
  resource = [ (fetchResource { url = ...; sha256 = ...; }) ... ];
}

where fetchResources is just cutting down on boilerplate to use fetchzip.

Does nix have an appropriate way of packaging these kind of nonexecutable resources that would usually go in /usr/share ? Eg how bin, lib, Applications, or include(?) seem to each have hardcoded meanings that set things up properly in environment paths, etc.

It seems a bit overkill to end up referencing a different nix store path for each and every item downloaded - it seems like it would make more sense to generate one package with all the data. However, then I need a way to reference it from other packages, and I'd like to conform to existing conventions if possible.

Thanks.

Upvotes: 0

Views: 198

Answers (1)

Robert Hensing
Robert Hensing

Reputation: 7369

A store path per item downloaded does have the benefit of deduplicating the data when copying closures with e.g. a binary cache. So if it makes sense for your data you could write a derivation that references the individual unpacked resources by symlink. The number of store paths only becomes a consideration if your data items are really tiny or if you want to use them in dockerTools.buildLayeredImage where store paths have a more significant cost (as of 2020).

Derivations exist in roughly two flavors. One uses the FHS inside its store path, allowing its contents to be discoverable when used with buildInputs, nix-env -i, environment.systemPackages, etc. Alternatively, a derivation can put its data directly at the root of its output path, which is simple and convenient when you're only referencing the path in a script.

The choice depends on whether your integration test expects the data in an FHS location that makes it discoverable. Discovery usually works via some PATH- like environment variable, but you could also make it discoverable by using e.g. symlinkJoin to "overlay" the test and data so that relative paths work.

I'd generally recommend against such autodiscovery mechanisms in new applications, unless there's a reason, like compatibility with non-Nix installations. To make it easy to understand, you can hardly beat the simplicity of for example

checkPhase = "${testRunner}/bin/run-tests ${testData}";

Upvotes: 1

Related Questions