Exclude internal deps from versioning requirement

Bug:b/449859271
Change-Id: I1b1d53e4c3f6a2c70d761342b0b030a19242157a
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/tools/depot_tools/+/7005408
Reviewed-by: Anne Redulla <aredulla@google.com>
Auto-Submit: Jordan Brown <rop@google.com>
Commit-Queue: Anne Redulla <aredulla@google.com>
This commit is contained in:
Jordan
2025-10-07 01:13:43 -07:00
committed by LUCI CQ
parent 276ae56a8e
commit 88b3c4e0b1
2 changed files with 172 additions and 143 deletions

View File

@@ -266,9 +266,10 @@ class DependencyMetadata:
# If the repository is hosted somewhere (i.e. Chromium isn't the # If the repository is hosted somewhere (i.e. Chromium isn't the
# canonical repositroy of the dependency), at least one of the fields # canonical repositroy of the dependency), at least one of the fields
# Version, Date or Revision must be provided. # Version, Date or Revision must be provided, unless it is canonical or internal.
if (not (self.is_canonical or self.version or self.date or self.revision if not (self.is_canonical or self.is_internal) and not (
or self.revision_in_deps)): self.version or self.date or self.revision
or self.revision_in_deps):
versioning_fields = [ versioning_fields = [
known_fields.VERSION, known_fields.DATE, known_fields.REVISION known_fields.VERSION, known_fields.DATE, known_fields.REVISION
] ]
@@ -435,6 +436,16 @@ class DependencyMetadata:
value = self._metadata.get(known_fields.URL, "") value = self._metadata.get(known_fields.URL, "")
return known_fields.URL.repo_is_canonical(value) return known_fields.URL.repo_is_canonical(value)
@property
def is_internal(self) -> bool:
"""
Returns whether this repository is internal to google/chromium.
This is derived from a special value in the URL field.
"""
value = self._metadata.get(known_fields.URL, "")
return known_fields.URL.repo_is_internal(value)
@property @property
def version(self) -> Optional[str]: def version(self) -> Optional[str]:
return self._return_as_property(known_fields.VERSION) return self._return_as_property(known_fields.VERSION)
@@ -577,10 +588,9 @@ class DependencyMetadata:
if self.url_is_package_manager: if self.url_is_package_manager:
return "sufficient:Package Manager URL and Version" return "sufficient:Package Manager URL and Version"
raw_url = self._metadata.get(known_fields.URL, None) if self.is_canonical:
if raw_url is not None and known_fields.URL.repo_is_canonical(raw_url):
return "ignore:Canonical" return "ignore:Canonical"
if raw_url is not None and known_fields.URL.repo_is_internal(raw_url): if self.is_internal:
return "ignore:Internal" return "ignore:Internal"
if self.update_mechanism and self.update_mechanism[0]: if self.update_mechanism and self.update_mechanism[0]:
if self.update_mechanism[0].lower() == "static": if self.update_mechanism[0].lower() == "static":

View File

@@ -114,29 +114,50 @@ class DependencyValidationTest(unittest.TestCase):
def test_versioning_field(self): def test_versioning_field(self):
"""Check that a validation error is returned for insufficient """Check that a validation error is returned for insufficient
versioning info. No Date/Revision and Version is N/A.""" versioning info."""
dependency = dm.DependencyMetadata() with self.subTest(msg="Insufficient versioning info"):
dependency.add_entry(known_fields.NAME.get_name(), dependency = dm.DependencyMetadata()
"Test metadata missing versioning info") dependency.add_entry(known_fields.NAME.get_name(),
dependency.add_entry(known_fields.URL.get_name(), "Test metadata missing versioning info")
"https://www.example.com") dependency.add_entry(known_fields.URL.get_name(),
dependency.add_entry(known_fields.VERSION.get_name(), "N/A") "https://www.example.com")
dependency.add_entry(known_fields.LICENSE.get_name(), "MIT") dependency.add_entry(known_fields.VERSION.get_name(), "N/A")
dependency.add_entry(known_fields.LICENSE_FILE.get_name(), "LICENSE") dependency.add_entry(known_fields.LICENSE.get_name(), "MIT")
dependency.add_entry(known_fields.SECURITY_CRITICAL.get_name(), "no") dependency.add_entry(known_fields.LICENSE_FILE.get_name(),
dependency.add_entry(known_fields.SHIPPED.get_name(), "no") "LICENSE")
dependency.add_entry(known_fields.SECURITY_CRITICAL.get_name(),
"no")
dependency.add_entry(known_fields.SHIPPED.get_name(), "no")
results = dependency.validate( results = dependency.validate(
source_file_dir=os.path.join(_THIS_DIR, "data"), source_file_dir=os.path.join(_THIS_DIR, "data"),
repo_root_dir=_THIS_DIR, repo_root_dir=_THIS_DIR,
) )
self.assertEqual(len(results), 1) self.assertEqual(len(results), 1)
self.assertTrue(isinstance(results[0], vr.ValidationError)) self.assertTrue(isinstance(results[0], vr.ValidationError))
self.assertEqual(results[0].get_reason(), self.assertEqual(results[0].get_reason(),
"Versioning fields are insufficient.") "Versioning fields are insufficient.")
with self.subTest(
msg="Google Internal URL skips versioning requirement"):
dependency = dm.DependencyMetadata()
dependency.add_entry(known_fields.NAME.get_name(),
"Test Google Internal URL")
dependency.add_entry(known_fields.URL.get_name(), "Google Internal")
dependency.add_entry(known_fields.VERSION.get_name(), "N/A")
dependency.add_entry(known_fields.LICENSE.get_name(), "MIT")
dependency.add_entry(known_fields.LICENSE_FILE.get_name(),
"LICENSE")
dependency.add_entry(known_fields.SECURITY_CRITICAL.get_name(),
"yes")
dependency.add_entry(known_fields.SHIPPED.get_name(), "yes")
results = dependency.validate(
source_file_dir=os.path.join(_THIS_DIR, "data"),
repo_root_dir=_THIS_DIR,
)
self.assertEqual(len(results), 0)
def test_cpe_prefix_and_version_validation(self):
"""Check validation for CPEPrefix and Version fields."""
with self.subTest(msg="CPEPrefix without version, N/A Version"): with self.subTest(msg="CPEPrefix without version, N/A Version"):
dependency = dm.DependencyMetadata() dependency = dm.DependencyMetadata()
dependency.add_entry(known_fields.NAME.get_name(), "Test") dependency.add_entry(known_fields.NAME.get_name(), "Test")
@@ -199,7 +220,6 @@ class DependencyValidationTest(unittest.TestCase):
source_file_dir=os.path.join(_THIS_DIR, "data"), source_file_dir=os.path.join(_THIS_DIR, "data"),
repo_root_dir=_THIS_DIR) repo_root_dir=_THIS_DIR)
self.assertEqual(len(results), 0) self.assertEqual(len(results), 0)
reasons = {r.get_reason() for r in results}
with self.subTest(msg="CPEPrefix unknown, N/A Version"): with self.subTest(msg="CPEPrefix unknown, N/A Version"):
dependency = dm.DependencyMetadata() dependency = dm.DependencyMetadata()
@@ -220,109 +240,130 @@ class DependencyValidationTest(unittest.TestCase):
repo_root_dir=_THIS_DIR) repo_root_dir=_THIS_DIR)
self.assertEqual(len(results), 0) self.assertEqual(len(results), 0)
def test_versioning_with_invalid_revision(self): with self.subTest(msg="Insufficient versioning with invalid revision"):
"""Check that a validation error is returned for insufficient dependency = dm.DependencyMetadata()
versioning info.""" dependency.add_entry(known_fields.NAME.get_name(),
dependency = dm.DependencyMetadata() "Test metadata missing versioning info")
dependency.add_entry(known_fields.NAME.get_name(), dependency.add_entry(known_fields.URL.get_name(),
"Test metadata missing versioning info") "https://www.example.com")
dependency.add_entry(known_fields.URL.get_name(), dependency.add_entry(known_fields.VERSION.get_name(), "N/A")
"https://www.example.com") dependency.add_entry(known_fields.REVISION.get_name(), "N/A")
dependency.add_entry(known_fields.VERSION.get_name(), "N/A") dependency.add_entry(known_fields.LICENSE.get_name(), "MIT")
dependency.add_entry(known_fields.REVISION.get_name(), "N/A") dependency.add_entry(known_fields.LICENSE_FILE.get_name(),
dependency.add_entry(known_fields.LICENSE.get_name(), "MIT") "LICENSE")
dependency.add_entry(known_fields.LICENSE_FILE.get_name(), "LICENSE") dependency.add_entry(known_fields.SECURITY_CRITICAL.get_name(),
dependency.add_entry(known_fields.SECURITY_CRITICAL.get_name(), "no") "no")
dependency.add_entry(known_fields.SHIPPED.get_name(), "no") dependency.add_entry(known_fields.SHIPPED.get_name(), "no")
results = dependency.validate( results = dependency.validate(
source_file_dir=os.path.join(_THIS_DIR, "data"), source_file_dir=os.path.join(_THIS_DIR, "data"),
repo_root_dir=_THIS_DIR, repo_root_dir=_THIS_DIR,
) )
self.assertEqual(len(results), 2) self.assertEqual(len(results), 2)
self.assertTrue(isinstance(results[0], vr.ValidationError)) self.assertTrue(isinstance(results[0], vr.ValidationError))
self.assertTrue(isinstance(results[1], vr.ValidationError)) self.assertTrue(isinstance(results[1], vr.ValidationError))
self.assertEqual(results[0].get_reason(), self.assertEqual(results[0].get_reason(),
"Revision is not a valid hexadecimal revision.") "Revision is not a valid hexadecimal revision.")
self.assertEqual(results[1].get_reason(), self.assertEqual(results[1].get_reason(),
"Versioning fields are insufficient.") "Versioning fields are insufficient.")
def test_invalid_revision(self): with self.subTest(msg="Invalid revision format"):
"""Check invalid revision formats return validation errors.""" dependency = dm.DependencyMetadata()
dependency.add_entry(known_fields.NAME.get_name(),
"Invalid Revision")
dependency.add_entry(known_fields.URL.get_name(),
"https://www.example.com")
dependency.add_entry(known_fields.VERSION.get_name(), "1.0.0")
dependency.add_entry(known_fields.REVISION.get_name(),
"invalid_revision")
dependency.add_entry(known_fields.LICENSE.get_name(), "MIT")
dependency.add_entry(known_fields.LICENSE_FILE.get_name(),
"LICENSE")
dependency.add_entry(known_fields.SECURITY_CRITICAL.get_name(),
"no")
dependency.add_entry(known_fields.SHIPPED.get_name(), "no")
# Test invalid revision format (non-hexadecimal). results = dependency.validate(
dependency = dm.DependencyMetadata() source_file_dir=os.path.join(_THIS_DIR, "data"),
dependency.add_entry(known_fields.NAME.get_name(), "Invalid Revision") repo_root_dir=_THIS_DIR,
dependency.add_entry(known_fields.URL.get_name(), )
"https://www.example.com") self.assertEqual(len(results), 1)
dependency.add_entry(known_fields.VERSION.get_name(), "1.0.0") self.assertTrue(isinstance(results[0], vr.ValidationError))
dependency.add_entry(known_fields.REVISION.get_name(), self.assertEqual(
"invalid_revision") results[0].get_reason(),
dependency.add_entry(known_fields.LICENSE.get_name(), "MIT") "Revision is not a valid hexadecimal revision.",
dependency.add_entry(known_fields.LICENSE_FILE.get_name(), "LICENSE") )
dependency.add_entry(known_fields.SECURITY_CRITICAL.get_name(), "no")
dependency.add_entry(known_fields.SHIPPED.get_name(), "no")
results = dependency.validate( with self.subTest(msg="Valid revision format"):
source_file_dir=os.path.join(_THIS_DIR, "data"), dependency = dm.DependencyMetadata()
repo_root_dir=_THIS_DIR, dependency.add_entry(known_fields.NAME.get_name(), "Valid Revision")
) dependency.add_entry(known_fields.URL.get_name(),
self.assertEqual(len(results), 1) "https://www.example.com")
self.assertTrue(isinstance(results[0], vr.ValidationError)) dependency.add_entry(known_fields.VERSION.get_name(), "N/A")
self.assertEqual( dependency.add_entry(known_fields.LICENSE.get_name(), "MIT")
results[0].get_reason(), dependency.add_entry(known_fields.LICENSE_FILE.get_name(),
"Revision is not a valid hexadecimal revision.", "LICENSE")
) dependency.add_entry(known_fields.SECURITY_CRITICAL.get_name(),
"no")
dependency.add_entry(known_fields.SHIPPED.get_name(), "no")
def test_valid_revision(self): # Expect an insufficient versioning error since version is N/A.
"""Check valid revision formats return no validation issues.""" results = dependency.validate(
source_file_dir=os.path.join(_THIS_DIR, "data"),
repo_root_dir=_THIS_DIR,
)
self.assertGreater(len(results), 0)
dependency = dm.DependencyMetadata() # Fix the error by adding a valid revision.
dependency.add_entry(known_fields.NAME.get_name(), "Valid Revision") dependency.add_entry(known_fields.REVISION.get_name(), "abcdef1")
dependency.add_entry(known_fields.URL.get_name(), results = dependency.validate(
"https://www.example.com") source_file_dir=os.path.join(_THIS_DIR, "data"),
dependency.add_entry(known_fields.VERSION.get_name(), "1.0.0") repo_root_dir=_THIS_DIR,
dependency.add_entry(known_fields.LICENSE.get_name(), "MIT") )
dependency.add_entry(known_fields.LICENSE_FILE.get_name(), "LICENSE") self.assertEqual(len(results), 0)
dependency.add_entry(known_fields.SECURITY_CRITICAL.get_name(), "no")
dependency.add_entry(known_fields.SHIPPED.get_name(), "no")
results = dependency.validate( with self.subTest(msg="Revision: DEPS is acceptable"):
source_file_dir=os.path.join(_THIS_DIR, "data"), dependency = dm.DependencyMetadata()
repo_root_dir=_THIS_DIR, dependency.add_entry(known_fields.NAME.get_name(), "Dependency")
) dependency.add_entry(known_fields.URL.get_name(),
# No errors for no revision. "https://www.example.com")
self.assertEqual(len(results), 0) dependency.add_entry(known_fields.VERSION.get_name(), "N/A")
dependency.add_entry(known_fields.REVISION.get_name(), "DEPS")
dependency.add_entry(known_fields.LICENSE.get_name(), "MIT")
dependency.add_entry(known_fields.LICENSE_FILE.get_name(),
"LICENSE")
dependency.add_entry(known_fields.SECURITY_CRITICAL.get_name(),
"no")
dependency.add_entry(known_fields.SHIPPED.get_name(), "no")
dependency.add_entry(known_fields.REVISION.get_name(), results = dependency.validate(
"abcdef1") # Valid. source_file_dir=os.path.join(_THIS_DIR, "data"),
results = dependency.validate( repo_root_dir=_THIS_DIR,
source_file_dir=os.path.join(_THIS_DIR, "data"), )
repo_root_dir=_THIS_DIR, self.assertEqual(len(results), 0)
)
# No errors for valid revision.
self.assertEqual(len(results), 0)
def test_valid_revision_in_deps(self): with self.subTest(
"""Check "Revision: DEPS" is acceptable.""" msg=
"Check versioning information isn't required for dependencies where"
"Chromium is the canonical repository."):
dependency = dm.DependencyMetadata()
dependency.add_entry(known_fields.NAME.get_name(),
"Test valid metadata")
dependency.add_entry(known_fields.URL.get_name(),
"This is the canonical repository")
dependency.add_entry(known_fields.VERSION.get_name(), "N/A")
dependency.add_entry(known_fields.LICENSE.get_name(), "MIT")
dependency.add_entry(known_fields.LICENSE_FILE.get_name(),
"LICENSE")
dependency.add_entry(known_fields.SECURITY_CRITICAL.get_name(),
"yes")
dependency.add_entry(known_fields.SHIPPED.get_name(), "yes")
dependency = dm.DependencyMetadata() results = dependency.validate(
dependency.add_entry(known_fields.NAME.get_name(), "Dependency") source_file_dir=os.path.join(_THIS_DIR, "data"),
dependency.add_entry(known_fields.URL.get_name(), repo_root_dir=_THIS_DIR,
"https://www.example.com") )
dependency.add_entry(known_fields.VERSION.get_name(), "N/A") self.assertEqual(len(results), 0)
dependency.add_entry(known_fields.REVISION.get_name(), "DEPS")
dependency.add_entry(known_fields.LICENSE.get_name(), "MIT")
dependency.add_entry(known_fields.LICENSE_FILE.get_name(), "LICENSE")
dependency.add_entry(known_fields.SECURITY_CRITICAL.get_name(), "no")
dependency.add_entry(known_fields.SHIPPED.get_name(), "no")
results = dependency.validate(
source_file_dir=os.path.join(_THIS_DIR, "data"),
repo_root_dir=_THIS_DIR,
)
# No errors for no revision.
self.assertEqual(len(results), 0)
def test_required_field(self): def test_required_field(self):
"""Check that a validation error is returned for a missing field.""" """Check that a validation error is returned for a missing field."""
@@ -431,28 +472,6 @@ class DependencyValidationTest(unittest.TestCase):
) )
self.assertEqual(len(results), 0) self.assertEqual(len(results), 0)
def test_dep_is_canonical_skips_versioning_requirement(self):
"""
Check versioning information isn't required for dependencies where
Chromium is the canonical repository.
"""
dependency = dm.DependencyMetadata()
dependency.add_entry(known_fields.NAME.get_name(),
"Test valid metadata")
dependency.add_entry(known_fields.URL.get_name(),
"This is the canonical repository")
dependency.add_entry(known_fields.VERSION.get_name(), "N/A")
dependency.add_entry(known_fields.LICENSE.get_name(), "MIT")
dependency.add_entry(known_fields.LICENSE_FILE.get_name(), "LICENSE")
dependency.add_entry(known_fields.SECURITY_CRITICAL.get_name(), "yes")
dependency.add_entry(known_fields.SHIPPED.get_name(), "yes")
results = dependency.validate(
source_file_dir=os.path.join(_THIS_DIR, "data"),
repo_root_dir=_THIS_DIR,
)
self.assertEqual(len(results), 0)
def test_all_licenses_allowlisted(self): def test_all_licenses_allowlisted(self):
"""Test that a single allowlisted license returns True.""" """Test that a single allowlisted license returns True."""
dependency = dm.DependencyMetadata() dependency = dm.DependencyMetadata()