【JavaScript】Jiraタスクを取得するコマンドを作ってみる

## はじめに
前回業務開始時に役立ちそうなJavaScriptコードをコマンドで実行する方法について書かせていただきました。

https://qiita.com/bluerabbits69/items/ba2ed2e73bf8c7512450

今回は、少し派生してJiraのTodoを取得できるようなサンプルを作成してみようと思います！

## Jiraとは
Atlassian社が提供するタスク管理ツールです。

https://www.atlassian.com/ja/software/jira

メールアドレスを登録するだけで、無料で簡単に使用することができます。（有料プラン有り）

※今回の記事では、Jiraの使い方や、Jiraのプロジェクトの作成方法などは割愛させていただきます。


## 目標
前回作成したwrkコマンドに、'jira'を追加して以下のように実行するサンプルを作成します。
```
wrk jira today
```
こちらを実行すると・・・
```
📋 [username] の今日のJiraタスク一覧（2025-03-27）

🚧 PROJ-102 | バックエンドのテスト修正中
📝 PROJ-103 | AWS構成図をアップデート（未着手）
```
こんな感じで、Todoとなっているタスクを表示するサンプルを考えてみます。

## 準備
### JiraでAPIトークン発行
まずは、Jiraで認証するためのAPIトークンを発行します。
Jiraの「アカウント設定」 -> 「セキュリティ」の、「APIトークン」からトークンを発行します。
![スクリーンショット 2025-03-27 10.51.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3582240/2352ebfa-ef67-4a41-9e39-cc6ff70ed77b.png)
適当名前を入力して、「作成」ボタンを押すとトークンが発行されます。
トークンは後で使用するので、どこかに控えておいてください。

### パッケージの追加
API通信を実現させるためのaxiosパッケージと、.envファイルから環境変数を取り込むためdotenvを使用します。
```
npm install axios dotenv
```

## lib/jira.js
```js
import axios from "axios";
import dotenv from "dotenv";
dotenv.config();

export async function fetchTodayTasks(){
  //アクセスに必要な情報を.envファイルから取得
  const baseURL = process.env.BASE_URL;
  const email = process.env.EMAIL;
  const token = process.env.API_TOKEN;
  const username = process.env.USER_NAME;

  // basic認証に必要なオブジェクト作成
  // オブジェクトのヘッダーにemailとtoken情報を詰め込む。
  const auth = Buffer.from(`${email}:${token}`).toString("base64");

  // JQL（今日の担当タスク）
  const jql = `assignee=currentUser() AND statusCategory != Done ORDER BY priority DESC`;

  try {
    // Jiraタスク取得
    const res = await axios.get(`${baseURL}/rest/api/3/search`, {
      headers: {
        Authorization: `Basic ${auth}`,
        Accept: "application/json"
      },
      params: {
        jql: jql,
        maxResults: 10,
        fields: "summary,status,key"
      }
    });
    // レスポンスで帰ってきたissues情報
    const issues = res.data.issues;
    console.log(`📋 [${username}] の今日のJiraタスク一覧（${new Date().toISOString().slice(0,10)}）\n`);

    for (const issue of issues) {
      // taskのID
      const key = issue.key;
      // summaryはチケットのタイトル。
      const summary = issue.fields.summary;
      // 現在のステータス。"To Do", "In Progress", "Done"
      const status = issue.fields.status.name;

      const icon = {
        "To Do": "📝",
        "進行中": "🚧",
        // その他、カスタムなステータスを追加できる。
      }[status] || "📄";

      console.log(`${icon} ${status} ${key} | ${summary}`);
    }
  } catch (err) {
    console.error("❌ Jiraタスク取得エラー:", err.message);
  }
}
```

このうち、以下の	"/rest/api/3/search"　の部分は「Jiraの課題をクエリで検索して取得する」という処理になります。
```js
const res = await axios.get(`${baseURL}/rest/api/3/search`{
    // ヘッダー情報などを記載
}
```
Jiraの公式docsにも使い方が記載されているので、確認しましょう！

https://developer.atlassian.com/cloud/jira/platform/rest/v3/api-group-issue-search/#api-group-issue-search

## .envにユーザー情報を記述
```
JIRA_BASE_URL=https://your-org.atlassian.net
JIRA_EMAIL=your-email@example.com
JIRA_API_TOKEN=your_api_token
JIRA_USER_NAME=your_name
```

## index.js
```js
#!/usr/bin/env node

import { runStartCommand } from "./lib/start.js";
import { fetchTodayTasks } from "./lib/jira.js";

const command = process.argv[2];

switch (command) {
    case "start":
        runStartCommand();
        break;
    // 前回作成した"start"の下に新しく"jira"を作成する。
    case "jira":
        const subcommand = process.argv[3];
        if (subcommand === "today") {
        fetchTodayTasks();
        } else {
        console.log("🔍 使い方: wrk jira today");
        }
        break;
    default:
        console.log("❓ 未知のコマンドです。例: wrk start");
}
```

## 実行結果
```
% wrk jira today
📋 [username] の今日のJiraタスク一覧（2025-03-27）

🚧 進行中 SCRUM-7 | 環境構築
```
これで、jiraからタスクを取得することができるようになりました！

![スクリーンショット 2025-03-27 11.00.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3582240/79bffa4e-c5b0-4d5b-9860-e9cd17054d4a.png)

ちなみに、jiraでは以上のように表示されています。
進行中となっている「環境構築」（SCRUM-7）だけが取得できていることがわかります。


## まとめ
今回はJiraのAPIを使用してTaskを取得する処理を作成してみました！JiraのAPIを使ったのは初めてでしたが、応用すればもっといろんなことができるので、上手く使えばかなり業務効率化に使えそうだなと思いました。
また色々試してみようと思います✨