The Use Case: A Quick Overview
You'd be surprised by the many ways Jira is able to integrate with other applications, such as Google Drive. I recently came across an interesting use case, one that involved storing a copy of a document in Google Drive when a Jira ticket went through an approval workflow. I'll walk you through how I handled it so you can set it up yourself.
The reason why this was important for this team was for legal reasons. The reporter would submit a link to the Google Drive document on the Jira ticket, so the legal team could track exactly what they had approved in their very own Google Drive folder. In order to save data space, this team decided to continue to allow the reporter to submit only the Google Doc link. It was time to use the Google Drive API!
The Solution
Here's how it works:
- Create an automated middleman. With all automation, you need a "user" whose sole purpose is to perform the automation. This is critical because if there are any issues with the implementation you can pin down who performed the action—in this case, an automation user, rather than an actual user. Another reason we don't want to use a real user is if this user leaves the company and their user is deactivated, it will affect the implementation. An IAM account will only act as player to impersonate a Jira service account. This account can't own a drive of its own, but allows you to download a JSON file with credentials to impersonate a service account. Lets call this account jira-middleman-google.
-
Authenticate with OAuth 2.0. There are different scopes the middleman can have access to that limit the user to act on only the necessary data. An important thing I stumbled upon was the fact that the scope below didn't allow me to impersonate my service account to copy, create, or update a file. The only way this scope will work is if you have a login screen and the service account is able to authenticate, which wasn't the case in this situation. This implementation was to be all automated.
https:
//www.googleapis.com/auth/drive.file
So we needed the scope below:
https:
//www.googleapis.com/auth/drive
-
Provide the data to Google Drive API. I used a post-function Groovy script that was triggered once the team approved the Jira ticket. The groovy script grabs the Google Doc link and parses only the file ID that needs copying.
Post-Function Groovy Scriptimport
com.atlassian.jira.component.ComponentAccessor
import
java.util.regex.Matcher
//Jira link field
def customfieldManager = ComponentAccessor.getCustomFieldManager()
String google_file_link = issue.getCustomFieldValue(customfieldManager.getCustomFieldObject(
"customfield_id"
))
if
(google_file_link){
Matcher matchGroup = fileLink =~ /.*(\/d)\/(.*)\/.*/
if
(matchGroup.matches()) {
String fileID = matchGroup.group(
2
)
def comm =
"python {python_file} {middleman_json_file} {middleman_account} service-account@domain.com ${fileID} ${fileName}"
def execComm = comm.execute()
execComm.waitFor()
def result = execComm.in.text
}
else
{log.warn(
"File URL doesn't match gdrive URL format."
)}
}
else
{ log.warn(
"There's no file URL provided."
)}
Once it has the parsed file ID, it runs the Python file that uses the jira-middleman to impersonate the service account and make a copy of the file with the provided file ID.
Python Filefrom oauth2client.service_account
import
ServiceAccountCredentials
from httplib2
import
Http, ServerNotFoundError
from apiclient.discovery
import
build
import
json, sys, os, time
def main():
# get the args
secret_file = sys.argv[
1
]
service_account_email = sys.argv[
2
].lower()
impersonate = sys.argv[
3
].lower()
file_id = sys.argv[
4
]
file_name = sys.argv[
5
]
# use the credentials to call the Google Drive API
service = get_service(service_account_email, secret_file, impersonate)
body={
"title"
: file_name}
result = copy_file(service, file_id , body)
def get_service(service_account_email, secret_file, impersonate, retry=
0
):
try
:
credentials = ServiceAccountCredentials.from_json_keyfile_name(secret_file, scopes=[
'https://www.googleapis.com/auth/drive'
])
delegated_credentials = credentials.create_delegated(impersonate)
http_auth = delegated_credentials.authorize(Http())
return
build(
'drive'
,
'v3'
, http=http_auth) # gets access to the drive API
except ServerNotFoundError as e:
if
retry >=
10
:
print(e)
exit()
else
:
retry +=
1
time.sleep(
5
)
return
get_service(secret_file, impersonate, retry)
def copy_file(service, source_file_id, body):
""
"Copy an existing file.
Args:
service: Drive API service instance.
source_file_id: ID of the source file to copy.
Returns:
The copied file
if
successful, None otherwise.
""
"
try
:
return
service.files().copy(fileId=source_file_id, body=body).execute()
except errors.HttpError, error:
print
'ERROR: %s'
% error
return
None
if
__name__ ==
'__main__'
:
main()
Now They're Talkin'
This is just one of the many powerful and customizable integrations we can perform with Jira. Stay tuned for more! And as always, reach out to Isos Technology if you'd like to speak with somebody about what Jira can do for your organization.
Sign up to receive more great content
Learn more about Atlassian and how Isos can help by signing up to receive our latest blogs, eBooks, whitepapers and more.