33
44import logging
55import re
6+ import semver
7+ import subprocess
68
7- logger = logging .getLogger (" generate_sbom" )
9+ logger = logging .getLogger (' generate_sbom' )
810logger .setLevel (logging .NOTSET )
911
10-
1112# ################ Component Filters ################
1213
1314# List of Endor Labs SBOM components that must be removed before processing
1415endor_components_remove = [
16+ # A dependency erroneously matched in build/CMakeFiles
17+ 'mozilla/cubeb' ,
1518 # An incorrect match from parts of pkg:github/madler/zlib
16- " zlib-ng/zlib-ng" ,
19+ ' zlib-ng/zlib-ng' ,
1720]
1821
1922# bom-ref prefixes (Endor Labs has been changing them, so add all that we have seen)
2023prefixes = [
21- "pkg:c/github.com/" ,
22- "pkg:generic/github.com/" ,
23- "pkg:github/" ,
24- ]
25-
26- components_remove = [
27- # Endor Labs includes the main component in 'components'. This is not standard, so we remove it.
28- "10gen/mongo" ,
29- # should be pkg:github/antirez/linenoise - waiting on Endor Labs fix
30- "amokhuginnsson/replxx" ,
31- # a transitive dependency of s2 that is not necessary to include
32- "sparsehash/sparsehash" ,
24+ 'pkg:c/github.com/' ,
25+ 'pkg:generic/github.com/' ,
26+ 'pkg:github/' ,
3327]
3428
35- for component in components_remove :
29+ for component in endor_components_remove :
3630 for prefix in prefixes :
3731 endor_components_remove .append (prefix + component )
3832
4337# Valid: pkg:github/abseil/abseil-cpp@20250512.1
4438# Run string replacements to correct for this:
4539endor_components_rename = [
46- ["pkg:generic/zlib.net/zlib" , "pkg:github/madler/zlib" ],
47- ["pkg:github/philsquared/clara" , "pkg:github/catchorg/clara" ],
48- ["pkg:generic/github.com/" , "pkg:github/" ],
49- ["pkg:c/github.com/" , "pkg:github/" ],
40+ ['pkg:generic/zlib.net/zlib' , 'pkg:github/madler/zlib' ],
41+ ['pkg:github/philsquared/clara' , 'pkg:github/catchorg/clara' ],
42+ # in case of regression
43+ ['pkg:generic/github.com/' , 'pkg:github/' ],
44+ ['pkg:c/github.com/' , 'pkg:github/' ],
5045]
5146
47+
48+ # ################ Primary Component Version ################
49+ def get_primary_component_version () -> str :
50+ """Attempt to determine primary component version using repo script."""
51+
52+ # mongo-cxx-driver: etc/calc_release_version.py
53+ try :
54+ result = subprocess .run (["python" , "etc/calc_release_version.py" ], capture_output = True , text = True )
55+ version = semver .VersionInfo .parse (result .stdout )
56+ if version .match ("0.0.0" ):
57+ return None
58+ else :
59+ return version
60+ except Exception as e :
61+ logger .warning ("PRIMARY COMPONENT VERSION: Unable to parse output from etc/calc_release_version.py: %s" , result .stdout )
62+ logger .warning (e )
63+ return None
64+
65+
5266# ################ Version Transformation ################
5367
5468# In some cases we need to transform the version string to strip out tag-related text
5569# It is unknown what patterns may appear in the future, so we have targeted (not broad) regex
5670# This a list of 'pattern' and 'repl' inputs to re.sub()
57- RE_VER_NUM = r" (0|[1-9]\d*)"
58- RE_VER_LBL = r" (?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?"
59- RE_SEMVER = rf" { RE_VER_NUM } \.{ RE_VER_NUM } \.{ RE_VER_NUM } { RE_VER_LBL } "
71+ RE_VER_NUM = r' (0|[1-9]\d*)'
72+ RE_VER_LBL = r' (?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?'
73+ RE_SEMVER = rf' { RE_VER_NUM } \.{ RE_VER_NUM } \.{ RE_VER_NUM } { RE_VER_LBL } '
6074regex_semver = re .compile (RE_SEMVER )
6175
76+ # Release Naming Conventions
77+ REGEX_RELEASE_BRANCH = rf'^releases/v{ RE_SEMVER } $' # e.g., releases/v4.1
78+ REGEX_RELEASE_TAG = rf'^(r{ RE_SEMVER } )|(debian/{ RE_SEMVER } -1)$' # e.g., r3.7.0-beta1, debian/4.1.4-1
79+
6280VERSION_PATTERN_REPL = [
6381 # 'debian/1.28.1-1' pkg:github/mongodb/mongo-c-driver (temporary workaround)
64- [re .compile (rf" ^debian/({ RE_SEMVER } )-\d$" ), r"\1" ],
82+ [re .compile (rf' ^debian/({ RE_SEMVER } )-\d$' ), r'\1' ],
6583 # 'gperftools-2.9.1' pkg:github/gperftools/gperftools
6684 # 'mongo/v1.5.2' pkg:github/google/benchmark
6785 # 'mongodb-8.2.0-alpha2' pkg:github/wiredtiger/wiredtiger
6886 # 'release-1.12.0' pkg:github/apache/avro
6987 # 'yaml-cpp-0.6.3' pkg:github/jbeder/yaml-cpp
70- [re .compile (rf" ^[-a-z]+[-/][vr]?({ RE_SEMVER } )$" ), r"\1" ],
88+ [re .compile (rf' ^[-a-z]+[-/][vr]?({ RE_SEMVER } )$' ), r'\1' ],
7189 # 'asio-1-34-2' pkg:github/chriskohlhoff/asio
7290 # 'cares-1_27_0' pkg:github/c-ares/c-ares
7391 [
74- re .compile (rf" ^[a-z]+-{ RE_VER_NUM } [_-]{ RE_VER_NUM } [_-]{ RE_VER_NUM } { RE_VER_LBL } $" ),
75- r" \1.\2.\3" ,
92+ re .compile (rf' ^[a-z]+-{ RE_VER_NUM } [_-]{ RE_VER_NUM } [_-]{ RE_VER_NUM } { RE_VER_LBL } $' ),
93+ r' \1.\2.\3' ,
7694 ],
7795 # 'pcre2-10.40' pkg:github/pcre2project/pcre2
78- [re .compile (rf" ^[a-z0-9]+-({ RE_VER_NUM } \.{ RE_VER_NUM } )$" ), r"\1" ],
96+ [re .compile (rf' ^[a-z0-9]+-({ RE_VER_NUM } \.{ RE_VER_NUM } )$' ), r'\1' ],
7997 # 'icu-release-57-1' pkg:github/unicode-org/icu
80- [re .compile (rf" ^[a-z]+-?[a-z]+-{ RE_VER_NUM } -{ RE_VER_NUM } $" ), r" \1.\2" ],
98+ [re .compile (rf' ^[a-z]+-?[a-z]+-{ RE_VER_NUM } -{ RE_VER_NUM } $' ), r' \1.\2' ],
8199 # 'v2.6.0' pkg:github/confluentinc/librdkafka
82100 # 'r2.5.1'
83- [re .compile (rf" ^[rv]({ RE_SEMVER } )$" ), r"\1" ],
101+ [re .compile (rf' ^[rv]({ RE_SEMVER } )$' ), r'\1' ],
84102 # 'v2025.04.21.00' pkg:github/facebook/folly
85- [re .compile (r" ^v(\d+\.\d+\.\d+\.\d+)$" ), r"\1" ],
103+ [re .compile (r' ^v(\d+\.\d+\.\d+\.\d+)$' ), r'\1' ],
86104]
87105
88106
89- def get_semver_from_release_version (release_ver : str ) -> str :
107+ def get_semver_from_release_version (release_ver : str ) -> semver :
90108 """Extract the version number from string with tags or other annotations"""
91109 if release_ver :
92110 for re_obj , repl in VERSION_PATTERN_REPL :
@@ -98,8 +116,8 @@ def get_semver_from_release_version(release_ver: str) -> str:
98116# region special component use-case functions
99117
100118
101- def process_component_special_cases (
102- component_key : str , component : dict , versions : dict , repo_root : str
103- ) -> None :
119+ def process_component_special_cases (component_key : str , component : dict , versions : dict , repo_root : str ) -> None :
104120 pass
121+
122+
105123# endregion special component use-case functions
0 commit comments