(root)/
gcc-13.2.0/
maintainer-scripts/
bugzilla-close-candidate.py
       1  #!/usr/bin/env python3
       2  
       3  # The script is used for finding PRs that have a GIT revision that
       4  # mentiones the PR and are not closed.  It's done by iterating all
       5  # comments of a PR and finding GIT commit entries.
       6  
       7  """
       8  Sample output of the script:
       9  Bugzilla URL page size: 50
      10  HINT: bugs with following comment are ignored: Can the bug be marked as resolved?
      11  
      12  Bug URL                                              GIT commits                   known-to-fail                           known-to-work                           Bug summary
      13  https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88129   master                                                                                                        Two blockage insns are emited in the function epilogue
      14  https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88122   master                                                                                                        [9 Regression] g++ ICE: internal compiler error: Segmentation fault
      15  https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88084   master                                                                                                        basic_string_view::copy doesn't use Traits::copy
      16  https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88083   master                                                                                                        ICE in find_constant_pool_ref_1, at config/s390/s390.c:8231
      17  ...
      18  Bugzilla lists:
      19  https://gcc.gnu.org/bugzilla/buglist.cgi?bug_id=88129,88122,88084,88083,88074,88073,88071,88070,88051,88018,87985,87955,87926,87917,87913,87898,87895,87874,87871,87855,87853,87826,87824,87819,87818,87799,87793,87789,87788,87787,87754,87725,87674,87665,87649,87647,87645,87625,87611,87610,87598,87593,87582,87566,87556,87547,87544,87541,87537,87528
      20  https://gcc.gnu.org/bugzilla/buglist.cgi?bug_id=87486
      21  """
      22  
      23  import argparse
      24  import json
      25  
      26  import requests
      27  
      28  base_url = 'https://gcc.gnu.org/bugzilla/rest.cgi/'
      29  statuses = ['UNCONFIRMED', 'ASSIGNED', 'SUSPENDED', 'NEW', 'WAITING', 'REOPENED']
      30  regex = '(.*\[)([0-9\./]*)( [rR]egression])(.*)'
      31  closure_question = 'Can the bug be marked as resolved?'
      32  start_page = 20
      33  url_page_size = 50
      34  
      35  def get_branches_by_comments(comments):
      36      versions = set()
      37      for c in comments:
      38          text = c['text']
      39          lines = text.split('\n')
      40          if 'URL: https://gcc.gnu.org/viewcvs' in text:
      41              version = 'master'
      42              for line in lines:
      43                  if 'branches/gcc-' in line:
      44                      parts = line.strip().split('/')
      45                      parts = parts[1].split('-')
      46                      assert len(parts) == 3
      47                      version = parts[1]
      48                      break
      49              versions.add(version)
      50          else:
      51              for line in lines:
      52                  if line.startswith('The ') and 'branch has been updated' in line:
      53                      version = 'master'
      54                      name = line.strip().split(' ')[1]
      55                      if '/' in name:
      56                          name = name.split('/')[1]
      57                          assert '-' in name
      58                          version = name.split('-')[1]
      59                      versions.add(version)
      60                      break
      61      return versions
      62  
      63  def get_bugs(query):
      64      u = base_url + 'bug'
      65      r = requests.get(u, params = query)
      66      return r.json()['bugs']
      67  
      68  def search():
      69      chunk = 1000
      70      ids = []
      71      print('%-30s%-30s%-40s%-40s%-60s' % ('Bug URL', 'GIT commits', 'known-to-fail', 'known-to-work', 'Bug summary'))
      72      for i in range(start_page, 0, -1):
      73          # print('offset: %d' % (i * chunk), flush = True)
      74          bugs = get_bugs({'bug_status': statuses, 'limit': chunk, 'offset': i * chunk})
      75          for b in sorted(bugs, key = lambda x: x['id'], reverse = True):
      76              id = b['id']
      77  
      78              fail = b['cf_known_to_fail']
      79              work = b['cf_known_to_work']
      80  
      81              u = base_url + 'bug/' + str(id) + '/comment'
      82              r = requests.get(u).json()
      83              keys = list(r['bugs'].keys())
      84              assert len(keys) == 1
      85              comments = r['bugs'][keys[0]]['comments']
      86              skip = False
      87              for c in comments:
      88                  if closure_question in c['text']:
      89                      skip = True
      90                      break
      91              if skip:
      92                  continue
      93  
      94              branches = sorted(list(get_branches_by_comments(comments)),
      95                                key=lambda b: 999 if b is 'master' else int(b))
      96              if branches:
      97                  branches_str = ','.join(branches)
      98                  print('%-30s%-30s%-40s%-40s%-60s' % ('https://gcc.gnu.org/PR%d' % id, branches_str, fail, work, b['summary']), flush=True)
      99                  ids.append(id)
     100  
     101      # print all URL lists
     102      print('\nBugzilla lists:')
     103      while len(ids) > 0:
     104          print('https://gcc.gnu.org/bugzilla/buglist.cgi?bug_id=%s' % ','.join([str(x) for x in ids[:url_page_size]]))
     105          ids = ids[url_page_size:]
     106  
     107  print('Bugzilla URL page size: %d' % url_page_size)
     108  print('HINT: bugs with following comment are ignored: %s\n' % closure_question)
     109  
     110  parser = argparse.ArgumentParser(description='')
     111  
     112  args = parser.parse_args()
     113  search()