Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New Feature: Add an Issue in-develop labeler and functions to close these issues #990

Merged
merged 11 commits into from
Jan 28, 2022
87 changes: 85 additions & 2 deletions .github/scripts/build_assets/api_handler.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
import requests
import sys
import re
from typing import List


# our base url which leads to devicon
base_url = "https://github.com/gitapi/repos/devicons/devicon/"
# testing url
# base_url = "https://github.com/gitapi/repos/Thomas-Boi/devicon/"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You might want to remove this comment?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for spotting that


def get_merged_pull_reqs_since_last_release(token):
"""
Get all the merged pull requests since the last release.
Expand Down Expand Up @@ -38,7 +44,7 @@ def get_merged_pull_reqs(token, page):
:param token, a GitHub API token.
:param page, the page number.
"""
queryPath = "https://github.com/gitapi/repos/devicons/devicon/pulls"
url = base_url + "pulls"
headers = {
"Authorization": f"token {token}"
}
Expand All @@ -50,7 +56,7 @@ def get_merged_pull_reqs(token, page):
}

print(f"Querying the GitHub API for requests page #{page}")
response = requests.get(queryPath, headers=headers, params=params)
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)
Expand Down Expand Up @@ -99,3 +105,80 @@ def find_all_authors(pull_req_data, token):
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
15 changes: 15 additions & 0 deletions .github/scripts/build_assets/arg_getters.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,3 +68,18 @@ def get_release_message_args():
help="The GitHub token to access the GitHub REST API.",
type=str)
return parser.parse_args()


def get_in_develop_labeler_args():
"""
Get the commandline arguments for in_develop_labeler.py.
"""
parser = ArgumentParser(description="Parse the PR body to find the issue(s) we are labelling.")
parser.add_argument("token",
help="The GitHub token to access the GitHub REST API.",
type=str)

parser.add_argument("body",
help="The PR's initial comment by the author AKA the `body` attribute of the `pull_request` API object.",
type=str)
return parser.parse_args()
5 changes: 5 additions & 0 deletions .github/scripts/icomoon_build.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,11 @@ def main():
print("Creating the release message by querying the GitHub API...")
get_release_message(args.token)

print("Closing issues with the `in-develop` label.")
issues = api_handler.get_issues_by_labels(args.token, ["in-develop"])
issue_nums = [issue_num["number"] for issue_num in issues]
api_handler.close_issues(args.token, issue_nums)

print("Task completed.")
except TimeoutException as e:
util.exit_with_err("Selenium Time Out Error: \n" + str(e))
Expand Down
20 changes: 20 additions & 0 deletions .github/scripts/in_develop_labeler.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import re
from build_assets import arg_getters, api_handler

def main():
args = arg_getters.get_in_develop_labeler_args()
try:
# find the issue closing line
issue_line = [line for line in args.body.split("\n") if line.startswith("**This PR closes")][0]

print("Issue Line is " + issue_line)
issue_pattern = re.compile(r"\d+")
issues_numbers = issue_pattern.findall(issue_line)
print("Labelling issues: " + str(issues_numbers))
api_handler.label_issues(args.token, issues_numbers, ["in-develop"])
except IndexError: # if can't find the issue line
print("The PR body doesn't contain `**This PR closes` keywords. Ending workflow.")
return

if __name__ == "__main__":
main()
2 changes: 1 addition & 1 deletion .github/workflows/build_icons.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: >
python ./.github/scripts/icomoon_build.py
./.github/scripts/build_assets/geckodriver-v0.29.1-win64/geckodriver.exe ./icomoon.json
./.github/scripts/build_assets/geckodriver-v0.30.0-win64/geckodriver.exe ./icomoon.json
./devicon.json ./icons ./ %GITHUB_TOKEN% --headless

- name: Upload geckodriver.log for debugging purposes
Expand Down
27 changes: 27 additions & 0 deletions .github/workflows/in_develop_labeler.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
name: Label Issue In Develop
on:
pull_request:
types: [closed]
jobs:
label:
name: Label Issue In Develop
runs-on: ubuntu-18.04
if: github.event.pull_request.merged == true
steps:
- uses: actions/checkout@v2

- name: Setup Python v3.8
uses: actions/setup-python@v2
with:
python-version: 3.8

- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r ./.github/scripts/requirements.txt

- name: Run in_develop_labeler.py
env:
TOKEN: ${{ secrets.GITHUB_TOKEN }}
BODY: ${{ github.event.pull_request.body }}
run: python ./.github/scripts/in_develop_labeler.py $TOKEN "$BODY"