Matrix Docker Ansible eploy
Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.
 
 
 

120 строки
4.3 KiB

  1. #!/usr/bin/env python3
  2. """Keeps Molecule-backed automerge rules in step with the available scenarios.
  3. .github/renovate.json automerges patch bumps for every role with a scenario. A narrower list of
  4. explicitly approved roles also automerges minor bumps. In both cases, the bump runs that role's
  5. Molecule scenario before merging, so the reasoning only holds while the role actually has one.
  6. The patch list must exactly match the scenarios. The minor list must be a subset of it: omission is
  7. an explicit policy choice, while an extra entry would merge a minor bump without the required gate.
  8. """
  9. import json
  10. import pathlib
  11. import sys
  12. REPO = pathlib.Path(__file__).resolve().parent.parent
  13. RENOVATE = REPO / ".github" / "renovate.json"
  14. PATCH_RULE_MARKER = "bin/check-molecule-automerge-list.py (patch rule)"
  15. MINOR_RULE_MARKER = "bin/check-molecule-automerge-list.py (minor rule)"
  16. def find_rule(config: dict, marker: str) -> dict | None:
  17. rules = [r for r in config.get("packageRules", []) if marker in r.get("description", "")]
  18. if len(rules) != 1:
  19. print(f"Expected exactly one rule mentioning {marker}, found {len(rules)}.", file=sys.stderr)
  20. return None
  21. return rules[0]
  22. def listed_roles(rule: dict, label: str) -> set[str] | None:
  23. listed = set()
  24. for name in rule.get("matchFileNames", []):
  25. parts = pathlib.PurePosixPath(name).parts
  26. if parts[:2] == ("roles", "custom") and parts[3:] == ("defaults", "main.yml"):
  27. listed.add(parts[2])
  28. else:
  29. print(f"Unexpected entry in the Molecule {label} automerge rule: {name}", file=sys.stderr)
  30. return None
  31. return listed
  32. def main() -> int:
  33. with_scenario = {
  34. p.parts[-4] for p in (REPO / "roles" / "custom").glob("*/molecule/default/molecule.yml")
  35. }
  36. config = json.loads(RENOVATE.read_text())
  37. patch_rule = find_rule(config, PATCH_RULE_MARKER)
  38. minor_rule = find_rule(config, MINOR_RULE_MARKER)
  39. if patch_rule is None or minor_rule is None:
  40. return 1
  41. patch_roles = listed_roles(patch_rule, "patch")
  42. minor_roles = listed_roles(minor_rule, "minor")
  43. if patch_roles is None or minor_roles is None:
  44. return 1
  45. errors = False
  46. if set(patch_rule.get("matchUpdateTypes", [])) != {"patch"}:
  47. print("The Molecule patch automerge rule must match only patch updates.", file=sys.stderr)
  48. errors = True
  49. if set(minor_rule.get("matchUpdateTypes", [])) != {"minor"}:
  50. print("The Molecule minor automerge rule must match only minor updates.", file=sys.stderr)
  51. errors = True
  52. automerged_without_scenario = sorted(patch_roles - with_scenario)
  53. scenario_without_automerge = sorted(with_scenario - patch_roles)
  54. if automerged_without_scenario:
  55. print(
  56. "These roles automerge patch bumps but have no Molecule scenario, so nothing would\n"
  57. "exercise the bump before it merges. Remove them from the rule in\n"
  58. ".github/renovate.json, or give them a scenario:",
  59. file=sys.stderr,
  60. )
  61. for role in automerged_without_scenario:
  62. print(f" {role}", file=sys.stderr)
  63. if scenario_without_automerge:
  64. print(
  65. "These roles have a Molecule scenario but are not in the automerge rule in\n"
  66. ".github/renovate.json, so their patch bumps still need a button press:",
  67. file=sys.stderr,
  68. )
  69. for role in scenario_without_automerge:
  70. print(f" {role}", file=sys.stderr)
  71. minor_without_scenario = sorted(minor_roles - with_scenario)
  72. minor_without_patch = sorted(minor_roles - patch_roles)
  73. if minor_without_scenario:
  74. print(
  75. "These roles automerge minor bumps but have no Molecule scenario:",
  76. file=sys.stderr,
  77. )
  78. for role in minor_without_scenario:
  79. print(f" {role}", file=sys.stderr)
  80. if minor_without_patch:
  81. print(
  82. "These roles automerge minor bumps but are missing from the patch rule:",
  83. file=sys.stderr,
  84. )
  85. for role in minor_without_patch:
  86. print(f" {role}", file=sys.stderr)
  87. return 1 if any(
  88. [
  89. errors,
  90. automerged_without_scenario,
  91. scenario_without_automerge,
  92. minor_without_scenario,
  93. minor_without_patch,
  94. ]
  95. ) else 0
  96. if __name__ == "__main__":
  97. sys.exit(main())