Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow specifying alternative paths for reading/writing flake locks #8042

Merged
merged 5 commits into from
Apr 3, 2023

Conversation

lheckemann
Copy link
Member

@lheckemann lheckemann commented Mar 13, 2023

Motivation

This allows having multiple separate lockfiles for a single project, which can be useful for testing against different versions of nixpkgs; it also allows tracking custom input overrides for remote flakes without requiring local clones of these flakes.

For example, if I want to build Nix against my locally pinned nixpkgs, and have a lock file tracking this override independently of future updates to said nixpkgs:

nix flake lock --output-lock-file /tmp/nix-flake.lock --override-input nixpkgs flake:nixpkgs
nix build --reference-lock-file /tmp/nix-flake.lock

Context

Hydra's current flake support is mediocre at best, and we think supporting alternative lock files would be extremely helpful to allow Hydra (and other CI systems!) to build jobsets against alternative input sets, update inputs (individually or all at once), etc.

Checklist for maintainers

Maintainers: tick if completed or explain if not relevant

  • agreed on idea
  • agreed on implementation strategy
  • tests, as appropriate
    • functional tests - tests/**.sh
    • unit tests - src/*/tests
    • integration tests - tests/nixos/*
  • documentation in the manual
  • code and comments are self-explanatory
  • commit message explains why the change was made
  • new feature or incompatible change: updated release notes

Priorities

Add 👍 to pull requests you find important.

This allows having multiple separate lockfiles for a single
project, which can be useful for testing against different versions of
nixpkgs; it also allows tracking custom input overrides for remote
flakes without requiring local clones of these flakes.

For example, if I want to build Nix against my locally pinned nixpkgs,
and have a lock file tracking this override independently of future
updates to said nixpkgs:

nix flake lock --output-lock-file /tmp/nix-flake.lock --override-input nixpkgs flake:nixpkgs
nix build --reference-lock-file /tmp/nix-flake.lock

Co-Authored-By: Will Fancher <[email protected]>
@knedlsepp
Copy link
Member

Awesome! Also fixes: #5673

src/libexpr/flake/flake.hh Outdated Show resolved Hide resolved
src/libcmd/installables.cc Outdated Show resolved Hide resolved
@@ -102,6 +102,28 @@ MixFlakeOptions::MixFlakeOptions()
}}
});

addFlag({
.longName = "reference-lock-file",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure if there is a real use case for a separate --reference-lock-file and --output-lock-file. With a unified --lock-file, the caller can always write the input lock file to that location to be overwritten.

Copy link
Member Author

@lheckemann lheckemann Mar 14, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like to keep the lock files of my projects in sync with that of my main deployment. With the separated options, I can use nix flake lock --reference-lock-file ~/deploy/flake.lock to keep them in sync (provided my deployment has a superset of the inputs of the project I'm updating).

It's also useful for updating individual inputs (but leaving everything else unmodified) without having a checkout of the whole repository, e.g. nix flake lock github:NixOS/patchelf --output-lock-file flake.lock --update-input nixpkgs or nix flake lock github:NixOS/patchelf --output-lock-file flake.lock --override-input nixpkgs github:nixos/nixpkgs/nixos-22.11. This is what I had in mind for Hydra, since it invokes multiple commands on the flake for a single evaluation and should use the same set of inputs each time.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

without having a checkout of the whole repository

Just for clarity: you mean checkout out the repository into a temporary directory because it will still land "checked out" in the nix store.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not necessarily in the future (#6530).

Co-authored-by: Eelco Dolstra <[email protected]>
@@ -102,6 +102,28 @@ MixFlakeOptions::MixFlakeOptions()
}}
});

addFlag({
.longName = "reference-lock-file",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we go for --output-lock-file, why not call it --input-lock-file?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"reference" seems more appropriate here, since the lock file may be completely foreign (e.g. I'm working on a project that uses nixos-22.11 and want it to use my deployment's lock file, so I run nix flake lock --reference-lock-file ~/deploy/flake.lock). This is very much my personal opinion though and if there's broad agreement that it should be called "input" I'd be willing to change it.

@edolstra
Copy link
Member

Can you add some tests? In particular, we need to test that --reference-lock-file requires --impure (since specifying a different lock file essentially modifies the flake).

@ElvishJerricco
Copy link
Contributor

@edolstra I wouldn't want --impure to be required. That enables a lot more impurity than I would be looking for if I just want to provide a different lock file. e.g. I still don't want builtins.currentTime to exist just because I want to change the lock file.

@lheckemann
Copy link
Member Author

lheckemann commented Mar 15, 2023

Yes, I'll have a look at adding some tests.

I don't think --reference-lock-file should require --impure though. It's not an ambient impurity (unlike the Flake registry for example, which doesn't even require --impure!), but one explicitly specified at invocation time and which can't be set globally (which is why I prefer this command-line arg approach over an environment variable as previously implemented by @colemickens).

Requiring disabling all purity would also be terrible for e.g. the Hydra use case, allowing environment variables or nixpkgs config to leak into eval (because restrict-eval has to be disabled for any non-github flake inputs to be supported, see #7098).

@ElvishJerricco
Copy link
Contributor

I think command line flags in general should be treated more like function arguments rather than impurities. They're explicit and require you to deliberately include them, as opposed to the implicit impurities like environment variables or out-of-tree files. So specifying a different lock file seems a lot more like a function argument than an impurity to me. It's effectively equivalent to making an ad-hoc parent flake and using the follows mechanism, which isn't considered impure.

@edolstra
Copy link
Member

@lheckemann Yeah I said that wrong. I didn't mean impure but that allow-dirty should be enabled. I.e. the top-level input must be considered dirty, in the same way as when you do nix build and the lock file gets updated without using --commit-lock-file.

@github-actions github-actions bot added the with-tests Issues related to testing. PRs with tests have some priority label Mar 19, 2023
Comment on lines +662 to +664
if (lockFlags.outputLockFilePath) {
throw Error("--commit-lock-file and --output-lock-file are currently incompatible");
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If output-lock-file ends up under the git repository it could be commited like flake.lock. Any none absolute path that flattened does not start with .. should be commitable.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This does not apply if symlinks are in use, and generating accurate commit messages would require reading the original lock file (if one already exists at the given path) as well as the reference lock file in order to generate an accurate commit message. Most of the value from this PR comes with the basic functionality and I'd welcome if someone else were to implement committing support in the future, but do not want to implement it myself at this time.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
with-tests Issues related to testing. PRs with tests have some priority
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants