Skip to content

most dev flake inputs flake=false#4294

Open
mightyiam wants to merge 7 commits into
nix-community:mainfrom
mightyiam:dev-inputs-flake-false
Open

most dev flake inputs flake=false#4294
mightyiam wants to merge 7 commits into
nix-community:mainfrom
mightyiam:dev-inputs-flake-false

Conversation

@mightyiam
Copy link
Copy Markdown
Member

This sets flake=false for 5 out of the 8 dev flake inputs.

These 5 inputs seem to support being used as vanilla nix.

This eliminates the inputs.<name>.inputs.<name>.follows.<name> shenanigans.
It also eliminates the risk of failing to notice that an input has a new input.

Yes, we benefit from some flake features, such as purity, eval cache and input pinning.
But we don't have to use inputs as flakes if that incurs a cost and no benefit.

This is how I personally would like to consume flake inputs whenever they support it, including NixVim.
That is discussed in #4288
and is mostly decoupled from this change.

By the way, I tried nix flake check in this repo and ran out of memory.
What's the trick to succeed?

Copy link
Copy Markdown
Member Author

@mightyiam mightyiam left a comment

Choose a reason for hiding this comment

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

For what it's worth, I've seen worse lockfiles. I've had worse lockfiles. The follows situation here seems minimal. And I don't think that the approach I'm suggesting here is terribly popular, but I think it's based.

Comment thread flake/dev/flake.lock
Comment on lines -96 to -116
"gitignore": {
"inputs": {
"nixpkgs": [
"git-hooks",
"nixpkgs"
]
},
"locked": {
"lastModified": 1709087332,
"narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=",
"owner": "hercules-ci",
"repo": "gitignore.nix",
"rev": "637db329424fd7e46cf4185293b9cc8c88c95394",
"type": "github"
},
"original": {
"owner": "hercules-ci",
"repo": "gitignore.nix",
"type": "github"
}
},
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Here is one input less 🕺

Comment thread flake/dev/devshell.nix
{
imports = [
inputs.devshell.flakeModule
(inputs.devshell + "/flake-module.nix")
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Small price to pay?

Comment thread flake/dev/flake.nix
# NOTE: Use a different name to the root flake's inputs.nixpkgs to avoid shadowing it.
# NOTE: The only reason we specify a nixpkgs input at all here, is so the other inputs can follow it.
# TODO: Once nix 2.26 is more prevalent, follow the root flake's inputs using a "path:../.." input.
dev-nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Nixpkgs will likely never have its own flake inputs, so I didn't bother.

Comment thread flake/dev/flake.nix Outdated
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

flake-compat is also unlikely to have any of its own flake inputs, so I didn't bother.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

flake-compat documents flake = false as its recommended usage.

Comment thread flake/dev/flake.nix
Comment on lines 34 to 38
nuschtosSearch = {
# TODO: newer versions fail with: TimeoutError: The operation was aborted due to timeout
url = "github:NuschtOS/search/b6f77b88e9009bfde28e2130e218e5123dc66796";
inputs.nixpkgs.follows = "dev-nixpkgs";
};
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

This input does not seem to support being used as vanilla. It seems possible with a few lines, but I don't think that we should take that on, especially since it seems to pin its ixx input to some particular version that corresponds with something internal.

Comment thread flake/dev/flake.nix
# keep-sorted start block=yes newline_separated=yes
devshell = {
url = "github:numtide/devshell";
inputs.nixpkgs.follows = "dev-nixpkgs";
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

followses be gone!

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I'm not entirely sold on flake = false being worth it just for eliminating transitive follows.

Imagine the scenario where an input changes its inputs without us noticing; if we pull it as a flake, then we get their new inputs transitively. If we don't, then things potentially break.


If the reason we can set flake = false is that we are explicitly only using a part of the project that is designed to be used without flake inputs, then that's fine and should probably be documented in a comment.

# Don't pull flake inputs or evaluate outputs.
# We exclusively use the flake-module file.
flake = false;

Or perhaps a top-level comment along the lines of:

# Avoid `flake = true` when we do not need to evaluate flake outputs or fetch flake inputs.
# e.g. when we only import loose files.

TL;DR a) consider whether we're setting flake = false for the right reasons b) consider whether flake = false is fragile and may miss future transitive dependencies c) document why we enable or disable flake in general or for specific inputs.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I've added that single comment above the inputs attribute.

I've pointed out in this PR for each flake=false why it is okay.

I think that projects that expose truly loose files such as /flake-module.nix and /lib/default.nix are aware that users will use them and are not likely to turn them into functions that first take local context such as flake inputs. I prefer this risk over lockfile drift.

Comment thread tests/platforms/darwin.nix Outdated
{ config, ... }:
{
nixpkgs = {
source = self.inputs.dev-nixpkgs;
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

In the case of this input, the follows actually has a purpose. For what it's worth, I think that the passing of an explicit nixpkgs this way makes more sense, due to it being located here instead of in the flake.nix.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

We should prefer inputs.nixpkgs over inputs.dev-nixpkgs.

We enforce that they are the same FOD, but dev-nixpkgs is an implementation detail of the dev-lockfile.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I'll assume you are correct about what we should be doing, but in main, the nix-darwin input has inputs.nixpkgs.follows = "dev-nixpkgs";. Would you like a separate PR that changes that?

Copy link
Copy Markdown
Member

@MattSturgeon MattSturgeon May 15, 2026

Choose a reason for hiding this comment

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

in main, the nix-darwin input has inputs.nixpkgs.follows = "dev-nixpkgs";.

In main it is necessary, because of the way nix flake lock works; we cannot follow an input from the top-level lockfile so we introduced dev-nixpkgs as a workaround.

inputs.dev-nixpkgs is a mirror of the top-level flake's inputs.nixpkgs and should only be used when the workaround is necessary.

Or to quote the inline comment:

The only reason we specify a nixpkgs input at all here, is so the other inputs can follow it.

As of this PR, I believe the only input that needs dev-nixpkgs is nuschtosSearch.

Comment thread tests/platforms/darwin.nix
@mightyiam mightyiam marked this pull request as ready for review May 15, 2026 07:10
Comment thread tests/platforms/darwin.nix Outdated
lib,
}:
self.inputs.nix-darwin.lib.darwinSystem {
(import (self.inputs.nix-darwin + "/eval-config.nix")) {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Is it worth naming this function?

Suggested change
(import (self.inputs.nix-darwin + "/eval-config.nix")) {
let
darwinSystem = import (self.inputs.nix-darwin + "/eval-config.nix");
in
darwinSystem {

Is this a publicly documented usage pattern? I.e. the "official" way to consume nix-darwin without flakes?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Also, because flake inputs are already in-store objects, we could consider using:

"${self.inputs.nix-darwin}/eval-config.nix"

string interpolation.

IIUC, this shouldn't copy-to-store if the path is already a store-object.

Either approach is fine by me, though. You current approach is technically more robust at avoiding potential copy-to-store operations.

let
inherit (self.inputs.home-manager.lib)

inherit (import (self.inputs.home-manager + "/lib") { inherit lib; })
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

For readability, is it worth doing something like:

Suggested change
inherit (import (self.inputs.home-manager + "/lib") { inherit lib; })
hmLib = import (self.inputs.home-manager + "/lib") { inherit lib; };
inherit (hmLib)

?

Comment thread tests/platforms/hm-submodule-merge.nix Outdated
# To be clear, this is an upstream module system bug, this test validates our workaround.
let
inherit (self.inputs.home-manager.lib)
inherit (import (self.inputs.home-manager + "/lib") { inherit lib; })
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Same

Comment thread tests/platforms/hm.nix Outdated
lib,
}:
self.inputs.home-manager.lib.homeManagerConfiguration {
(import (self.inputs.home-manager + "/lib") { inherit lib; }).homeManagerConfiguration {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Same

@MattSturgeon
Copy link
Copy Markdown
Member

It's worth noting that the dev-lockfile you've worked on here is not user-facing.

It does not get evaluated by end-users unless they evaluate things like our test suite or dev shell.

@MattSturgeon
Copy link
Copy Markdown
Member

By the way, I tried nix flake check in this repo and ran out of memory.
What's the trick to succeed?

I believe this is documented in CONTRIBUTING.md.

IIRC, we still have our entire test suite in the checks output, and when nix flake check tries to evaluate it all in one go it runs out of memory.

We have a tests command in our dev shell that runs the test suite via chunked evals. We also chunk them up in our ci.buildbot output, which you could build using something like nix-fast-build. We should probably look into dropping tests that can't be evaluated from the flake checks output.

@mightyiam mightyiam force-pushed the dev-inputs-flake-false branch 2 times, most recently from 6c4c27f to d0b625b Compare May 15, 2026 15:31
Copy link
Copy Markdown
Member Author

@mightyiam mightyiam left a comment

Choose a reason for hiding this comment

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

I totally get that this whole change does not affect users.

Well, here are some changes. Please let me know whether I missed anything.

Comment thread flake/dev/flake.nix
devshell = {
url = "github:numtide/devshell";
inputs.nixpkgs.follows = "dev-nixpkgs";
flake = false;
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Exposes a vanilla /flake-module.nix, so we're good.

Comment thread flake/dev/flake.nix
url = "github:cachix/git-hooks.nix";
inputs.nixpkgs.follows = "dev-nixpkgs";
inputs.flake-compat.follows = "flake-compat";
flake = false;
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Exposes a vanilla /flake-module.nix, so we're good.

Comment thread flake/dev/flake.nix
home-manager = {
url = "github:nix-community/home-manager";
inputs.nixpkgs.follows = "dev-nixpkgs";
flake = false;
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Provides a /lib/default.nix that takes { inherit lib; } so we're golden.

Comment thread flake/dev/flake.nix
treefmt-nix = {
url = "github:numtide/treefmt-nix";
inputs.nixpkgs.follows = "dev-nixpkgs";
flake = false;
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Provides a vanilla /flake-module.nix so we're golden.

Comment thread flake/dev/flake.nix
Comment thread flake/dev/flake.nix
flake-compat.url = "github:NixOS/flake-compat";
flake-compat = {
url = "github:NixOS/flake-compat";
flake = false;
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

As @MattSturgeon pointed, flake-compat instructs declaring it with flake=false in its readme.

Comment thread flake/dev/flake.nix
# keep-sorted start block=yes newline_separated=yes
devshell = {
url = "github:numtide/devshell";
inputs.nixpkgs.follows = "dev-nixpkgs";
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I've added that single comment above the inputs attribute.

I've pointed out in this PR for each flake=false why it is okay.

I think that projects that expose truly loose files such as /flake-module.nix and /lib/default.nix are aware that users will use them and are not likely to turn them into functions that first take local context such as flake inputs. I prefer this risk over lockfile drift.

Comment thread flake/dev/flake.nix
nix-darwin = {
url = "github:lnl7/nix-darwin";
inputs.nixpkgs.follows = "dev-nixpkgs";
flake = false;
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Provides a vanilla /eval-config.nix so we're golden.

Comment thread tests/platforms/darwin.nix Outdated
{ config, ... }:
{
nixpkgs = {
source = self.inputs.dev-nixpkgs;
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I'll assume you are correct about what we should be doing, but in main, the nix-darwin input has inputs.nixpkgs.follows = "dev-nixpkgs";. Would you like a separate PR that changes that?

@mightyiam mightyiam force-pushed the dev-inputs-flake-false branch from d0b625b to 4d35f4d Compare May 16, 2026 09:01
@mightyiam mightyiam requested a review from MattSturgeon May 16, 2026 09:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants