Skip to content

Commit

Permalink
fix(project create): optimize release state handling on update
Browse files Browse the repository at this point in the history
Instead of storing all release states before project update and
restoring it in a big loop afterwards, SW360 REST API also allows to
pass full release information during release update.

We however don't keep the release states set in SW360, but use the
states provided in the SBOM.
  • Loading branch information
gernot-h committed Feb 5, 2025
1 parent 86ce234 commit 1df7aaa
Show file tree
Hide file tree
Showing 2 changed files with 13 additions and 41 deletions.
1 change: 1 addition & 0 deletions ChangeLog.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
## UNRELEASED

* `project createbom` stores release relations (`CONTAINED`, `SIDE_BY_SIDE` etc.) as capycli:projectRelation
* fix slowdown/crash in `project update` for large projects (#121) introduced in 2.7.0

## 2.7.0

Expand Down
53 changes: 12 additions & 41 deletions capycli/project/create_project.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,9 @@ def __init__(self, onlyUpdateProject: bool = False) -> None:
self.onlyUpdateProject = onlyUpdateProject
self.project_mainline_state: str = ""

def bom_to_release_list(self, sbom: Bom) -> List[str]:
"""Creates a list with linked releases"""
linkedReleases = []
def bom_to_release_list(self, sbom: Bom) -> Dict[str, Any]:
"""Creates a list with linked releases from the SBOM."""
linkedReleases: Dict[str, Any] = {}

for cx_comp in sbom.components:
rid = CycloneDxSupport.get_property_value(cx_comp, CycloneDxSupport.CDX_PROP_SW360ID)
Expand All @@ -45,31 +45,17 @@ def bom_to_release_list(self, sbom: Bom) -> List[str]:
+ ", " + str(cx_comp.version))
continue

linkedReleases.append(rid)

return linkedReleases

def get_release_project_mainline_states(self, project: Optional[Dict[str, Any]]) -> List[Dict[str, Any]]:
pms: List[Dict[str, Any]] = []
if not project:
return pms
linkedReleases[rid] = {}

if "linkedReleases" not in project:
return pms
mainlineState = CycloneDxSupport.get_property_value(cx_comp, CycloneDxSupport.CDX_PROP_PROJ_STATE)
if mainlineState:
linkedReleases[rid]["mainlineState"] = mainlineState
relation = CycloneDxSupport.get_property_value(cx_comp, CycloneDxSupport.CDX_PROP_PROJ_RELATION)
if relation:
# No typo. In project structure, it's "relation", while release update API uses "releaseRelation".
linkedReleases[rid]["releaseRelation"] = relation

for release in project["linkedReleases"]: # NOT ["sw360:releases"]
pms_release = release.get("release", "")
if not pms_release:
continue
pms_state = release.get("mainlineState", "OPEN")
pms_relation = release.get("relation", "UNKNOWN")
pms_entry: Dict[str, Any] = {}
pms_entry["release"] = pms_release
pms_entry["mainlineState"] = pms_state
pms_entry["new_relation"] = pms_relation
pms.append(pms_entry)

return pms
return linkedReleases

def update_project(self, project_id: str, project: Optional[Dict[str, Any]],
sbom: Bom, project_info: Dict[str, Any]) -> None:
Expand All @@ -79,7 +65,6 @@ def update_project(self, project_id: str, project: Optional[Dict[str, Any]],
sys.exit(ResultCode.RESULT_ERROR_ACCESSING_SW360)

data = self.bom_to_release_list(sbom)
pms = self.get_release_project_mainline_states(project)

ignore_update_elements = ["name", "version"]
# remove elements from list because they are handled separately
Expand Down Expand Up @@ -114,20 +99,6 @@ def update_project(self, project_id: str, project: Optional[Dict[str, Any]],
if not result2:
print_red(" Error updating project!")

if pms and project:
print_text(" Restoring original project mainline states...")
for pms_entry in pms:
update_release = False
for r in project.get("linkedReleases", []):
if r["release"] == pms_entry["release"]:
update_release = True
break

if update_release:
rid = self.client.get_id_from_href(pms_entry["release"])
self.client.update_project_release_relationship(
project_id, rid, pms_entry["mainlineState"], pms_entry["new_relation"], "")

except SW360Error as swex:
if swex.response is None:
print_red(" Unknown error: " + swex.message)
Expand Down

0 comments on commit 1df7aaa

Please sign in to comment.