react-to-product-owners-yml-changes.py 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. #!/usr/bin/env python3
  2. from __future__ import annotations
  3. import os
  4. import sys
  5. from os.path import dirname, join, realpath
  6. import yaml
  7. PREFIX = "Product Area: "
  8. LABELS_YAML = ".github/labels.yml"
  9. def main():
  10. # Run from project root.
  11. os.chdir(realpath(join(dirname(sys.argv[0]), "..")))
  12. product_owners = yaml.safe_load(open(sys.argv[1]))
  13. labels = open(LABELS_YAML)
  14. areas = [
  15. # For `sentry` repo we don't want SDK or Docs areas, that stuff should
  16. # be transferred to other repos.
  17. x
  18. for x in product_owners["by_area"]
  19. if not x.startswith("SDK") and not x == "Docs"
  20. ]
  21. fastforward = False
  22. head: list[str] = []
  23. area_lines = ["- name: 'Product Area: Unknown'\n", " color: '8D5494'\n"]
  24. tail: list[str] = []
  25. current = head
  26. # Best to look the other way, Buck. This is just waaaay easier than trying to
  27. # use ruamel.yaml to preserve comments and other formatting. What this does is
  28. # loop through line by line, collecting everything before the Product Area
  29. # labels in `head` and everything after in `tail`. It "fast-forwards" past the
  30. # existing Product Area labels. Then we generate output for the new Product
  31. # Area labels, then emit the three parts (head, area_lines, tail) in order.
  32. for line in labels:
  33. if line == "\n":
  34. fastforward = False
  35. elif fastforward:
  36. continue
  37. elif line.startswith("- name: 'Product Area: "):
  38. fastforward = True
  39. current = tail
  40. continue
  41. current.append(line)
  42. for area in areas:
  43. # These are specifically placed at the front and end of the list of product areas.
  44. # They will always exist, so ignore what is coming in from security-as-code as a workaround.
  45. if area != "Other" and area != "Unknown":
  46. if "'" in area:
  47. area_lines.append(f'- name: "Product Area: {area}"\n')
  48. else:
  49. area_lines.append(f"- name: 'Product Area: {area}'\n")
  50. area_lines.append(" color: '8D5494'\n")
  51. area_lines += ["- name: 'Product Area: Other'\n", " color: '8D5494'\n"]
  52. with open(".github/labels.yml", "w+") as fp:
  53. fp.writelines(head)
  54. fp.writelines(area_lines)
  55. fp.writelines(tail)
  56. # Now for issue templates. Same game. Hang in there.
  57. BEGINNING = " # begin product areas - autogenerated by bin/react-to-product-owners-yml-changes.py\n"
  58. END = " # end product areas\n"
  59. for template in ("bug", "feature"):
  60. filepath = f".github/ISSUE_TEMPLATE/{template}.yml"
  61. head = []
  62. area_lines = [BEGINNING, " - 'Unknown'\n"]
  63. tail = []
  64. current = head
  65. for line in open(filepath):
  66. if line == END:
  67. fastforward = False
  68. elif line == BEGINNING:
  69. fastforward = True
  70. current = tail
  71. elif not fastforward:
  72. current.append(line)
  73. for area in areas:
  74. if area != "Other" and area != "Unknown":
  75. if "'" in area:
  76. area_lines.append(f' - "{area}"\n')
  77. else:
  78. area_lines.append(f" - '{area}'\n")
  79. area_lines += [" - 'Other'\n", END]
  80. with open(filepath, "w+") as fp:
  81. fp.writelines(head)
  82. fp.writelines(area_lines)
  83. fp.writelines(tail)
  84. return 0
  85. if __name__ == "__main__":
  86. raise SystemExit(main())