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

[cli] Fix JSON format of CodeChecker version subcommand #3558

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 40 additions & 26 deletions analyzer/codechecker_analyzer/cmd/analyzer_version.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,10 @@
"""
Defines a subcommand for CodeChecker which prints version information.
"""


import argparse
import json

from typing import Dict, List, Tuple
from codechecker_analyzer import analyzer_context

from codechecker_report_converter import twodim
Expand All @@ -21,6 +20,44 @@
from codechecker_common.output import USER_FORMATS


LOG = logger.get_logger('system')


class Version:
def __init__(self):
context = analyzer_context.get_context()

self.version = context.version
self.build_date = context.package_build_date
self.git_hash = context.package_git_hash
self.git_tag = context.package_git_tag

def to_dict(self) -> Dict[str, str]:
""" Get version information in dictionary format. """
return {
"base_package_version": self.version,
"package_build_date": self.build_date,
"git_commit": self.git_hash,
"git_tag": self.git_tag}

def to_list(self) -> List[Tuple[str, str]]:
""" Get version information in list format. """
return [
("Base package version", self.version),
("Package build date", self.build_date),
("Git commit ID (hash)", self.git_hash),
("Git tag information", self.git_tag)]

def print(self, output_format: str):
""" Print analyzer version information in the given format. """
if output_format == "json":
print(json.dumps(self.to_dict()))
else:
LOG.info("CodeChecker analyzer version:")
print(twodim.to_str(
output_format, ["Kind", "Version"], self.to_list()))


def get_argparser_ctor_args():
"""
This method returns a dict containing the kwargs for constructing an
Expand Down Expand Up @@ -58,29 +95,6 @@ def add_arguments_to_parser(parser):
parser.set_defaults(func=main)


def print_version(output_format=None):
"""
Print analyzer version information in the given format.
"""
context = analyzer_context.get_context()

rows = [
("Base package version", context.version),
("Package build date", context.package_build_date),
("Git commit ID (hash)", context.package_git_hash),
("Git tag information", context.package_git_tag)
]

if output_format == "json":
# Use a special JSON format here, instead of
# [ {"kind": "something", "version": "0.0.0"}, {"kind": "foo", ... } ]
# do
# { "something": "0.0.0", "foo": ... }
print(json.dumps(dict(rows)))
else:
print(twodim.to_str(output_format, ["Kind", "Version"], rows))


def main(args):
"""
Get and print the version information from the version config
Expand All @@ -94,4 +108,4 @@ def main(args):

logger.setup_logger(args.verbose if 'verbose' in args else None, stream)

print_version(args.output_format)
Version().print(args.output_format)
42 changes: 26 additions & 16 deletions codechecker_common/cmd/version.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,16 @@
Defines a subcommand for CodeChecker which prints version information.
"""


import argparse
import json

from codechecker_common import logger
from codechecker_common.output import USER_FORMATS


LOG = logger.get_logger('system')


def get_argparser_ctor_args():
"""
This method returns a dict containing the kwargs for constructing an
Expand Down Expand Up @@ -61,25 +64,32 @@ def main(args):

output_format = args.output_format

has_analyzer_version = False
# Get analyzer version information if the module is available.
analyzer_version = None
try:
from codechecker_analyzer.cmd import analyzer_version
has_analyzer_version = True

# Print analyzer version information.
print("CodeChecker analyzer version:")
analyzer_version.print_version(output_format)
from codechecker_analyzer.cmd.analyzer_version import Version
analyzer_version = Version()
except Exception:
pass

# Get web version information if the module is available.
web_version = None
try:
from codechecker_web.cmd import web_version

if has_analyzer_version:
print() # Print a new line to separate version information.

# Print web server version information.
print("CodeChecker web version:")
web_version.print_version(output_format)
from codechecker_web.cmd.web_version import Version
web_version = Version()
except Exception:
pass

# Print the version information.
if output_format == "json":
print(json.dumps({
"analyzer":
analyzer_version.to_dict() if analyzer_version else None,
"web": web_version.to_dict() if web_version else None}))
else:
if analyzer_version:
analyzer_version.print(output_format)
print()

if web_version:
web_version.print(output_format)
44 changes: 44 additions & 0 deletions docs/web/user_guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ Table of Contents
* [`login` (Authenticate to the server)](#cmd-login)
* [`export` (Export comments and review statuses from CodeChecker)](#cmd-export)
* [`import` (Import comments and review statuses into CodeChecker)](#cmd-import)
* [`version`](#version)
* [JSON format](#json-format)
* [Debugging CodeChecker](#debug)

# CodeChecker <a name="codechecker"></a>
Expand Down Expand Up @@ -1677,6 +1679,7 @@ common arguments:
--verbose {info,debug_analyzer,debug}
Set verbosity level.
```
</details>

### Authenticate to the server (`login`) <a name="cmd-login"></a>
<details>
Expand Down Expand Up @@ -1766,6 +1769,47 @@ optional arguments:
Import findings from the json file into the database.
```

## `version`
### JSON format
The JSON output format looks like this:
```json
{
"analyzer": {
"base_package_version": "6.19.0",
"package_build_date": "2021-12-15T16:07",
"git_commit": "ed16b5d58f75002b465ea0944be0abf071f0b958",
"git_tag": "6.19"
},
"web": {
"base_package_version": "6.19.0",
"package_build_date": "2021-12-15T16:07",
"git_commit": "ed16b5d58f75002b465ea0944be0abf071f0b958",
"git_tag": "6.19",
"server_api_version": [
"6.47"
],
"client_api_version": "6.47"
}
}
```

In JSON output we have two main sections:
- `analyzer` (null | object): Analyzer version information if it's available.
- `base_package_version` (string): Base package version in
`<major>.<minor>.<revision>` format.
- `package_build_date` (string): Date time when the package was built.
- `git_commit` (null | string): Git commit ID (hash).
- `git_tag` (null | string): Git tag information.
- `web` (null | object): Web version information if it's available.
- `base_package_version` (string): Base package version in
`<major>.<minor>.<revision>` format.
- `package_build_date` (string): Date time when the package was built.
- `git_commit` (null | string): Git commit ID (hash).
- `git_tag` (null | string): Git tag information.
- `server_api_version` (list[string]): Server supported Thrift API version.
- `client_api_version` (str): Client Thrift API version.


# Debugging CodeChecker <a name="debug"></a>

To change the log levels check out the [logging](../logging.md) documentation.
86 changes: 51 additions & 35 deletions web/codechecker_web/cmd/web_version.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
import argparse
import json

from typing import Dict, List, Tuple

from codechecker_report_converter import twodim

from codechecker_common import logger
Expand All @@ -21,6 +23,54 @@
from codechecker_web.shared import webserver_context, version


LOG = logger.get_logger('system')


class Version:
def __init__(self):
context = webserver_context.get_context()

self.server_versions = [
f'{major}.{minor}'
for major, minor in version.SUPPORTED_VERSIONS.items()]

self.version = context.version
self.build_date = context.package_build_date
self.git_hash = context.package_git_hash
self.git_tag = context.package_git_tag
self.client_api = version.CLIENT_API

def to_dict(self) -> Dict[str, str]:
""" Get version information in dictionary format. """
return {
"base_package_version": self.version,
"package_build_date": self.build_date,
"git_commit": self.git_hash,
"git_tag": self.git_tag,
"server_api_version": self.server_versions,
"client_api_version": self.client_api}

def to_list(self) -> List[Tuple[str, str]]:
""" Get version information in list format. """
server_versions = ', '.join(self.server_versions)
return [
("Base package version", self.version),
("Package build date", self.build_date),
("Git commit ID (hash)", self.git_hash),
("Git tag information", self.git_tag),
("Server supported Thrift API version", server_versions),
("Client Thrift API version", self.client_api)]

def print(self, output_format: str):
""" Print web server version information in the given format. """
if output_format == "json":
print(json.dumps(self.to_dict()))
else:
LOG.info("CodeChecker web version:")
print(twodim.to_str(
output_format, ["Kind", "Version"], self.to_list()))


def get_argparser_ctor_args():
"""
This method returns a dict containing the kwargs for constructing an
Expand Down Expand Up @@ -58,40 +108,6 @@ def add_arguments_to_parser(parser):
parser.set_defaults(func=main)


def print_version(output_format=None):
"""
Print web server version information in the given format.
"""
context = webserver_context.get_context()

server_versions = ['{0}.{1}'.format(major, minor) for
major, minor in
version.SUPPORTED_VERSIONS.items()]

if output_format != 'json':
server_versions = ', '.join(server_versions)

rows = [
("Base package version", context.version),
("Package build date", context.package_build_date),
("Git commit ID (hash)", context.package_git_hash),
("Git tag information", context.package_git_tag),
("Server supported API (Thrift)", server_versions),
("Client API (Thrift)", version.CLIENT_API)
]

if output_format != "json":
print(twodim.to_str(output_format,
["Kind", "Version"],
rows))
elif output_format == "json":
# Use a special JSON format here, instead of
# [ {"kind": "something", "version": "0.0.0"}, {"kind": "foo", ... } ]
# do
# { "something": "0.0.0", "foo": ... }
print(json.dumps(dict(rows)))


def main(args):
"""
Get and print the version information from the version config
Expand All @@ -105,4 +121,4 @@ def main(args):

logger.setup_logger(args.verbose if 'verbose' in args else None, stream)

print_version(args.output_format)
Version().print(args.output_format)