diff --git a/CHANGELOG.md b/CHANGELOG.md index 45f6fba1..ece4a242 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,8 @@ ### 0.9.18-dev +* The `lobster-codebeamer` tool now supports `refs` as upstream reference + * The `lobster-codebeamer` tool now allows items without summary * The `lobster-codebeamer` tool now uses codebeamer api v3. diff --git a/lobster/tools/codebeamer/codebeamer.py b/lobster/tools/codebeamer/codebeamer.py index 3d1e4e5c..3ee65b30 100755 --- a/lobster/tools/codebeamer/codebeamer.py +++ b/lobster/tools/codebeamer/codebeamer.py @@ -41,6 +41,8 @@ import argparse import netrc from urllib.parse import quote +from enum import Enum +import json import requests from lobster.items import Tracing_Tag, Requirement @@ -49,6 +51,26 @@ from lobster.io import lobster_read, lobster_write +class References(Enum): + REFS = "refs" + + +SUPPORTED_REFERENCES = [References.REFS.value] + + +def add_refs_refrences(req, flat_values_list): + # refs + for value in flat_values_list: + if value.get("id"): + ref_id = value.get("id") + req.add_tracing_target(Tracing_Tag("req", str(ref_id))) + + +map_reference_name_to_function = { + References.REFS.value: add_refs_refrences +} + + def query_cb_single(cb_config, url): assert isinstance(cb_config, dict) assert isinstance(url, str) @@ -193,6 +215,30 @@ def to_lobster(cb_config, cb_item): text = None, status = status) + if cb_config.get('references'): + for reference_name, displayed_chosen_names in ( + cb_config['references'].items()): + if reference_name not in map_reference_name_to_function.keys(): + continue + + for displayed_name in displayed_chosen_names: + if cb_item.get(displayed_name): + flat_values_list = cb_item.get(displayed_name) if ( + isinstance(cb_item.get(displayed_name), list)) \ + else [cb_item.get(displayed_name)] + else: + flat_values_list = ( + list(value for custom_field + in cb_item["customFields"] + if custom_field["name"] == displayed_name and + custom_field.get("values") + for value in custom_field["values"])) + if not flat_values_list: + continue + + (map_reference_name_to_function[reference_name] + (req, flat_values_list)) + return req @@ -210,6 +256,36 @@ def import_tagged(mh, cb_config, items_to_import): return rv +def ensure_array_of_strings(instance): + if (isinstance(instance, list) and + all(isinstance(item, str) + for item in instance)): + return instance + else: + return [str(instance)] + + +def parse_cb_config(file_name): + assert isinstance(file_name, str) + assert os.path.isfile(file_name) + + with open(file_name, "r") as file: + data = json.loads(file.read()) + + provided_config_keys = set(data.keys()) + supported_references = set(SUPPORTED_REFERENCES) + + if not provided_config_keys.issubset(supported_references): + raise Exception("The provided references are not supported! " + "supported referenes: '%s'" % + ', '.join(SUPPORTED_REFERENCES)) + + json_config = {} + for key, value in data.items(): + json_config[key] = ensure_array_of_strings(value) + return json_config + + def main(): ap = argparse.ArgumentParser() @@ -217,10 +293,17 @@ def main(): modes.add_argument("--import-tagged", metavar="LOBSTER_FILE", default=None) + modes.add_argument("--import-query", metavar="CB_QUERY_ID", default=None) + ap.add_argument("--config", + help=("name of codebeamer " + "config file, supported references: '%s'" % + ', '.join(SUPPORTED_REFERENCES)), + default=None) + ap.add_argument("--ignore-ssl-errors", action="store_true", default=False, @@ -254,6 +337,12 @@ def main(): "timeout" : options.timeout, } + if options.config: + if os.path.isfile(options.config): + cb_config["references"] = parse_cb_config(options.config) + else: + ap.error("cannot open config file '%s'" % options.config) + if cb_config["root"] is None: ap.error("please set CB_ROOT or use --cb-root") diff --git a/packages/lobster-tool-codebeamer/README.md b/packages/lobster-tool-codebeamer/README.md index d5eb22fb..ce076c38 100644 --- a/packages/lobster-tool-codebeamer/README.md +++ b/packages/lobster-tool-codebeamer/README.md @@ -13,6 +13,30 @@ requirements management tool * `lobster-codebeamer`: Extrat requirements from codebeamer. +## Configuration +This tool works with an optional config file. In it you can declare which +codebeamer fields should be used as 'refs' reference in the codebeamer file. + +For the 'refs' reference in config file you can write: + +``` +{ +"refs" : "cb-fieldname" +} +``` +or +``` +{ +"refs" : ["cb-fieldname"] +} +``` +or +``` +{ +"refs" : ["cb-fieldname1", "cb-fieldname2"] +} +``` + ## Usage There are two ways you can use this tool: @@ -21,7 +45,9 @@ There are two ways you can use this tool: way you do not get a completeness check) (using `--import-tagged`) * Download all requirements generated by a saved codebeamer query - (using `--import-query`) + +* Configure the 'refs' upstream reference (this argument is optional) +(using `--config`) ## Limitations