1
0
Fork 0
firefox/tools/lint/updatebot/validate_yaml.py
Daniel Baumann 5e9a113729
Adding upstream version 140.0.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
2025-06-25 09:37:52 +02:00

98 lines
3.5 KiB
Python

# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
import json
import urllib.error
import urllib.request
from mozbuild.vendor.moz_yaml import load_moz_yaml
from mozlint import result
from mozlint.pathutils import expand_exclusions
class UpdatebotValidator:
def __init__(self):
self._bmo_cache = {}
def lint_file(self, path, **kwargs):
if not kwargs.get("testing", False):
if not path.endswith("moz.yaml"):
return None
if "test/files/updatebot" in path:
return None
try:
yaml = load_moz_yaml(path)
if "vendoring" in yaml and yaml["vendoring"].get("flavor", None) == "rust":
yaml_revision = yaml["origin"]["revision"]
with open("Cargo.lock") as f:
for line in f:
if yaml_revision in line:
break
else:
return f"Revision {yaml_revision} specified in {path} wasn't found in Cargo.lock"
if "bugzilla" in yaml:
product = yaml["bugzilla"].get("product")
component = yaml["bugzilla"].get("component")
if product and component:
if not self._is_valid_bmo_category(product, component):
return (
f"Invalid Bugzilla product/component in {path}: '{product} / {component}'.\n"
f"If {path} was recently modified, it's likely the Bugzilla information was not correctly supplied.\n"
f"If it has not been recently modified, it's likely the Bugzilla component was recently renamed and it must be updated."
)
return None
except Exception as e:
return f"Could not load {path} according to schema in moz_yaml.py: {e}"
def _is_valid_bmo_category(self, product, component):
cache_key = (product, component)
if cache_key in self._bmo_cache:
return self._bmo_cache[cache_key]
url = (
f"https://bugzilla.mozilla.org/rest/component?"
f"product={urllib.parse.quote(product)}&component={urllib.parse.quote(component)}"
)
try:
with urllib.request.urlopen(url, timeout=5) as response:
if response.status == 200:
data = json.load(response)
valid = "error" not in data
self._bmo_cache[cache_key] = valid
return valid
except urllib.error.HTTPError as e:
# Most likely a 404-style result with a useful JSON error body
try:
data = json.load(e)
if data.get("error") == 1:
self._bmo_cache[cache_key] = False
return False
except Exception:
return True # Be lenient
except Exception:
return True # Be lenient
return True # Be lenient
def lint(paths, config, **lintargs):
if not isinstance(paths, list):
paths = [paths]
errors = []
files = list(expand_exclusions(paths, config, lintargs["root"]))
validator = UpdatebotValidator()
for f in files:
message = validator.lint_file(f, **lintargs)
if message:
errors.append(result.from_config(config, path=f, message=message))
return errors