LoginSignup
18
1

Jira Cloud REST APIとGASを使ったチケット起票のしくみについて

Last updated at Posted at 2023-12-03

はじめに

こんにちは。前年エンジニアリング・トライアルについて記事を書きました@tsugumiriです。
今年は、前年に引き続き審査の業務に従事しつつ、エンジニアリング・トライアル2年生として、牛歩の歩みながら知見を深めて参りました。

今回は、取り組みを通じ制作した、Jira Cloud REST APIとGASを使ったチケット起票の仕組みについて、頭を悩ませた結果、エンジニアさんにアドバイスいただき、解決に至ったものがありましたので、紹介させていただければと思います。

Jira Software Cloudへの移行

今年経験した弊社の大きなイベントとして、Jira Software Cloudへの移行がありました。
Jira Software Cloudとは、チケット管理を基本とした、バグトラッキングや課題管理、プロジェクト管理に用いられるAtlassian社の製品です。
品質管理の業務に従事されている方にとっては、おなじみのツールではないかと思います。

審査業務においては、QA業務ほど多くのチケット起票は発生しないものの、できることへの工数削減として、移管とともに、Google Apps Script (以降GASと記載します)を利用した、チケット起票の自動化に取り組むことになりました。

Jira Cloud REST APIとGASを使ったチケット起票

チケット起票の自動化については、公式ドキュメントとともにQiita内の以下記事を参考とさせていただきました。

今回は、チケット起票に関する基本的な内容はすでに記事があることから、複数名で仕組みを利用することを前提とした上で、個人のアクセストークンをどのように管理するか、制作にあたり頭を悩ませた結果、エンジニアさんにアドバイスいただいた内容について、後述いたします。

個人のアクセストークンをどのように保管するか

今回、ツールを利用する際のAPI トークンは、最終的に、個人で発行可能なものを利用する方法としました。

この方法に行き着くまでには、共通アカウントの利用なども検討しましたが、審査業務は、社内の多くのプロジェクトに横断的に関わることから、共通アカウントを利用するよりは、セキュリティの側面からも、すでにJiraのプロジェクトに対し、必要な範囲の権限を所持している、個人のアカウントで投稿を行えたほうがよいのではないかと、アドバイスをいただきました。

また、個人のトークンを、ツールを利用する他者に閲覧されることなく、登録する仕組みについてアドバイスをいただいた方法が、Class PropertiesServiceのUserPropertyに登録できる仕組みとする点でした。

アクセストークンを登録・削除するためのコード

Jiraのアクセストークンを登録・削除する仕組みは、以下のようなコードで構築しました。

//以下をスプレッドシート起動時のトリガーとして設定することでUIにメニューを表示する
function createUi()
{
  SpreadsheetApp.getUi()
    .createMenu('メニュー')
      .addItem('アクセストークンを登録する', 'setJiraToken')
      .addItem('アクセストークンを削除する', 'deleteJiraToken')
      .addToUi()
}

var userProperties = PropertiesService.getUserProperties();
var jira_user_key = getUserKey();

//UserKeyは任意の接頭語とメールアドレスで生成する
function getUserKey()
{
  var jira_user_name = Session.getActiveUser().getEmail();
  var jira_user_key = 'JIRA_TOKEN_' + jira_user_name;
  return jira_user_key;
}

//JIRAトークンをUserPropertiesに登録する
function setJiraToken()
{
  //すでにトークンが登録されているかのチェックを行う。
  if (hasJiraToken(jira_user_key)) {
    if (Browser.msgBox("すでに登録が完了しています。既存の登録内容を上書きしますか?", Browser.Buttons.OK_CANCEL) != 'ok') {
      Browser.msgBox('登録を中止しました。終了します');
      return
    }else{
      userProperties.deleteProperty(jira_user_key);
    }
  }
  var input = Browser.inputBox('アクセストークンを入力してください\\n※アクセストークンは他の人へ共有しないでください', Browser.Buttons.OK_CANCEL) 

  if (input != '' || 'cancel') {
    var token = input
    userProperties.setProperty(jira_user_key, token);
      Browser.msgBox('アクセストークンを登録しました。終了します');
      return
  }else{
    Browser.msgBox('登録を中止しました。終了します');
  }
}

//user_keyに紐づくトークンがすでに登録されているかを確認する
function hasJiraToken(user_key)
{
  keys =  userProperties.getKeys();
  var ret = false
  keys.forEach(function(col){
    if (col == user_key) {
      ret = true
    }
  })
  return ret
}

//トークンの削除を行う仕組み
function deleteJiraToken()
{
  if (hasJiraToken(jira_user_key)) {
    if (Browser.msgBox("登録済みのアクセストークンを削除しますか?", Browser.Buttons.OK_CANCEL) != 'ok') {
      Browser.msgBox('中止しました。終了します');
      return
    }

    userProperties.deleteProperty(jira_user_key);
    Browser.msgBox('削除を行いました。終了します');
    return
  }else{
    Browser.msgBox('登録されているアクセストークンはありません。終了します');
  }
}

登録が行えているかの確認については、以下のコードで行いました。

function showUserProperties()
{
  Logger.log(userProperties.getProperties())
}

登録を行ったアカウントでの出力結果は以下となりました。

{JIRA_TOKEN_XXXXXX@XXXX.net=XXXXX}

登録を行ったアカウント以外での出力結果は以下となりました。

{}

確認の結果からも、個人のアクセストークンを、ツールを利用する他者に閲覧されることなく、登録することができていることが確認できました。

チケット起票を行うコード

上記で登録を行ったアクセストークンを利用したチケット起票の仕組みは、以下のようなコードで構築しました。
なお、今回、JSON部分は、仮のものとして記載しております。実際の制作時は、以下のドキュメントを参考とし、スプレッドシートから取得したデータをもとに、構築いたしました。

var scriptProperties = PropertiesService.getScriptProperties();
var userProperties = PropertiesService.getUserProperties();

function createJiraIssue()
{
  //JSON部分は仮の内容として作成
  var json = createJSON();
  
  try{
    //投稿結果(戻り値)は後続の結果をスプレッドシートに記録する動作などに用いる
    var result = postJiraIssue(json)
  }catch(e){
    console.error('エラーが発生しました:' + e["message"]);
  }
}

function createJSON()
{
  var ret = {
    "fields": {
      "summary": 'summary',
      "project": {
        "key": 'project_name'
      },
      "description":'XXXXX',
      "issuetype": {
        "id": 'XXXXX'
      }
    }
  }
  return JSON.stringify(ret);
}

function postJiraIssue(json)
{  
  //呼び出し先のAPIのURLを設定。なおJIRA_BASE_URLはスクリプトプロパティに登録
  var script_prop = scriptProperties.getProperties();
  var request_url = script_prop["JIRA_BASE_URL"] + 'rest/api/2/issue/';

  //optionsに含める情報構築のためメールアドレスを取得する
  var jira_user_name = Session.getActiveUser().getEmail();
  var jira_user_key = getUserKey();
  
  var user_prop = userProperties.getProperties();
  var token = Utilities.base64Encode(jira_user_name + ':' + user_prop[jira_user_key], Utilities.Charset.UTF_8);

  var options = {
    method: 'post',
    payload: json,
    contentType: 'application/json',
    headers: {'Authorization': ' Basic ' + token}, 
    muteHttpExceptions:true,
  }

  var response = UrlFetchApp.fetch(request_url, options);

  var response_code = response.getResponseCode();
  var response_body = response.getContentText();

  if (response_code != 201) {
    // 戻り値より取得したresponse_codeが201以外の場合はエラーの扱いとする
    throw new Error(`code:${response_code} responseBody:${response_body}`);
  }else{
    return JSON.parse(response_body);
  }
}

//UserKeyは任意の接頭語とメールアドレスで生成する
function getUserKey()
{
  var jira_user_name = Session.getActiveUser().getEmail();
  var jira_user_key = 'JIRA_TOKEN_' + jira_user_name;
  return jira_user_key;
}

取り組みを通じ得られた知見

今回アドバイスをいただいたUserPropertyを利用する仕組みは、その性質上、同一シートを複数名で利用するシーンが多いGoogle スプレッドシートを利用し、他の仕組みへ投稿を行う際に、セキュリティに配慮した方法でサービスに対し、アクセスに必要な情報を管理できる方法でした。

情報の管理に対する知識や意識付けは、社内研修で学ぶ機会があります。また、エンジニアリング・トライアルでは、ツールの設計や、コードの記述方法をアドバイスいただくことが多いですが、今回は、加えて、機密情報の管理に対する知識とその方法について、学ぶことができました。

セキュリティと言う言葉を聞く機会は多いですが、いざ、自分がツールを作成しているときに、特に初学者の自分が、どれだけセキュリティに配慮した設計とできているかについては、自己評価が難しいと感じます。今回は、制作の初期の段階で、アクセストークンの管理方法のアドバイスをいただけたことで、その重要さについて、改めて認識しました。

さいごに

GASは身近なツールであり、Google スプレッドシートと組み合わせることで、多くの自動化が実現できます。
今年もエンジニアリング・トライアルを通じ、いくつかのツール制作に取り組ませていただくことで、できる「自動化」の方法をより増やすことができました。

牛の歩みも千里を心に、来年も知見を深めたいと考えています。
最後までお読みいただきありがとうございました。

18
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
18
1