やりたいこと
弊社では開発の進捗はJIRAで管理、現場からの開発依頼はスプレッドシート、開発と現場のコミュニケーションツールはslackを使っています。
ディレクターはJIRAをスプレッドシートを行ったり来たり、slackに開発の進捗を報告したりしてめんどくさいので、
①JIRAのチケットが発行された、またかチケットのステータスが完了した際にスプレッドシートに情報を転記。
②開発内容をslackんい投稿する。
をGoogle Apps Script(以下gas)で自動化しました。
そのためにやったことは以下のことです。
①JIRAからスプレッドシートにチケットデータ送る(JIRAのwebhookを利用)
②チケットデータをスプレッドシートに転記(gasを利用)
③slackにスプレッドに転記したデータを投稿(incoming webhookを利用)
になります。順に説明していきます。
①JIRAのwebhookの作成する
webhook作成は超簡単です。
システム>詳細_Webフック>Webフックの作成をクリックします。
今回はJIRAチケット作成時、ステータス完了の更新時にスプレッドシートにデータを送りたいので、課題の作成済、更新済にチェックマークをつけて、保存します。
※課題関連イベントにproject = hogehoge と記載すると特定のプロジェクトのデータのみを送ることができます。
webhookから送られるデータは以下のようなjson形式になっています。
{
"changelog": {
"id": "id",
"items": [
{
"field": "assignee",
"fieldId": "assignee",
"fieldtype": "jira",
"from": null,
"fromString": null,
"to": "name",
"toString": "name"
},
{
"field": "priority",
"fieldId": "priority",
"fieldtype": "jira",
"from": null,
"fromString": null,
"to": "3",
"toString": "Medium"
},
{
"field": "reporter",
"fieldId": "reporter",
"fieldtype": "jira",
"from": null,
"fromString": null,
"to": "name",
"toString": "name"
},
{
"field": "ステータス",
"fieldId": "status",
"fieldtype": "jira",
"from": null,
"fromString": null,
"to": "1",
"toString": "Open"
}
]
},
"issue": {
"fields": {
"aggregateprogress": {
"progress": 0,
"total": 0
},
"aggregatetimeestimate": null,
"aggregatetimeoriginalestimate": null,
"aggregatetimespent": null,
"assignee": {
"accountId": "hoge",
"active": true,
"avatarUrls": {
"16x16": "hoge",
"24x24": "hoge",
"32x32": "hoge",
"48x48": "hoge"
},
"displayName": "mail",
"emailAddress": "mail",
"key": "name",
"name": "name",
"self": "hoge",
"timeZone": "Asia/Tokyo"
},
"attachment": [],
"comment": {
"comments": [],
"maxResults": 0,
"startAt": 0,
"total": 0
},
"components": [],
"created": "datetim",
"creator": {
"accountId": "hoge",
"active": true,
"avatarUrls": {
"16x16": "hoge",
"24x24": "hoge",
"32x32": "hoge",
"48x48": "hoge"
},
"displayName": "name",
"emailAddress": "mail",
"key": "name",
"name": "name",
"self": "hoge",
"timeZone": "Asia/Tokyo"
},
"customfield_10900": null,
"description": null,
"duedate": null,
"environment": null,
"issuelinks": [],
"issuetype": {
"avatarId": 10308,
"description": "雑作業",
"iconUrl": "hoge"
"id": "10300",
"name": "雑作業",
"self": "hoge",
"subtask": false
},
"labels": [],
"lastViewed": "2017-12-11T16:26:07.383+0900",
"priority": {
"iconUrl": "hoge",
"id": "3",
"name": "普通",
"self": "hoge"
},
"progress": {
"progress": 0,
"total": 0
},
"project": {
"avatarUrls": {
"16x16": "hoge",
"24x24": "hoge",
"32x32": "hoge",
"48x48": "hoge"
},
"id": "id",
"key": "hoge",
"name": "hoge",
"self": "hoge"
},
"reporter": {
"accountId": "hoge",
"active": true,
"avatarUrls": {
"16x16": "hoge",
"24x24": "hoge",
"32x32": "hoge",
"48x48": "hoge"
},
"displayName": "name",
"emailAddress": "mail",
"key": "name",
"name": "name",
"self": "hoge",
"timeZone": "Asia/Tokyo"
},
"resolution": null,
"resolutiondate": null,
"security": null,
"status": {
"description": "担当者が作業を開始できる状態を表します。",
"iconUrl": "hoge",
"id": "1",
"name": "オープン",
"self": "hoge",
"statusCategory": {
"colorName": "blue-gray",
"id": 2,
"key": "new",
"name": "To Do",
"self": "hoge"
}
},
"subtasks": [],
"summary": "てすと",
"timeestimate": null,
"timeoriginalestimate": null,
"timespent": null,
"timetracking": {},
"updated": "2017-12-11T16:26:07.184+0900",
"versions": [],
"votes": {
"hasVoted": false,
"self": "hoge",
"votes": 0
},
"watches": {
"isWatching": true,
"self": "hoge",
"watchCount": 0
},
"workratio": -1
},
"id": "id",
"key": "key",
"self": "hoge"
},
"issue_event_type_name": "issue_created",
"timestamp": 1512977167230,
"user": {
"accountId": "id",
"active": true,
"avatarUrls": {
"16x16": "hoge",
"24x24": "hoge",
"32x32": "hoge",
"48x48": "hoge"
},
"displayName": "name",
"emailAddress": "mail",
"key": "name",
"name": "name",
"self": "hoge",
"timeZone": "Asia/Tokyo"
},
"webhookEvent": "jira:issue_created"
}
正直、長っ!!って感じです。さて、次はこのデータをスプレッドシートにカキカキしていきましょう。
②Google App Scriptの作成する
まずはコードを書くためのgasのファイルを作成します。
Google driveにアクセスして新規→その他→Google Apps Scriptをクリックします。(Google Apps Scriptがない方はアプリを追加からインストールしましょう。
function doPost(response) {
//jira webfookのdataを取得
var json = response.postData.contents;
var data = JSON.parse(json);
var jiraNumber = data.issue.key; // チケットIDを取得
var title = data.issue.fields.summary; // summaryを取得
var status = data.issue.fields.status.statusCategory.name; // 解決状況を取得
var developlistId = data.issue.fields.customfield_[hoge]; // 開発依頼番号取得
var issueCreated = data.webhookEvent; // チケット作成フラグ
//スプレッドシートを取得
var sheets = SpreadsheetApp.openById('spreadsheetId');
var sheet = sheets.getSheetByName("sheetName");
var sheetData = sheet.getDataRange().getValues();
var sheetLastRow = sheet.getLastRow();
//スプレッドシートで取得する列番号(配列なので実列番号-1)今回は開発IDとタイトルを取得しています
var developIdColumn = 0;
var developTitleColumn = 0;
//スプレッドシートで書き込む列番号。今回はチケットID, 検証環境のリリース日、リリースフラグに書き込みます
var jiraNumberColumn = 0;
var stagingReleaseDayColumn = 0;
var stagingReleaseFlagColumn = 0;
//本日の曜日を取得。弊社では火、金に検証環境にリリースするので曜日を比較するために本日の曜日を取得しています
var today = new Date();
var dayOfTheWeek = today.getDay();
//slack投稿用変数
var message = "";
//jira作った場合、jira完了した場合
if(status == "完了"){
for(var j=0;j<sheetLastRow;j++){ //スプレッド最終行までループまわす
if(developlistId == sheetData[j][developIdColumn]){ //jiraの開発依頼番号とスプレッドの開発依頼番号が等しい場合
var stagingReleaseDay = stagingReleaseDayfnc(dayOfTheWeek); //検証環境のリリース日を取得
var writeRowNumber = j + 1; //スプレッドシート入力用の行番号を格納
sheet.getRange(writeRowNumber,stagingReleaseDayColumn).setValue(stagingReleaseDay); //スプレッドシートにjiraで取得した内容を書き込む
sheet.getRange(writeRowNumber,stagingReleaseFlagColumn).setValue(1);
message = "開発依頼ID: " + String(sheetData[j][developIdColumn]) + "\n" + sheetData[j][developTitleColumn] + "の開発が完了しました。" //slackに送るメッセージ作成
slackpost(message); //slack送信
}
}
} else if(issueCreated == 'jira:issue_created' ){
for(var i=0;i<sheetLastRow;i++){ //スプレッド最終行までループまわす
if(developlistId == sheetData[i][developIdColumn]){ //開発依頼番号があった場合
var writeRowNumber = i + 1; //スプレッドシート入力用の行番号を格納
sheet.getRange(writeRowNumber, jiraNumberColumn).setValue(jiraNumber); //スプレッドシートにjiraで取得した内容を書き込む
message = "開発依頼ID: " + String(sheetData[j][developIdColumn]) + "\n" + sheetData[j][developTitleColumn] + "の開発が開始しました。"; //slackに送るメッセージ作成
slackpost(message); //slack送信
}
}
}
}
//検証環境のリリース日を出力する関数
function stagingReleaseDayfnc(dayOfTheWeek) {
//当日の日付を格納
var today = new Date();
//翌日の日付を格納
var tomorrow = new Date();
tomorrow.setDate(tomorrow.getDate()+1);
var formatTomorrow = Utilities.formatDate(tomorrow,"JST","yyyy/MM/dd");
//2日後の日付を格納
var twoDaysLater = new Date();
twoDaysLater.setDate(twoDaysLater.getDate()+2);
var formattwoDaysLater = Utilities.formatDate(twoDaysLater,"JST","yyyy/MM/dd");
//3日後の日付を格納
var threeDaysLater = new Date();
threeDaysLater.setDate(threeDaysLater.getDate()+3);
var formatthreeDaysLater = Utilities.formatDate(threeDaysLater,"JST","yyyy/MM/dd");
//検証環境のリリース日を出力
if(dayOfTheWeek == 0){
return twoDaysLater
}else if(dayOfTheWeek == 1){
return tomorrow
} else if(dayOfTheWeek == 2){
return threeDaysLater
} else if(dayOfTheWeek == 3){
return twoDaysLater
} else if(dayOfTheWeek == 4){
return tomorrow
} else if(dayOfTheWeek == 5){
return threeDaysLater
} else if(dayOfTheWeek == 6){
return twoDaysLater
}
}
//slackへの投稿する関数
function slackpost(message) {
var postUrl = 'hoge'; //Incoming WebHooksのWebhook URLをコピペする
var username = 'jirabot'; // 通知時に表示されるユーザー名
//slackで送るのもを格納
var jsonData =
{
"username": username,
"text":message
};
var payload = JSON.stringify(jsonData); //jsonデータに変換
//送り方とかもろもろの設定を記入
var options =
{
"method" : "post",
"contentType" : "application/json",
"payload" : payload
};
UrlFetchApp.fetch(postUrl, options); //postUrlにデータを送る
}
③slackにスプレッドに転記したデータを投稿する
webhookの設定
slackでデータを送信したいチャネルに移動し、Add an appをクリック
投稿したいチャネルを選択してAdd Incoming WebHooks integrationをクリック
iconなどを適当に変更してSave Settingsをクリック