Home Python Filtering & Closing Pull Requests on GitHub utilizing the API

Filtering & Closing Pull Requests on GitHub utilizing the API

0
Filtering & Closing Pull Requests on GitHub utilizing the API

[ad_1]

Hello everybody! 👋 On this submit, I’m going to indicate you ways you should utilize the GitHub API to question Pull Requests, verify the content material of a PR and shut it.

The motivation for this undertaking got here from my private web site. I launched static feedback on the web site utilizing Staticman and solely after a day or two, bought bombarded with spam. I hadn’t enabled Akismet or any honey pot discipline so it was kinda anticipated. Nonetheless, this resulted in me getting 200+ PRs on GitHub for bogus feedback which had been primarily commercials for amoxicillin (this was additionally the primary time I came upon how well-known this drugs is).

I used to be in no temper for going via the PRs manually so I made a decision to put in writing a brief script which went via them on my behalf and closed the PRs which talked about sure key phrases.

You may see the totally different PRs opened by staticman. Most of those are spam:

Image

For this undertaking, I made a decision to make use of PyGithub library. It’s tremendous straightforward to put in it utilizing pip:

pip set up pygithub

Now we will go forward and log in to GitHub utilizing PyGithub. Write the next code in a github_clean.py file:

from github import Github
import argparse

def parse_arguments():
    """
    Parses arguments
    """
    parser = argparse.ArgumentParser()
    parser.add_argument('-u', '--username', 
        required=True, assist="GitHub username")
    parser.add_argument('-p', '--password', 
        required=True, assist="GitHub password")
    parser.add_argument('-r', '--repository', 
        required=True, assist="repository title")
    parsed_args = parser.parse_args()
    if "/" not in parsed_args.repository:
        logging.error("repo title also needs to include username like: username/repo_name")
        sys.exit()
    return parsed_args
    
def essential():
    args = parse_arguments()
    g = Github(args.username, args.password)
    
if __name__ == '__main__':
    essential()

Up to now I’m simply utilizing argparse to simply accept and parse the command line arguments after which utilizing the arguments to create a Github object.

You can be passing in three arguments:

  • Your GitHub username
  • Your GitHub password
  • The repo you need to work with

Subsequent step is to determine the way to loop via all of the pull requests and verify if their physique comprises any “spam” phrases:

repo =  g.get_repo(args.repository)
points = repo.get_issues()

page_num = 0
whereas True:
    issue_page = points.get_page(page_num)
    if issue_page == []:
        break
    for difficulty in issue_page:
        # Do one thing with the person difficulty
        if spam_word in difficulty.raw_data['body'].decrease():
            print("Accommodates spam phrase!!")

First, we question GitHub for a selected repo utilizing g.get_repo after which we question for points for that repo utilizing repo.get_issues. You will need to word that each one PRs are registered as points as nicely so querying for points will return pull requests as nicely. GitHub returns a paginated outcome so we simply proceed asking for successive points shortly loop till we get an empty web page.

We will verify the physique of a difficulty (PR) utilizing difficulty.raw_data[‘body’]. Two necessary items are lacking from the above code. One is the spam_word variable and one other is a few form of a mechanism to shut a difficulty.

For the spam_word, I took a have a look at some points and created an inventory of some fairly frequent spam phrases. That is the record I got here up with:

spam_words = ["buy", "amoxi", "order", "tablets", 
"pills", "cheap", "viagra", "forex", "cafergot", 
"kamagra", "hacker", "python training"]

Add this record on the prime of your github_clean.py file and modify the if assertion like this:

closed = False
if any(spam_word in difficulty.raw_data['body'].decrease() for spam_word in spam_words):
    difficulty.edit(state="closed")
    closed = True
print(f"{difficulty.quantity}, closed: {closed}")

With this ultimate snippet of code, we have now every part we want. My favorite perform on this code snippet is any. It checks if any of the weather being handed in as a part of the argument is True.

That is what your complete file ought to appear to be:

import argparse
import sys
import re
import logging

from github import Github

spam_words = ["buy", "amoxi", "order", "tablets", 
"pills", "cheap", "viagra", "forex", "cafergot", 
"kamagra", "hacker", "python training"]
logging.basicConfig(degree=logging.INFO)

def parse_arguments():
    """
    Parses arguments
    """
    parser = argparse.ArgumentParser()
    parser.add_argument('-u', '--username', 
        required=True, assist="GitHub username")
    parser.add_argument('-p', '--password', 
        required=True, assist="GitHub password")
    parser.add_argument('-r', '--repository', 
        required=True, assist="repository title")
    parsed_args = parser.parse_args()
    if "/" not in parsed_args.repository:
        logging.error("repo title also needs to include username like: username/repo_name")
        sys.exit()
    return parsed_args

def process_issue(difficulty):
    """
    Processes every difficulty and closes it 
    based mostly on the spam_words record
    """
    closed = False
    if any(bad_word in difficulty.raw_data['body'].decrease() for bad_word in phrases):
        difficulty.edit(state="closed")
        closed = True
    return closed

def essential():
    """
    Coordinates the move of the entire program
    """
    args = parse_arguments()
    g = Github(args.username, args.password)
    logging.information("efficiently logged in")
    repo =  g.get_repo(args.repository)

    logging.information("getting points record")
    points = repo.get_issues()

    page_num = 0
    whereas True:
        issue_page = points.get_page(page_num)
        if issue_page == []:
            logging.information("No extra points to course of")
            break
        for difficulty in issue_page:
            closed = process_issue(difficulty)
            logging.information(f"{difficulty.quantity}, closed: {closed}")
        page_num += 1

    
if __name__ == '__main__':
    essential()

I simply added a few various things to this script, just like the logging. If you need, you may create a brand new command-line argument and use that to regulate the log degree. It isn’t actually helpful right here as a result of we don’t have quite a lot of totally different log ranges.

Now if you happen to run this script you need to see one thing just like this:

INFO:root:efficiently logged in
INFO:root:getting points record
INFO:root:No extra points to course of

It doesn’t course of something on this run as a result of I’ve already run this script as soon as and there are not any extra spam points left.

So there you go! I hope you had enjoyable making this! If in case you have any questions/feedback/ideas please let me know within the feedback beneath! See you within the subsequent submit 🙂 ♥️

[ad_2]

LEAVE A REPLY

Please enter your comment!
Please enter your name here