選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。
 
 
 
 
 
 

148 行
4.0 KiB

  1. import json
  2. import os
  3. import re
  4. import shlex
  5. import subprocess
  6. import sys
  7. import time
  8. import urllib.request
  9. from functools import lru_cache
  10. from urllib.error import HTTPError
  11. @lru_cache(maxsize=None)
  12. def fetch_pr_data(pr_number, repo, endpoint=""):
  13. api_url = f"https://api.github.com/repos/{repo}/pulls/{pr_number}"
  14. if endpoint:
  15. api_url += f"/{endpoint}"
  16. res = req(api_url)
  17. return json.loads(res.read().decode("utf8"))
  18. def req(url):
  19. "Simple resilient request call to handle rate limits."
  20. headers = None
  21. token = os.environ.get("GITHUB_TOKEN")
  22. if token:
  23. headers = {"authorization": f"Bearer {token}"}
  24. retries = 0
  25. while True:
  26. try:
  27. req = urllib.request.Request(url, headers=headers)
  28. return urllib.request.urlopen(req)
  29. except HTTPError as exc:
  30. if exc.code == 403 and retries < 5:
  31. retries += 1
  32. time.sleep(retries)
  33. continue
  34. raise
  35. def get_files_list(pr_number, repo="xhiveframework/xhiveframework"):
  36. return [change["filename"] for change in fetch_pr_data(pr_number, repo, "files")]
  37. def get_output(command, shell=True):
  38. print(command)
  39. command = shlex.split(command)
  40. return subprocess.check_output(command, shell=shell, encoding="utf8").strip()
  41. def has_skip_ci_label(pr_number, repo="xhiveframework/xhiveframework"):
  42. return has_label(pr_number, "Skip CI", repo)
  43. def has_run_server_tests_label(pr_number, repo="xhiveframework/xhiveframework"):
  44. return has_label(pr_number, "Run Server Tests", repo)
  45. def has_run_ui_tests_label(pr_number, repo="xhiveframework/xhiveframework"):
  46. return has_label(pr_number, "Run UI Tests", repo)
  47. def has_label(pr_number, label, repo="xhiveframework/xhiveframework"):
  48. return any(
  49. [
  50. fetched_label["name"]
  51. for fetched_label in fetch_pr_data(pr_number, repo)["labels"]
  52. if fetched_label["name"] == label
  53. ]
  54. )
  55. def is_py(file):
  56. return file.endswith("py")
  57. def is_ci(file):
  58. return ".github" in file
  59. def is_frontend_code(file):
  60. return file.lower().endswith(
  61. (".css", ".scss", ".less", ".sass", ".styl", ".js", ".ts", ".vue", ".html")
  62. )
  63. def is_docs(file):
  64. regex = re.compile(r"\.(md|png|jpg|jpeg|csv|svg)$|^.github|LICENSE")
  65. return bool(regex.search(file))
  66. if __name__ == "__main__":
  67. files_list = sys.argv[1:]
  68. build_type = os.environ.get("TYPE")
  69. pr_number = os.environ.get("PR_NUMBER")
  70. repo = os.environ.get("REPO_NAME")
  71. # this is a push build, run all builds
  72. if not pr_number:
  73. os.system('echo "::set-output name=build::strawberry"')
  74. os.system('echo "::set-output name=build-server::strawberry"')
  75. sys.exit(0)
  76. files_list = files_list or get_files_list(pr_number=pr_number, repo=repo)
  77. if not files_list:
  78. print("No files' changes detected. Build is shutting")
  79. sys.exit(0)
  80. ci_files_changed = any(f for f in files_list if is_ci(f))
  81. only_docs_changed = len(list(filter(is_docs, files_list))) == len(files_list)
  82. only_frontend_code_changed = len(list(filter(is_frontend_code, files_list))) == len(files_list)
  83. updated_py_file_count = len(list(filter(is_py, files_list)))
  84. only_py_changed = updated_py_file_count == len(files_list)
  85. if has_skip_ci_label(pr_number, repo):
  86. if build_type == "ui" and has_run_ui_tests_label(pr_number, repo):
  87. print("Running UI tests only.")
  88. elif build_type == "server" and has_run_server_tests_label(pr_number, repo):
  89. print("Running server tests only.")
  90. else:
  91. print("Found `Skip CI` label on pr, stopping build process.")
  92. sys.exit(0)
  93. elif ci_files_changed:
  94. print("CI related files were updated, running all build processes.")
  95. elif only_docs_changed:
  96. print("Only docs were updated, stopping build process.")
  97. sys.exit(0)
  98. elif (
  99. only_frontend_code_changed
  100. and build_type == "server"
  101. and not has_run_server_tests_label(pr_number, repo)
  102. ):
  103. print("Only Frontend code was updated; Stopping Python build process.")
  104. sys.exit(0)
  105. elif build_type == "ui" and only_py_changed and not has_run_ui_tests_label(pr_number, repo):
  106. print("Only Python code was updated, stopping Cypress build process.")
  107. sys.exit(0)
  108. os.system('echo "::set-output name=build::strawberry"')