Repository: conan-io/conan
Pull request: Add conan version as separated command
Changelog: Feature: Add new command `conan version` to format the output.
Docs: https://github.com/conan-io/docs/pull/3243

The `--version` option stays as usual, but `conan version` offer format output.

closes https://github.com/conan-io/conan/issues/13952

- [x] Refer to the issue that supports this Pull Request.
- [x] If the issue has missing info, explain the purpose/use case/pain/need that covers this Pull Request.
- [x] I've read the [Contributing guide](https://github.com/conan-io/conan/blob/develop/.github/CONTRIBUTING.md).
- [x] I've followed the PEP8 style guides for Python code.
- [x] I've opened another PR in the Conan docs repo to the ``develop`` branch, documenting this one.


Problem statement:
[feature] Include `conan --version` command in `conan --help` text
### What is your suggestion?

Hi, 

1. When I use, `conan --help` command, I can see help text message around `conan --version`. Currently, `conan --version`  command is hidden and not documented in help message. This is so, as a user I can identify which conan version I'm using easily.
2. When I use, `conan --version` command, I can retrieve version, of conan.
3. When I use, `conan --version json` command, I can retrieve machine-readable version, of conan.
4. When I use, `conan --version json` command, I can retrieve machine-readable version, of python. This is so, I can easily see which python environment is being used by conan, as this is a field requested when creating a bug report. 

Maybe something like this:
**`conan --help`** and **`conan`**
```bash
~/code/sbom (feat/conan-sbom) » conan  --help

Options
--version [FORMAT] Prints conan version in format. Valid format options are: text, json. By default, text is chosen. 

Consumer commands
...

Creator commands
...

Type "conan <command> -h" for help
```


**`conan --version`**
```bash
~/code/sbom (feat/conan-sbom) » conan  --version
Conan version 2.0.5
```

**`conan --version json`**
```bash
~/code/sbom (feat/conan-sbom) » conan  --version json
{
   "conan": {
       "version": "x.x.x",
    },
   "python": {
       "version": "x.x.x",
   }
}
```

### Have you read the CONTRIBUTING guide?

- [X] I've read the CONTRIBUTING guide

Hints from issue discussion:
Hi @meghfossa 

Thanks for your suggestion.

However, I think this proposal goes a bit too far. Basically all other tools out there do not implement anything remotely similar. ``cmake --version``, ``gcc --version``, etc, which one is expected to be able to give a json output? None of them. Furthermore, reporting also a sub-tool like Python version in the return is also too much. The expectation for dev tools for ``xxx --version`` is outputting some plain text with the version number included plus other details, but not json output.

If you want to control the Conan version, you have the ``required_conan_version`` that you can use both in the recipes and in your ``global.conf`` (as ``core:required_conan_version``).
> However, I think this proposal goes a bit too far. Basically all other tools out there do not implement anything remotely similar. cmake --version, gcc --version, etc, which one is expected to be able to give a json output? None of them. Furthermore, reporting also a sub-tool like Python version in the return is also too much. The expectation for dev tools for xxx --version is outputting some plain text with the version number included plus other details, but not json output.

That's fair. But I do think including `--version` command explicitly in help text or even when you just run `conan` is helpful.

As a additional datapoint, I've added few popular app/pkg-manager that I've come across in past that either include additional attrs (rel dep) or provide machine-readable formatting. 

```
>> cargo version -vv
cargo 1.64.0 (387270bc7 2022-09-16)
release: 1.64.0
commit-hash: 387270bc7f446d17869c7f208207c73231d6a252
commit-date: 2022-09-16
host: x86_64-apple-darwin
libgit2: 1.4.2 (sys:0.14.2 vendored)
libcurl: 7.87.0 (sys:0.4.55+curl-7.83.1 system ssl:(SecureTransport) LibreSSL/3.3.6)
os: Mac OS 13.3.0 [64-bit]

>> npm version
{
  npm: '9.5.0',
  node: '18.15.0',
  v8: '10.2.154.26-node.25',
  uv: '1.44.2',
  zlib: '1.2.13',
  brotli: '1.0.9',
  ares: '1.18.1',
  modules: '108',
  nghttp2: '1.51.0',
  napi: '8',
  llhttp: '6.0.10',
  uvwasi: '0.0.15',
  acorn: '8.8.2',
  simdutf: '3.1.0',
  undici: '5.20.0',
  openssl: '3.0.8+quic',
  cldr: '42.0',
  icu: '72.1',
  tz: '2022g',
  unicode: '15.0',
  ngtcp2: '0.8.1',
  nghttp3: '0.7.0'
}

>> docker version --format json
{....}

>> podman version --format json
{....}

>> gradle --version
------------------------------------------------------------
Gradle 8.1.1
------------------------------------------------------------

Build time:   2023-04-21 12:31:26 UTC
Revision:     1cf537a851c635c364a4214885f8b9798051175b

Kotlin:       1.8.10
Groovy:       3.0.15
Ant:          Apache Ant(TM) version 1.10.11 compiled on July 10 2021
JVM:          17.0.7 (Homebrew 17.0.7+0)
OS:           Mac OS X 13.3 aarch64
>> ...
```
Good point.
Lets re-consider it, but not as ``--version``, that would break the CLI design and make the implementation dirty. We can consider a ``conan version --format=json`` command.
Lets go for it, lets do it

Commit message: Add conan version command

Signed-off-by: Uilian Ries <uilianries@gmail.com>

Patch to review:
diff --git a/conan/cli/commands/version.py b/conan/cli/commands/version.py
new file mode 100644
index 00000000000..0a388002fe5
--- /dev/null
+++ b/conan/cli/commands/version.py
@@ -0,0 +1,21 @@
+import os
+
+from conan.api.output import cli_out_write
+from conan.cli.command import conan_command
+from conan.cli.formatters import default_json_formatter
+from conan import conan_version
+
+
+def version_text_formatter(version):
+    cli_out_write(f"Conan version {version['version']}")
+
+
+@conan_command(group="Consumer", formatters={"text": version_text_formatter, "json": default_json_formatter})
+def version(conan_api, parser, *args):
+    """
+    Give information about the Conan client version.
+    """
+
+    result = {'version': str(conan_version)}
+    return result
+
diff --git a/conans/test/integration/command_v2/test_version.py b/conans/test/integration/command_v2/test_version.py
new file mode 100644
index 00000000000..5f523fdf11f
--- /dev/null
+++ b/conans/test/integration/command_v2/test_version.py
@@ -0,0 +1,19 @@
+from conans.test.utils.tools import TestClient
+
+
+def test_version_json():
+    t = TestClient()
+    t.run("version --format=json")
+    assert ['{', '    "version": "2.0.4"', '}'] == t.out.splitlines()
+
+
+def test_version_text():
+    t = TestClient()
+    t.run("version --format=text")
+    assert ['Conan version 2.0.4'] == t.out.splitlines()
+
+
+def test_version_raw():
+    t = TestClient()
+    t.run("version")
+    assert ['Conan version 2.0.4'] == t.out.splitlines()


Code review comments:
diff_hunk: @@ -0,0 +1,19 @@
+from conans.test.utils.tools import TestClient
+
+
+def test_version_json():
+    t = TestClient()
+    t.run("version --format=json")
+    assert ['{', '    "version": "2.0.4"', '}'] == t.out.splitlines()
path: conans/test/integration/command_v2/test_version.py
text: @user1:
```suggestion
    t.run("version --format=json")
    js = json.loads(t.stdout)
    assert js["version"] == __version__
```
These tests will fail whenever there is a version bump. They need to be parameterized using the current ``__version__``

@author:
Fixed. I forgot to replace hardcoded values 🤦

diff_hunk: @@ -0,0 +1,21 @@
+import os
+
+from conan.api.output import cli_out_write
+from conan.cli.command import conan_command
+from conan.cli.formatters import default_json_formatter
+from conan import conan_version
+
+
+def version_text_formatter(version):
+    cli_out_write(f"Conan version {version['version']}")
path: conan/cli/commands/version.py
text: @user1:
Make it a generic ``k: v`` printing

@author:
Done, but I printed a bit more friendly, like:

```
% conan version
version: 2.0.6
python.version: 3.10.4
python.sys_version: 3.10.4 (main, May 17 2022, 10:53:07) [Clang 13.1.6 (clang-1316.0.21.2.3)]
```

diff_hunk: @@ -0,0 +1,21 @@
+import os
+
+from conan.api.output import cli_out_write
+from conan.cli.command import conan_command
+from conan.cli.formatters import default_json_formatter
+from conan import conan_version
+
+
+def version_text_formatter(version):
+    cli_out_write(f"Conan version {version['version']}")
+
+
+@conan_command(group="Consumer", formatters={"text": version_text_formatter, "json": default_json_formatter})
+def version(conan_api, parser, *args):
+    """
+    Give information about the Conan client version.
+    """
+
+    result = {'version': str(conan_version)}
path: conan/cli/commands/version.py
text: @user1:
Add the Python version too. Probably as ``python: {version: version, sys_version: full sys-verssion}``, just to leave room for other further data in the future, like vers

@author:
Done, printing Python version now.