Skip to content

Commit 61dd1b2

Browse files
author
Michael Schlenker
committed
Allow serializing of patches with resolves nodes for xml
Signed-off-by: Michael Schlenker <[email protected]>
1 parent 6c0c174 commit 61dd1b2

File tree

4 files changed

+321
-22
lines changed

4 files changed

+321
-22
lines changed

cyclonedx/output/xml.py

+27-22
Original file line numberDiff line numberDiff line change
@@ -428,27 +428,7 @@ def _add_release_notes_element(release_notes: ReleaseNotes, parent_element: Elem
428428
for tag in release_notes.tags:
429429
ElementTree.SubElement(release_notes_tags_e, 'tag').text = tag
430430
if release_notes.resolves:
431-
release_notes_resolves_e = ElementTree.SubElement(release_notes_e, 'resolves')
432-
for issue in release_notes.resolves:
433-
issue_e = ElementTree.SubElement(
434-
release_notes_resolves_e, 'issue', {'type': issue.type.value}
435-
)
436-
if issue.id:
437-
ElementTree.SubElement(issue_e, 'id').text = issue.id
438-
if issue.name:
439-
ElementTree.SubElement(issue_e, 'name').text = issue.name
440-
if issue.description:
441-
ElementTree.SubElement(issue_e, 'description').text = issue.description
442-
if issue.source:
443-
issue_source_e = ElementTree.SubElement(issue_e, 'source')
444-
if issue.source.name:
445-
ElementTree.SubElement(issue_source_e, 'name').text = issue.source.name
446-
if issue.source.url:
447-
ElementTree.SubElement(issue_source_e, 'url').text = str(issue.source.url)
448-
if issue.references:
449-
issue_references_e = ElementTree.SubElement(issue_e, 'references')
450-
for reference in issue.references:
451-
ElementTree.SubElement(issue_references_e, 'url').text = str(reference)
431+
Xml._add_resolves_element(release_notes.resolves, release_notes_e)
452432
if release_notes.notes:
453433
release_notes_notes_e = ElementTree.SubElement(release_notes_e, 'notes')
454434
for note in release_notes.notes:
@@ -473,9 +453,34 @@ def add_patch_element(patch: Patch) -> ElementTree.Element:
473453
diff_element.append(Xml._add_attached_text(attached_text=patch.diff.text))
474454
if patch.diff.url:
475455
ElementTree.SubElement(diff_element, 'url').text = str(patch.diff.url)
476-
456+
if patch.resolves:
457+
Xml._add_resolves_element(patch.resolves, patch_element)
477458
return patch_element
478459

460+
@staticmethod
461+
def _add_resolves_element(resolves: "SortedSet[IssueType]", parent_element: ElementTree.Element) -> None:
462+
resolves_e = ElementTree.SubElement(parent_element, 'resolves')
463+
for issue in resolves:
464+
issue_e = ElementTree.SubElement(
465+
resolves_e, 'issue', {'type': issue.type.value}
466+
)
467+
if issue.id:
468+
ElementTree.SubElement(issue_e, 'id').text = issue.id
469+
if issue.name:
470+
ElementTree.SubElement(issue_e, 'name').text = issue.name
471+
if issue.description:
472+
ElementTree.SubElement(issue_e, 'description').text = issue.description
473+
if issue.source:
474+
issue_source_e = ElementTree.SubElement(issue_e, 'source')
475+
if issue.source.name:
476+
ElementTree.SubElement(issue_source_e, 'name').text = issue.source.name
477+
if issue.source.url:
478+
ElementTree.SubElement(issue_source_e, 'url').text = str(issue.source.url)
479+
if issue.references:
480+
issue_references_e = ElementTree.SubElement(issue_e, 'references')
481+
for reference in issue.references:
482+
ElementTree.SubElement(issue_references_e, 'url').text = str(reference)
483+
479484
@staticmethod
480485
def _add_properties_element(properties: "SortedSet[Property]", parent_element: ElementTree.Element) -> None:
481486
properties_e = ElementTree.SubElement(parent_element, 'properties')

tests/data.py

+18
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,10 @@ def get_bom_with_component_setuptools_complete() -> Bom:
141141
return Bom(components=[get_component_setuptools_complete()])
142142

143143

144+
def get_bom_with_component_setuptools_complete_resolves() -> Bom:
145+
return Bom(components=[get_component_setuptools_complete_resolves()])
146+
147+
144148
def get_bom_with_component_setuptools_with_vulnerability() -> Bom:
145149
bom = Bom()
146150
component = get_component_setuptools_simple()
@@ -375,6 +379,12 @@ def get_component_setuptools_complete(include_pedigree: bool = True) -> Componen
375379
return component
376380

377381

382+
def get_component_setuptools_complete_resolves() -> Component:
383+
component = get_component_setuptools_complete(False)
384+
component.pedigree = get_pedigree_2()
385+
return component
386+
387+
378388
def get_component_setuptools_simple(
379389
bom_ref: Optional[str] = 'pkg:pypi/[email protected]?extension=tar.gz') -> Component:
380390
return Component(
@@ -495,6 +505,14 @@ def get_pedigree_1() -> Pedigree:
495505
)
496506

497507

508+
def get_pedigree_2() -> Pedigree:
509+
pedigree = get_pedigree_1()
510+
pedigree.patches.add(
511+
Patch(type_=PatchClassification.BACKPORT, resolves=[get_issue_1()])
512+
)
513+
return pedigree
514+
515+
498516
def get_properties_1() -> List[Property]:
499517
return [
500518
Property(name='key1', value='val1'),
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,268 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<bom xmlns="http://cyclonedx.org/schema/bom/1.4" version="1" serialNumber="urn:uuid:f9b53ef1-ce03-4a66-9594-f6efe0d26d15">
3+
<metadata>
4+
<timestamp>2022-10-20T15:55:25.045777+00:00</timestamp>
5+
<tools>
6+
<tool>
7+
<vendor>CycloneDX</vendor>
8+
<name>cyclonedx-python-lib</name>
9+
<version>3.1.0</version>
10+
<externalReferences>
11+
<reference type="build-system">
12+
<url>https://github.com/CycloneDX/cyclonedx-python-lib/actions</url>
13+
</reference>
14+
<reference type="distribution">
15+
<url>https://pypi.org/project/cyclonedx-python-lib/</url>
16+
</reference>
17+
<reference type="documentation">
18+
<url>https://cyclonedx.github.io/cyclonedx-python-lib/</url>
19+
</reference>
20+
<reference type="issue-tracker">
21+
<url>https://github.com/CycloneDX/cyclonedx-python-lib/issues</url>
22+
</reference>
23+
<reference type="license">
24+
<url>https://github.com/CycloneDX/cyclonedx-python-lib/blob/main/LICENSE</url>
25+
</reference>
26+
<reference type="release-notes">
27+
<url>https://github.com/CycloneDX/cyclonedx-python-lib/blob/main/CHANGELOG.md</url>
28+
</reference>
29+
<reference type="vcs">
30+
<url>https://github.com/CycloneDX/cyclonedx-python-lib</url>
31+
</reference>
32+
<reference type="website">
33+
<url>https://cyclonedx.org</url>
34+
</reference>
35+
</externalReferences>
36+
</tool>
37+
</tools>
38+
</metadata>
39+
<components>
40+
<component type="library" bom-ref="cd3e9c95-9d41-49e7-9924-8cf0465ae789">
41+
<supplier>
42+
<name>CycloneDX</name>
43+
<url>https://cyclonedx.org</url>
44+
<contact>
45+
<name>A N Other</name>
46+
<email>[email protected]</email>
47+
<phone>+44 (0)1234 567890</phone>
48+
</contact>
49+
<contact>
50+
<name>Paul Horton</name>
51+
<email>[email protected]</email>
52+
</contact>
53+
</supplier>
54+
<author>Test Author</author>
55+
<publisher>CycloneDX</publisher>
56+
<name>setuptools</name>
57+
<version>50.3.2</version>
58+
<description>This component is awesome</description>
59+
<scope>required</scope>
60+
<licenses>
61+
<expression>MIT License</expression>
62+
</licenses>
63+
<copyright>Apache 2.0 baby!</copyright>
64+
<cpe>cpe:2.3:a:python:setuptools:50.3.2:*:*:*:*:*:*:*</cpe>
65+
<purl>pkg:pypi/[email protected]?extension=tar.gz</purl>
66+
<swid tagId="swidgen-242eb18a-503e-ca37-393b-cf156ef09691_9.1.1" name="Test Application" version="3.4.5">
67+
<text content-type="text/xml" encoding="base64">PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiID8+CjxTb2Z0d2FyZUlkZW50aXR5IHhtbDpsYW5nPSJFTiIgbmFtZT0iQWNtZSBBcHBsaWNhdGlvbiIgdmVyc2lvbj0iOS4xLjEiIAogdmVyc2lvblNjaGVtZT0ibXVsdGlwYXJ0bnVtZXJpYyIgCiB0YWdJZD0ic3dpZGdlbi1iNTk1MWFjOS00MmMwLWYzODItM2YxZS1iYzdhMmE0NDk3Y2JfOS4xLjEiIAogeG1sbnM9Imh0dHA6Ly9zdGFuZGFyZHMuaXNvLm9yZy9pc28vMTk3NzAvLTIvMjAxNS9zY2hlbWEueHNkIj4gCiB4bWxuczp4c2k9Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvWE1MU2NoZW1hLWluc3RhbmNlIiAKIHhzaTpzY2hlbWFMb2NhdGlvbj0iaHR0cDovL3N0YW5kYXJkcy5pc28ub3JnL2lzby8xOTc3MC8tMi8yMDE1LWN1cnJlbnQvc2NoZW1hLnhzZCBzY2hlbWEueHNkIiA+CiAgPE1ldGEgZ2VuZXJhdG9yPSJTV0lEIFRhZyBPbmxpbmUgR2VuZXJhdG9yIHYwLjEiIC8+IAogIDxFbnRpdHkgbmFtZT0iQWNtZSwgSW5jLiIgcmVnaWQ9ImV4YW1wbGUuY29tIiByb2xlPSJ0YWdDcmVhdG9yIiAvPiAKPC9Tb2Z0d2FyZUlkZW50aXR5Pg==</text>
68+
</swid>
69+
<pedigree>
70+
<ancestors>
71+
<component type="library" bom-ref="ccc8d7ee-4b9c-4750-aee0-a72585152291">
72+
<author>Test Author</author>
73+
<name>setuptools</name>
74+
<version>50.3.2</version>
75+
<licenses>
76+
<expression>MIT License</expression>
77+
</licenses>
78+
<purl>pkg:pypi/[email protected]?extension=tar.gz</purl>
79+
</component>
80+
<component type="library" bom-ref="8a3893b3-9923-4adb-a1d3-47456636ba0a">
81+
<author>Test Author</author>
82+
<name>setuptools</name>
83+
<licenses>
84+
<expression>MIT License</expression>
85+
</licenses>
86+
<purl>pkg:pypi/setuptools?extension=tar.gz</purl>
87+
</component>
88+
</ancestors>
89+
<descendants>
90+
<component type="library" bom-ref="28b2d8ce-def0-446f-a221-58dee0b44acc">
91+
<author>Test Author</author>
92+
<name>setuptools</name>
93+
<licenses>
94+
<expression>MIT License</expression>
95+
</licenses>
96+
<purl>pkg:pypi/setuptools?extension=tar.gz</purl>
97+
</component>
98+
<component type="library" bom-ref="555ca729-93c6-48f3-956e-bdaa4a2f0bfa">
99+
<name>toml</name>
100+
<version>0.10.2</version>
101+
<hashes>
102+
<hash alg="SHA-256">806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b</hash>
103+
</hashes>
104+
<purl>pkg:pypi/[email protected]?extension=tar.gz</purl>
105+
<externalReferences>
106+
<reference type="distribution">
107+
<url>https://cyclonedx.org</url>
108+
<comment>No comment</comment>
109+
<hashes>
110+
<hash alg="SHA-256">806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b</hash>
111+
</hashes>
112+
</reference>
113+
</externalReferences>
114+
</component>
115+
</descendants>
116+
<variants>
117+
<component type="library" bom-ref="ded1d73e-1fca-4302-b520-f1bc53979958">
118+
<author>Test Author</author>
119+
<name>setuptools</name>
120+
<version>50.3.2</version>
121+
<licenses>
122+
<expression>MIT License</expression>
123+
</licenses>
124+
<purl>pkg:pypi/[email protected]?extension=tar.gz</purl>
125+
</component>
126+
<component type="library" bom-ref="e7abdcca-5ba2-4f29-b2cf-b1e1ef788e66">
127+
<name>toml</name>
128+
<version>0.10.2</version>
129+
<hashes>
130+
<hash alg="SHA-256">806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b</hash>
131+
</hashes>
132+
<purl>pkg:pypi/[email protected]?extension=tar.gz</purl>
133+
<externalReferences>
134+
<reference type="distribution">
135+
<url>https://cyclonedx.org</url>
136+
<comment>No comment</comment>
137+
<hashes>
138+
<hash alg="SHA-256">806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b</hash>
139+
</hashes>
140+
</reference>
141+
</externalReferences>
142+
</component>
143+
</variants>
144+
<commits>
145+
<commit>
146+
<uid>a-random-uid</uid>
147+
<message>A commit message</message>
148+
</commit>
149+
</commits>
150+
<patches>
151+
<patch type="backport" />
152+
<patch type="backport">
153+
<resolves>
154+
<issue type="security">
155+
<id>CVE-2021-44228</id>
156+
<name>Apache Log3Shell</name>
157+
<description>Apache Log4j2 2.0-beta9 through 2.12.1 and 2.13.0 through 2.15.0 JNDI features...</description>
158+
<source>
159+
<name>NVD</name>
160+
<url>https://nvd.nist.gov/vuln/detail/CVE-2021-44228</url>
161+
</source>
162+
<references>
163+
<url>https://central.sonatype.org/news/20211213_log4shell_help</url>
164+
<url>https://logging.apache.org/log4j/2.x/security.html</url>
165+
</references>
166+
</issue>
167+
</resolves>
168+
</patch>
169+
</patches>
170+
<notes>Some notes here please</notes>
171+
</pedigree>
172+
<externalReferences>
173+
<reference type="distribution">
174+
<url>https://cyclonedx.org</url>
175+
<comment>No comment</comment>
176+
<hashes>
177+
<hash alg="SHA-256">806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b</hash>
178+
</hashes>
179+
</reference>
180+
</externalReferences>
181+
<properties>
182+
<property name="key1">val1</property>
183+
<property name="key2">val2</property>
184+
</properties>
185+
<components>
186+
<component type="library" bom-ref="pkg:pypi/[email protected]?extension=tar.gz">
187+
<author>Test Author</author>
188+
<name>setuptools</name>
189+
<version>50.3.2</version>
190+
<licenses>
191+
<expression>MIT License</expression>
192+
</licenses>
193+
<purl>pkg:pypi/[email protected]?extension=tar.gz</purl>
194+
</component>
195+
<component type="library" bom-ref="pkg:pypi/[email protected]?extension=tar.gz">
196+
<name>toml</name>
197+
<version>0.10.2</version>
198+
<hashes>
199+
<hash alg="SHA-256">806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b</hash>
200+
</hashes>
201+
<purl>pkg:pypi/[email protected]?extension=tar.gz</purl>
202+
<externalReferences>
203+
<reference type="distribution">
204+
<url>https://cyclonedx.org</url>
205+
<comment>No comment</comment>
206+
<hashes>
207+
<hash alg="SHA-256">806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b</hash>
208+
</hashes>
209+
</reference>
210+
</externalReferences>
211+
</component>
212+
</components>
213+
<evidence>
214+
<copyright>
215+
<text>Commercial</text>
216+
<text>Commercial 2</text>
217+
</copyright>
218+
</evidence>
219+
<releaseNotes>
220+
<type>major</type>
221+
<title>Release Notes Title</title>
222+
<featuredImage>https://cyclonedx.org/theme/assets/images/CycloneDX-Twitter-Card.png</featuredImage>
223+
<socialImage>https://cyclonedx.org/cyclonedx-icon.png</socialImage>
224+
<description>This release is a test release</description>
225+
<timestamp>2021-12-31T10:00:00+00:00</timestamp>
226+
<aliases>
227+
<alias>First Test Release</alias>
228+
</aliases>
229+
<tags>
230+
<tag>alpha</tag>
231+
<tag>test</tag>
232+
</tags>
233+
<resolves>
234+
<issue type="security">
235+
<id>CVE-2021-44228</id>
236+
<name>Apache Log3Shell</name>
237+
<description>Apache Log4j2 2.0-beta9 through 2.12.1 and 2.13.0 through 2.15.0 JNDI features...</description>
238+
<source>
239+
<name>NVD</name>
240+
<url>https://nvd.nist.gov/vuln/detail/CVE-2021-44228</url>
241+
</source>
242+
<references>
243+
<url>https://central.sonatype.org/news/20211213_log4shell_help</url>
244+
<url>https://logging.apache.org/log4j/2.x/security.html</url>
245+
</references>
246+
</issue>
247+
</resolves>
248+
<notes>
249+
<note>
250+
<locale>en-GB</locale>
251+
<text content-type="text/plain; charset=UTF-8" encoding="base64">U29tZSBzaW1wbGUgcGxhaW4gdGV4dA==</text>
252+
</note>
253+
<note>
254+
<locale>en-US</locale>
255+
<text content-type="text/plain; charset=UTF-8" encoding="base64">U29tZSBzaW1wbGUgcGxhaW4gdGV4dA==</text>
256+
</note>
257+
</notes>
258+
<properties>
259+
<property name="key1">val1</property>
260+
<property name="key2">val2</property>
261+
</properties>
262+
</releaseNotes>
263+
</component>
264+
</components>
265+
<dependencies>
266+
<dependency ref="cd3e9c95-9d41-49e7-9924-8cf0465ae789" />
267+
</dependencies>
268+
</bom>

0 commit comments

Comments
 (0)