Introduction
This article will guide you to configure an automation flow that will update your Jira board to the right status. To implement this I assume you already have an AWS account and a pipeline deploy using CodeBuild in place. So you will be able to plug it into your code as the last part of it.
This piece of code will be added to the buildspec.yml
, inside the post-build
block. It means when the artifact is in fact deployed to the environment, then the automation will update the stories correctly.
For reference, check the buildspec.yml
file documentation.
Creating Lambda Function
To create a new Lambda function you new to go to Lambda's service:
Then, when creating the function, choose the python3.9
runtime:
Once the new Lambda's Python3.9 runtime does not support some dependencies we need to make it work, we will need to upload our package in a zip
file. You can do this here:
So you can use docker
or venv
to zip all the dependencies with the python
file.
I'm using docker
so the dependencies are in this path /usr/local/lib/python3.12/site-packages
Make sure the name of the lambda code file is lambda_function.py
and it is at the same level as the dependencies so that AWS can validate it.
The Flow
For instance, I'm using an SCM based on Gitflow, so I have the develop
branch -- in which we will apply this -- and the master
branch. This way allows me to compare those issues the automation should update the status.
By the way, another important thing is all of the commits should begin with the issue's key
. Like this:
git commit -m "AE-28: <your-commit-message>"
CodeBuild
Every time the deploy is triggered manually, this snippet will be started as a post-build
action.
Then it will verify on the remote repository if there were tickets deployed in the given job:
- TICKETS_LIST=$(git log origin/develop --no-merges --pretty=format:"%B" --not "origin/master" | tr a-z A-Z | tr ' ,' '\n' | grep -o '[A-Z]\+-[0-9]\+' | sort --version-sort | uniq | tr '\n' ',')
The result of this command is:
AE-28,AE-27,AE-30,AE-34,AE-35,
After that, if the command's output is not null
, CodeBuild will send it to the Environment Variables on Lambda, and then, send the tickets list to the Environment Variables on Lambda, and finally triggers the jira_automation_tickets
function passing the status 3
which is the transition ID to move issues to the QA lane:
- |
if [ "$TICKETS_LIST" = "" ]; then
echo "No tickets deployed";
else
aws lambda update-function-configuration --function-name jira_automation_tickets --environment "Variables={TICKETS_LIST='${TICKETS_LIST}'}";
aws lambda invoke \
--function-name jira_automation_tickets \
--cli-binary-format raw-in-base64-out \
--payload '{"status": "3"}' output.txt;
fi
- cat output.txt
Tip: You can see that Environment Variable, on the Lambda Service Dashboard:
Configuration > Environment Variable
Tip: To know what the transition
id, use this command:
curl -u <jira-user>:<token-api> -X GET -H "Content-Type: application/json" "https://<your-domain-jira-board>.atlassian.net/rest/api/3/issue/<issue-number>/transitions" | jq '.[]'
You will receive an array containing objects with all transitions' id
as well as all status' id
, like this one for QA which the transition id
is 3
and the status id
is 10004
-- I will use it here:
{
"id": "3",
"name": "QA",
"to": {
"self": "https://<your-domain-jira-board>/rest/api/3/status/10004",
"description": "",
"iconUrl": "https://<your-domain-jira-board>/",
"name": "QA",
"id": "10004",
"statusCategory": {
"self": "https://<your-domain-jira-board>/rest/api/3/statuscategory/4",
"id": 4,
"key": "indeterminate",
"colorName": "yellow",
"name": "In Progress"
}
},
"hasScreen": false,
"isGlobal": true,
"isInitial": false,
"isAvailable": true,
"isConditional": false,
"isLooped": false
}
Lambda
We are using Python 3.9 as the runtime for this Lambda function. To use Jira SDK we needed to import it and its dependencies with the Lambda code as a zip
file.
The code is simple is a simple one and it's commented line-by-line. This code will be committed to our repository to maintain a history of it. And the zip file with the necessary dependencies is attached as well.
First of all, create the file lambda_function.py
-- it should have this name to avoid AWS errors -- then, import all dependencies we will need:
import boto3
import json
import os
import re
from jira import JIRA
from datetime import date
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
The main method must have to be named lambda_handler
. So create this method and initialize the credentials variables, then use the SDK to authenticate:
def lambda_handler(event, context):
# set credentials using basic authentication
jira_url = 'https://<your-domain-jira-board>.atlassian.net'
jira_username = '<user-name>'
jira_api_token = '<api-token>'
# Connect to Jira
jira = JIRA(server=jira_url, basic_auth=(jira_username, jira_api_token))
Now use the os
to get the tickets list from the environment variables:
# Get ticket list sent by CodeBuild and transform it in an Array/list
ticket_list = re.split(r"\r\,|\,|\r", os.environ['TICKETS_LIST'])
Then, you can start to create the email template and initialize an empty list to control whether you should send an email or not.
# Starts the email template
email_body = """<p>List of tickets to be tested:</p>"""
# Initiate an empty list/array to check its size later when it will send the email notification
tickets_to_send_email = []
Now it's time to iterate that list and validate them. My criteria here was only to update the tickets that are not in the QA lane yet. In my case, the QA status id is 10004
. It will increment a line in the email body.
for ticket in ticket_list:
if ticket != '':
# instantiate Issue's object
issue = jira.issue(ticket)
# get the current status
current_status = issue.fields.status
# 10004 is the id of the QA lane
if current_status.id != '10004':
# increments the array to send notifications
tickets_to_send_email.append(ticket)
# include a issue link into the email template
email_body += f"""
<div>
<a href="{jira_url+'/browse/'+issue.key}">{issue.key} - {issue.fields.summary}</a>
</div>
"""
# Change the status to status 3 -- QA
jira.transition_issue(issue, event["status"])
Then, close the email body:
# closing the email template
email_body += """<p>If you find an issue with the ticket reach out to the reporter.</p>
"""
After validating and updating the status of the issues on Jira, set a variable called response_email
to receive the funtion's response. Also, you will need to format this email with the correct MIME Type
, to send it through the SES service:
# setting default response to Lambda function
response_email = "Email not sent"
# checking if the array is populate to send email notification
if len(tickets_to_send_email) > 0:
# Compose the email subject and body
subject = f'Tickets Available To Test In QA - {date.today()}'
body = email_body
# Create the email message
email_message = MIMEMultipart()
email_message['Subject'] = subject
# Attach the HTML part
html_part = MIMEText(body, 'html')
email_message.attach(html_part)
# Calling AWS SDK to send email
ses_client = boto3.client('ses')
response_email = ses_client.send_raw_email(
Source='<authenticates-ses-email>',
Destinations=['<email-1>, <email-2>'],
RawMessage={'Data': email_message.as_string()}
)
Finally, close your code returning a JSON
with the send_raw_email
method:
return {
'statusCode': 200,
'body': json.dumps(response_email)
}
Jira Board
Your board will be updated and those tickets that were merged in your development environment and are not in the QA lane already will be moved to this lane. This way the automation will assure the correct visibility.
Simple Email Service
Once the Lambda code was finished and there are changes to notify, it will trigger the SES (Simple Email Service) to send an email notification to the emails you passed as the destination.
The email will contain instructions to QAs to access the ticket by the links that will be listed on the email body, like this:
List of tickets to be tested:
AE-28: 'issue-title'
AE-27: 'issue-title'
AE-30: 'issue-title'
AE-34: 'issue-title'
AE-35: 'issue-title'If you find an issue with the ticket reach out to the reporter.
Conclusion
Make sure your CodeBuild job has permission to write in Lambda:
As well as the Lambda has permission to trigger the SES service:
I'd be very happy if this article helps you anyhow. Feel free to collaborate with this solution. I'd like to see it getting as better as possible!
Top comments (0)