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

[RFC 0144] Versioned Flake References #144

Closed
wants to merge 5 commits into from
Closed

[RFC 0144] Versioned Flake References #144

wants to merge 5 commits into from

Conversation

figsoda
Copy link
Member

@figsoda figsoda commented Mar 19, 2023

Summary

Flake references can have a special placeholder that will specify the version
requirement of the flake, which nix flake update can use to update the pin to
the latest version compatible with the version specification. A new Nix
command, nix flake upgrade will upgrade the version requirement in
flake.nix to the latest possible version without regard to compatibility.

Rendered

@nixos-discourse
Copy link

This pull request has been mentioned on NixOS Discourse. There might be relevant details there:

https://discourse.nixos.org/t/rfc-0144-versioned-flake-references/26502/1

@alyssais
Copy link
Member

I'm not sure it makes sense to have RFCs for modifications to flakes, when flakes itself is still experimental and pending an RFC? (Previously) It might be better to just discuss with the Nix developers.

@Profpatsch
Copy link
Member

It was only a matter of time.

@figsoda
Copy link
Member Author

figsoda commented Mar 20, 2023

@edolstra @roberth What do you think?

I feel that this proposal would benefit from being an RFC, but if it fundamentally shouldn't be, feel free to close this and I can turn this into an issue in the nix repo.

@roberth
Copy link
Member

roberth commented Mar 20, 2023

would benefit from being an RFC

Unlike the first flakes RFC, this one has a reasonable scope. I feel like this RFC could provide a good centerpoint for the discussion of such a feature.

@figsoda do you plan to implement this feature yourself? An issue in the repo could serve a complementary role, such as for discussion of implementation work for example. We have an RFC label :)

@Profpatsch it's not clear to me what you are referring to. Could you elaborate?

@7c6f434c
Copy link
Member

Unlike the first flakes RFC, this one has a reasonable scope. I feel like this RFC could provide a good centerpoint for the discussion of such a feature.

Well, another question is which of the assumptions about flakes might become complicated issues in the next attempt to perform stabilisation through RFC. (The current plan might avoid all of them; but RFCs often get large rewrites during the discussion)

@vcunat
Copy link
Member

vcunat commented Mar 20, 2023

I'd rather add some --flag(s) to the update sub-command instead of adding upgrade?

@figsoda
Copy link
Member Author

figsoda commented Mar 20, 2023

do you plan to implement this feature yourself?

no, since I don't know C++

@thufschmitt
Copy link
Member

I don't really have an opinion whether that change could be a good one for Nix or not. However, since this looks like it could be easily implemented outside of Nix, I'd strongly suggest doing so first so that everyone can judge the usefulness. It would be much faster for a first version, and that would make the case much stronger. Especially since the main concern right now with Flakes is getting them stabilized, which goes against adding extra features on top of them in the short term.

@figsoda
Copy link
Member Author

figsoda commented Mar 20, 2023

I can work on a proof of concept when I get time

@shlevy
Copy link
Member

shlevy commented Mar 21, 2023

How would this be implemented outside of nix? Doesn't it change the schema of the inputs of flake.nix?

@shlevy
Copy link
Member

shlevy commented Mar 21, 2023

I like the idea, but think versions should be in flake.nix and not use SCM tags.

@figsoda
Copy link
Member Author

figsoda commented Mar 21, 2023

How would this be implemented outside of nix? Doesn't it change the schema of the inputs of flake.nix?

I can write a preprocessor that expands the placeholders

I like the idea, but think versions should be in flake.nix and not use SCM tags.

How would nix be able to find the version without fetching every single tag?

rfcs/0144-versioned-flake-references.md Outdated Show resolved Hide resolved
Comment on lines +60 to +61
A new Nix command, `nix flake upgrade`, will edit `flake.nix` and upgrade all
the version placeholders in the inputs. A new flag, `--upgrade-input` will
Copy link
Member

Choose a reason for hiding this comment

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

Upgrading flake.nix in-place is not really an option since we don't have the ability to do that. But I also don't see why it's necessary. nix flake update can simply update to the latest versions that are consistent with the version placeholders. At most, we want a flag to nix flake update to allow/disallow major upgrades that wouldn't be semantically compatible.

Choose a reason for hiding this comment

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

If a flag were to temporarily ignore semantic compatibility, wouldn't that introduce some weird behaviour? Wouldn't the update behaviour on subsequent uses (without the flag) be to downgrade to a compatible version, thus defeating the purpose of initially using the flag? The idea here is to permanently alter the semver to accept the latest version as a convenience (so the user doesn't need to track down the latest tags of every input). I can't see any way of doing that (without potentially confusing behaviour) but inplace changes to flake.nix.

Alternatively, we could have a command/flag which would report the latest tags of the inputs (similar to how update reports lock file changes). This way there's no need to edit flake.nix inplace and the user gets the necessary information at once instead of playing tag whack-a-mole. It's less powerful but still works to make version tracking much less annoying which, I think, is the ulterior motive of this RFC.

- Not adding the feature, manually update the flake references

# Unresolved questions
[unresolved]: #unresolved-questions
Copy link
Member

Choose a reason for hiding this comment

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

Not discussed here is the algorithm for selecting versions. In conjunction with follows/overrides, finding a feasible solution could become expensive, e.g. in

inputs.foo.url = "github:bla/foo/{>1.2,<1.5}";
inputs.bar.url = "github:bla/bar/{^1}";
inputs.bar.inputs.foo.follows = "foo";

Nix would need to find a version of bar whose foo input has constraints compatible with the ones given here.

I wouldn't want to have a SAT solver in Nix...

Copy link
Member Author

@figsoda figsoda Mar 21, 2023

Choose a reason for hiding this comment

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

My thought was that bar's requirement for foo would be ignored/overridden, so only {>1.2,<1.5} would be used, and version requirements would always be combined with and

maybe I should clarify that in detailed design

Copy link
Member

Choose a reason for hiding this comment

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

I wouldn't want to have a SAT solver in Nix...

We should consider having one outside of Nix, making lockfile generation pluggable.
Perhaps the version constraints should be in a separate attribute that's open for extension?

In fact, we could consider the lock reading and fetching to be part of Nix, and the Flake CLI to be one implementation of the broader Nix package management idea. Dream2nix is also in the business of lock file generation. Perhaps the role of Nix should be limited to the integration of lock file generators, and not actually implementing them. We don't even need a dumb lock file generator like we currently have because that one could just as well live in a flake that's already been locked.

Nix should focus on its core competencies that it does very well.

  • building immutable store paths
  • bootstrapping other software

Anything that's built on top of that functionality is going to feel as good as native, plus have the benefit of pinning, patching, and decentralized development.

Flakes is oddly centralized for a package manager built on Nix...

Copy link
Member

Choose a reason for hiding this comment

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

Late to the party, but let me just write this down just in case. One way to avoid the need for SAT-solving is to allow only semver open (^1.2.3) version requirements. That way, a greedy algorithm which just always picks the latest semver-compatible version works.

Moreover, in practice, in Cargo:

  • 99% of constraints are in fact just ^1.2.3 (it was genius design decision to make version="1.2.3" be a syntactic sugar for version="^1.2.3")
  • people often try to use non-semver open constraints, most of the time that's a wrong thing to do, and leads to problem down the line (eg, their build works, but builds of folks depending on them gridlocks due to unsatisfiable constraints)
  • at some point we even considered deprecating non-^ constraints, but didn't do that, because there are occasionally good reasons for them

So, perhaps a safe move wold be to allow only ^1.2.3 constraints, (and using only implicit 1.2.3 syntax). If that turns out to be expressive enough, that would be a massive simplification. If not, fancier constrains can be added later.

[motivation]: #motivation

This will allow Nix libraries to be versioned without requiring their users
to manually update them. Some package managers (e.g. cargo) for more
Copy link
Member

Choose a reason for hiding this comment

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

Here you cite cargo, but the specification they employ to do those machine-driven updates is very dumb - by design. Cargo can update patch version, but minor version has restrictions and major is almost impossible.

It looks so full of restrictions that it is easier to edit by hand.

Copy link
Member Author

@figsoda figsoda Mar 25, 2023

Choose a reason for hiding this comment

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

Could you elaborate on what "full of restrictions" means? I don't think attacking a reference I made is a good explanation.

Copy link
Member

Choose a reason for hiding this comment

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

The example tool you gave, Cargo, is purposefully very limited. This design decision conveys the idea that major and minor versions should not be upgraded by a machine, but by a human being.

But your specification is too complex (maybe a consequence of Nix flakes being too complex), and it feels problematic to me.

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 design decision conveys the idea that major and minor versions should not be upgraded by a machine, but by a human being.

The whole point of defining a set of rules for the version specification is to make them upgradable by a machine, hence the strict rules on what version bumps can introduce breaking changes. This is so libraries can follow a predictable pattern, instead of their own preference, so updating can be automated.

Your response still doesn't explain what is limited, and I don't see why Cargo being supposedly limited has anything to do with my proposal being problematic. The purpose of this proposal is to give library authors the freedom to version their library, instead of the current situation of users following the main branch and library authors not having a good communicable way to introduce breaking changes.

Copy link
Member

Choose a reason for hiding this comment

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

Your response still doesn't explain what is limited

I said, and I will say again: Cargo (or more precisely cargo.toml) is limited. Being limited, it is easy to understand and implement.

Your proposal is too wide. It introduces more syntatical and semantical rules - implying more burden for the compiler writer (of a language with no formal specification yet, by the way).

Further,

give library authors the freedom to version their library

Goes against

strict rules on what version bumps can introduce breaking changes.

The design decision should find the equilibrium between these two points.

Copy link
Member Author

Choose a reason for hiding this comment

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

Cargo (or more precisely cargo.toml) is limited.

If you are talking about the expressiveness of Cargo.toml vs flake.nix, I agree. However, I don't think the difference applies to this specific feature.

It introduces more syntatical and semantical rules.

Cargo defines much more rules in this aspect and also more strictly enforces it, as it will fail if the version is absent or not a valid semver.

Implying more burden for the compiler writer

I agree.

freedom goes against strict rules

It doesn't. They are talking about completely different things. This feature will always be opt-in. Library authors can still not version their libraries, or define their own versioning scheme - they just wouldn't be benefited by the change. The only way tooling like this can happen is if people following a predictable set of rules when versioning their libraries, which this proposal will allow by defining strict rules.

@AndersonTorres
Copy link
Member

Overall, to me this RFC looks like a solution to a non-existent problem.

@roberth
Copy link
Member

roberth commented Mar 26, 2023

solution to a non-existent problem.

It comes down to how we define the scope of Flakes. Is it a small extension to a functional build system, or is it a package manager for a highly distributed ecosystem of packages similar to language-specific package managers?
Both are valid perspectives.

If you use Nix for a traditional snapshot-style distribution like Nixpkgs or NixOS, your needs are covered by the functionality already provided.

If you use many flakes, to the point where either the libraries used in your expressions, or the many semi-independent components that constitute your build, all coming from independently versioned flakes, then the problem domain starts to look a lot like that of the language-specific package managers. Bumping to latest doesn't work, and tracking all constraints manually becomes a pain.

EDIT: Continuing from scope to design, continue reading here

@lheckemann lheckemann added the status: open for nominations Open for shepherding team nominations label May 3, 2023
@edolstra
Copy link
Member

This RFC has not acquired enough shepherds. This typically shows lack of interest from the community. In order to progress a full shepherd team is required. Consider trying to raise interest by posting in Discourse, talking in Matrix or reaching out to people that you know.

If not enough shepherds can be found in the next month we will close this RFC until we can find enough interested participants. The PR can be reopened at any time if more shepherd nominations are made.

See more info on the Nix RFC process here

@edolstra
Copy link
Member

This RFC is being closed due to lack interest. If enough shepherds are found this issue can be reopened. If you don't have permission to reopen please open an issue for the NixOS RFC Steering Committee linking to this PR.

@edolstra edolstra closed this Jul 12, 2023
@figsoda figsoda deleted the version branch July 12, 2023 14:57
@nixos-discourse
Copy link

This pull request has been mentioned on NixOS Discourse. There might be relevant details there:

https://discourse.nixos.org/t/announcing-flakestry-dev-new-registry-for-flakes/34583/1

@nixos-discourse
Copy link

This pull request has been mentioned on NixOS Discourse. There might be relevant details there:

https://discourse.nixos.org/t/announcing-flakestry-dev-new-registry-for-flakes/34583/7

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
status: open for nominations Open for shepherding team nominations
Projects
None yet