settings.py 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. import enum
  2. import os
  3. import subprocess
  4. from typing import Optional, Dict, Tuple
  5. from ray_release.exception import ReleaseTestConfigError
  6. from ray_release.logger import logger
  7. from ray_release.wheels import DEFAULT_BRANCH, get_buildkite_repo_branch
  8. class Frequency(enum.Enum):
  9. DISABLED = enum.auto()
  10. ANY = enum.auto()
  11. MULTI = enum.auto()
  12. NIGHTLY = enum.auto()
  13. WEEKLY = enum.auto()
  14. frequency_str_to_enum = {
  15. "disabled": Frequency.DISABLED,
  16. "any": Frequency.ANY,
  17. "any-smoke": Frequency.ANY,
  18. "multi": Frequency.MULTI,
  19. "nightly": Frequency.NIGHTLY,
  20. "weekly": Frequency.WEEKLY,
  21. }
  22. class Priority(enum.Enum):
  23. DEFAULT = 0
  24. MANUAL = 10
  25. HIGH = 50
  26. HIGHEST = 100
  27. priority_str_to_enum = {
  28. "default": Priority.DEFAULT,
  29. "manual": Priority.MANUAL,
  30. "high": Priority.HIGH,
  31. "highest": Priority.HIGHEST,
  32. }
  33. def get_frequency(frequency_str: str) -> Frequency:
  34. frequency_str = frequency_str.lower()
  35. if frequency_str not in frequency_str_to_enum:
  36. raise ReleaseTestConfigError(
  37. f"Frequency not found: {frequency_str}. Must be one of "
  38. f"{list(frequency_str_to_enum.keys())}."
  39. )
  40. return frequency_str_to_enum[frequency_str]
  41. def get_priority(priority_str: str) -> Priority:
  42. priority_str = priority_str.lower()
  43. if priority_str not in priority_str_to_enum:
  44. raise ReleaseTestConfigError(
  45. f"Priority not found: {priority_str}. Must be one of "
  46. f"{list(priority_str_to_enum.keys())}."
  47. )
  48. return priority_str_to_enum[priority_str]
  49. def get_test_attr_regex_filters(filters_str: str) -> Dict[str, str]:
  50. if not filters_str:
  51. return {}
  52. test_attr_regex_filters = {}
  53. for line in filters_str.splitlines():
  54. line = line.strip()
  55. if not line:
  56. continue
  57. parts = line.split(":", maxsplit=1)
  58. if len(parts) != 2:
  59. raise ReleaseTestConfigError(
  60. f"Invalid test attr regex filter: {line}. "
  61. "Should be of the form attr:regex"
  62. )
  63. test_attr_regex_filters[parts[0]] = parts[1]
  64. return test_attr_regex_filters
  65. def split_ray_repo_str(repo_str: str) -> Tuple[str, str]:
  66. if "https://" in repo_str:
  67. if "/tree/" in repo_str:
  68. url, branch = repo_str.split("/tree/", maxsplit=2)
  69. return f"{url}.git", branch.rstrip("/")
  70. return repo_str, DEFAULT_BRANCH # Default branch
  71. if ":" in repo_str:
  72. owner_or_url, commit_or_branch = repo_str.split(":")
  73. else:
  74. owner_or_url = repo_str
  75. commit_or_branch = DEFAULT_BRANCH
  76. # Else, construct URL
  77. url = f"https://github.com/{owner_or_url}/ray.git"
  78. return url, commit_or_branch
  79. def get_buildkite_prompt_value(key: str) -> Optional[str]:
  80. try:
  81. value = subprocess.check_output(
  82. ["buildkite-agent", "meta-data", "get", key], text=True
  83. )
  84. except Exception as e:
  85. logger.warning(f"Could not fetch metadata for {key}: {e}")
  86. return None
  87. logger.debug(f"Got Buildkite prompt value for {key}: {value}")
  88. return value
  89. def get_pipeline_settings() -> Dict:
  90. """Get pipeline settings.
  91. Retrieves settings from the buildkite agent, environment variables,
  92. and default values (in that order of preference)."""
  93. settings = get_default_settings()
  94. settings = update_settings_from_environment(settings)
  95. settings = update_settings_from_buildkite(settings)
  96. return settings
  97. def get_default_settings() -> Dict:
  98. settings = {
  99. "frequency": Frequency.ANY,
  100. "prefer_smoke_tests": False,
  101. "test_attr_regex_filters": None,
  102. "ray_wheels": None,
  103. "ray_test_repo": None,
  104. "ray_test_branch": None,
  105. "priority": Priority.DEFAULT,
  106. "no_concurrency_limit": False,
  107. }
  108. return settings
  109. def update_settings_from_environment(settings: Dict) -> Dict:
  110. if "RELEASE_FREQUENCY" in os.environ:
  111. settings["frequency"] = get_frequency(os.environ["RELEASE_FREQUENCY"])
  112. if "RELEASE_PREFER_SMOKE_TESTS" in os.environ:
  113. settings["prefer_smoke_tests"] = bool(
  114. int(os.environ["RELEASE_PREFER_SMOKE_TESTS"])
  115. )
  116. elif os.environ.get("RELEASE_FREQUENCY", "").endswith("-smoke"):
  117. settings["prefer_smoke_tests"] = True
  118. if "RAY_TEST_REPO" in os.environ:
  119. settings["ray_test_repo"] = os.environ["RAY_TEST_REPO"]
  120. settings["ray_test_branch"] = os.environ.get("RAY_TEST_BRANCH", DEFAULT_BRANCH)
  121. elif "BUILDKITE_BRANCH" in os.environ:
  122. repo_url, branch = get_buildkite_repo_branch()
  123. settings["ray_test_repo"] = repo_url
  124. settings["ray_test_branch"] = branch
  125. if "RAY_WHEELS" in os.environ:
  126. settings["ray_wheels"] = os.environ["RAY_WHEELS"]
  127. if "TEST_NAME" in os.environ:
  128. # This is for backward compatibility.
  129. settings["test_attr_regex_filters"] = get_test_attr_regex_filters(
  130. "name:" + os.environ["TEST_NAME"]
  131. )
  132. if "TEST_ATTR_REGEX_FILTERS" in os.environ:
  133. settings["test_attr_regex_filters"] = get_test_attr_regex_filters(
  134. os.environ["TEST_ATTR_REGEX_FILTERS"]
  135. )
  136. if "RELEASE_PRIORITY" in os.environ:
  137. settings["priority"] = get_priority(os.environ["RELEASE_PRIORITY"])
  138. if "NO_CONCURRENCY_LIMIT" in os.environ:
  139. settings["no_concurrency_limit"] = bool(int(os.environ["NO_CONCURRENCY_LIMIT"]))
  140. return settings
  141. def update_settings_from_buildkite(settings: Dict):
  142. release_frequency = get_buildkite_prompt_value("release-frequency")
  143. if release_frequency:
  144. settings["frequency"] = get_frequency(release_frequency)
  145. if release_frequency.endswith("-smoke"):
  146. settings["prefer_smoke_tests"] = True
  147. ray_test_repo_branch = get_buildkite_prompt_value("release-ray-test-repo-branch")
  148. if ray_test_repo_branch:
  149. repo, branch = split_ray_repo_str(ray_test_repo_branch)
  150. settings["ray_test_repo"] = repo
  151. settings["ray_test_branch"] = branch
  152. ray_wheels = get_buildkite_prompt_value("release-ray-wheels")
  153. if ray_wheels:
  154. settings["ray_wheels"] = ray_wheels
  155. test_name_filter = get_buildkite_prompt_value("release-test-name")
  156. if test_name_filter:
  157. settings["test_attr_regex_filters"] = get_test_attr_regex_filters(
  158. "name:" + test_name_filter
  159. )
  160. test_attr_regex_filters = get_buildkite_prompt_value(
  161. "release-test-attr-regex-filters"
  162. )
  163. if test_attr_regex_filters:
  164. settings["test_attr_regex_filters"] = get_test_attr_regex_filters(
  165. test_attr_regex_filters
  166. )
  167. test_priority = get_buildkite_prompt_value("release-priority")
  168. if test_priority:
  169. settings["priority"] = get_priority(test_priority)
  170. no_concurrency_limit = get_buildkite_prompt_value("release-no-concurrency-limit")
  171. if no_concurrency_limit == "yes":
  172. settings["no_concurrency_limit"] = True
  173. return settings