見出し画像

Google Apps ScriptではじめるBacklog API

こちらはヌーラボブログリレー2024 for Tech Advent Calendar 2024の14日目の記事です。

こんにちは、ヌーラボBacklog課の江口です。

Backlogでは多数のAPIを提供していますが、これらのAPIを活用できると必要なデータの集計、操作をより効率的にすることが可能です。
今回のエントリではBacklog APIの手軽な利用方法として、Google Apps Script(GAS)上からAPIを呼び出しGoogle スプレッドシートに結果を出力する方法を紹介します。
以降はGoogle スプレッドシート、GASの基本的な利用方法は分かる前提で説明を進めていきます。


APIキーを取得する

Backlog APIを利用するにはまずAPIにアクセスするためのアクセスキーを取得する必要があります。
Backlog APIではOAuth2.0とAPIキー、2種類の認可方式を提供していますがここでは利用の簡単なAPIキーを利用した方法を使用します。

APIキーを新しく生成して利用するには自身のBacklogにログインし、「個人設定 > API」のページにアクセスします。

APIの設定ページ

このページの「登録」ボタンを押下すると現在ログインしているユーザーとしてAPIにアクセスすることが可能なAPIキーが生成されます。

このAPIキーが第三者に流出するとAPIを通じてデータに不正にアクセスされる可能性があるため、取り扱いには十分注意してください。
必要なくなったキーは削除しておくことで漏洩リスクを低減することができます。
サンプルではAPIキーをコード内にハードコーディングしていますが、プロパティサービスに保存するのがセキュリティ的に安全です。

次に、Webブラウザ上でGoogle スプレッドシートを新しく作成します。

Google スプレッドシートのメニューバーから「拡張機能 > Apps Script」を選択しすると以下のようにスクリプトエディタの画面が表示されます。
ここにBacklog APIにアクセスするためにスクリプトを記述していきます。

スクリプトエディタ

APIでプロジェクト一覧を取得する

まずはじめに簡単なサンプルとしてプロジェクト一覧を取得するAPIを呼び出してみます。
以下のスクリプトをスクリプトエディタにペーストし(1)SPACE_URL (2)API_KEYの定数の内容を自身のBacklogのURLと、先程取得したのAPIキーの値に書き換えます。

const SPACE_URL = 'https://___.backlog.com'; // (1)スペースのURLを設定
const API_KEY = '___'; // (2)APIキーを設定

function main() {

  const options = {
    'method': 'GET',
    'muteHttpExceptions': true
  };

  let response = UrlFetchApp.fetch(SPACE_URL + '/api/v2/projects?apiKey=' + API_KEY, options);
  let statusCode = response.getResponseCode();
  if (statusCode !== 200) {
    Logger.log('エラー: ステータスコード ' + statusCode);
    Logger.log('レスポンス: ' + response.getContentText());
    return;
  }

  let data = JSON.parse(response.getContentText());

  let sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
  sheet.getRange(1, 1).setValue('ID');
  sheet.getRange(1, 2).setValue('プロジェクトキー');
  sheet.getRange(1, 3).setValue('プロジェクト名');

  for (let i = 0; i < data.length; i++) {
    let row = 2 + i;
    sheet.getRange(row, 1).setValue(data[i].id);
    sheet.getRange(row, 2).setValue(data[i].projectKey);
    sheet.getRange(row, 3).setValue(data[i].name);
  }

}

入力内容を保存し、ツールバーの「実行」ボタンを押下するとスクリプトが実行されます。

以下のような承認ダイアログが表示された場合は「権限を承認」を選択し、アカウントと実行の許可を行ってください。

実行が成功すれば以下のようにスプレッドシート内にアクセス可能なプロジェクトのID、プロジェクトキー、プロジェクト名が出力されます。
ここではID、プロジェクトキー、プロジェクト名だけを出力していますが、レスポンス内には他にも様々な情報が含まれています。
どのような情報がAPIのレスポンスに含まれているかは、Backlog APIサイトのページでエンドポイント毎に公開されています。
https://developer.nulab.com/ja/docs/backlog/api/2/get-project-list/

プロジェクト一覧

構文エラーが表示された場合は、スクリプトに構文上の問題があるので問題箇所を修正します。
実行ログにエラーが出力された場合はエラーメッセージを参考に原因を調べて修正します。
以下のページに簡易ですがエラーコードの一覧と説明があります。

https://developer.nulab.com/ja/docs/backlog/error-response/

APIで課題一覧を取得する

次に、もう少し実用的な例として課題一覧を取得するAPIを呼び出してみます。
ここでは課題の検索条件としてプロジェクトIDとステータスを指定してみます。
以下のスクリプトをスクリプトエディタにペーストし、先程と同様に(1)(2)の変数の内容を書き換えるのに加え、(3)で検索対象とするプロジェクトIDを整数の配列として指定します。
課題の一覧を取得するAPIをはじめ、いくつかのAPIでは一回の呼び出しで最大100件までしかデータを取得できないため、ここではクエリパラメーターのoffsetの値を0から100ずつ加算して連続で呼び出すことで検索対象のすべての課題を取得して配列に保存しています(4)。

const SPACE_URL = 'https://___.backlog.com'; // (1)スペースのURLを設定
const API_KEY = '___'; // (2)APIキーを設定

function main() {
  const query = {
    'projectId[]': [___], // (3)プロジェクトIDを指定
    'statusId[]': [1] // ステータスが未対応の課題を指定
  };

  const response = getIssues(query);
  outputToActiveSheet(response);
}

function getIssues(query = {}) {
  query.offset = 0;
  query.count = 100;
  query.apiKey = API_KEY;
  return getAllPage(_getIssues, query);
}

function _getIssues(query) {
  const options = {
    'method': 'GET',
    'muteHttpExceptions': true
  };

  const response = UrlFetchApp.fetch(buildUrl(SPACE_URL, '/api/v2/issues', query), options);
  const statusCode = response.getResponseCode();

  if (statusCode === 200) {
    return JSON.parse(response.getContentText());
  } else {
    Logger.log('エラー: ステータスコード ' + statusCode);
    Logger.log('レスポンス: ' + response.getContentText());
    throw new Error('APIエラー');
  }
}

function buildUrl(spaceUrl, path, query) {
  return spaceUrl + path + '?' + objectToQueryString(query);
}

function objectToQueryString(obj) {
  return Object.keys(obj)
    .map(function (key) {
      if (key.endsWith("[]")) {
        return obj[key].map(function (value) {
          return key + "=" + encodeURIComponent(value);
        })
          .join("&");
      } else {
        return key + "=" + encodeURIComponent(obj[key]);
      }
    })
    .join("&");
}

function outputToActiveSheet(data) {
  const sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
  const output = [['ID', '課題キー', '件名']];

  for (let i = 0; i < data.length; i++) {
    output.push([data[i].id, data[i].issueKey, data[i].summary]);
  }

  sheet.getRange(1, 1, output.length, 3).setValues(output);
}

// (4)課題を100個ずつ取得する
function getAllPage(f, query) {
  let allResponses = [];
  let response;
  do {
    response = f(query);
    allResponses = allResponses.concat(response);
    query.offset += 100;
  } while (response.length === 100);
  return allResponses;
}

実行が成功すれば以下のように指定したプロジェクト内にある未対応の課題が出力されます。
条件に当てはまる課題数が多い場合は実行終了までに時間がかかる場合があります。

課題一覧

Backlog APIでは課題一覧の取得だけではなく、追加や更新、そのほかWeb上から可能な操作の大部分をカバーしています。
ぜひ活用してみてください。

いいなと思ったら応援しよう!