[JS] Google Form Trello Integration
Purpose
For bug tracking, we wanted to use a specific Google Form that would capture only data specified and require certain fields for our testers to fill out, like reproducibility steps. Our team predominantly uses Trello as our means of task management, so this meant communicating with Trello would be ideal for bug management as well. Every bug that is submitted using our form is sent to our Development Board, given the appropriate labels and then stacked with other tasks at a priority. This enables us to keep all of our work flow localized, while we can have stricter requirements than Trello allows for bug tracking, as well as the added flexibility of GAS (Google Apps Scripts) for any other steps to take when logging a bug.
Trello.gs
/** * \brief This script will convert a bug report using the * provided Google Form into a Trello Card on our * development board. This is useful for maintaing * a consistent style, while localizing all of our * tasks in a simple place. * * The Trello API utilizies the REST API, while this * implementation uses OAuthService to automatically * generate tokens for the app. * * \param e The event sent with the Form Response. */ function OnFormSubmit(e) { // This is the title given to the card. var name = "[BUG] " + e.namedValues["Title"]; // The following is what will be written into the description // of the Trello card. Tokens: // ** - Bold // *** - A divider line // --- - Header var description = "**Entered**: " + e.namedValues["Timestamp"] + "\n"; description += "**Severity**: " + e.namedValues["Severity"] + "\n"; description += "**Difficulty**: " + e.namedValues["Difficulty"] + "\n"; description += "**Category**: " + e.namedValues["Category"] + "\n"; description += "**Reproducibility**: " + e.namedValues["Consistency"] + "\n"; if(e.namedValues["DxDiag"] != "") { description += "**DxDiag Link:** " + e.namedValues["DxDiag"] + "\n"; } if(e.namedValues["Description"] != "") { description += "***" + "\n"; description += "**Description**:" + "\n"; description += "---" + "\n"; description += e.namedValues["Description"] + "\n"; } if(e.namedValues["Reproducible Steps"] != "") { description += "***" + "\n"; description += "**Reproducible Steps**:" + "\n"; description += "---" + "\n"; description += e.namedValues["Reproducible Steps"] + "\n"; } // The trelloListIDs object holds the idLists of all the lists on our board var trelloListID = trelloListIDs[e.namedValues["Category"]]; // The following will populate the labels variable depending on the // severity of the logged bug. var labels = ""; switch(e.namedValues["Severity"].toString()) { case(severities[0]): var labels = "red"; break; case(severities[1]): var labels = "orange"; break; case(severities[2]): var labels = "yellow"; break; case(severities[3]): var labels = "green"; break; case(severities[4]): default: var labels = null; } // See below for full documentation CreateTrelloCard(name, description, trelloListID, labels); } /** * \brief Creates a Trello Card by utilizing OAuthService * and sends the POST request to the Trello API. * * \param name The title of the card. * * \param description The description field for the card. * See above for full details. * * \param trelloListID The correct idList for the card to * be put under. * * \param labels What labels to associate the card with. */ function CreateTrelloCard(name, description, trelloListID, labels) { // Setting up the OAuthConfig object that will handle Trello Authorization var oauthConfig = UrlFetchApp.addOAuthService("trello"); oauthConfig.setAccessTokenUrl("https://trello.com/1/OAuthGetAccessToken"); oauthConfig.setRequestTokenUrl("https://trello.com/1/OAuthGetRequestToken"); oauthConfig.setAuthorizationUrl("https://trello.com/1/OAuthAuthorizeToken?scope=read,write"); // The Trello Keys are generated from https://trello.com/1/appKey/generate oauthConfig.setConsumerKey(trelloKey); oauthConfig.setConsumerSecret(trelloSecret); //POST to [/1/cards], Required permissions: write var payload = {"name":name, //(required) Valid Values: a string with a length from 1 to 16384 "desc":description, //(optional) Valid Values: a string with a length from 0 to 16384 "pos":"bottom", //(optional) Default: bottom Valid Values: A position. top, bottom, or a positive number. "due": null, //(required) Valid Values: A date, or null "idList":trelloListID, //(required) Valid Values: id of the list that the card should be added to "labels": labels, //(optional) Valid Values: green, yellow, orange, red, blue, purple //"idMembers": "", //(optional) Valid Values: A comma-separated list of objectIds, 24-character hex strings //"idCardSource": "", //(optional) Valid Values: The id of the card to copy into a new card. //"keepFromSource": "all", //(optional) Default: all Valid Values: Properties of the card to copy over from the source. }; // Proper url for card POST requests var url = "https://api.trello.com/1/cards"; var options = {"method" : "post", "payload" : payload, "oAuthServiceName" : "trello", "oAuthUseToken" : "always", }; // URL Fetch Request UrlFetchApp.fetch(url, options); } /** * \brief This function can be used to identify the ids of the * cards and lists for the given boardKey. * * To find your board key, look at the url of the Trello * board you want. E.g.: * 1a2b3c4d5e6f78901a2b3c4d */ function TrelloExample() { // Setting up the OAuthConfig object that will handle Trello Authorization var oauthConfig = UrlFetchApp.addOAuthService("trello"); oauthConfig.setAccessTokenUrl("https://trello.com/1/OAuthGetAccessToken"); oauthConfig.setRequestTokenUrl("https://trello.com/1/OAuthGetRequestToken"); oauthConfig.setAuthorizationUrl("https://trello.com/1/OAuthAuthorizeToken?scope=read,write"); oauthConfig.setConsumerKey(trelloKey); oauthConfig.setConsumerSecret(trelloSecret); var options = { "method": "GET", "oAuthServiceName": "trello", "oAuthUseToken": "always", }; // Capturing all of the URL Fetch data in result var result = UrlFetchApp.fetch( "https://api.trello.com/1/boards/" + boardKey + "/cards", options); // Because the data is in JSON, we need to parse it var response = JSON.parse(result); // r represents each card that was retrieved in response for (var r in response) Logger.log(response[r]); }