mirror of
https://github.com/konpa/devicon.git
synced 2025-02-24 09:12:36 +01:00
183 lines
6.0 KiB
Python
183 lines
6.0 KiB
Python
import requests
|
|
import sys
|
|
import re
|
|
from typing import List
|
|
from io import FileIO
|
|
|
|
|
|
# our base url which leads to devicon
|
|
base_url = "https://api.github.com/repos/devicons/devicon/"
|
|
|
|
def get_merged_pull_reqs_since_last_release(token, log_output: FileIO=sys.stdout):
|
|
"""
|
|
Get all the merged pull requests since the last release.
|
|
"""
|
|
stopPattern = r"^(r|R)elease v"
|
|
pull_reqs = []
|
|
found_last_release = False
|
|
page = 1
|
|
|
|
while not found_last_release:
|
|
data = get_merged_pull_reqs(token, page, log_output)
|
|
# assume we don't encounter it during the loop
|
|
last_release_index = 101
|
|
|
|
for i in range(len(data)):
|
|
if re.search(stopPattern, data[i]["title"]):
|
|
found_last_release = True
|
|
last_release_index = i
|
|
break
|
|
pull_reqs.extend(data[:last_release_index])
|
|
page += 1
|
|
|
|
# should contain all the PRs since last release
|
|
return pull_reqs
|
|
|
|
|
|
def get_merged_pull_reqs(token, page, log_output: FileIO=sys.stdout):
|
|
"""
|
|
Get the merged pull requests based on page. There are
|
|
100 results per page. See https://docs.github.com/en/rest/reference/pulls
|
|
for more details on the parameters.
|
|
:param token, a GitHub API token.
|
|
:param page, the page number.
|
|
"""
|
|
url = base_url + "pulls"
|
|
headers = {
|
|
"Authorization": f"token {token}"
|
|
}
|
|
params = {
|
|
"accept": "application/vnd.github.v3+json",
|
|
"state": "closed",
|
|
"per_page": 100,
|
|
"page": page
|
|
}
|
|
|
|
print(f"Querying the GitHub API for requests page #{page}", file=log_output)
|
|
response = requests.get(url, headers=headers, params=params)
|
|
if not response:
|
|
print(f"Can't query the GitHub API. Status code is {response.status_code}. Message is {response.text}")
|
|
sys.exit(1)
|
|
|
|
closed_pull_reqs = response.json()
|
|
return [merged_pull_req
|
|
for merged_pull_req in closed_pull_reqs
|
|
if merged_pull_req["merged_at"] is not None]
|
|
|
|
|
|
def is_feature_icon(pull_req_data):
|
|
"""
|
|
Check whether the pullData is a feature:icon PR.
|
|
:param pull_req_data - the data on a specific pull request from GitHub.
|
|
:return true if the pullData has a label named "feature:icon"
|
|
"""
|
|
for label in pull_req_data["labels"]:
|
|
if label["name"] == "feature:icon":
|
|
return True
|
|
return False
|
|
|
|
|
|
def find_all_authors(pull_req_data, token):
|
|
"""
|
|
Find all the authors of a PR based on its commits.
|
|
:param pull_req_data - the data on a specific pull request from GitHub.
|
|
:param token - a GitHub API token.
|
|
"""
|
|
headers = {
|
|
"Authorization": f"token {token}"
|
|
}
|
|
response = requests.get(pull_req_data["commits_url"], headers=headers)
|
|
if not response:
|
|
print(f"Can't query the GitHub API. Status code is {response.status_code}")
|
|
print("Response is: ", response.text)
|
|
return
|
|
|
|
commits = response.json()
|
|
authors = set() # want unique authors only
|
|
for commit in commits:
|
|
try:
|
|
# this contains proper referenceable github name
|
|
authors.add(commit["author"]["login"])
|
|
except TypeError:
|
|
# special case
|
|
authors.add(commit["commit"]["author"]["name"])
|
|
print(f"This URL didn't have an `author` attribute: {pull_req_data['commits_url']}")
|
|
return ", ".join(["@" + author for author in list(authors)])
|
|
|
|
|
|
def label_issues(token: str, issues: List[str], labels: List[str]):
|
|
"""
|
|
Label the issues specified with the label specified.
|
|
:param token: the GitHub API token.
|
|
:param issues: the issue numbers (as str) that we are labelling.
|
|
:param labels: the labels that we are labelling.
|
|
"""
|
|
headers = {
|
|
"Authorization": f"token {token}",
|
|
"accept": "application/vnd.github.v3+json"
|
|
}
|
|
url = base_url + "issues/{}/labels"
|
|
for issue in issues:
|
|
body = {
|
|
"labels": labels
|
|
}
|
|
response = requests.post(url.format(issue), headers=headers, json=body)
|
|
if not response:
|
|
raise Exception(f"Can't label the Issue provided. Issue: {issue}, labels: {labels}, API response: " + response.text)
|
|
else:
|
|
print(f"Successfully labelled issue {issue}")
|
|
|
|
|
|
def close_issues(token: str, issues: List[str]):
|
|
"""
|
|
Close issues.
|
|
:param token: the GitHub API token.
|
|
:param issues: the issue numbers (as str) that we are labelling.
|
|
"""
|
|
headers = {
|
|
"Authorization": f"token {token}",
|
|
"accept": "application/vnd.github.v3+json"
|
|
}
|
|
url = base_url + "issues/{}"
|
|
body = {
|
|
"state": "closed"
|
|
}
|
|
for issue in issues:
|
|
response = requests.patch(url.format(issue), headers=headers, json=body)
|
|
if not response:
|
|
raise Exception(f"Can't close Issue provided. Issue: {issue}, API response: " + response.text)
|
|
else:
|
|
print(f"Successfully closed issue {issue}")
|
|
|
|
|
|
def get_issues_by_labels(token: str, labels: List[str]):
|
|
"""
|
|
Get a list of issues based on their labels.
|
|
:param token: the GitHub API token.
|
|
:param labels: the labels that we are labelling.
|
|
"""
|
|
url = base_url + "issues?per_page=100&labels={}&page={}"
|
|
headers = {
|
|
"Authorization": f"token {token}",
|
|
"accept": "application/vnd.github.v3+json"
|
|
}
|
|
issues = []
|
|
done = False
|
|
page_num = 1
|
|
while not done:
|
|
response = requests.get(url.format(",".join(labels), page_num), headers=headers)
|
|
if not response:
|
|
raise Exception(f"Can't access API. Can't get issues for labels: {labels}, API response: " + response.text)
|
|
else:
|
|
results = response.json()
|
|
if len(results) < 100:
|
|
done = True # we are done
|
|
else:
|
|
page_num += 1 # page is full => might need to check another page
|
|
|
|
# GitHub API also returns PRs for issues queries => have to check
|
|
issues_only = [issue for issue in results if issue.get("pull_request") is None]
|
|
issues.extend(issues_only)
|
|
|
|
return issues
|