rerun-apps-version-check.py 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. #!/usr/bin/env python3
  2. # Usage: python3 rerun-apps-version-check.py -t <github token> -r <repo>
  3. #
  4. # Default repo is emqx/emqx
  5. #
  6. import requests
  7. import http.client
  8. import json
  9. import os
  10. import sys
  11. import time
  12. import math
  13. import inspect
  14. from optparse import OptionParser
  15. from urllib.parse import urlparse, parse_qs
  16. from requests.adapters import HTTPAdapter
  17. from requests.packages.urllib3.util.retry import Retry
  18. user_agent = sys.argv[0].split('/')[-1]
  19. def query(owner, repo):
  20. return """
  21. query {
  22. repository(owner: "%s", name: "%s") {
  23. pullRequests(first: 25, states: OPEN, orderBy: {field:CREATED_AT, direction:DESC}) {
  24. nodes {
  25. url
  26. commits(last: 1) {
  27. nodes {
  28. commit {
  29. checkSuites(first: 25) {
  30. nodes {
  31. url
  32. checkRuns(first: 1, filterBy: {checkName: "check_apps_version"}) {
  33. nodes {
  34. url
  35. }
  36. }
  37. }
  38. }
  39. }
  40. }
  41. }
  42. }
  43. }
  44. }
  45. }
  46. """ % (owner, repo)
  47. def get_headers(token: str):
  48. return {'Accept': 'application/vnd.github+json',
  49. 'Authorization': f'Bearer {token}',
  50. 'X-GitHub-Api-Version': '2022-11-28',
  51. 'User-Agent': f'{user_agent}'
  52. }
  53. def get_session():
  54. session = requests.Session()
  55. retries = Retry(total=10,
  56. backoff_factor=1, # 1s
  57. allowed_methods=None,
  58. status_forcelist=[ 429, 500, 502, 503, 504 ]) # Retry on these status codes
  59. session.mount('https://', HTTPAdapter(max_retries=retries))
  60. return session
  61. def get_check_suite_ids(token: str, repo: str):
  62. session = get_session()
  63. url = f'https://api.github.com/graphql'
  64. [repo_owner, repo_repo] = repo.split('/')
  65. r = session.post(url, headers=get_headers(token), json={'query': query(repo_owner, repo_repo)})
  66. if r.status_code == 200:
  67. resp = r.json()
  68. if not 'data' in resp:
  69. print(f'Failed to fetch check runs: {r.status_code}\n{r.json()}')
  70. sys.exit(1)
  71. result = []
  72. for pr in resp['data']['repository']['pullRequests']['nodes']:
  73. if not pr['commits']['nodes']:
  74. continue
  75. if not pr['commits']['nodes'][0]['commit']['checkSuites']['nodes']:
  76. continue
  77. for node in pr['commits']['nodes'][0]['commit']['checkSuites']['nodes']:
  78. if node['checkRuns']['nodes']:
  79. url_parsed = urlparse(node['url'])
  80. params = parse_qs(url_parsed.query)
  81. check_suite_id = params['check_suite_id'][0]
  82. result.extend([(check_suite_id, pr['url'], node['checkRuns']['nodes'][0]['url'])])
  83. return result
  84. else:
  85. print(f'Failed to fetch check runs: {r.status_code}\n{r.text}')
  86. sys.exit(1)
  87. def rerequest_check_suite(token: str, repo: str, check_suite_id: str):
  88. session = get_session()
  89. url = f'https://api.github.com/repos/{repo}/check-suites/{check_suite_id}/rerequest'
  90. r = session.post(url, headers=get_headers(token))
  91. if r.status_code == 201:
  92. print(f'Successfully triggered {url}')
  93. else:
  94. print(f'Failed to trigger {url}: {r.status_code}\n{r.text}')
  95. def main():
  96. parser = OptionParser()
  97. parser.add_option("-r", "--repo", dest="repo",
  98. help="github repo", default="emqx/emqx")
  99. parser.add_option("-t", "--token", dest="gh_token",
  100. help="github API token")
  101. (options, args) = parser.parse_args()
  102. # Get github token from env var if provided, else use the one from command line.
  103. # The token must be exported in the env from ${{ secrets.GITHUB_TOKEN }} in the workflow.
  104. token = os.environ['GITHUB_TOKEN'] if 'GITHUB_TOKEN' in os.environ else options.gh_token
  105. for id, pr_url, check_run_url in get_check_suite_ids(token, options.repo):
  106. print(f'Attempting to re-request {check_run_url} for {pr_url}')
  107. rerequest_check_suite(token, options.repo, id)
  108. if __name__ == '__main__':
  109. main()