mirror of
				https://github.com/zulip/zulip.git
				synced 2025-11-04 05:53:43 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			96 lines
		
	
	
		
			3.2 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			96 lines
		
	
	
		
			3.2 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable File
		
	
	
	
	
#!/usr/bin/env python
 | 
						|
from __future__ import print_function
 | 
						|
 | 
						|
import requests
 | 
						|
import re
 | 
						|
import argparse
 | 
						|
import sys
 | 
						|
import os
 | 
						|
 | 
						|
from six.moves.configparser import ConfigParser
 | 
						|
from typing import Any, Dict, MutableMapping
 | 
						|
 | 
						|
# Scans zulip repositary for issues that don't have any `area` labels.
 | 
						|
# GitHub API token is required as GitHub limits unauthenticated
 | 
						|
# requests to 60/hour. There is a good chance that this limit is
 | 
						|
# bypassed in consecutive attempts.
 | 
						|
# The api token can be generated here
 | 
						|
# https://github.com/settings/tokens/new?description=Zulip%20Issue%20Label%20Checker
 | 
						|
#
 | 
						|
# Copy conf.ini-template to conf.ini and populate with your api token.
 | 
						|
#
 | 
						|
# usage: python check-issue-labels
 | 
						|
# Pass --force as an argument to run without a token.
 | 
						|
 | 
						|
def get_config():
 | 
						|
    # type: () -> ConfigParser
 | 
						|
    config = ConfigParser()
 | 
						|
    config.read(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'conf.ini'))
 | 
						|
    return config
 | 
						|
 | 
						|
def area_labeled(issue):
 | 
						|
    # type: (Dict[str, Any]) -> bool
 | 
						|
    for label in issue["labels"]:
 | 
						|
        label_name = str(label["name"])
 | 
						|
        if "area:" in label_name:
 | 
						|
            return True
 | 
						|
    return False
 | 
						|
 | 
						|
def is_issue(item):
 | 
						|
    # type: (Dict[str, Any]) -> bool
 | 
						|
    return "issues" in item["html_url"]
 | 
						|
 | 
						|
def get_next_page_url(link_header):
 | 
						|
    # type: (str) -> str
 | 
						|
    matches = re.findall(r'\<(\S+)\>; rel=\"next\"', link_header)
 | 
						|
    try:
 | 
						|
        return matches[0]
 | 
						|
    except IndexError:
 | 
						|
        return None
 | 
						|
 | 
						|
def check_issue_labels():
 | 
						|
    # type: () -> None
 | 
						|
    parser = argparse.ArgumentParser()
 | 
						|
    parser.add_argument('--force', action="store_true", dest="force", default=False)
 | 
						|
    args = parser.parse_args()
 | 
						|
 | 
						|
    if not args.force:
 | 
						|
        config = get_config()
 | 
						|
        try:
 | 
						|
            token = config.get('github', 'api_token')
 | 
						|
        except KeyError:
 | 
						|
            print("Error fetching GitHub api token. Copy conf.ini-template to conf.ini and populate with "
 | 
						|
                  "your api token. If you want to continue without using a token use --force.")
 | 
						|
            sys.exit(1)
 | 
						|
 | 
						|
    next_page_url = 'https://api.github.com/repos/zulip/zulip/issues'
 | 
						|
    unlabeled_issue_urls = []
 | 
						|
    while next_page_url:
 | 
						|
        try:
 | 
						|
            if args.force:
 | 
						|
                response = requests.get(next_page_url)
 | 
						|
            else:
 | 
						|
                response = requests.get(next_page_url, headers={'Authorization': 'token %s' % token})
 | 
						|
            if response.status_code == 401:
 | 
						|
                sys.exit("Error. Please check the token.")
 | 
						|
            if response.status_code == 403:
 | 
						|
                sys.exit("403 Error. This is generally caused when API limit is exceeded. You use an api "
 | 
						|
                         "token to overcome this limit.")
 | 
						|
        except requests.exceptions.RequestException as e:
 | 
						|
            print(e)
 | 
						|
            sys.exit(1)
 | 
						|
 | 
						|
        next_page_url = get_next_page_url(response.headers["Link"])
 | 
						|
        for item in response.json():
 | 
						|
            if is_issue(item) and not area_labeled(item):
 | 
						|
                unlabeled_issue_urls.append(item["html_url"])
 | 
						|
 | 
						|
    if len(unlabeled_issue_urls):
 | 
						|
        print("The following issues don't have any area labels associated with it")
 | 
						|
        print("\n".join(unlabeled_issue_urls))
 | 
						|
    else:
 | 
						|
        print("No GitHub issues found with missing area labels.")
 | 
						|
 | 
						|
if __name__ == '__main__':
 | 
						|
    check_issue_labels()
 |