Merge ~andrey-fedoseev/launchpad:uct-import-export-break-fix into launchpad:master

Proposed by Andrey Fedoseev
Status: Needs review
Proposed branch: ~andrey-fedoseev/launchpad:uct-import-export-break-fix
Merge into: launchpad:master
Prerequisite: ~andrey-fedoseev/launchpad:bug-presense
Diff against target: 486 lines (+260/-4)
5 files modified
lib/lp/bugs/model/bugpresence.py (+3/-0)
lib/lp/bugs/scripts/tests/test_uct.py (+102/-0)
lib/lp/bugs/scripts/uct/models.py (+93/-4)
lib/lp/bugs/scripts/uct/uctexport.py (+16/-0)
lib/lp/bugs/scripts/uct/uctimport.py (+46/-0)
Reviewer Review Type Date Requested Status
Launchpad code reviewers Pending
Review via email: mp+432181@code.launchpad.net

Commit message

UCT import/export: handle the `break-fix` entries

Description of the change

For each `break-fix` entry create a `BugPresence` instance linked to the default git repository of the project (if exists)

If a `break-fix` entry includes multiple git commits in the "fixed" section it means that either of them fixes the issue. So, we create multiple `BugPresence` instances, one per commit listed in the "fixed" section.

Items such as `local-CVE-2022-23222-fix` are currently ignored

To post a comment you must log in.
d62597c... by Andrey Fedoseev

UCT import/export: handle the `break-fix` entries

For each `break-fix` entry create a `BugPresence` instance linked to the default git repository of the project (if exists)

If a `break-fix` entry includes multiple git commits in the "fixed" section it means that either of them fixes the issue. So, we create multiple `BugPresence` instances, one per commit listed in the "fixed" section.

Items such as `local-CVE-2022-23222-fix` are currently ignored

Unmerged commits

d62597c... by Andrey Fedoseev

UCT import/export: handle the `break-fix` entries

For each `break-fix` entry create a `BugPresence` instance linked to the default git repository of the project (if exists)

If a `break-fix` entry includes multiple git commits in the "fixed" section it means that either of them fixes the issue. So, we create multiple `BugPresence` instances, one per commit listed in the "fixed" section.

Items such as `local-CVE-2022-23222-fix` are currently ignored

Succeeded
[SUCCEEDED] docs:0 (build)
[SUCCEEDED] lint:0 (build)
[SUCCEEDED] mypy:0 (build)
13 of 3 results
460e925... by Andrey Fedoseev

Add `BugPresence` model

It represents a range of versions or git commits in which the bug was present.

Succeeded
[SUCCEEDED] docs:0 (build)
[SUCCEEDED] lint:0 (build)
[SUCCEEDED] mypy:0 (build)
13 of 3 results

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
diff --git a/lib/lp/bugs/model/bugpresence.py b/lib/lp/bugs/model/bugpresence.py
index b21371e..4ca8128 100644
--- a/lib/lp/bugs/model/bugpresence.py
+++ b/lib/lp/bugs/model/bugpresence.py
@@ -20,6 +20,9 @@ class BugPresence(StormBase):
20 """See `IBugPresence`."""20 """See `IBugPresence`."""
2121
22 __storm_table__ = "BugPresence"22 __storm_table__ = "BugPresence"
23 __storm_order__ = [
24 "id",
25 ]
2326
24 id = Int(primary=True)27 id = Int(primary=True)
2528
diff --git a/lib/lp/bugs/scripts/tests/test_uct.py b/lib/lp/bugs/scripts/tests/test_uct.py
index 9813d86..3ce76b7 100644
--- a/lib/lp/bugs/scripts/tests/test_uct.py
+++ b/lib/lp/bugs/scripts/tests/test_uct.py
@@ -6,10 +6,12 @@ from typing import List
66
7from pytz import UTC7from pytz import UTC
8from zope.component import getUtility8from zope.component import getUtility
9from zope.security.proxy import removeSecurityProxy
910
10from lp.app.enums import InformationType11from lp.app.enums import InformationType
11from lp.app.interfaces.launchpad import ILaunchpadCelebrities12from lp.app.interfaces.launchpad import ILaunchpadCelebrities
12from lp.bugs.enums import VulnerabilityStatus13from lp.bugs.enums import VulnerabilityStatus
14from lp.bugs.interfaces.bugpresence import IBugPresenceSet
13from lp.bugs.interfaces.bugtask import BugTaskImportance, BugTaskStatus15from lp.bugs.interfaces.bugtask import BugTaskImportance, BugTaskStatus
14from lp.bugs.model.bug import Bug16from lp.bugs.model.bug import Bug
15from lp.bugs.model.bugtask import BugTask17from lp.bugs.model.bugtask import BugTask
@@ -274,6 +276,20 @@ class TestCVE(TestCaseWithFactory):
274 tags=set(),276 tags=set(),
275 patches=[277 patches=[
276 UCTRecord.Patch(278 UCTRecord.Patch(
279 patch_type="break-fix",
280 entry=(
281 "457f44363a8894135c85b7a9afd2bd8196db24ab "
282 "c25b2ae136039ffa820c26138ed4a5e5f3ab3841|"
283 "4969c06a0d83c9c3dc50b8efcdc8eeedfce896f6"
284 ),
285 ),
286 UCTRecord.Patch(
287 patch_type="break-fix",
288 entry=(
289 "- c25b2ae136039ffa820c26138ed4a5e5f3ab3841"
290 ),
291 ),
292 UCTRecord.Patch(
277 patch_type="upstream",293 patch_type="upstream",
278 entry=(294 entry=(
279 "https://github.com/389ds/389-ds-base/"295 "https://github.com/389ds/389-ds-base/"
@@ -416,6 +432,30 @@ class TestCVE(TestCaseWithFactory):
416 importance=None,432 importance=None,
417 status=BugTaskStatus.FIXRELEASED,433 status=BugTaskStatus.FIXRELEASED,
418 status_explanation="reason 4",434 status_explanation="reason 4",
435 break_fixes=[
436 CVE.BreakFix(
437 broken_git_commit_sha1=(
438 "457f44363a8894135c85b7a9afd2bd8196db24ab"
439 ),
440 fixed_git_commit_sha1=(
441 "c25b2ae136039ffa820c26138ed4a5e5f3ab3841"
442 ),
443 ),
444 CVE.BreakFix(
445 broken_git_commit_sha1=(
446 "457f44363a8894135c85b7a9afd2bd8196db24ab"
447 ),
448 fixed_git_commit_sha1=(
449 "4969c06a0d83c9c3dc50b8efcdc8eeedfce896f6"
450 ),
451 ),
452 CVE.BreakFix(
453 broken_git_commit_sha1=None,
454 fixed_git_commit_sha1=(
455 "c25b2ae136039ffa820c26138ed4a5e5f3ab3841"
456 ),
457 ),
458 ],
419 ),459 ),
420 CVE.UpstreamPackage(460 CVE.UpstreamPackage(
421 target=product_2,461 target=product_2,
@@ -423,6 +463,7 @@ class TestCVE(TestCaseWithFactory):
423 importance=None,463 importance=None,
424 status=BugTaskStatus.FIXRELEASED,464 status=BugTaskStatus.FIXRELEASED,
425 status_explanation="",465 status_explanation="",
466 break_fixes=[],
426 ),467 ),
427 ],468 ],
428 importance=BugTaskImportance.CRITICAL,469 importance=BugTaskImportance.CRITICAL,
@@ -564,6 +605,13 @@ class TestUCTImporterExporter(TestCaseWithFactory):
564 distroseries=self.esm_current_series,605 distroseries=self.esm_current_series,
565 ).productseries.product606 ).productseries.product
566607
608 self.product_1_git_repo = self.factory.makeGitRepository(
609 target=self.product_1, target_default=True
610 )
611 self.product_2_git_repo = self.factory.makeGitRepository(
612 target=self.product_2, target_default=True
613 )
614
567 for series in (615 for series in (
568 self.ubuntu_supported_series,616 self.ubuntu_supported_series,
569 self.ubuntu_current_series,617 self.ubuntu_current_series,
@@ -661,6 +709,24 @@ class TestUCTImporterExporter(TestCaseWithFactory):
661 importance=BugTaskImportance.HIGH,709 importance=BugTaskImportance.HIGH,
662 status=BugTaskStatus.FIXRELEASED,710 status=BugTaskStatus.FIXRELEASED,
663 status_explanation="fix released",711 status_explanation="fix released",
712 break_fixes=[
713 CVE.BreakFix(
714 broken_git_commit_sha1=(
715 "054623105728b06852f077299e2bf1bf3d5f2b0b"
716 ),
717 fixed_git_commit_sha1=(
718 "db7bee653859ef7179be933e7d1384644f795f26"
719 ),
720 ),
721 CVE.BreakFix(
722 broken_git_commit_sha1=(
723 "054623105728b06852f077299e2bf1bf3d5f2b0b"
724 ),
725 fixed_git_commit_sha1=(
726 "6e61dc9da0b7a0d91d57c2e20b5ea4fd2d4e7e53"
727 ),
728 ),
729 ],
664 ),730 ),
665 CVE.UpstreamPackage(731 CVE.UpstreamPackage(
666 target=self.product_2,732 target=self.product_2,
@@ -668,6 +734,20 @@ class TestUCTImporterExporter(TestCaseWithFactory):
668 importance=BugTaskImportance.LOW,734 importance=BugTaskImportance.LOW,
669 status=BugTaskStatus.WONTFIX,735 status=BugTaskStatus.WONTFIX,
670 status_explanation="ignored",736 status_explanation="ignored",
737 break_fixes=[
738 CVE.BreakFix(
739 broken_git_commit_sha1=None,
740 fixed_git_commit_sha1=(
741 "6e61dc9da0b7a0d91d57c2e20b5ea4fd2d4e7e53"
742 ),
743 ),
744 CVE.BreakFix(
745 broken_git_commit_sha1=(
746 "4e9b4a6883dd97aff53ae3b08eb900716a5469dc"
747 ),
748 fixed_git_commit_sha1=None,
749 ),
750 ],
671 ),751 ),
672 ],752 ],
673 importance=BugTaskImportance.MEDIUM,753 importance=BugTaskImportance.MEDIUM,
@@ -724,6 +804,7 @@ class TestUCTImporterExporter(TestCaseWithFactory):
724 self.assertEqual(sorted(cve.bug_urls), sorted(w.url for w in watches))804 self.assertEqual(sorted(cve.bug_urls), sorted(w.url for w in watches))
725805
726 self.checkBugAttachments(bug, cve)806 self.checkBugAttachments(bug, cve)
807 self.checkBugPresence(bug, cve)
727808
728 def checkBugTasks(self, bug: Bug, cve: CVE):809 def checkBugTasks(self, bug: Bug, cve: CVE):
729 bug_tasks = bug.bugtasks # type: List[BugTask]810 bug_tasks = bug.bugtasks # type: List[BugTask]
@@ -799,6 +880,27 @@ class TestUCTImporterExporter(TestCaseWithFactory):
799 )880 )
800 self.assertEqual(expected_title, attachment.title)881 self.assertEqual(expected_title, attachment.title)
801882
883 def checkBugPresence(self, bug: Bug, cve: CVE):
884 expected_break_fixes = set()
885 for upstream_package in cve.upstream_packages:
886 for break_fix in upstream_package.break_fixes:
887 expected_break_fixes.add(
888 (upstream_package.target.name, break_fix)
889 )
890 actual_break_fixes = set()
891 for bp in getUtility(IBugPresenceSet).getByBug(bug):
892 project = removeSecurityProxy(bp).git_repository.project
893 actual_break_fixes.add(
894 (
895 project.name,
896 CVE.BreakFix(
897 broken_git_commit_sha1=bp.broken_git_commit_sha1,
898 fixed_git_commit_sha1=bp.fixed_git_commit_sha1,
899 ),
900 )
901 )
902 self.assertSetEqual(expected_break_fixes, actual_break_fixes)
903
802 def checkVulnerabilities(self, bug: Bug, cve: CVE):904 def checkVulnerabilities(self, bug: Bug, cve: CVE):
803 vulnerabilities = bug.vulnerabilities905 vulnerabilities = bug.vulnerabilities
804906
diff --git a/lib/lp/bugs/scripts/uct/models.py b/lib/lp/bugs/scripts/uct/models.py
index fd77ea5..2540eda 100644
--- a/lib/lp/bugs/scripts/uct/models.py
+++ b/lib/lp/bugs/scripts/uct/models.py
@@ -450,6 +450,14 @@ class CVE:
450 ),450 ),
451 )451 )
452452
453 BreakFix = NamedTuple(
454 "BreakFix",
455 (
456 ("broken_git_commit_sha1", Optional[str]),
457 ("fixed_git_commit_sha1", Optional[str]),
458 ),
459 )
460
453 UpstreamPackage = NamedTuple(461 UpstreamPackage = NamedTuple(
454 "UpstreamPackage",462 "UpstreamPackage",
455 (463 (
@@ -458,6 +466,7 @@ class CVE:
458 ("importance", Optional[BugTaskImportance]),466 ("importance", Optional[BugTaskImportance]),
459 ("status", BugTaskStatus),467 ("status", BugTaskStatus),
460 ("status_explanation", str),468 ("status_explanation", str),
469 ("break_fixes", List[BreakFix]),
461 ),470 ),
462 )471 )
463472
@@ -475,6 +484,7 @@ class CVE:
475 # https://github.com/389ds/389-ds-base/commit/123 (1.4.4)484 # https://github.com/389ds/389-ds-base/commit/123 (1.4.4)
476 # https://github.com/389ds/389-ds-base/commit/345485 # https://github.com/389ds/389-ds-base/commit/345
477 PATCH_URL_RE = re.compile(r"^(?P<url>.+?)(\s+\((?P<notes>.+)\))?$")486 PATCH_URL_RE = re.compile(r"^(?P<url>.+?)(\s+\((?P<notes>.+)\))?$")
487 GIT_HASH_RE = re.compile(r"^[a-f0-9]{40}$")
478488
479 PRIORITY_MAP = {489 PRIORITY_MAP = {
480 UCTRecord.Priority.CRITICAL: BugTaskImportance.CRITICAL,490 UCTRecord.Priority.CRITICAL: BugTaskImportance.CRITICAL,
@@ -563,6 +573,7 @@ class CVE:
563 distro_packages = []573 distro_packages = []
564 series_packages = []574 series_packages = []
565 patch_urls = []575 patch_urls = []
576 break_fixes = {} # type: Dict[SourcePackageName, List[CVE.BreakFix]]
566577
567 spn_set = getUtility(ISourcePackageNameSet)578 spn_set = getUtility(ISourcePackageNameSet)
568579
@@ -577,6 +588,10 @@ class CVE:
577 cls.get_patch_urls(source_package_name, uct_package.patches)588 cls.get_patch_urls(source_package_name, uct_package.patches)
578 )589 )
579590
591 break_fixes[source_package_name] = cls.get_break_fixes(
592 uct_package.patches
593 )
594
580 package_importance = (595 package_importance = (
581 cls.PRIORITY_MAP[uct_package.priority]596 cls.PRIORITY_MAP[uct_package.priority]
582 if uct_package.priority597 if uct_package.priority
@@ -665,6 +680,7 @@ class CVE:
665 ),680 ),
666 status=cls.BUG_TASK_STATUS_MAP[upstream_status.status],681 status=cls.BUG_TASK_STATUS_MAP[upstream_status.status],
667 status_explanation=upstream_status.reason,682 status_explanation=upstream_status.reason,
683 break_fixes=break_fixes[source_package_name],
668 )684 )
669 )685 )
670686
@@ -786,15 +802,32 @@ class CVE:
786 patches=[],802 patches=[],
787 )803 )
788804
805 grouped_break_fixes = OrderedDict()
806 for break_fix in upstream_package.break_fixes:
807 if break_fix.broken_git_commit_sha1 not in grouped_break_fixes:
808 grouped_break_fixes[break_fix.broken_git_commit_sha1] = []
809 if break_fix.fixed_git_commit_sha1:
810 grouped_break_fixes[
811 break_fix.broken_git_commit_sha1
812 ].append(break_fix.fixed_git_commit_sha1)
813
814 for break_commit, fixed_commits in grouped_break_fixes.items():
815 entry = "{} {}".format(
816 break_commit or "-",
817 "|".join(fixed_commits) or "-",
818 )
819 packages_by_name[
820 upstream_package.package_name.name
821 ].patches.append(
822 UCTRecord.Patch(patch_type="break-fix", entry=entry)
823 )
824
789 for patch_url in self.patch_urls:825 for patch_url in self.patch_urls:
790 entry = patch_url.url826 entry = patch_url.url
791 if patch_url.notes:827 if patch_url.notes:
792 entry = "{} ({})".format(entry, patch_url.notes)828 entry = "{} ({})".format(entry, patch_url.notes)
793 packages_by_name[patch_url.package_name.name].patches.append(829 packages_by_name[patch_url.package_name.name].patches.append(
794 UCTRecord.Patch(830 UCTRecord.Patch(patch_type=patch_url.type, entry=entry)
795 patch_type=patch_url.type,
796 entry=entry,
797 )
798 )831 )
799832
800 return UCTRecord(833 return UCTRecord(
@@ -909,3 +942,59 @@ class CVE:
909 url=url,942 url=url,
910 notes=notes,943 notes=notes,
911 )944 )
945
946 @classmethod
947 def get_break_fixes(
948 cls,
949 patches: List[UCTRecord.Patch],
950 ) -> List[BreakFix]:
951
952 break_fixes = []
953
954 for patch in patches:
955 if patch.patch_type != "break-fix":
956 continue
957
958 try:
959 broken_entry, joint_fixed_entries = patch.entry.split()
960 except ValueError:
961 logger.error(
962 "Could not parse break-fix entry: %s", patch.entry
963 )
964 continue
965
966 if broken_entry == "-":
967 broken_entry = None
968 elif not cls.GIT_HASH_RE.match(broken_entry):
969 logger.error(
970 "broken entry doesn't look like git commit SHA1: %s",
971 broken_entry,
972 )
973 continue
974
975 if joint_fixed_entries == "-":
976 if broken_entry:
977 break_fixes.append(
978 cls.BreakFix(
979 broken_git_commit_sha1=broken_entry,
980 fixed_git_commit_sha1=None,
981 )
982 )
983 continue
984
985 for fixed_entry in joint_fixed_entries.split("|"):
986 # TODO: handle the with fixed_entry="local-CVE-2021-20177"
987 if cls.GIT_HASH_RE.match(fixed_entry):
988 break_fixes.append(
989 cls.BreakFix(
990 broken_git_commit_sha1=broken_entry,
991 fixed_git_commit_sha1=fixed_entry,
992 )
993 )
994 else:
995 logger.error(
996 "fixed entry doesn't look like git commit " "SHA1: %s",
997 fixed_entry,
998 )
999
1000 return break_fixes
diff --git a/lib/lp/bugs/scripts/uct/uctexport.py b/lib/lp/bugs/scripts/uct/uctexport.py
index 8a1dd27..ff1a9c5 100644
--- a/lib/lp/bugs/scripts/uct/uctexport.py
+++ b/lib/lp/bugs/scripts/uct/uctexport.py
@@ -12,6 +12,7 @@ from zope.security.proxy import removeSecurityProxy
1212
13from lp.bugs.interfaces.bug import IBugSet13from lp.bugs.interfaces.bug import IBugSet
14from lp.bugs.interfaces.bugattachment import BugAttachmentType14from lp.bugs.interfaces.bugattachment import BugAttachmentType
15from lp.bugs.interfaces.bugpresence import IBugPresenceSet
15from lp.bugs.model.bug import Bug as BugModel16from lp.bugs.model.bug import Bug as BugModel
16from lp.bugs.model.bugtask import BugTask17from lp.bugs.model.bugtask import BugTask
17from lp.bugs.model.cve import Cve as CveModel18from lp.bugs.model.cve import Cve as CveModel
@@ -173,6 +174,13 @@ class UCTExporter:
173 )174 )
174 )175 )
175176
177 bug_presence_by_product = defaultdict(list)
178 for bp in getUtility(IBugPresenceSet).getByBug(bug):
179 if bp.git_repository:
180 bug_presence_by_product[
181 removeSecurityProxy(bp).git_repository.project
182 ].append(bp)
183
176 upstream_packages = []184 upstream_packages = []
177 for bug_task in bug_tasks:185 for bug_task in bug_tasks:
178 target = removeSecurityProxy(bug_task.target)186 target = removeSecurityProxy(bug_task.target)
@@ -187,6 +195,7 @@ class UCTExporter:
187 package_name = package_name_by_product[target]195 package_name = package_name_by_product[target]
188 up_importance = bug_task.importance196 up_importance = bug_task.importance
189 package_importance = package_importances.get(target.name)197 package_importance = package_importances.get(target.name)
198 bug_presences = bug_presence_by_product.get(target, [])
190 upstream_packages.append(199 upstream_packages.append(
191 CVE.UpstreamPackage(200 CVE.UpstreamPackage(
192 target=target,201 target=target,
@@ -198,6 +207,13 @@ class UCTExporter:
198 ),207 ),
199 status=bug_task.status,208 status=bug_task.status,
200 status_explanation=bug_task.status_explanation,209 status_explanation=bug_task.status_explanation,
210 break_fixes=[
211 CVE.BreakFix(
212 broken_git_commit_sha1=bp.broken_git_commit_sha1,
213 fixed_git_commit_sha1=bp.fixed_git_commit_sha1,
214 )
215 for bp in bug_presences
216 ],
201 )217 )
202 )218 )
203219
diff --git a/lib/lp/bugs/scripts/uct/uctimport.py b/lib/lp/bugs/scripts/uct/uctimport.py
index 5bc8411..607dd2e 100644
--- a/lib/lp/bugs/scripts/uct/uctimport.py
+++ b/lib/lp/bugs/scripts/uct/uctimport.py
@@ -25,6 +25,7 @@ Three types of bug tags are created:
25 status of the package in upstream.25 status of the package in upstream.
26"""26"""
27import logging27import logging
28from collections import defaultdict
28from datetime import timezone29from datetime import timezone
29from itertools import chain30from itertools import chain
30from pathlib import Path31from pathlib import Path
@@ -39,6 +40,7 @@ from lp.app.interfaces.launchpad import ILaunchpadCelebrities
39from lp.bugs.interfaces.bug import CreateBugParams, IBugSet40from lp.bugs.interfaces.bug import CreateBugParams, IBugSet
40from lp.bugs.interfaces.bugactivity import IBugActivitySet41from lp.bugs.interfaces.bugactivity import IBugActivitySet
41from lp.bugs.interfaces.bugattachment import BugAttachmentType42from lp.bugs.interfaces.bugattachment import BugAttachmentType
43from lp.bugs.interfaces.bugpresence import IBugPresenceSet
42from lp.bugs.interfaces.bugtask import BugTaskImportance, IBugTaskSet44from lp.bugs.interfaces.bugtask import BugTaskImportance, IBugTaskSet
43from lp.bugs.interfaces.bugwatch import IBugWatchSet45from lp.bugs.interfaces.bugwatch import IBugWatchSet
44from lp.bugs.interfaces.cve import ICveSet46from lp.bugs.interfaces.cve import ICveSet
@@ -48,6 +50,7 @@ from lp.bugs.model.bugtask import BugTask
48from lp.bugs.model.cve import Cve as CveModel50from lp.bugs.model.cve import Cve as CveModel
49from lp.bugs.model.vulnerability import Vulnerability51from lp.bugs.model.vulnerability import Vulnerability
50from lp.bugs.scripts.uct.models import CVE, UCTRecord52from lp.bugs.scripts.uct.models import CVE, UCTRecord
53from lp.code.interfaces.gitrepository import IGitRepositorySet
51from lp.registry.model.distribution import Distribution54from lp.registry.model.distribution import Distribution
52from lp.registry.model.person import Person55from lp.registry.model.person import Person
53from lp.services.database.constants import UTC_NOW56from lp.services.database.constants import UTC_NOW
@@ -168,6 +171,7 @@ class UCTImporter:
168171
169 self._update_external_bug_urls(bug, cve.bug_urls)172 self._update_external_bug_urls(bug, cve.bug_urls)
170 self._update_patches(bug, cve.patch_urls)173 self._update_patches(bug, cve.patch_urls)
174 self._update_bug_presence(bug, cve.upstream_packages)
171175
172 self._create_bug_tasks(176 self._create_bug_tasks(
173 bug,177 bug,
@@ -225,6 +229,7 @@ class UCTImporter:
225 self._assign_bug_tasks(bug, cve.assignee)229 self._assign_bug_tasks(bug, cve.assignee)
226 self._update_external_bug_urls(bug, cve.bug_urls)230 self._update_external_bug_urls(bug, cve.bug_urls)
227 self._update_patches(bug, cve.patch_urls)231 self._update_patches(bug, cve.patch_urls)
232 self._update_bug_presence(bug, cve.upstream_packages)
228233
229 # Update or add new Vulnerabilities234 # Update or add new Vulnerabilities
230 vulnerabilities_by_distro = {235 vulnerabilities_by_distro = {
@@ -455,6 +460,47 @@ class UCTImporter:
455 description=title,460 description=title,
456 )461 )
457462
463 def _update_bug_presence(
464 self, bug: BugModel, upstream_packages: List[CVE.UpstreamPackage]
465 ):
466 bug_presence_set = getUtility(IBugPresenceSet)
467 bug_presences_by_target = defaultdict(list)
468 for bp in bug_presence_set.getByBug(bug):
469 bug_presences_by_target[bp.target].append(bp)
470 for upstream_package in upstream_packages:
471 if not upstream_package.break_fixes:
472 continue
473 git_repo = getUtility(IGitRepositorySet).getDefaultRepository(
474 upstream_package.target
475 )
476
477 if not git_repo:
478 logger.error(
479 "Could not find a git repository for %s "
480 "to save bug presence information",
481 upstream_package.target.name,
482 )
483 continue
484
485 existing_break_fixes = set()
486 for bp in bug_presences_by_target.get(git_repo, []):
487 existing_break_fixes.add(
488 CVE.BreakFix(
489 broken_git_commit_sha1=bp.broken_git_commit_sha1,
490 fixed_git_commit_sha1=bp.fixed_git_commit_sha1,
491 )
492 )
493
494 for break_fix in upstream_package.break_fixes:
495 if break_fix is existing_break_fixes:
496 continue
497 bug_presence_set.new(
498 bug=bug,
499 target=git_repo,
500 broken_git_commit_sha1=break_fix.broken_git_commit_sha1,
501 fixed_git_commit_sha1=break_fix.fixed_git_commit_sha1,
502 )
503
458 def _make_bug_description(self, cve: CVE) -> str:504 def _make_bug_description(self, cve: CVE) -> str:
459 """505 """
460 Some `CVE` fields can't be mapped to Launchpad models.506 Some `CVE` fields can't be mapped to Launchpad models.

Subscribers

People subscribed via source and target branches

to status/vote changes: