diff --git a/CHANGELOG.md b/CHANGELOG.md index 457ea869..0be354b0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,8 +4,13 @@ ### 0.9.18-dev -* The `lobster-codebeamer` tool now uses an authentication token. - Token can be added either in the config file or as an argument. +* Add support to `lobster-codebeamer` to generate output using the following schemas: + - requirement + - implementation + - activity + + The user can select the schema with a command line flag, + or through the configuration file. * The `lobster-python` tool adds the counter logic to the function identifier. This improves the situations where different functions have diff --git a/lobster/tools/codebeamer/codebeamer.py b/lobster/tools/codebeamer/codebeamer.py index 2b9d7746..794c6cc6 100755 --- a/lobster/tools/codebeamer/codebeamer.py +++ b/lobster/tools/codebeamer/codebeamer.py @@ -45,7 +45,7 @@ import json import requests -from lobster.items import Tracing_Tag, Requirement +from lobster.items import Tracing_Tag, Requirement, Implementation, Activity from lobster.location import Codebeamer_Reference from lobster.errors import Message_Handler, LOBSTER_Error from lobster.io import lobster_read, lobster_write @@ -56,9 +56,10 @@ class References(Enum): REFS = "refs" + SCHEMA = "schema" -SUPPORTED_REFERENCES = [References.REFS.value] +SUPPORTED_REFERENCES = [References.REFS.value, References.SCHEMA.value] def add_refs_refrences(req, flat_values_list): @@ -194,6 +195,11 @@ def to_lobster(cb_config, cb_item): assert isinstance(cb_config, dict) assert isinstance(cb_item, dict) and "id" in cb_item + schema_map = {'implementation', 'requirement', 'activity'} + schema = cb_config.get("schema", "requirement").lower() + if schema not in schema_map: + raise LOBSTER_Error(f"Unsupported SCHEMA '{schema}' provided in configuration.") + # This looks like it's business logic, maybe we should make this # configurable? @@ -217,20 +223,46 @@ def to_lobster(cb_config, cb_item): else: item_name = "Unnamed item %u" % cb_item["id"] - req = Requirement( - tag = Tracing_Tag(namespace = "req", - tag = str(cb_item["id"]), - version = cb_item["version"]), - location = Codebeamer_Reference(cb_root = cb_config["root"], - tracker = cb_item["tracker"]["id"], - item = cb_item["id"], - version = cb_item["version"], - name = item_name), - framework = "codebeamer", - kind = kind, - name = item_name, - text = None, - status = status) + # Create common parameters for all kinds + common_params = { + 'tag': Tracing_Tag( + namespace="req" if schema == 'requirement' else "imp" if schema == 'implementation' else "act", + tag=str(cb_item["id"]), + version=cb_item["version"] + ), + 'location': Codebeamer_Reference( + cb_root=cb_config["root"], + tracker=cb_item["tracker"]["id"], + item=cb_item["id"], + version=cb_item["version"], + name=item_name + ), + 'kind': kind + } + # Construct the appropriate object based on 'kind' + + if schema == 'requirement': + req = Requirement( + **common_params, + framework="codebeamer", + text=None, + status=status, + name= item_name + ) + + elif schema == 'implementation': + req = Implementation( + **common_params, + language="python", + name= item_name, + ) + + else: # 'activity' + req = Activity( + **common_params, + framework="codebeamer", + status=status + ) if cb_config.get(REFERENCES): for reference_name, displayed_chosen_names in ( @@ -294,6 +326,11 @@ def parse_cb_config(file_name): if TOKEN in data: json_config["token"] = data.pop(TOKEN) + schema = data.get("schema", "Requirement").lower() + schema_map = {'implementation', 'requirement', 'activity'} + if schema not in schema_map: + raise LOBSTER_Error(f"Unsupported SCHEMA '{schema}' provided in configuration.") + provided_config_keys = set(data.keys()) supported_references = set(SUPPORTED_REFERENCES) @@ -305,6 +342,10 @@ def parse_cb_config(file_name): for key, value in data.items(): json_config[REFERENCES][key] = ensure_array_of_strings(value) + json_config[key] = ensure_array_of_strings(value) + + json_config["schema"] = schema + return json_config @@ -341,6 +382,11 @@ def main(): default=30, help="Timeout in s (by default 30) for each REST call.") + ap.add_argument("--schema", + default='requirement', + help="Specify the output schema (Requirement, Implementation, Activity)." + ) + ap.add_argument("--cb-root", default=os.environ.get("CB_ROOT", None)) ap.add_argument("--cb-user", default=os.environ.get("CB_USERNAME", None)) ap.add_argument("--cb-pass", default=os.environ.get("CB_PASSWORD", None)) @@ -351,6 +397,7 @@ def main(): mh = Message_Handler() cb_config = { + 'schema' : options.schema, "root" : options.cb_root, "base" : "%s/cb/api/v3" % options.cb_root, "user" : options.cb_user, @@ -433,14 +480,18 @@ def main(): except LOBSTER_Error: return 1 - if options.out is None: - lobster_write(sys.stdout, Requirement, "lobster_codebeamer", items) - print() - else: - with open(options.out, "w", encoding="UTF-8") as fd: - lobster_write(fd, Requirement, "lobster_codebeamer", items) - print("Written %u requirements to %s" % (len(items), - options.out)) + schema_map = { + "requirement": Requirement, + "implementation": Implementation, + "activity": Activity + } + + schema_obj = schema_map.get(cb_config["schema"].lower(), Requirement) + output = sys.stdout if options.out is None else open(options.out, "w", encoding="UTF-8") + with output as fd: + lobster_write(fd, schema_obj, "lobster_codebeamer", items) + if options.out: + print(f"Written {len(items)} requirements to {options.out}") return 0 diff --git a/packages/lobster-tool-codebeamer/README.md b/packages/lobster-tool-codebeamer/README.md index 06cf3545..e9e46bad 100644 --- a/packages/lobster-tool-codebeamer/README.md +++ b/packages/lobster-tool-codebeamer/README.md @@ -11,81 +11,48 @@ requirements management tool ## Tools -* `lobster-codebeamer`: Extrat requirements from codebeamer. +* `lobster-codebeamer`: Extract requirements from codebeamer. ## Configuration -This tool works with an optional config file. -It allows to configure the following features: - -### References -Codebeamer items can reference other items through -[Reference Fields](https://support.ptc.com/help/codebeamer/r2.1/en/index.html#page/codebeamer/user_guide/ug_reference_fields.html). -This piece of information can be extracted by the tool, and serialized into the -LOBSTER output file. -It only needs to know which fields to take into account. -Following the LOBSTER JSON schema, the item references will be added to the -`refs` property of the LOBSTER item. -Accordingly, the configuration parameter to specify the codebeamer field names -is called `refs`, too. -It can contain a single field name, or a list of field names. -Field IDs cannot be used, only the field names. - -Examples: -```json -{ - "refs" : "cb-fieldname" -} -``` -or -```json -{ - "refs" : ["cb-fieldname"] -} -``` -or -```json -{ - "refs" : ["cb-fieldname1", "cb-fieldname2"] -} -``` - -### Bearer Authentication Token -It is also possible to define the Bearer authentication token in the -configuration file: -```json -{ - "token" : "your-codebeamer-Bearer-token" -} -``` -Note: -- The Bearer authentication token can also be provided as a command line - argument (use `--cb-token=your-codebeamer-Bearer-token`). -- If the token is provided in the configuration file and as command line - argument, then the configuration file takes precedence. -- If `--cb-user` or `--cb-pass` is given together with a Bearer token (either - as a command line argument or through the configuration file), then the - Bearer authentication method is used, and the username and/or password are - ignored. -- If neither a token nor a username or password are given, then the tool tries - to read the username and password from the `.netrc` file in the user's home - directory. - -### Example Configuration -Here is an example configuration file: -```json -{ - "refs" : ["derived from", "satisfied by"], - "token" : "SomeTokenStringABC123" -} -``` - -Is it also possible to define the codebeamer token in this file: -``` -{ -"refs" : "cb-fieldname", -"token" : "your cb-token" -} -``` + +* 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"] + } + ``` + +* Schema (kind) + + You can also specify the type of schema for the resulting output file. The supported values for the kind field are: + 1. Activity: Sets the schema to lobster-act-trace. + 2. Implementation: Sets the schema to lobster-imp-trace. + 3. Requirement: Sets the schema to lobster-req-trace. + + If the kind is not specified, the tool will default to Requirement, and the schema lobster-req-trace will be used. + + Here’s an example configuration: + `json code:` {"kind": "Activity", // Specifies schema + "refs": ["custom_ref_1", "custom_ref_2"] // Specifies references + } + + If an invalid kind is provided, the tool will raise an exception. Supported kind values are Activity, Implementation, and Requirement. ## Usage @@ -97,6 +64,21 @@ There are two ways you can use this tool: 2. Download all requirements generated by a saved codebeamer query (using `--import-query`) +* Configure the 'refs' upstream reference (this argument is optional) +(using `--config`) + +* Additionally, you can specify the schema and references: + + 1. Specify the kind of trace to be generated (optional, defaults to Requirement) + using the --schema argument, or configure it in the config file. + 2. Configure the 'refs' upstream reference (optional) using --config or + specify directly via command line. + + * For example: + ``` codepython lobster_codebeamer.py --config lobster-codebeamer-config.json --schema "Activity" --references "custom_ref_1``` + + This command will extract activity traces (lobster-act-trace) with specified references. + ## Limitations The key limitation is item text, which is currently not