LANG SELRCT

コードを書く場所

2019年9月9日月曜日

JIRA APIでissueの変更履歴を取得する3


指定したissue keyでステータスが変更された最終日時を取得してシートに書き出したい

と思って書き出すコードを書きました。

書き出す前のシート:

  • KEY:issue keyは入力しておく
  • created:ステータスが変更された最終日時
  • from:変更前のステータス
  • to:変更後のステータス



書き出した後のシート:
コード.gsの get_last_status_change_date() を実行すると、created, from, to が入力されます。


関連記事

JIRA APIでissueの変更履歴を取得する
JIRA APIでissueの変更履歴を取得する2


事前準備
  • シートのA列にissue keyを入れておく
  • スクリプトのプロパティにtokenという名前でbasic認証する文字列を入れておく


コード.gs内で各自で変更する箇所
  1. ISSUE_URLの SITENAME
  2. ss_urlの SPREADSHEET_ID



コード.gs
var ISSUE_URL = 'https://SITENAME.atlassian.net/rest/api/2/issue/';
var ss_url = "https://docs.google.com/spreadsheets/d/SPREADSHEET_ID/edit#gid=0";

/************************************
これを実行する
シートを取得して
シートからJIRAのissue keyを取得して
最終ステータスの日時と何から何へを取得して
シートに書き込む
************************************/
function get_last_status_change_date() {
  var sheet = get_sheet();
  var keys = get_keys(sheet);// ["KT-6", "KT-7"];
  var last_statuses = get_last_statuses(keys);
  var values = create_value(last_statuses, sheet);
  set_values(values, sheet);
}

/************************************
指定したss_urlのシートの0番目のシートを取得して返す
************************************/
function get_sheet() {
  var ss = SpreadsheetApp.openByUrl(ss_url);
  var sheet = ss.getSheets()[0];
  return sheet;
}

/************************************
シート内のA列の2行目から入力されているissue keyを取得して
二次元配列で取得されるので一次元配列にして返す
************************************/
function get_keys(sheet) {
  var last_row = sheet.getLastRow();
  var rangeA = sheet.getRange(2, 1, last_row-1, 1);
  var valuesA = rangeA.getValues();
  var keys = array_push_apply(valuesA);
  return keys;
}

/************************************
二次元配列を一次元配列にして返す
************************************/
function array_push_apply(arrays){
  for(var i = 1; i < arrays.length; i++){
    Array.prototype.push.apply(arrays[0], arrays[i]);
  }
  return arrays[0];
}

/************************************
issue keyの最後のステータス変更を取得して
last_statuses配列に入れて返す
************************************/
function get_last_statuses(keys) {
  var last_statuses = [];
  for(var i = 0; i < keys.length; i++) {
    var key = keys[i];
    var latest_status = get_latest_status(key);
    last_statuses.push(latest_status);
  }
  return last_statuses;
}

/************************************
issue keyの最後のステータス変更の履歴を取得して返す
************************************/
function get_latest_status(key) {
  var histories = get_issue_histories(key);
  var arrays = get_status(histories);
  var latest_status = arrays[0];// descにした配列の先頭がlatest
  return latest_status;
}

/************************************
issueの情報からchangelogのhistoriesを取得して返す
************************************/
function get_issue_histories(key) {
  var response = get_issue(key);
  var jobj = JSON.parse(response);
  var histories = jobj["changelog"]["histories"];
  return histories;
}

/************************************
issueの情報を?expand=changelog付けて取得して返す
************************************/
function get_issue(key) {
  var token = getProp("token");
  var options = {
    contentType: "application/json",
    headers: {"Authorization": " Basic " + token}
  };
  var url = ISSUE_URL + key + "?expand=changelog";
  var response = UrlFetchApp.fetch(url, options);
  return response;
}

/************************************
histories(履歴)の数だけ繰り返す
さらに履歴の中のitemsの数だけ繰り返す
fieldがstatusならcreatedとfromとtoのオブジェクトを作って
arrays配列に入れて
descending_arrayで日時を基準に降順にして返す
************************************/
function get_status(histories) {
  var arrays = [];
  for(var i = 0; i < histories.length; i++) {
    var history = histories[i];
    var created = format_date(history["created"]);
    var items = history["items"];
    for(var j = 0; j < items.length; j++) {
      var item = items[j];
      var field = item["field"];
      if(field === "status") {
        var obj = {};
        obj["created"] = created;
        obj["from"] = item["fromString"];
        obj["to"] = item["toString"];
        arrays.push(obj);
      }
    }
  }
  var desc = descending_array(arrays);
  return desc;  
}

/************************************
シートに入れる値を作って入れる
************************************/
function create_value(last_statuses, sheet) {
  var values = [];
  for(var i = 0; i < last_statuses.length; i++) {
    var latest_status = last_statuses[i];
    if(latest_status === undefined) {
      values.push(["-", "-", "-"]);// statusの変更履歴がなければ-にする→しないとlatest_status["created"]などがエラーになるのでここで回避
    } else {
      var created = latest_status["created"];
      var from = latest_status["from"];
      var to = latest_status["to"];
      values.push([created, from, to]);
    }
  }
  return values;
}

/************************************
シートに値を入れる
************************************/
function set_values(array, sheet){
  var start_col = 2;
  var last_row = get_last_row(sheet, start_col);
  var start_row = last_row + 1;
  var num_rows = array.length;
  var num_cols = array[0].length;
  var range = sheet.getRange(start_row, start_col, num_rows, num_cols);
  range.setValues(array); 
}

/************************************
指定したcol(列)の値が入っている最終行を取得して返す
************************************/
function get_last_row(sheet, col) {
  var start_row = 1;
  var num_cols = 1;
  var sh_last_row = sheet.getLastRow();
  var values = sheet.getRange(start_row, col, sh_last_row, num_cols).getValues();
  for (var i = values.length - 1; i >= 0; i--) {
    if (values[i] != "") {
      break;
    }
  }
  var last_row = i + 1;
  return last_row;
}

/************************************
受け取ったkeyの値をスクリプトのプロパティから返す
************************************/
function getProp(key) {
  return PropertiesService.getScriptProperties().getProperty(key);
}

/************************************
日時をフォーマットして返す
************************************/
function format_date(date) {
  return Utilities.formatDate(new Date(date), "asia/tokyo", "yyyy-MM-dd HH:mm:ss");
}

/************************************
日時を降順にした配列を返す
************************************/
function descending_array(array) {
  var descending = array.sort(sorting_desc);
  return descending;
}

/************************************
array配列内の日時を降順にする
************************************/
function sorting_desc(a, b){
  if(a[0] > b[0]){
    return -1;
  }else if(a[0] < b[0] ){
    return 1;
  }else{
   return 0;
  }
}