BacklogのAPIで課題の添付ファイルのサイズを取得してみた #ヌーラボ真夏のブログリレー2024

こんにちは。Backlog テクニカルサポートの立石です。

前回はよくあるお問い合わせの中から課題の登録(2022年真夏のブログリレー)とファイルのアップロード(2022年冬のブログリレー)について Backlog API にチャレンジしてみましたが、今回も引き続き Backlog API を使うことで何かお役に立てることがないかと思い、本ブログを書いてみようと思いました。

前回から時間も経ちましたので改めてテクニカルサポートについて紹介したいと思います。

テクニカルサポートというとあまり聞きなれない方もおられるかもしれませんが、ヌーラボのサポートにはカスタマーサポートとテクニカルサポートの部署がそれぞれあり、カスタマーサポートは主にお客様のお問い合わせなどに対して直接接している部署になります。対してヌーラボのテクニカルサポートは主にプロダクトの技術的なサポートを専門に行っている部署となります。カスタマーサポートと一緒にお客様のサポートを行なったりすることもありますし、仕様の確認や不具合やログの調査をすることもあります。またそれ以外にもカスタマーサポートの運用がスムーズにできるようサポートで利用する管理システムやツールを作ったり、改善を行なったりすることもあります。

エンドユーザーはお客様やカスタマーサポートになるのですが、ツールを作る時には、その方の負担を少しでも減らすことで幸せになれないかと思いながら日々お仕事に取り組んでいます。

早速ですが、前回同様にお客様のよくあるお声の中から何かお役に立てることがないかなと思い、その中から選ばせていただきました。 今回はプロジェクトを整理するために各課題の添付ファイルの合計サイズを把握したいというご要望について取り組んでみようと思います。例えばファイルサイズの大きい課題があれば、その課題から余計な添付ファイルを削除したいのに利用したいとのことです。

ぜひ最後までお付き合いいただけますと幸いです。

課題の添付ファイルのサイズを取得しよう

データを一覧化し、出力しますので Googleスプレッドシートや Excel などの表形式のアプリケーションが相性が良いかと思います。 そのため今回は出力先としてGoogleスプレッドシートを使いたいと思います。データは前回に引き続き Google Apps Script(以下 GAS)と Backlog API を使って取得したいと思います。

※ Backlog API の概要については 2022年真夏のブログリレーの ブログ を読んでいただければと思います。

Googleスプレッドシートを準備しよう

早速、Googleスプレッドシートを準備しましょう。 スプレッドシートを新規で開くと上部にメニューバーがあります。メニューバーにある「拡張機能」を開くと、その中に「Apps Script」というものがあるのでそちらを選択してください。

開きますと GAS のスクリプトエディタが起動します。そちらで取得するプログラムを作っていきたいと思います。

課題一覧を取得しよう

今回は、課題毎の添付ファイルの合計サイズを把握したいとのことなので、課題の一覧を取得するところから始めたいと思います。課題の一覧は 課題一覧の取得の API を使って取得します。

はじめに、課題の一覧を取得するに当たってプロジェクトはまずは1つに限定したいと思います。理由はプロジェクト数件とかであれば問題ないのですが、例えばプロジェクトの件数が1000件とかだったりすると、その下にある課題は膨大な数の可能性もあり、取得するためのツールがパンクするかもしれないからです。もしくは数が多すぎて処理がいつまでも終わらなくなり、実行環境にも負荷を与える可能性もあります。そのため、まずは取得するプロジェクトを1件とするところから始めたいと思います。その後、必要に応じて徐々に負荷のない範囲で改良していくのが良いかと思います。

課題についても同様です。まずは取得する課題の件数については1000件から始めたいと思います。こちらも作成後、必要に応じて負荷のない範囲で改良いただけますと幸いです。

では早速ですが、前回と同様に GAS には UrlFetchApp というユーティリティが用意されていますので、今回もそのユーティリティを使って Backlog へアクセスしたいと思います。

function getIssues() {
  let result = UrlFetchApp.fetch("https://<スペースID>.backlog.com/api/v2/issues?apiKey=<あなたのAPIキー>&projectId[]=<取得したいプロジェクトのID>");
  let issues = JSON.parse(result.getContentText());

  for (let ii = 0; ii < issues.length; ii++) {
    Logger.log(String(issues[ii]["id"]));
  }
}
  • <スペースID> にはご利用のスペースのスペースIDに置き換えてください。詳しくは スペースIDとは のヘルプを参考にしてください。
  • <あなたのAPIキー> はご利用のアカウントの API に置き換えてください。詳しくは APIキーのヘルプ を参考にしてください。
  • <取得したいプロジェクトのID> は プロジェクト情報を取得する API を使って取得することもできますが、ブラウザの画面からも確認することができます。ブラウザで対象プロジェクトのプロジェクト設定画面に移動するとブラウザのアドレスバーに URL が表示されます。そちらに「project.id=34521」などと出力されていますのでその値に置き換えていただくだけになります。

課題の取得処理を getIssues() という1つのファンクションとして切り出しています。ファンクションは1つの処理をするプログラムのかたまりと理解するのが良いかと思います。

早速、getIssues() を実行したいと思います。エディタの上部の「実行」「デバッグ」というメニューがあり、その「デバッグ」の右側には実行する関数を選択する選択エリアがあります。そこで getIssues を選び、「実行」ボタンを押下するとそのファンクションが実行されます。

getIssues を実行すると、エディタの下部に実行ログが表示されます。その実行ログに課題のIDが出力されるようなるかと思います。出力できていれば成功となります。

条件を追加しよう

次は条件を追加していきたいと思います。

先ほどの課題の取得ではプロジェクトのID(projectId[])しか指定していません。そのため、今の状態では 20件しか取得できません。これは取得条件の取得上限(以下 count)の初期値が 20件が上限になっているためです。20件のままでも良いのですが、今回は取得する課題の件数として 1000件を目指したいと思っていますので、 1000件取得するとなると 50回も繰り返す必要があります。それだと大変なので取得上限を引き上げたいと思います。count は1度に取得できる課題の取得件数の上限を 1〜100 で指定できますので、上限件数の最大の 100で指定したいと思います。

次に取得する課題の並び順(以下 sort と order)を決めたいと思います。こちらはあらかじめ並び順を指定しておくことで、次の課題を取得する際に並びに狂いがなく取得できるようにするためです。 今回は課題が作成された順として created(課題の登録日)を条件にしたいと思います。また昇順にしたいので order には昇順の asc を指定したいと思います。

では、早速 1000件取得するコードを作成したいと思います。

function getIssues() {
  for (let offset_count = 0; offset_count < 10; offset_count++) {
    let offset = offset_count * 100;

    let result = UrlFetchApp.fetch("https://<スペースID>.backlog.com/api/v2/issues?apiKey=<あなたのAPIキー>&projectId[]=<取得したいプロジェクトのID>&sort=created&order=asc&count=100&offset=" + offset);
    let issues = JSON.parse(result.getContentText());

    for (let ii = 0; ii < issues.length; ii++) {
      Logger.log(String(issues[ii]["id"]));
    }
  }
}

何か count や sort、order 以外のパラメーターが入っていますね?

offset というものが増えていると思います。こちらは取得するものの開始位置を決めるパラメーターになります。offset=100 だと 101件目から取得してください。という指示になります。

今回、課題 1000件を取得を目指したいと思いますが、count=100 だけではそちらを満たすことができません。そのため、100件取得したら次の 100件を取得していくようにしなければいけないのですが、特に指定がないと 100件取得し、また同じ API を実行しても同じ 100件しか取得できません。そこでこの offset を使うことで 101件目から取得するようにします。これで次の 101件目〜200件目が取得できるようになりますので、あとはそれを 1000件になるまで繰り返していくだけになります。

これで課題を 1000件まで取得できるようになりました。 では、次のステップにいきたいと思います。

取得した課題一覧をGoogleスプレッドシートに出力しよう

取得した課題をGoogleスプレッドシートに出力します。

そのまま一覧としてスプレッドシートに出力するのも良いのですが、後で並び替えとかしたくなるので予めヘッダーを作成しておきたいと思います。スプレッドシートの方に移動し、ヘッダーを作成します。

今回はシンプルに課題のIDと課題キー、課題の件名、添付ファイルの件数と合計サイズのみとしたいと思います。

では、早速出力してみましょう。

スプレッドシートの操作は GAS のユーティリティの SpreadsheetApp を使用します。SpreadsheetApp の利用方法については、Googleのリファレンスをご参照ください。

mySS = SpreadsheetApp.getActiveSpreadsheet();
sheet = mySS.getActiveSheet();

function getIssues() {
  let range = sheet.getRange("A2");

  for (let offset_count = 0; offset_count < 10; offset_count++) {
    let offset = offset_count * 100;

    let result = UrlFetchApp.fetch("https://<スペースID>.backlog.com/api/v2/issues?apiKey=<あなたのAPIキー>&projectId[]=<取得したいプロジェクトのID>&sort=created&order=asc&count=100&offset=" + offset);
    let issues = JSON.parse(result.getContentText());

    if (issues.length > 0) {
      for (let ii = 0; ii < issues.length; ii++) {
        range.offset(offset + ii, 0).setBorder(null, null, true, true, null, null, "black", SpreadsheetApp.BorderStyle.SOLID);
        range.offset(offset + ii, 1).setBorder(null, null, true, true, null, null, "black", SpreadsheetApp.BorderStyle.SOLID);
        range.offset(offset + ii, 2).setBorder(null, null, true, true, null, null, "black", SpreadsheetApp.BorderStyle.SOLID);
        range.offset(offset + ii, 3).setBorder(null, null, true, true, null, null, "black", SpreadsheetApp.BorderStyle.SOLID);
        range.offset(offset + ii, 4).setBorder(null, null, true, true, null, null, "black", SpreadsheetApp.BorderStyle.SOLID);
        
        range.offset(offset + ii, 0).setValue(issues[ii]["id"]);
        range.offset(offset + ii, 1).setValue(issues[ii]["issueKey"]);
        range.offset(offset + ii, 2).setValue(issues[ii]["summary"]);
      }
    }
  }
}

そのままだと飾り気がありませんので、罫線の装飾も入れております。 あとは取得した id や issueKey, summary をそれぞれの列にセットしていけば完成です。

実行結果は以下のようになります。

課題の一覧を出すだけであれば大した量じゃありませんね。 では、次はいよいよ添付ファイルのサイズを取得していきたいと思います。

添付ファイルのサイズを取得しよう

課題の一覧は先ほど取得しましたので、次はその一覧を使って各課題の添付ファイルの合計サイズを出力していきたいと思います。使用する API は 課題添付ファイル一覧の取得の API になります。

こちらの API を使用することで課題に添付されているファイルの一覧を取得できます。具体的にはファイル名、ファイルサイズ、誰がいつ添付したかの情報が取得できます。条件は課題のID、もしくは課題キーがわかっていれば取得することが可能です。今回は課題の ID を使って取得したいと思います。

課題の ID は先ほど課題の一覧で取得していますので、そちらを利用していきたいと思います。ファイルサイズの取得処理は getAttachmentsSize() というファンクションとして切り出しました。

function getAttachmentsSize() {
  let lastRow = sheet.getLastRow();

  for (let ii = 2; ii <= lastRow; ii++) {
    let result = UrlFetchApp.fetch("https://<スペースID>.backlog.com/api/v2/issues/" + sheet.getRange("A" + ii).getValue() + "/attachments?apiKey=<あなたのAPIキー>");
    let attachments = JSON.parse(result.getContentText());

    let totalSize = 0;
    if (attachments.length > 0) {
      for (let ii = 0; ii < attachments.length; ii++) {
        totalSize = totalSize + attachments[ii]["size"];
      }
    }

    sheet.getRange("D" + ii).setValue(attachments.length);
    sheet.getRange("E" + ii).setValue(totalSize);

    Utilities.sleep(500);
  }
}

こちらもさほど難しくはないかと思います。 課題添付ファイル一覧の取得の API のリファレンスに記載されている URL に課題の ID を挟むだけで、その課題の添付ファイルの一覧を取得することが可能です。

あとはその課題の添付ファイルの件数と、添付ファイルのサイズを集計し、そちらをスプレッドシートの列に出力するのみとなります。

ただ、1点だけ注意点があります。こちらの 課題添付ファイル一覧の取得の API は課題の件数分 API を実行することになります。今回、課題の件数を 1000件としていますが、仮に 1000件を一度に取得するとレート制限に引っ掛かる可能性が出てきます。そこで Utilities.sleep を使いたいと思います。 ※ レート制限の詳細についてはリファレンスをご参照ください。

Utilities.sleep は指定した時間プログラムの実行を中止するユーティリティになります。指定できる時間はミリ秒単位での指定となります。例えば1秒中止したい場合は、Utilities.sleep(1000) と指定することで一時的に実行を止めることが可能です。

もし様々な API を使って情報を取得する場合は、レート制限を意識していただくと良いかと思います。今回は課題1個につき 0.5秒(500ミリ秒)のインターバルを挟むようにし、レート制限に掛からないようにしたいと思います。

動かしてみましょう

早速、作ったプログラム getAttachmentsSize() を使って実行してみたいと思います。

実行結果は以下のようになりました。

ファイルのサイズも取得できましたね。

これで課題に何件の添付ファイルが保存されており、そのサイズの合計が何バイトかがわかるようになりました(サイズの単位はバイトで出力しておりますが、必要に応じて見やすい単位に変更いただければと思います)。こちらを元に課題の整理等を行っていただければと思います。

次の1000件を取得したい場合は、offset_count の初期値を 0 ではなく 10 に変え、offset_count の範囲を < 20 とかにすることで次の 1000件を取得してくれるようになりますので、件数が多いプロジェクトなどは順にお試しいただければと思います。

for (let offset_count = 10; offset_count < 20; offset_count++)

さいごに

いかがでしたでしょうか?

Backlog の API は幅広くデータを取り扱っています。そのためリファレンスを見るだけでもこういうこともできるのかという発見もきっとあると思います。今回はその中の一部として知ってもらえたらと思います。

また今回、プログラムはさほど難しいものではなかったものの、データ量が多いところにアクセスする形だったため、サーバーや実行環境の負荷、またはレート制限を意識しながら作成しています。そのためその分に割いた説明が増えております。データにアクセスする場合、その壁に当たることもあると思いますので、今後の皆様の一助となれば幸いです。

今後も Backlog をどうぞよろしくお願いいたします。

より良いチームワークを生み出す

チームの創造力を高めるコラボレーションツール

製品をみる