In the first part of the tutorial series, you saw how to set up the project and its required configurations. You processed the project git logs and printed them in the terminal. In this part, we'll take it to the next level and send out the code review requests.
Getting Started
Start by cloning the source code from the first part of the tutorial series.
git clone https://github.com/royagasthyan/CodeReviewer CodeReviewer
Once you have cloned the repository, navigate to the project directory CodeReviewer
and try to execute the following command in the terminal.
python scheduler.py -n 20 -p "project_x"
It should print the commit IDs, commit date and the commit author in the terminal.
Collecting All Commits With Details
You'll get the commit details while iterating the commit logs. Now you need to collect the commit details and store them in a list, so that you can iterate them later to send out the code review request. In order to collect the commit details, start by creating a Commit
class with the required members as shown:
# ------------------------------------------- # # Commit class to contain commit related info # # ------------------------------------------- class Commit: def __init__(self, Id, Author, Date): self.Id = Id; self.Author = Author; self.Date = Date;
While iterating the commit logs in the process_commits
method, create a Commit
instance to keep the commit detail.
In the process_commits
method, define a few variables as shown:
commitId = '' author = '' date = '' commits = []
You'll be collecting each commit detail into a Python list called commits
. While reading the commit logs, the first time when the commit ID is encountered, keep the commit Id and flush the date and author variables since it's a new commit. Modify the process_commits
method's code after the commit keyword checking as shown:
if line.startswith('commit '): author = '' date = '' commitId = line[7:]
When the commit Id is not null, that's when the commit details have been collected and it's time to add the commit to the commits list. Add the following line of code to the above code:
if line.startswith('commit '): if commitId <> "": commits.append(Commit(commitId, author, date)) author = '' date = '' commitId = line[7:]
Modify the Author
keyword check and the Date
keyword check to keep the respective commit details in the author and date variables.
if line.startswith('Author:'): if(re.search('\<(.*?)\>',line)): author = re.search('\<(.*?)\>',line).group(1) if line.startswith('Date:'): date = line[5:]
Now, if there is only one commit in the source code, the details will be saved inside the commit list. So add the following code to the end of the loop to handle that scenario.
if commitId <> "": commits.append(Commit(commitId, author, date))
Here is the complete process_commits
method which collects the commit details and returns a list of commits.
# ---------------------------------- # # Process the git log # # ---------------------------------- def process_commits(): cmd = "cd " + project + "; git log --all --since=" + str(no_days) + ".day --name-status" response = execute_cmd(cmd) commitId = '' author = '' date = '' commits = [] for line in response.splitlines(): if line.startswith('commit '): if commitId <> "": commits.append(Commit(commitId, author, date)) author = '' date = '' commitId = line[7:] if line.startswith('Author:'): if(re.search('\<(.*?)\>',line)): author = re.search('\<(.*?)\>',line).group(1) if line.startswith('Date:'): date = line[5:] if commitId <> "": commits.append(Commit(commitId, author, date)) return commits
Scheduling a Code Review Request
You have the commit details collected from the project log. You need to select random developers to send the code review request. Inside the config.json
file, let's add the developers associated with the project who can review the code. Here is the modified config.json
file:
[{ "name": "project_x", "git_url": "https://github.com/royagasthyan/project_x", "members": [ "royagasthyan", "hari", "sam", "shaun" ] }, { "name": "project_y", "git_url": "https://github.com/royagasthyan/project_y", "members": [ "royagasthyan", "hari", "sam", "shaun" ] }]
Let's read the developer's info related to a particular project. Define a public variable called project_members
.
project_members = ''
While reading the project configurations, fill in the project member details in the project_members
list variable.
# # Read the scheduler config file # with open('config.json') as cfg_file: main_config = json.load(cfg_file) for p in main_config: if p['name'] == project: project_url = p['git_url'] project_members = p['members'] break
Now you have the developer list related to a particular project in the project_members
variable.
Define a method called schedule_review_request
which you'll call to schedule the review request corresponding to each project commit. The review request will be sent to a random developer from the project_members
list, excluding the commit author.
Create a method called select_reviewer
to select the random developer from the project_members
list. To select random developers from the list, you'll be making use of the random
Python module. Import the random
Python module.
import random
Here is how the code would look:
# ----------------------------------------- # # Method to select random reviewer # # ----------------------------------------- def select_reviewer(author, group): if author in group: group.remove(author) reviewer = random.choice(group) return reviewer
As seen in the above code, the commit author has been removed from the developer list before selecting random developers to review the code. To select random developers from the list, you have made use of the random.choice
method from the random
module.
Inside the schedule_review_request
method, iterate through each commit from the commits list. For each commit, select a random developer other than the author of the commit to send out the review request. Here is how the code would look:
def schedule_review_request(commits): for commit in commits: reviewer = select_reviewer(commit.Author, project_members)
Format the Code Review Request
You selected random developers to send out the code review request. Before sending the review request, you need to format it with details about the review request. Define a method called format_review_commit
which will format the code review request. Here is how the code would look:
def format_review_commit(commit): review_req = "" review_req += "URL: " + project_url + '/commit/' + commit.Id + "\n" review_req += "Commit: " + commit.Id + "\n" review_req += "Author: " + commit.Author + "\n" review_req += "Date: " + commit.Date + "\n" return review_req
In the schedule_review_request
method, build up the review request email content which will be sent to the reviewer. The email content will contain the required information for the reviewer to review the code commit. Modify the schedule_review_request
as shown:
def schedule_review_request(commits): date = time.strftime("%Y-%m-%d") for commit in commits: reviewer = select_reviewer(commit.Author, project_members) subject = date + " Code Review [commit:" + commit.Id + "]" body = "Hello '" + reviewer + "', you have been selected to review the code for commit\n" body += "done by '" + commit.Author + "'.\n" body += "\n" body += format_review_commit(commit) print body
Save the above changes and run the Python scheduler program.
python scheduler.py -n 25 -p "project_x"
You should be able to see an output similar to the one shown below:
Emailing the Code Review Request
Create a method called send_email
which will email the review request with the required subject and content. You'll be making use of the smtplib
module to send out the emails. Import smptlib
in the scheduler.py
file:
import smtplib
Define the mail server details along with the public variables:
FROM_EMAIL = "[email protected]" FROM_PWD = "your password" SERVER = "smtp.gmail.com" PORT = 587
Create a method called send_email
which will send out the email to the address specified. Here is how the send_email
code would look:
def send_email(to, subject, body): header = "From: " + FROM_EMAIL + "\n" header += "To: " + to + "\n" header += "Subject: " + subject + "\n" header += "\n" header += body print "** Sending email to '" + to + "'" mail_server = smtplib.SMTP(SERVER, PORT) mail_server.starttls() mail_server.login(FROM_EMAIL, FROM_PWD) mail_server.sendmail(FROM_EMAIL, to, header) mail_server.quit()
As seen in the above code, you created the smtp
server using the gmail server and port number. Using the defined username and password, you logged into the email account and sent the email to the recipient.
Modify the schedule_review_request
method to send the email instead of printing the email content to the terminal.
def schedule_review_request(commits): date = time.strftime("%Y-%m-%d") for commit in commits: reviewer = select_reviewer(commit.Author, project_members) subject = date + " Code Review [commit:" + commit.Id + "]" body = "Hello '" + reviewer + "', you have been selected to review the code for commit\n" body += "done by '" + commit.Author + "'.\n" body += "\n" body += format_review_commit(commit) send_email(reviewer,subject,body)
Save the above changes. Modify the config.json
file to include a valid email address which you can check. Run the scheduler using the following command:
python scheduler.py -n 30 -p "project_x"
You should be able to see the following output on the terminal:
Verify the email address to see the code review request mailed from the Code Review scheduler.
Wrapping It Up
In this part of the Python Code Review Scheduler series, you collected the commit information into a list. The commit list was further iterated to format the review request. Random developers were selected to send out the code review request.
In the next part of this series, you'll see how to follow up the code review request.
Source code from this tutorial is available on GitHub.
I hope you enjoyed this part. Do let us know your thoughts in the comments below.
Comments