neil icon indicating copy to clipboard operation
neil copied to clipboard

Commands to bump or set version patch | minor | major

Open borkdude opened this issue 3 years ago • 23 comments

Npm has npm version:

$ npm version --help
npm version

Bump a package version

Usage:
npm version [<newversion> | major | minor | patch | premajor | preminor | prepatch | prerelease | from-git]

I think neil could have the same (but for now only these three):

neil version patch
neil version minor
neil version major

similar to what npm does: it increments the current number.

And then use this {:neil {:project {:version ...}}} in build.clj

Npm also creates a git tag but I think we could have this as a separate command:

neil tag

which takes the current version and creates a git tag.

Or does it make sense to do it as npm does it and combine these two?

I think it makes sense to store the version numbers separately: {:major ".." :minor ".." :patch ".." :qualifier ".."} similar to how *clojure-version* is stored.

borkdude avatar Aug 06 '22 18:08 borkdude

We should probably also support setting the patch version to a user-supplied value:

neil version patch $(git commit-count)

borkdude avatar Aug 06 '22 18:08 borkdude

Going to start working on a PR for this.

rads avatar Aug 06 '22 19:08 rads

Sweet!

borkdude avatar Aug 06 '22 19:08 borkdude

@borkdude: Right now we have neil version which prints the version of the neil tool itself:

$ neil version
neil 0.1.43

The equivalent npm version will print out library versions from package.json for the project.

$ npm version
{
  mylib: '1.0.0',
  ...
}

$ npm --version
8.11.0

Since neil version [subcommand] uses deps.edn, not the neil version, I think it would make sense to have neil version work the same way to be consistent.

This would be a breaking change to neil version. We could still support printing the neil version with something like neil --version.

What do you think about this?

rads avatar Aug 06 '22 20:08 rads

Good point. I'm ok with breaking the current neil version.

borkdude avatar Aug 06 '22 20:08 borkdude

Some more thoughts:

In the tools.build Guide, the version is defined as a dynamic value based on the Git commit count:

(ns build
  (:require [clojure.tools.build.api :as b]))

(def version (format "1.2.%s" (b/git-count-revs nil)))

This is the same result as the neil version patch $(git commit-count) example, but it seems like neil version patch is really oriented around manual version bumps? Whereas in the tools.build example, there is no manual version bumping.

  1. Would it make sense to allow a config like this?
    {:neil {:project {:version (format "1.2.%s" (b/git-count-revs nil))}}}
    
  2. If so, would it be useful to have a command like neil version git-count-revs to add this automatically?

Edit: I realize now since this config is inside deps.edn, not bb.edn, we're more limited in what kind of expressions can go in the :version value, so it might not look exactly like the example I provided in practice. Maybe just a symbol with a function name would be enough.

rads avatar Aug 06 '22 20:08 rads

I've personally moved away from git-count-based versioning for a few reasons:

  1. I find commit count not really useful information (vs just the release count).
  2. It complicates releases, in CI you have to check out the full commit history to count the commit, etc (fetch-depth: 0 in github actions).
  3. Larger numbers (babashka now has over 3k commits) are more difficult to remember for users
  4. It requires you to have a git repo (which is almost always true, but not always). In this blog post you can read that I first had to git init etc before I could even clojure -T:build uberjar. I don't think that's great.

Personally I've adopted: major.minor.release-count. So the patch version is incremented on every release and the minor or major version is incremented based on if something important was added but usually stays the same.

This is also why I've updated the build.clj in neil to not use commit count anymore.

borkdude avatar Aug 06 '22 21:08 borkdude

Repeating from the original post:

I think it makes sense to store the version numbers separately: {:major ".." :minor ".." :patch ".." :qualifier ".."} similar to how clojure-version is stored.

borkdude avatar Aug 06 '22 21:08 borkdude

The idea here is to store the latest released version in the deps.edn: that is the source of truth, like in project.clj: not some string or expression that still needs interpolation/evaluation.

borkdude avatar Aug 06 '22 21:08 borkdude

@borkdude: That makes sense to me. I can go ahead with the original plan.

This does make me wonder if the tools.build guide should be updated based on your points above, but that's a separate issue from neil, and not a blocker for this issue.

rads avatar Aug 06 '22 21:08 rads

@borkdude: Coming back to this:

Npm also creates a git tag but I think we could have this as a separate command:

neil tag

which takes the current version and creates a git tag.

Or does it make sense to do it as npm does it and combine these two?

I think since we're already implementing a subset of the npm version interface, we should be consistent with the npm behavior:

If run in a git repo, it will also create a version commit and tag. This behavior is controlled by git-tag-version (see below), and can be disabled on the command line by running npm --no-git-tag-version version. It will fail if the working directory is not clean, unless the -f or --force flag is set.

I think this would be good since neil would "just work" if you're already familiar with npm. In summary:

  • By default we create a commit and tag based on the version (when a Git repo is available)
  • This can be disabled with a --no-git-tag-version flag
  • If the working directory is not clean, -f or --force is required

What do you think about that?

rads avatar Aug 07 '22 00:08 rads

OK, let's do it

borkdude avatar Aug 07 '22 12:08 borkdude

Sweet, I'll get this going! Since this is a new API (for neil at least), I'm happy to update my PR or provide more follow-up PRs if we change our minds on the best interface after trying it out.

rads avatar Aug 07 '22 12:08 rads

I wonder if we should store the version attributes as strings (since perhaps people will use different things) or even as a single string, as this allows people to be more flexible. E.g. clj-kondo uses 2022.08.01 as the version format and clojure-lsp even uses a more elaborate date-based format. If we would have neil version set <...> then people could choose any date format they like. But for most projects, the major/minor/patch format probably works and even for clj-kondo, I think I could use 2022.8.1 instead of the leading zeros. There's also benefit of having consistency across projects.

Should the neil version patch command be more explicit: neil version patch inc and neil version patch set ... perhaps? Maybe I'm overthinking and having the same command set as npm is beneficial.

borkdude avatar Aug 08 '22 09:08 borkdude

Storing the version as a single string has the benefit that you don't need any other libraries to pull it out and use it e.g. in build.clj. Storing the single string is also what other tools like mvn and npm seem to be doing. Maybe we should do that too and parse the version: if it's unparsable as major/minor/patch then users just won't be able to use our neil version patch commands and they are on their own (they could edit the version manually).

borkdude avatar Aug 08 '22 10:08 borkdude

Actually another idea:

It might be better to store this project data inside a resources/META-INF/org/lib/project.edn file instead.

Why? Since CLI tools like neil often want to print their own version and they could just read it uses (edn/read-string (slurp (io/resource "META-INF/babashka/neil/project.edn)))

borkdude avatar Aug 08 '22 10:08 borkdude

  1. I think version as data managed by neil is an amazing idea.
  2. I'm slightly worried about us confusing users about the meaning of "version". Is the idea to move the old neil version to neil --version? --version (short -V) seems to be the convention for most tools I use. Go prints its version with go version.
teodorlu@teod-t490s ~ % ls --version
ls (GNU coreutils) 9.1
Copyright (C) 2022 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Written by Richard M. Stallman and David MacKenzie.

teodorlu@teod-t490s ~ % go version
go version go1.18 linux/amd64

teodorlu@teod-t490s ~ % emacs --version
GNU Emacs 28.1
Copyright (C) 2022 Free Software Foundation, Inc.
GNU Emacs comes with ABSOLUTELY NO WARRANTY.
You may redistribute copies of GNU Emacs
under the terms of the GNU General Public License.
For more information about these matters, see the file named COPYING.

teodorlu@teod-t490s ~ % clojure --version
Clojure CLI version 1.11.1.1155

teodorlu@teod-t490s ~ % java --version
openjdk 18.0.1.1 2022-04-22
OpenJDK Runtime Environment (build 18.0.1.1+2)
OpenJDK 64-Bit Server VM (build 18.0.1.1+2, mixed mode)

teodorlu@teod-t490s ~ % python --version
Python 3.10.5
teodorlu@teod-t490s ~ % python -V
Python 3.10.5

teodorlu@teod-t490s ~ % node --version
v18.6.0
teodorlu@teod-t490s ~ % node -V
/sbin/node: bad option: -V

teodorlu avatar Aug 08 '22 10:08 teodorlu

@teodorlu Already discussed here: https://github.com/babashka/neil/issues/81#issuecomment-1207275456

borkdude avatar Aug 08 '22 10:08 borkdude

It might be better to store this project data inside a resources/META-INF/org/lib/project.edn file instead.

But on the other hand, it has tremendous benefit of having data stored in a predictable location as well.

borkdude avatar Aug 08 '22 10:08 borkdude

Option: neil --neil-version to print neil's version. Assumes the user mostly cares about the version of their own project.

teodorlu avatar Aug 08 '22 10:08 teodorlu

Option: neil version is the subcommand to control project version. But we try to help the user in case they want neil's own version. When we print help text, we can add a little "if you want Neil's own version, please use neil --version".

Kind of like Wikipedia's "may refer to" or "did you mean".

teodorlu avatar Aug 08 '22 10:08 teodorlu

Yes, I think adding a hint in the help seems good. Let's keep neil --version for neil's own version.

borkdude avatar Aug 08 '22 10:08 borkdude

Let's continue discussion different sub-topic here:

https://github.com/babashka/neil/discussions/90

I'll update this issue with conclusions from those discussions.

borkdude avatar Aug 08 '22 10:08 borkdude