milestone_check.py 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. # Copyright (c) 2018 Jupyter Development Team.
  2. # Distributed under the terms of the Modified BSD License.
  3. # Generate a GitHub token at https://github.com/settings/tokens
  4. # Invoke this script using something like:
  5. # python scripts/milestone_check.py
  6. import subprocess
  7. import requests
  8. import os
  9. try:
  10. api_token = os.environ['GITHUB_TOKEN']
  11. except KeyError:
  12. print('Error: set the environment variable GITHUB_TOKEN to a GitHub authentication token (see https://github.com/settings/tokens)')
  13. exit(1)
  14. MILESTONE=18
  15. ranges = {
  16. 18: 'origin/master --not origin/0.34.x' #0.35.0
  17. }
  18. out = subprocess.run("git log {} --format='%H,%cE,%s'".format(ranges[MILESTONE]), shell=True, encoding='utf8', stdout=subprocess.PIPE)
  19. commits = {i[0]: (i[1], i[2]) for i in (x.split(',',2) for x in out.stdout.splitlines())}
  20. url = 'https://api.github.com/graphql'
  21. json = { 'query' : """
  22. query test($milestone: Int!) {
  23. repository(owner:"jupyterlab" name:"jupyterlab") {
  24. milestone(number:$milestone) {
  25. title
  26. pullRequests(first:100 states:[MERGED]) {
  27. nodes {
  28. title
  29. number
  30. mergeCommit {
  31. oid
  32. }
  33. commits(first:100) {
  34. nodes {
  35. commit {
  36. oid
  37. }
  38. }
  39. }
  40. }
  41. }
  42. }
  43. }
  44. }
  45. """,
  46. 'variables': {
  47. 'milestone': MILESTONE
  48. }
  49. }
  50. headers = {'Authorization': 'token %s' % api_token}
  51. r = requests.post(url=url, json=json, headers=headers)
  52. milestone_data = r.json()['data']['repository']['milestone']
  53. pr_list = milestone_data['pullRequests']['nodes']
  54. # construct a commit to PR dictionary
  55. prs = {}
  56. for pr in pr_list:
  57. prs[pr['number']] = {'mergeCommit': pr['mergeCommit']['oid'],
  58. 'commits': set(i['commit']['oid'] for i in pr['commits']['nodes'])}
  59. # Reverse dictionary
  60. commits_to_prs={}
  61. for key,value in prs.items():
  62. commits_to_prs[value['mergeCommit']]=key
  63. for c in value['commits']:
  64. commits_to_prs[c]=key
  65. # Check to see if commits in the repo are represented in PRs
  66. good = set()
  67. notfound = set()
  68. for c in commits:
  69. if c in commits_to_prs:
  70. good.add(commits_to_prs[c])
  71. else:
  72. notfound.add(c)
  73. prs_not_represented = set(prs.keys()) - good
  74. print("Milestone: %s, %d merged PRs"%(milestone_data['title'], len(milestone_data['pullRequests']['nodes'])))
  75. print("""
  76. PRs that are in the milestone, but have no commits in the version range.
  77. These PRs probably belong in a different milestone.
  78. """)
  79. print('\n'.join('https://github.com/jupyterlab/jupyterlab/pull/%d'%i for i in prs_not_represented))
  80. print('-'*40)
  81. print("""
  82. Commits that are not included in any PR on this milestone.
  83. This probably means the commit's PR needs to be assigned to this milestone,
  84. or the commit was pushed to master directly.
  85. """)
  86. print('\n'.join('%s %s %s'%(c, commits[c][0], commits[c][1]) for c in notfound))