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

Agree on a standard format for a .node-version file? #13

Open
ljharb opened this issue Dec 22, 2016 · 97 comments
Open

Agree on a standard format for a .node-version file? #13

ljharb opened this issue Dec 22, 2016 · 97 comments

Comments

@ljharb
Copy link
Member

ljharb commented Dec 22, 2016

It seems like, at a minimum, this would need to support v4.5.6 and 6.7.8 - ie, static versions, both with and without the v.

It would certainly not support aliases, since a) that varies widely by version management tool, and b) the point of an "x-version" file is to target one specific version.

This raises the question, however, about io.js versions, which it should also support. Should iojs-v1.2.3 be allowed? If not, v1.2.3 would still unambiguously point to an io.js version. What about a future where there's more than the version number to target - like, "engine" or "architecture"?

@marcelklehr
Copy link
Member

I agree with the minimum of static versions and would cast a vote for treating iojs versions and node versions as one range.

Something I'd like to throw into the ring:

the point of an "x-version" file is to target one specific version.

I'd like to question this. npm's package.json dependencies field has demonstrated the power of version patterns and semantic versioning. Usually, what people want is not to run 6.1.3 forever, but e.g. run the latest version in the 6.x series. So, if .node-version only holds static versions, that would mean having to update the file in every project every time a new version is released. This is not a user experience I'd advocate, but, I look forward to hearing your opinions on this.

@koenpunt
Copy link

that would mean having to update the file in every project every time a new version is released.

That's how rbenv works, and from what I read on the documentation this accounts the same for rvm.

@koenpunt
Copy link

koenpunt commented Dec 23, 2016

Although the reasoning behind it isn't really applicable to node, here is @mislav's take on why .ruby-version has to be precise: https://gist.github.com/fnichol/1912050#gistcomment-682506

@marcelklehr
Copy link
Member

The examples from #14 (comment) would also mean fuzzy constraints in .node-version files are out of the question.

In classic node fashion, I would propose a JSON-structure for .node-version files:

{
  "version": "1.2.3"
}

Extensible as follows:

{
  "version": "1.2.3",
  "engine": "..."
}

On the plus side, it's extensible, it's simple and still readable. On the downside, it's a departure from how .node-version files are used currently.

@ljharb
Copy link
Member Author

ljharb commented Dec 23, 2016

Another downside, parsing JSON without node available (since version managers generally need to operate without node available, like nvm) is very difficult.

@koenpunt
Copy link

@marcelklehr package.json already provides that. The purpose of a .node-version file would be simplicity.

@marcelklehr
Copy link
Member

So, you are talking about ease of implementation. I think not having node (or any json parsing platform) available is a superficial constraint, since the user needs to install something, why can't it be a version manager that runs on node? It can be. nvs, for example, shows that.

I'm all for re-using package.json for this, but someone else said, the purpose of .node-version files is that not all environments use npm and thus have a package.json (as per #12 (comment)). If the purpose is to be able to easily read a file within a shell script then that's certainly the way to go. I find that purpose not convincing, though, since a version manager should work across all platforms, so choosing a programming environment less archaic than shell scripts is in order anyway.

@ljharb
Copy link
Member Author

ljharb commented Dec 23, 2016

@marcelklehr yes, and a version manager implemented in node might be a great solution. but choosing a configuration format that imposes constraints like that on which implementations work is untenable - anything we choose absolutely must work for existing solutions as well as future ones, and nvm relies on posix, where adding a JSON parser is a heavyweight requirement.

@marcelklehr
Copy link
Member

So, you're arguing, in fact a posthumous standard is necessary that works already, instead of a new standard. Fair point. I was assuming a new standard would be a good choice since a) we're trying to integrate more than just the version and b) .node-version contents are already incompatible. I don't necessarily agree that anything we choose here must work for existing solutions, but then I would rather see a new 'official' version manager than a fully backwards-compatible standard that all version managers slowly gravitate to.

@ljharb
Copy link
Member Author

ljharb commented Dec 23, 2016

How are they already incompatible?

@marcelklehr
Copy link
Member

marcelklehr commented Dec 27, 2016

Some version managers allow aliases, some don't, some treat io.js as a separate version range with its own tag, some don't, some provide fuzzy matching, some don't.

@ljharb
Copy link
Member Author

ljharb commented Dec 27, 2016

That doesn't mean they're incompatible, as long as there is a union of consistent behavior. In other words, if all accept static versions with and/or without a v prefix, then that's compatibility.

@marcelklehr
Copy link
Member

I think there's a mere intersection of consistent behavior. How would you integrate architecture and engine, then, without losing this compatibility?

@ljharb
Copy link
Member Author

ljharb commented Dec 29, 2016

Sorry, s/union/intersection, is what I meant :-)

I don't know how, that's an important question. Perhaps on a second line, since it's likely that tools currently only grab the first line of the file?

It really depends what the parsing rules are for all the current engines. They may ignore everything after the third version number grouping; they may ignore everything after the first line - or they may hard-break if any unrecognized input exists. We'll have to research it.

@philsturgeon
Copy link

Bump. Where is this at? nvm-sh/nvm#1625 is a-waiting. :)

@felixfbecker
Copy link

Just wanted to throw this in here, ps-nvm supports both .nvmrc and reads package.json's engines.node field, with full npm semver range support. Because parsing JSON in PowerShell is trivial ;)

@ngryman
Copy link

ngryman commented Jan 5, 2018

I think that all node version managers should agree on this without having any feedback from the Node core team. Nothing against the core team but I don't think they'll make this a priority and we might be waiting a long time before things move on. Plus a bunch of node version managers already support it: avn, nodenv, fnm (I probably forget some).

So, I would propose that .node-version become a defacto standard. It should be a plain text file containing a semver or an alias (to be defined precisely). The reason it should be plain text is to allow easy processing for limited tools (aka no easy JSON support).

What do you think? Should we put an RFC somewhere and gather all Node manager authors around it? @ljharb Are you up for this?

Thanks!

@ljharb
Copy link
Member Author

ljharb commented Jan 5, 2018

@ngryman the "core team" is those in the Version Management group, which just happens to be many of the maintainers of "all node version managers". It is us that have been unable to make a decision; we're not waiting on "node core" for anything whatsoever.

This very issue is where such an RFC should be posted, if someone comes up with one. The above comments pose problems that nobody has yet suggested a solution for; any RFC should address them before being posted.

@marcelklehr
Copy link
Member

It looks like I have been the only one opposed to "prematurely" fixating on a de facto standard :)
(Sorry, for my absence lately, too.)

I can see that not using a well-defined markup format for this standard makes sense for maintaining compatibility to the status quo. Thus, in the interest of extensibility I would definitely welcome some loophole that allows extending the data in the file. E.g. stressing that this standard only concerns itself with the first line of .node-version files seems very handy.

@ljharb
Copy link
Member Author

ljharb commented Jan 5, 2018

The concern about limiting ourselves to one line is that then we can't do other things like specify npm version, or node-gyp version, etc.

@marcelklehr
Copy link
Member

The idea is to limit the standard to one line, for now, as this seems to be the common denominator. If some version manager wants to specify the npm version, they might do so on a second line, as you pointed out yourself, while others would ignore that line if they don't recognize its meaning. So, we'd have partial compatibility :'D

On the other hand, it's probably smarter to standardize as much as possible, with the option to ignore it. So, we could have the full node version in the first line as mandatory, and afterwards a key=value pair per line, that can optionally be respected by the version manager, if it recognizes the key. If it doesn't recognize a key, it might throw a warning but would still work. If it ignores everything after the first line, it still works, partially, as intended. We should of course standardize a few common keys and appropriate values for those.

@ljharb
Copy link
Member Author

ljharb commented Jan 5, 2018

I like that general approach - something like "first line is nothing but the node version, further lines must either be blank/only whitespace (ignored), begin with "#" (a comment, also ignored), or be in the format key=value (leading and trailing whitespaces are trimmed)"

@ngryman
Copy link

ngryman commented Jan 6, 2018

@ljharb Thanks for the precisions and sorry for my misunderstanding here. My goal was more to give a new impulsion to that topic more than blaming anyone, which I wouldn't dare to!
And it seems that you guys are now discussing it, so yay!

Please allow me to give my point of view on this one. I think that .node-version should be as simple as it can be: a one-liner node version, that's it.
To me, the justification behind this is that:

  • It already exists in the form of .nvmrc so it's already something used.
  • We generally only want to check the node version 80% of the time (M. Pareto told me, but worth validating this point).
  • It should be super quick to check. It would be useful for deep shell integration or similar.
  • It should be easy enough to implement so that everybody will align on this quickly. I think it shouldn't rely on any serialization scheme (JSON, key-value, ...)

For the other "20% checks" (which are basically 80% of the time npm, Pareto inception), I think we should pass the torch to the engines field of package.json since a project checking against an npm version should always have a package.json.

So to sum up:

  • 80% of checks, fast path, .node-version
  • 20% of checks, slow path, package.json

@ljharb
Copy link
Member Author

ljharb commented Jan 6, 2018

That's also a reasonable approach.

Even in the "one-line" part, we'd have to figure out a union of semantics:

  • leading v optional/required/forbidden?
  • 3 version groups required, or are 2 or 1 allowed?
  • 3.2.x, or just 3.2, or both, or neither?

etc.

@koenpunt
Copy link

koenpunt commented Jan 6, 2018

Might be good to follow the .ruby-version convention, which is also is a single static value.

@shadowspawn
Copy link
Member

In the interested of clarity, while I do think future implementations should support Windows line endings, I have not investigated current implementations and would do that before deciding on how to word that aspect.

@shadowspawn
Copy link
Member

shadowspawn commented Jun 25, 2020

I am dropping my effort to get consensus here on a minimal backwards compatible standard format. I suspect I joined this conversation years too late to gain interest from the original contributors, besides pushing a very conservative and unexciting format! Ah well.

@MatthewHerbst
Copy link

@ljharb At some point an executive decision needs to be made here. If you think this is dead then please close this ticket so we can stop spending years on it.

I think if nvm pushes a standard the rest will fall in line. @shadowspawn's proposal strikes me as a pretty reasonable starting point, with easy expansion into a likely key=value system in the future on subsequent lines.

It's also unclear to me why every previous version of the file needs to work. Publish nvn v1.0.0, clearly and loudly tell people about the breaking change, and they can either conform, stick to an older version, or find another solution that works for them.

@jasonkarns
Copy link
Member

jasonkarns commented Jun 26, 2020

FWIW, nodenv will continue supporting .node-version as the primary means to specify a file. Regardless how heavy the use of n may be, the many users of it will not have started to use and rely on the file overnight. (Despite nodenv users having been using it for many years.)

I think if nvm pushes a standard the rest will fall in line.

We will be happy to make slight modifications to increase commonality, but we won't drastically change a file format that we've been using for years simply to match a late arrival.

I would be in favor of at least documenting the behavior of current tooling so that a minimal set of conformance could be decided. Implementors would then be free to implement as desired; but at least with the knowledge of where compatibility is possible.

@MatthewHerbst
Copy link

we won't drastically change a file format that we've been using for years simply to match a late arrival

@jasonkarns very bluntly: the end users and downstream tooling will decide that. npm is about to start supporting yarn.lock files. Change is inevitable.

@ljharb
Copy link
Member Author

ljharb commented Jun 26, 2020

@MatthewHerbst i'm not aware of any plans for npm to support yarn.lock files, and i've been following the repos and in the RFC calls for many months.

I think that, if nodenv did not already use this file, then certainly it would be reasonable for the most popular projects - all of which are represented in this working group - to agree on something and thus defacto define it as the ecosystem standard. I don't think it would be reasonable, ethical, or kind for a majority to steamroll a single project, regardless of which project it is or that project's usage.

If there's a common format we can use that's compatible with nodenv, and its extensibility is specified and is also compatible with individual version managers, then that is a viable path forward.

It's also unclear to me why every previous version of the file needs to work. Publish nvn v1.0.0, clearly and loudly tell people about the breaking change, and they can either conform, stick to an older version, or find another solution that works for them.

Breaking users causes harm and costs a lot of time and money. Doing it out of necessity is one thing, but doing it capriciously - ie, when any nonbreaking option remains available - is a hostile act. nvm's v1.0 will be to indicate it's fully stable, not to justify radical breakage.

@MatthewHerbst
Copy link

MatthewHerbst commented Jun 26, 2020

i'm not aware of any plans for npm to support yarn.lock files, and i've been following the repos and in the RFC calls for many months

@ljharb Based on the most recent npm blog post, it seems yarn.lock support is coming in npm v7.

I don't think it would be reasonable, ethical, or kind for a majority to steamroll a single project, regardless of which project it is or that project's usage.

I agree, I don't want to "steamroll" anyone either. However, at some point a decision needs to be made, and based on every comment above, no one/no project is going to be perfectly happy with the outcome. There is no lack of community input on this thread.

Doing it out of necessity is one thing, but doing it capriciously - ie, when any nonbreaking option remains available

We've been at this for four years. Based on the requirements laid out in many, many comments above, and what you and others who have executive power here are and are not amenable to, it seems increasingly clear that there is not such an option.

nvm's v1.0 will be to indicate it's fully stable, not to justify radical breakage

I was just picking an easy/random sem-ver breaking number. I'm well aware that, as the package isn't at 1.0.0 yet any minor change is a breaking change.

@ljharb
Copy link
Member Author

ljharb commented Jun 26, 2020

Thanks, I missed the blog post.

at some point a decision needs to be made

You say that as if it's a given, but I don't think it is. Often, "no decision" is the best course of action rather than "the wrong decision".

@MatthewHerbst
Copy link

Often, "no decision" is the best course of action rather than "the wrong decision".

I fully support "no decision" if that's what you think is best. If that's the case, let's close this and move on.

@koenpunt
Copy link

I'm honestly surprised that there hasn't been any progress on this issue for the past 4 years. Wouldn't it be a start to have an MVP kinda .node-env file, starting with only exact matches, and see how the community receives it.

If even that isn't acceptable, then I think it's better to just close this issue, and forget about a universal standard.

I'm happy with how nodenv works nonetheless.

@shadowspawn
Copy link
Member

shadowspawn commented Jul 8, 2020

@jasonkarns #13 (comment)

I would be in favor of at least documenting the behavior of current tooling so that a minimal set of conformance could be decided. Implementors would then be free to implement as desired; but at least with the knowledge of where compatibility is possible.

I had started investigating this early in the year. Dug out my notes and tidied up into a repo, and been filling out the compatibility matrix: https://github.com/shadowspawn/node-version-usage

@jasonkarns
Copy link
Member

@shadowspawn That research is fantastic, thank you for that!

Would there be interest in hosting a file in this repo proposing at least this format (https://github.com/shadowspawn/node-version-usage#suggested-compatible-format)? That could function as a reference for tooling to aim at or link to.

@srl295
Copy link
Member

srl295 commented Mar 30, 2023

Per the compatibility matrix there's only one manager that doesn’t support a leading v, and there’s a PR open to fix that direnv/direnv#1071 (I tested the logic there).

In that light, it might make sense to require the leading v as part of the common format.

Then, the common format becomes minimally:

v{major}[.{minor}[.{patch}]][optional CR/LF]

Also, it doesn't support .node-version (yet?) but the maintainer of this plugin describes why it requires a leading v: eirslett/frontend-maven-plugin#1075 (comment)

@webervin
Copy link

webervin commented Apr 8, 2024

In perfect life docker pull node:$(cat .node-version) would just always work as one expects, allowing SRE/DevOps/Sys.Admins to write knowledge about expected node version exactly once per code reposiory.

@srl295
Copy link
Member

srl295 commented Apr 8, 2024

In perfect life docker pull node:$(cat .node-version) would just always work as one expects, allowing SRE/DevOps/Sys.Admins to write knowledge about expected node version exactly once per code reposiory.

Per the compatibility matrix there's only one manager that doesn’t support a leading v, and there’s a PR open to fix that direnv/direnv#1071 (I tested the logic there).

In that light, it might make sense to require the leading v as part of the common format.

Then, the common format becomes minimally:

v{major}[.{minor}[.{patch}]][optional CR/LF]

The PR was merged, so all support leading v.

@shadowspawn
Copy link
Member

To clarify, the Docker Hub node images are tagged without a leading v.

https://hub.docker.com/_/node/tags?page=&page_size=&ordering=&name=20

@shadowspawn
Copy link
Member

shadowspawn commented Apr 9, 2024

The PR was merged, so all support leading v.

Clarifying "all". All as of March 2023 when PR was opened. Not all in the current compatibility table.

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

No branches or pull requests