Source code
Revision control
Copy as Markdown
Other Tools
# 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
"""Check every vendored moz.yaml is verified by a vendor-verify task.
Turns the tree orange if a vendored moz.yaml (has a `vendoring:` section,
non-rust) is not in any task's `members` in vendor-verify.yml -- so a newly added
vendored library can't silently escape the re-vendoring checks. Also flags stale
entries, in `members` or in the expected-fail annotations, whose moz.yaml no longer
exists or is no longer vendored. Run as a source-test task gated on moz.yaml
+ config changes.
"""
import os
import sys
import yaml
TASKS = "taskcluster/kinds/source-test/vendor-verify.yml"
EXPECTED_FAIL = "taskcluster/scripts/misc/vendor-verify-expected-fail.yml"
def vendored_moz_yamls():
found = set()
for dirpath, dirnames, filenames in os.walk("."):
dirnames[:] = [
d
for d in dirnames
if d not in (".hg", ".git", "node_modules", "__pycache__")
and not d.startswith("obj-")
]
if "moz.yaml" not in filenames:
continue
path = os.path.join(dirpath, "moz.yaml").replace("./", "", 1)
try:
with open(path) as fh:
data = yaml.safe_load(fh) or {}
except Exception:
continue
vendoring = data.get("vendoring") or {}
# rust flavor is covered by the separate `rust` vendoring task.
if vendoring and vendoring.get("flavor") != "rust":
found.add(path)
return found
def main():
with open(TASKS) as fh:
# Every top-level key in a `tasks-from` file is a task, except the defaults.
tasks = yaml.safe_load(fh) or {}
tasks.pop("task-defaults", None)
with open(EXPECTED_FAIL) as fh:
annotations = (yaml.safe_load(fh) or {}).get("expected-fail") or {}
verified = {m for task in tasks.values() for m in (task.get("members") or [])}
annotated = set(annotations)
vendored = vendored_moz_yamls()
unassigned = sorted(vendored - verified)
stale_member = sorted(verified - vendored)
stale_expected_fail = sorted(annotated - vendored)
for path in unassigned:
print(
f"TEST-UNEXPECTED-ERROR | {path} | this vendored library (its moz.yaml has "
f"a `vendoring:` section) is not in any task's `members` in {TASKS}, so its "
f"vendoring would not be verified. Add `{path}` to one of them -- any task "
"works; it only picks which job verifies it, so put it with related "
f"libraries. See the header of {TASKS}. (vendoring-coverage)"
)
for path in stale_member:
print(
f"TEST-UNEXPECTED-ERROR | {TASKS} | a task's `members` lists `{path}`, which "
"is no longer a vendored moz.yaml (it was removed, or its "
f"`vendoring:` section was). Delete that entry from {TASKS}. "
"(vendoring-coverage)"
)
for path in stale_expected_fail:
print(
f"TEST-UNEXPECTED-ERROR | {EXPECTED_FAIL} | `expected-fail` references "
f"`{path}`, which is not a vendored moz.yaml -- likely a typo or a "
f"removed library. Fix or delete that entry in {EXPECTED_FAIL}. "
"(vendoring-coverage)"
)
if unassigned or stale_member or stale_expected_fail:
print(
f"vendor-verify coverage FAILED: {len(unassigned)} unassigned, "
f"{len(stale_member)} stale `members` entries, "
f"{len(stale_expected_fail)} stale expected-fail entries."
)
sys.exit(1)
print(
f"vendor-verify coverage OK: all {len(vendored)} vendored "
"moz.yaml are verified by a task, and every expected-fail entry is valid."
)
if __name__ == "__main__":
main()