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

Require Release Tags #1051

Open
ryukoposting opened this issue Apr 10, 2019 · 33 comments
Open

Require Release Tags #1051

ryukoposting opened this issue Apr 10, 2019 · 33 comments

Comments

@ryukoposting
Copy link
Contributor

The Problem

There are a ton of packages on nimble.directory that have no releases. These packages are completely and totally unusable for any project that takes itself seriously. Without releases, there is no way for me to confirm that all users of my own packages have the correct version of my package's dependencies.

The Solution

Require all Nimble packages to have at least one release tag before they are accepted into the package list.

In addition, if I were to have it my way (though the problem may be so bad at this point that doing this would be self-destructive), any package currently in the list that doesn't have release tags should be removed until they have at least one release tag.

@dom96
Copy link
Contributor

dom96 commented Apr 10, 2019

Without releases, there is no way for me to confirm that all users of my own packages have the correct version of my package's dependencies.

That's not quite true, you can depend on a specific commit hash.

@ryukoposting
Copy link
Contributor Author

Without releases, there is no way for me to confirm that all users of my own packages have the correct version of my package's dependencies.

That's not quite true, you can depend on a specific commit hash.

I can depend on a specific git hash, but that doesn't actually fix the problem. If someone puts their package on Nimble, they are effectively saying "I want people to use this." If they want people to use their package, it is their responsibility (not their users' responsibility) to make sure that users don't have to comb through commits to find a version that's usable.

Maybe instead of git tags, people could have a list of stable hashes in their readmes, with changelogs describing the changes since the last stable hash. That would clutter up the readme though, so maybe such a capability should be directly integrated into git. Oh wait, that's just a git tag.

@disruptek
Copy link
Contributor

It sounds like you're fine with git hashes or versions, as long as the software is usable. Is that right?

@ryukoposting
Copy link
Contributor Author

ryukoposting commented Apr 10, 2019

I am absolutely not fine with JUST a git hash. If someone expects users to filter through a tree of commits to find a hash that's usable, then they clearly don't care if people actually use their package or not. Such a package does not belong in a public package distribution system like Nimble.

A release tag is just a commit (with its corresponding hash) that's been tagged to denote a version that is suitable for regular use. While semantic versioning would be much preferred, I'll take any tags at all over nothing. At least I wouldn't have to scroll through a couple hundred commits to find a revision that actually works.

If you're going to have a package manger, it should actually manage packages. Nimble packages seem to suffer from a horrible epidemic of:

  • terrible documentation, if any at all.
  • no indication of whether a particular commit is stable, let alone actual versioning.
  • years without even a single commit, despite open issues add lack of example code or documentation.

@genotrance
Copy link
Contributor

The premise is that people check in junk code into master. That typically does not happen when things get serious. People should work in branches and only push to master when CI passes. Then it doesn't matter whether you tag or not.

A better logic is to check if the package works but that depends on tests which again some packagers may not care about. Overall, it is hard to assess quality by just tags.

@ryukoposting
Copy link
Contributor Author

ryukoposting commented Apr 10, 2019

The premise is that people check in junk code into master. That typically does not happen when things get serious.

The moment you submit your package to Nimble is the moment your package becomes serious. If you aren't going to take basic steps to document (including, but not limited to, tagging) your package, then it doesn't belong on Nimble, period.

On the topic of pushing directly to master, it took me about 15 seconds to find an example of that happening with a nimble package. One of the most recently-added packages, whose name I will spare, did exactly that about 24 hours ago at the time of this post. If you'd like more examples, I'd be happy to dig up more.

People should work in branches and only push to master when CI passes. Then it doesn't matter whether you tag or not.

That would be fine if people actually automated their tests. The fact of the matter is that a large number of people don't do that, and there's some packages where remote automated tests simply are not possible without creating security concerns.

Passing/failing automated tests also doesn't tell you if one version of a package is compatible with another, hence proper versioning practice.

As an aside, that package I used as an example earlier also doesn't have a CI pipeline, nor does it have any tags, or any commit with an obvious message indicating that it is a stable enough version for regular use.

it is hard to assess quality by just tags.

It's impossible to assess quality of a program by just tags, but it would at least make it possible for me to know which commit the developer wants me to use. I don't expect every nimble package to be a masterpiece of project management, I just want to be able find a package on nimble.directory without having to sort through a dozen broken, undocumented, neglected abominations.

@GoogleBot42
Copy link

Versioning would be nice as an example, the latest tagged version of the opengl package is broken (v1.2.0). It is broken because the x11 package doesn't use tagging and only pushes to master. The x11 package changed the way it structures its files so the imports are not the same. If x11 had a tagged version, this would not have been an issue. Moving the files around would have been a bump in the major version number.

To avoid this issue, the opengl package could have used a specific git hash but that keeps from getting updates for patch level package changes and could even lead to security issues.

@Araq
Copy link
Member

Araq commented Apr 11, 2019

I don't like git tag, it's always friction to use and to ensure these version tags are 100% consistent. Having said that, I have to agree with @ryukoposting completely, it would be better than the current situation. One thing that is annoying is that Nimble's version is not based on "git" but instead in the .nimble file, violating DRY.

@ryukoposting
Copy link
Contributor Author

I don't like git tag, it's always friction to use and to ensure these version tags are 100% consistent.

Tags certainly have their flaws, that's for sure. That said, I think they still have a correlation with good project management habits. That, combined with the problems you and @GoogleBot42 mention, are good reasons for Nimble to require their use.

I apologize if my last message came off a bit heated. As silly as it may sound, I have very strong feelings on proper documentation and versioning habits. With Nim's ecosystem being so young, it can be very frustrating to see packages being neglected by their maintainers, and I hope that some higher standards for inclusion in packages.json will serve as a "kick in the pants" for some package maintainers, while potentially drawing the attention of more serious contributors.

@dom96
Copy link
Contributor

dom96 commented Apr 11, 2019

Yeah, I understand the annoyance of installing a package and it not working. This usually happens because people forget that once they tag, Nimble will not install #head anymore. So enforcing tags would help.

So yeah, I support this.

@disruptek
Copy link
Contributor

I think everyone understands your frustration, and to a large extent, we all share your concerns both with Nim and other language ecosystems, but the point I'm trying to make is that if you want to assert that your software WILL work (for any given static input), a couple things MUST happen:

  1. you must be able to prevent your dependencies from changing, and
  2. you must be able to achieve reproducible builds, and
  3. you must test your software against your dependencies.

Anything else is just wishin', and wishin' won't make it so.

If you still don't believe me, consider the scenario in which all parties are performing proper maintenance and a bug is fixed in a dependency which changes behavior which you (intentionally or not) depended upon. The semver gets updated correctly with a new patchlevel. Nimble presumes correctness. That presumption is simply wrong when it comes to your software, though it may be correct for other packages which share the dependency.

Now, we could build a canary that monitors packages and does things like executing earlier test suites against newer code, or is smart enough to identify which tags tests were developed against. I'm not trying to say that there aren't solutions. I'm trying to say that as long as the proposed solution is not curative and provably hygienic, we will continue to propagate bugs via semver-based package management.

@GoogleBot42
Copy link

GoogleBot42 commented Apr 11, 2019

@disruptek
In theory, if functionality must change to fix a bug that is a bump in the minor version since promised functionality changed. On the other hand, fixing a bug in the implementation of promised functionality is a bump in the patch version. The distinction here is the promised functionality changes to fix a bug... or you are fixing a bug that caused incorrect behavior.

If your application is dependent on a bug in the implementation of promised behavior, that isn't the fault of the package you are using. I do not see what you bring up as an issue. Although, if is isn't clear what the promised functionality is (bad/incomplete API documentation), or if the package violates the versioning system, that would be the fault of the dependent package.

@GoogleBot42
Copy link

While it is possible that a dependent package can violate versioning rules, implement incorrect behavior, and bugs, this is inevitable regardless if nimble requires release tags or not.

@GoogleBot42
Copy link

The specific issue you brought up could be prevented if every package used a specific git hash version. I see this as bringing in even more problems than it solves. Not trying to be rude but patch level versioning exists for a reason. In the extreme case, imagine depending on a specific git hash for a crypto library and it has a critical vulnerability. With patch level versioning (and depending a what the vulnerability is) that could be solved by just recompiling your application with the newer version and no changes to your code are needed. Yes, it doesn't always work out so well. As a consequence, the possibility of using a specific library version based on git hash should still be available imo. But I don't think anyone was suggesting its removal only the requirement of tags.

@disruptek
Copy link
Contributor

In theory, if functionality must change to fix a bug that is a bump in the minor version since promised
functionality changed.

Hey man, out here in the real world, the theory breaks down. Often, I'm sorry to report. The fact that bugs exist at all, in any form, is proof that sometimes software developers get it wrong. I count myself in that group, and as long as we continue to fail at preventing bugs from changing any behavior, we must allow that we may not always be able to assign a version tag perfectly.

If your application is dependent on a bug in the implementation of promised behavior, that isn't the fault of the package you are using.

Correct, but it doesn't matter who is responsible -- my users don't care why my software stopped working, and I don't have the resources to debug all the interactions between all the permutations of all my dependencies' versions (and those users' environments) in which defects can be traced to changes which violate the reproducibility of my software build.

I'm surprised that there are members of the Nim community who can afford that amount of work, especially given the pre-1.0 nature of the ecosystem. Is anyone really finding it easy to debug everyone else's software across the myriad of platforms and backends supported by Nim?

In the extreme case, imagine depending on a specific git hash for a crypto library and it has a critical
vulnerability.

Not trying to be rude, but shared libraries exist for a reason. 😉

If you want to decouple your code from that of your crypto dependency, you link to the dependency as a shared library. Use majors, minors, whatever you want -- go nuts. Then you don't even need to recompile your software (let alone change its code) to achieve the fix you want; clearly, a superior approach. I don't know about you, but I don't have any static crypto libraries on my system and I recommend against building crypto directly into your Nim products.

On the other hand, if you build your software as a product of both your code and that of all your dependencies, your program will be no more reliable than your least reliable dependency. This thread is literally about your fellow developers, who craft dependencies, violating a vague social contract; it's exactly this that @ryukoposting is railing against. To suggest that the solution is to whitewash over the problem with another unreliable social contract doesn't make much sense to me.

No one is suggesting that you can't use semver. If you're happy depending on it, great. I personally will never depend on it in any of my software, and if I cannot control my dependencies with Nimble, I simply won't use Nimble. I'm totally fine with that and I'm not trying to change anyone's mind; I'm just trying to highlight the technical argument against codifying a reliable on semver that does not serve all users.

While it is possible that a dependent package can violate versioning rules, implement incorrect behavior, > and bugs, this is inevitable regardless if nimble requires release tags or not.

Exactly, and the point is that as an author such as @ryukoposting, without depending upon semver, I have the ability to control whether those bugs are exhibited by my software. I don't know how to make that any clearer. Imagine never having to read a thread like this again. We can do it! We have the technology! 😄

@ryukoposting
Copy link
Contributor Author

Hey man, out here in the real world, the theory breaks down. Often, I'm sorry to report.

@disruptek you sound like you think you're the only one in this thread with a job. If you'd tone down the arrogance for a second, I think you might notice a pattern: you're the only one in this thread whose had these problems to such an incredible extent. If you want to link against the same unpatched version of OpenSSL for the next 7 years because of "muh reproducible builds," that's fine with me. Just let me know so I can stay as far away from your software as possible.

@GoogleBot42
Copy link

GoogleBot42 commented Apr 12, 2019

@disruptek
You seem to be under the false impression that it is being suggested that versioning through git hashes should be removed. This is not the case.

The fact that bugs exist at all, in any form, is proof that sometimes software developers get it wrong.

we must allow that we may not always be able to assign a version tag perfectly

I address this later.

Correct, but it doesn't matter who is responsible -- my users don't care why my software stopped working, and I don't have the resources to debug all the interactions between all the permutations of all my dependencies' versions

Yes, do you have a better system? I am not sure what your point is. If anything required tags improves this it won't make it worse. ... Or is just pushing to master better?

Not trying to be rude, but shared libraries exist for a reason.

If you want to decouple your code from that of your crypto dependency, you link to the dependency as a shared library.

Yes shared libs are good for this. But this isn't how nim works. You can compile a nim into a shared lib but that lib is a c/c++ object. So you would need a wrapper for the nim lib to be usable in a nim program. It could probably be generated. As far as I know, using nim as a shared lib for a nim program isn't a common workflow and isn't something that is easy nor is supported by nimble. So this strategy of shared libs is only good for creating an api wrapper for an existing c/c++ lib. Since this discussion is about how to improve nimble and nim packages (which are not shared libs) not how to better use c/c++ libs, this isn't relevant in how to improve package stability in the package manager. If you think nim/nimble should have the ability to create shared libs from nim code, maybe a new issue/suggestion but this isn't the right place.

Use majors, minors, whatever you want -- go nuts.

That's not how shared libs work. The numbers indicate if the api and/or functionality changed and by how much...

I don't know about you, but I don't have any static crypto libraries on my system and I recommend against building crypto directly into your Nim products.

I agree. It doesn't change my point though. I acknowledged it is an extreme example. There are much less extreme examples (see my first post in this thread). To counter your example, what if the wrapper around openssl had a little active code to translate nim and c (maybe just memory handling) and it didn't initialize memory right so the previous value of the memory could be accessed if poked right. What if that memory had a key in it? A shared lib won't help you but tag versioning could assist you when updating since the update/fix might be just a patch. Granted maybe not a real world situation because I don't know how the openssl wrapper is actually written and I haven't written one myself. Point is, a dynamic lib is not some solution that will save you from all package updating problems. Sometimes, no matter what language you use, the problem is in your own code even if it is code to just enable use of openssl.

I personally will never depend on it in any of my software, and if I cannot control my dependencies with Nimble, I simply won't use Nimble.

I am not sure what your issue is... this actually makes your life better. All this means is that devs cannot just have HEAD of master be how they distribute call their code in nimble. Since tagging would be enforced, you would have the option of using a tag version for all packages. That said, you can always just use a git hash if you want to use specific code. This change makes it easier not harder to tighten dependencies and avoid breaking. If you want it to be perfectly consistent though, you can just use a git hash.

my users don't care why my software stopped working, and I don't have the resources to debug all the interactions between all the permutations of all my dependencies' versions (and those users' environments) in which defects can be traced to changes which violate the reproducibility of my software build.

Just use git hashes. No one is taking that away. What is the concern you have? What were you using before? Because, the only thing that does what you seem to want has always been specifying a version of code through git hashes.

I'm totally fine with that and I'm not trying to change anyone's mind

Again, what you are trying to argue for? This doesn't change anything you seem to care about.

have the ability to control whether those bugs are exhibited by my software

No one is suggesting removing specifying a package version through git hash. I would be against it if someone was.

As @ryukoposting wrote,

I am absolutely not fine with JUST a git hash

Note that he said "JUST".
He is not suggesting the removal of the git hash for versioning. I don't think I can be any more clear.

@ryukoposting
Copy link
Contributor Author

ryukoposting commented Apr 12, 2019

Note that he said "JUST".
He is not suggesting the removal of the git hash for versioning. I don't think I can be any more clear.

@disruptek If you wouldn't mind me interrupting your holy war with semver, I'd like to emphasize this. If you want to choose a specific version of a package, and always link against that no matter what, that's fine by me, I really don't care. I think it's short-sighted and your rationale for it is hand-wavey at best, but it's your work, not mine.

@disruptek
Copy link
Contributor

If you want to talk about your technical challenges (which are mine, as I depend upon your software!) and how we might work together to solve them, well, you can always reach out on IRC. 😉

I'm not going to spend time composing technical arguments (purely for the benefit of others) just to be told I'm being arrogant. I'm sorry if my passionate distrust of software communicated anything but a desire for Nim products to exemplify the best possible development experience for you, my peers, and the many who will come after us.

I don't code in Rust, but there are aspects of its development and tooling which I admire (okay, which I covet. I said it!)[0][1]. In particular, I appreciate what I would characterize as a fearless dissatisfaction with the status quo. Of course, there's a certain amount of this inherent in the development of any new language, and Nim continues to demonstrate this contempt for "good enough" nearly 15 years after its inception. I'm thinking of Araq's newruntime here; some might say an unnecessary innovation, but I would argue that it's another in a long line of developments that are critical to its future.

Nim is, as it says on the tin, an expressive, elegant, and immensely powerful tool while still being portable and performant. It solves real, practical problems that we have today, without bloodletting or boilerplate. You don't have to dig deep to find real innovation in this thing; it's clearly state of the art in many ways. And not least, it's fun. 😄

However, make no mistake -- we are in competition (or, holy war, as your prefer) for programmers. By growing the community, we stand a better chance of surviving as the development of these and future languages accelerate. I honestly don't know if I'll be able to afford to code in Nim in five years, and that worries me.

When one of our own exhibits the kind of frustration @ryukoposting did, I see a chance for Nim to again look to the future and both distinguish itself from other languages steeped in 1970's tradition while simultaneously offering yet another compelling incentive to those programmers that represent our lifeblood.
To frame @ryukoposting's grief as opportunity in this way requires a certain suspension of disbelief -- you might prefer to call it callous disregard in my case, and that may even be fair -- but I promise I mean no disrespect and my aim is not to diminish the scale of the problem. If anything, I want to draw attention to it.

Nim is still small, but we all know that this lean featherweight can easily punch above its weight class, and the years of careful polishing of this language have yielded a very sharp instrument. I'm simply asking that we consider whether Nim's packaging system may offer another chance to take a major step forward in software reliability by knocking out an entire class of software errors via surgical, technical, solutions powered by that same fearless dissatisfaction that has served you (and now me, thanks!) so well. Araq doesn't have to be the only one to get some glory around here. 😛

[0] "not rocket science" (the story of monotone and bors)
[1] lolbench: automagically and empirically discovering Rust performance regressions

@Araq
Copy link
Member

Araq commented Apr 12, 2019

Araq doesn't have to be the only one to get some glory around here

Sorry, I think I beat you here, https://github.com/Araq/nawabs ;-)

@disruptek
Copy link
Contributor

Sorry, I think I beat you here, https://github.com/Araq/nawabs ;-)

I like it, I use it, I recommend it, and I think it's part of the solution, but the fact that this thread exists suggests that the problem remains. 🙁

@ryukoposting
Copy link
Contributor Author

ryukoposting commented Apr 12, 2019

I don't code in Rust, but there are aspects of its development and tooling which I admire (okay, which I covet. I said it!)[0][1]. In particular, I appreciate what I would characterize as a fearless dissatisfaction with the status quo

We can agree on this much, at least. I tried my best to like Rust, but (hot opinion incoming) it exchanges readability and maintainability for safety to a counterproductive extent. However, Rust's tooling is genuinely incredible. Any other package management tool should consider it a compliment to be compared to Cargo.

The rest of your post seems like something that isn't particularly relevant to this thread, so I'll leave it for IRC or the forum. Regardless, you lead us to a valuable question that pertains to the topic of this thread: what can Nimble learn from other package managers? What did they get right? What did they get wrong?

One answer that's pretty obvious is that, semver or not, good package managers emphasize structured, formally-defined versioning semantics. Cargo explicitly states that packages use semver, and semver is a part of its formal grammar for package IDs. Maven, which is a critical part of the shared ecosystem of the big JVM langs, also has a formally-defined standard for version numbers. Cargo gives absolutely no exceptions to its standard- semver is a part of its grammar, and that's that. Maven is more lax, though it still gives us this tidbit:

If you do not follow Maven versioning standards in your project versioning scheme, then for version comparison, Maven interprets the entire version as a simple string.
...
If you use a nonstandard versioning scheme, Maven release and version plug-in goals might not yield the expected results.

Maven is effectively saying "here's the standard, if you don't use it, don't blame us when your users come banging down your door because something broke." Maven recognizes that a single versioning model can't possibly be a perfect fit for every single Java/Kotlin/Scala/whatever program on earth. Rust seems satisfied that semver will to the job well enough for all use cases. Both have this in common: structured versioning is standardized and required.

I'm just a passionate idealist who writes Nim libraries- it's up to @Araq et al. to decide where Nimble actually goes on this issue. I hope to see it move towards some kind of formal versioning requirements, regardless of what they may be.

@disruptek
Copy link
Contributor

What did they get wrong?

What package management generally gets wrong, in my opinion, is that it makes developers opt-in to most of the workflow that best promotes quality, and it puts newcomers to the codebase in the position of either guessing at whether a problem is on their end or upstream, or having to repeat the same debugging efforts that others have already performed given the same environment. These are developers who are inexpert in the codebase; exactly the users who are least well-equipped to perform this debugging and least willing to invest resources into software that has not yet yielded any value to them, whatsoever.

  • How many times have you cloned a repo only to find that you can't make the code work?
  • Why is that something that every single victim needs to spend a few minutes digging into?
  • Can't we make unit tests opt-out instead of opt-in? Can't we share the results of those tests as feedback to the ecosystem?
  • When I install a library, I'd like to know that 5000 other installations yielding the same reproducible build succeeded in passing the same unit tests.
  • I'd also like to know when 15% of the installations failed, and I'd like to be able to look at a histogram of what failed and in what context. This kind of data would be useful to me both as a library user and a library developer, and it could be reliable enough for automatic use by tooling, as well.
  • For example, it could integrate with bug reporting or perform differential diagnosis and git bisection automatically, or you could have a bot (or the build tool itself) automatically test and upgrade your dependency specifications.

But maybe you don't think this is relevant to the thread. If you only want to talk about semver, what I think they got wrong are two things:

  1. It's not infallible (social contract yadda yadda), so some versions that should work, do not.
  2. It's insufficient to specify exactly which versions do and do not work with your software (see 1.)

Here is a flexible use of semver that may work for everyone, both in the early days of the ecosystem and much later, when we wish to converge on tighter control:

  • Dependencies must be specified as a series of rules composed of version specifications
  • Each version specification is an atom, optionally modified by operators to produce ranges
  • The first matching rule wins, just like routing filters
  • If it helps, imagine an implicit negation rule which terminates the series

The syntax isn't important; the semantics are what matter. Examples:

# any available version of foo; latest semver if so tagged, else HEAD
foo: +
# only 1.0.0
foo: +1.0.0
# any with a 1.x.x major
foo: !>=2.0.0, +>=1.0.0
# i believe in semver!  (anything that exposes at least the 1.6 API)
foo: +^1.6.0
# any over 1.x.x except 1.0.3 -- the intern broke that release
foo: !1.0.3, +>=1.0.0
# any point in master containing commit f3j9572o
foo: +>=master:f3j9572o
# but nothing after hh84so43 -- we haven't tested the new stuff yet
foo: !>=master:hh84so43, +>=master:f3j9572o
# any tag after rc3; that one was really half-baked
foo: +>"rc3"
# use (some) pre-1.6.4 commits while waiting for 1.6.4 to get tagged
foo: +1.6.4, !>=1.6.5, +>=master:2d4100mr

Did I miss anything?

Of course, I believe there needs to be a declarative specification above each library, so that you can say something to the effect of "I can use foo-1.0 or a combination of (bar-HEAD and bif-2.2)", but that can come later.

@mratsim
Copy link
Contributor

mratsim commented Apr 17, 2019

I think this conversation is drifting/colliding with the lock files thread: nim-lang/nimble#127.

I agree that releases provide something to target that is supposed to be reliable at one point and less costly for a developer to implement than a full one master+devel branches development model.

For rapid prototyping though, I'd like to be able to set nimble requirements to latest commit available when libraries are developed in parallel and have a nimble update command(nim-lang/nimble#169). Otherwise we're never sure of the versions nimble will pull which forces monorepo, git submodules and also regularly nuking our .nimble/pkgs.

@ryukoposting
Copy link
Contributor Author

I'd like to be able to set nimble requirements to latest commit available

Agreed. I can see where this could be very useful in the development process for multiple large, codependent packages. Sadly, my day job's tooling consists of "makefiles and RTFM" so I can't speak to any specific examples the way you can.

I think the easiest temporary solution would be this: When a package gets submitted to packages.json, whoever accepts the PR should check that there's at least one release tag. There's already a manual step for getting packages accepted, so this isn't really adding a whole lot to the process.

As for a long-term solution, we should consider:

  • What will be the formal semantics for version numbers in Nimble packages? Should semver be adopted, should it mimic Maven, or should we come up with something different?

  • How strict should it be? Should it be required that all packages follow the rules, or should it be something like "here's the standard, break it at your own risk" ?

  • How does this affect nimble project files? We will need to consider how things like requires "foo >= 0.1.0 will be affected. If semver is used, does >= 0.1.0 now mean "any version 0.1.X where X >= 0" ?

@mratsim
Copy link
Contributor

mratsim commented Apr 18, 2019

I think the easiest temporary solution would be this: When a package gets submitted to packages.json, whoever accepts the PR should check that there's at least one release tag. There's already a manual step for getting packages accepted, so this isn't really adding a whole lot to the process.

Sounds good

What will be the formal semantics for version numbers in Nimble packages? Should semver be adopted, should it mimic Maven, or should we come up with something different?

How strict should it be? Should it be required that all packages follow the rules, or should it be something like "here's the standard, break it at your own risk" ?

I have no preference but we shouldn't be too strict as I expect many packages will be wrappers for C/C++ libraries and will follow their upstream project versioning.

How does this affect nimble project files? We will need to consider how things like requires "foo >= 0.1.0 will be affected. If semver is used, does >= 0.1.0 now mean "any version 0.1.X where X >= 0" ?

I'd rather have explicit requires foo >= 0.1.0, foo < 0.2.0 than implicit. This is much better for packagers that are non-Nim developers (say that want to package a Nim project for Debian or Archlinux).

Also ideally you could have task level requirements from nim-lang/nimble#482, like:

task build_stable:
  requires
    "foo >= 0.1.0",
    "foo <= 0.2.0"
  setCommand "c --outdir build"

task build_devel:
  requires "foo#master"
  setCommand "c --outdir build"

task fuzzer:
  requires "fuzzer >= 0.2.0"
  setCommand "c --outdir:build test/fuzzer.nim"

Note: the outdir flag has been introduced in https://github.com/nim-lang/Nim/pull/10729/files#diff-42ba1d994f4fa8c6ad17a7efae7936ccR198

@genotrance
Copy link
Contributor

Looks like an easy near term fix is to no longer install #head unless explicitly instructed to. If no tags are found then just error. That way, package writers will be forced to tag in order to get their packages normally used. And if they don't then users immediately know and can then decide to use #head or not.

@ryukoposting
Copy link
Contributor Author

ryukoposting commented Apr 22, 2019

I have no preference but we shouldn't be too strict as I expect many packages will be wrappers for C/C++ libraries and will follow their upstream project versioning.

That might be true in the short term, but the long-term hope (my long-term hope, at least) is that people will have incentive to create Nim libraries that work for both the native (C and/or C++) and JS backends. I think the versioning semantics should be flexible nevertheless, but the top priorities should be making sure it is easy for both humans and Nimble to understand.

@ryukoposting
Copy link
Contributor Author

ryukoposting commented Apr 22, 2019

Quick additional idea, that I have not thought out at all and have absolutely no idea how hard it would be to implement: maybe have some kind of default versioning semantics, then if a package wants to define its own versioning semantics, then they can define something like this in their package.nimble file?

proc `>`(l, r: Version): bool

This would be cool as a feature, but I can see it going south very quickly if someone cooks up a versioning grammar that they don't fully think through.

@disruptek
Copy link
Contributor

Having versioning semantics that are not shared by all packages will add an expensive burden to all tooling despite the requirement of such semantics existing for perhaps only a small subset of all packages. Additionally, it's hard to believe that the requirement cannot be met without static human-readable text in a simple grammar.

requires
    "foo >= 0.1.0",
    "foo <= 0.2.0"

Regardless of how versions are specified, again I must ask that there be a means by which we can specify not only which versions are acceptable, but which versions are not acceptable. The following would suffice, though I think we could do better:

requires
    "foo >= 0.1.0",
    "foo <= 0.1.2",
    # ie. omit 0.1.3
    "foo >= 0.1.4",
    "foo <= 0.2.0"

@arnetheduck
Copy link
Contributor

all this tag stuff sort of assumes there's only one package per git repo. sounds pretty limiting - works for tiny stuff but anything slightly more serious will want to be a monorepo with multiple projects in it, perhaps versioned separately. slightly tougher nut to crack, to get the resolution of version to hash stable.

here's an example of a language for version specs: https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html - it covers all the use cases and follows semver - before inventing a new one, make sure it's an actual improvement. as pointed out by others, the rust tooling is hard to complain about, comparatively speaking, to most PM's out there - similarly its approach to lock files, as pointed out in the other thread.

versions are and remain a social tool, they have no value to accurately point out specific code - that's better left to hashes. a tag can be moved for example to point to a different hash, and this has been used to create exploits in the wild. it might have been ok 10 years ago but it would be sad to build a tool that doesn't deal with this well-known problem in 2019.

since versions a social tool, it makes sense that they come with a social contract that's useful and meaningful for humans - semver is one such contract that works adequately / really has no competition that works better. you use them not for creating reproducible builds, but for managing complexity at specific points in the development process - those points when it's time to find a candidate mixture of compatible packages to test. this is why package managers exist and are useful, to begin with - otherwise we'd all be using submodules which already solve the repro-build part just fine.

at the end of the day, you still need to test your software even if the upstream developer promises that it'll be compatible, unless your software is sufficiently unimportant that it doesn't matter if it breaks occasionally - you should be able to enable this unsafe practice for those occasions. if the poor and broken method is the default, that's what most people will do, decreasing the overall value of the nim package community and entrenching its reputation for poor quality, over time.

@genotrance
Copy link
Contributor

I just reread this entire discussion and still don't see any real next steps.

I made the suggestion to no longer install head unless explicitly requested. Was there anything else that can be done to make this easier?

@EchoPouet
Copy link
Contributor

I just read this discussion.

In response to @genotrance, we are ok that everybody use git or anything version control system that use tag. So, it can be possible to check if version number in the nimble file corresponds to a existing tag. When a dev use a package without a corresponding tag, a warning can inform his.

Also, to be very strict, the CI of nim-lang/packages can reject a pull request of package without this constraint. I thinks it is necessary, to improve the serious of nim package manager and improve Nim development practice.

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

9 participants