Skip to content

Commit 38d7087

Browse files
committed
feat(project createbom): store release relation data
1 parent 974eb52 commit 38d7087

File tree

6 files changed

+26
-14
lines changed

6 files changed

+26
-14
lines changed

ChangeLog.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,12 @@
1414
* CaPyCLI now supports color console output also when running in GitLab CI.
1515
* `bom map` fix: In few cases with --nocache, it added mixed matches to output
1616
BOM, now we assure that only the best mapping results are added.
17+
* `project createbom` stores release relations (`CONTAINED`, `SIDE_BY_SIDE` etc.) as capycli:projectRelation
1718

1819
## 2.7.0
1920

2021
* fix for `bom findsources` for some JavaScript SBOMs.
21-
* `bom show` command also lists purl and source code download url in verbose mode.
22+
* `bom show` command also lists purl and source code download url in verbose mode.
2223
If one of the values is missing and `--forceerror` has been specified, error code 97 is returned.
2324
* `bom show` command also lists license information in verbose mode, but
2425
only for CycloneDX 1.6 and later.

capycli/common/capycli_bom_support.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ class CycloneDxSupport():
6666
CDX_PROP_CLEARING_STATE = "capycli:clearingState"
6767
CDX_PROP_CATEGORIES = "capycli:categories"
6868
CDX_PROP_PROJ_STATE = "capycli:projectClearingState"
69+
CDX_PROP_PROJ_RELATION = "capycli:projectRelation"
6970
CDX_PROP_PROFILE = "siemens:profile"
7071

7172
@staticmethod

capycli/project/create_bom.py

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
import logging
1010
import sys
11-
from typing import Any, Dict, List
11+
from typing import Any, Dict, List, Tuple
1212

1313
from cyclonedx.model import ExternalReferenceType, HashAlgorithm
1414
from cyclonedx.model.bom import Bom
@@ -36,14 +36,13 @@ def get_external_id(self, name: str, release_details: Dict[str, Any]) -> str:
3636

3737
return release_details["externalIds"].get(name, "")
3838

39-
def get_clearing_state(self, proj: Dict[str, Any], href: str) -> str:
40-
"""Returns the clearing state of the given component/release"""
39+
def get_linked_state(self, proj: Dict[str, Any], href: str) -> Tuple[str, str]:
40+
"""Returns project mainline state and relation of the given release"""
4141
rel = proj["linkedReleases"]
4242
for key in rel:
4343
if key["release"] == href:
44-
return key["mainlineState"]
45-
46-
return ""
44+
return (key["mainlineState"], key["relation"])
45+
return ("", "")
4746

4847
def create_project_bom(self, project: Dict[str, Any]) -> List[Component]:
4948
bom: List[Component] = []
@@ -112,9 +111,10 @@ def create_project_bom(self, project: Dict[str, Any]) -> List[Component]:
112111
print_red(" ERROR: unable to access project:" + repr(swex))
113112
sys.exit(ResultCode.RESULT_ERROR_ACCESSING_SW360)
114113

115-
state = self.get_clearing_state(project, href)
116-
if state:
117-
CycloneDxSupport.set_property(rel_item, CycloneDxSupport.CDX_PROP_PROJ_STATE, state)
114+
mainline_state, relation = self.get_linked_state(project, href)
115+
if mainline_state and relation:
116+
CycloneDxSupport.set_property(rel_item, CycloneDxSupport.CDX_PROP_PROJ_STATE, mainline_state)
117+
CycloneDxSupport.set_property(rel_item, CycloneDxSupport.CDX_PROP_PROJ_RELATION, relation)
118118

119119
sw360_id = self.client.get_id_from_href(href)
120120
CycloneDxSupport.set_property(rel_item, CycloneDxSupport.CDX_PROP_SW360ID, sw360_id)

tests/test_base.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -214,10 +214,10 @@ def get_project_for_test() -> Dict[str, Any]:
214214
{
215215
"createdBy": "[email protected]",
216216
"release": "https://my.server.com/resource/api/releases/r002",
217-
"mainlineState": "SPECIFIC",
217+
"mainlineState": "MAINLINE",
218218
"comment": "Automatically updated by SCC",
219219
"createdOn": "2023-03-14",
220-
"relation": "UNKNOWN"
220+
"relation": "DYNAMICALLY_LINKED"
221221
}
222222
],
223223
"_links": {

tests/test_create_bom.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,16 @@ def test_project_by_id(self) -> None:
230230
assert len(ext_refs_vcs) == 1
231231
assert str(ext_refs_vcs[0].url) == release["repository"]["url"]
232232

233+
prj_ml_state = CycloneDxSupport.get_property(cx_comp, CycloneDxSupport.CDX_PROP_PROJ_STATE)
234+
assert prj_ml_state.value == "MAINLINE"
235+
releaseRelation = CycloneDxSupport.get_property(cx_comp, CycloneDxSupport.CDX_PROP_PROJ_RELATION)
236+
assert releaseRelation.value == "DYNAMICALLY_LINKED"
237+
238+
prj_ml_state = CycloneDxSupport.get_property(cdx_bom.components[1], CycloneDxSupport.CDX_PROP_PROJ_STATE)
239+
assert prj_ml_state.value == "SPECIFIC"
240+
releaseRelation = CycloneDxSupport.get_property(cdx_bom.components[1], CycloneDxSupport.CDX_PROP_PROJ_RELATION)
241+
assert releaseRelation.value == "UNKNOWN"
242+
233243
assert cdx_bom.metadata.component is not None
234244
if cdx_bom.metadata.component:
235245
assert cdx_bom.metadata.component.name == project["name"]

tests/test_show_project.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ def test_project_show_by_id(self) -> None:
168168
self.assertTrue("Project owner: [email protected]" in out)
169169
self.assertTrue("Clearing state: IN_PROGRESS" in out)
170170
self.assertTrue("No linked projects" in out)
171-
self.assertTrue("cli-support, 1.3 = SPECIFIC, APPROVED" in out)
171+
self.assertTrue("cli-support, 1.3 = MAINLINE, APPROVED" in out)
172172
self.assertTrue("wheel, 0.38.4 = SPECIFIC, APPROVED" in out)
173173

174174
@responses.activate
@@ -337,7 +337,7 @@ def test_project_show_with_subproject(self) -> None:
337337
self.assertTrue("Clearing state: IN_PROGRESS" in out)
338338
self.assertTrue("Linked projects:" in out)
339339
self.assertTrue("sub-project-dummy, 2.0.1" in out)
340-
self.assertTrue("cli-support, 1.3 = SPECIFIC, APPROVED" in out)
340+
self.assertTrue("cli-support, 1.3 = MAINLINE, APPROVED" in out)
341341
self.assertTrue("wheel, 0.38.4 = SPECIFIC, APPROVED" in out)
342342

343343
self.assertTrue(os.path.isfile(self.OUTPUTFILE), "no output file generated")

0 commit comments

Comments
 (0)