Backlog の課題に Power Automate の承認を組み込もう

みなさんこんにちわ、りなたむです。  
Backlog は、様々なタスクを効率的に管理できるクラウドサービスです。
使いやすいインターフェースで、しかもタスクの対応を称賛する「スター機能」があったりします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269159/874b1b27-0e68-c991-7582-3a2a0c66ecb5.png)

また、Microsoft には ローコード開発が可能なソリューション、Power Platform があり、その中に、様々なサービスを連携して自動運用する iPaaS、Power Automate があります。

Power Automate には、Microsoft 365 での業務を支援するために様々な機能がありますが、その中に承認機能があります。
この承認機能を使うことで、様々なアクションに対して、上長の承認プロセスを組み込むことができます。

Backlog には、タスクの状態を管理する機能があり、現状のタスクがどのステータスであるかを判断できるようになっていますが、タスクの完了も含めて手動で操作することができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269159/4f029feb-8386-38f5-065f-e2e624f66b15.png)

この状態ステータスが処理済みとなった場合に、特定の人に対して承認を要求し、承認されれば「完了」、そうでなければ「差し戻し」といった機能を実装してみたいと思います。

## 1. Power Automate トリガー の準備

1. Requestコネクタの HTTP要求の受信時トリガーを使用します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269159/46b5b4c1-45f1-3b55-4c2b-74434c0b8c1d.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269159/9e4bf58f-db5e-f2fc-4dfe-6c20736b0d15.png)

2. トリガーできるユーザーを「誰でも」にします
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269159/12a9b8fa-cf40-8c4a-ca52-a41d9ad58049.png)

3. JSONスキーマを以下にします
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269159/de46617c-1b41-39e1-c9ce-6fc057d18a43.png)

```JSON:Schema
{
    "type": "object",
    "properties": {
        "id": {
            "type": "integer"
        },
        "project": {
            "type": "object",
            "properties": {
                "id": {
                    "type": "integer"
                },
                "projectKey": {
                    "type": "string"
                },
                "name": {
                    "type": "string"
                },
                "chartEnabled": {
                    "type": "boolean"
                },
                "subtaskingEnabled": {
                    "type": "boolean"
                },
                "projectLeaderCanEditProjectLeader": {
                    "type": "boolean"
                },
                "useWikiTreeView": {
                    "type": "boolean"
                },
                "textFormattingRule": {
                    "type": "string"
                },
                "archived": {
                    "type": "boolean"
                }
            }
        },
        "type": {
            "type": "integer"
        },
        "content": {
            "type": "object",
            "properties": {
                "id": {
                    "type": "integer"
                },
                "key_id": {
                    "type": "integer"
                },
                "summary": {
                    "type": "string"
                },
                "description": {
                    "type": "string"
                },
                "issueType": {
                    "type": "object",
                    "properties": {
                        "id": {
                            "type": "integer"
                        },
                        "projectId": {
                            "type": "integer"
                        },
                        "name": {
                            "type": "string"
                        },
                        "color": {
                            "type": "string"
                        },
                        "displayOrder": {
                            "type": "integer"
                        }
                    }
                },
                "resolution": {},
                "priority": {
                    "type": "object",
                    "properties": {
                        "id": {
                            "type": "integer"
                        },
                        "name": {
                            "type": "string"
                        }
                    }
                },
                "status": {
                    "type": "object",
                    "properties": {
                        "id": {
                            "type": "integer"
                        },
                        "name": {
                            "type": "string"
                        }
                    }
                },
                "assignee": {},
                "category": {
                    "type": "array"
                },
                "versions": {
                    "type": "array"
                },
                "milestone": {
                    "type": "array"
                },
                "startDate": {},
                "dueDate": {},
                "estimatedHours": {},
                "actualHours": {},
                "parentIssueId": {},
                "customFields": {
                    "type": "array"
                },
                "attachments": {
                    "type": "array"
                },
                "shared_files": {
                    "type": "array"
                },
                "externalFileLinks": {
                    "type": "array"
                },
                "diff": {},
                "comment": {},
                "changes": {
                    "type": "array"
                }
            }
        },
        "notifications": {
            "type": "array"
        },
        "createdUser": {
            "type": "object",
            "properties": {
                "id": {
                    "type": "integer"
                },
                "userId": {},
                "name": {
                    "type": "string"
                },
                "roleType": {
                    "type": "integer"
                },
                "lang": {
                    "type": "string"
                },
                "mailAddress": {},
                "nulabAccount": {
                    "type": "object",
                    "properties": {
                        "nulabId": {
                            "type": "string"
                        },
                        "name": {
                            "type": "string"
                        },
                        "uniqueId": {
                            "type": "string"
                        }
                    }
                }
            }
        },
        "created": {
            "type": "string"
        }
    }
}
```
4.メソッドを POST にします
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269159/f235d903-96b3-3a7d-ad42-09789cb92bf6.png)

5.設定のトリガー条件を以下のようにします
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269159/bdcd7b9f-963b-2fee-f97f-33c1e0149e60.png)
``` @equals(triggerBody()?['content']?['status']?['name'],'処理済み') ```

6.後続のアクションを適当に設定し、いったん保存します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269159/4806ae43-8155-4f3d-459e-4d19fca30c2a.png)

7.HTTP URL が生成されるので、メモ帳に張り付けておきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269159/8b655e23-dcc6-19a5-297f-67bfc03197d2.png)

## 2. Backlog プロジェクトの設定

承認を組み込みたい Backlog プロジェクトの設定を開きます。

### 2.1. 却下時の状態追加

1. 状態から、状態の追加をクリックします
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269159/79ba6c73-7df7-e89b-b683-cd14ce1bc197.png)

2. 新しく状態を登録します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269159/4db331dc-a45e-f0fc-b8cc-b352deb2936d.png)

3. 作成された状態をクリックします
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269159/94d8364a-a9e2-b3b7-19c0-6cc72a0a5432.png)

4. 状態IDをメモしておきます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269159/999ff179-b223-a942-0266-7421bcf99e30.png)

### 2.2. Webhook の設定

課題の更新通知を Power Automate に送る設定を行います

1. インテグレーションから Webhook の設定をクリックします
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269159/42323822-87ae-d21e-499c-ae63b5a48e7f.png)

2. Webhook を追加する をクリックします
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269159/37bc02c2-0eb4-fe4b-f68d-88aa60947c28.png)

3. WebHook URL に Power Automate フローで生成されたURLを張り付けます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269159/dc081342-789a-a5b5-505a-97a1a1ab61f9.png)

4. 課題の更新 にチェックを入れます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269159/f25e04f5-8fea-26e3-b85f-1ae702a7bcb3.png)

5. Webhook を追加するをクリックします
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269159/dd06c184-4dcc-71c4-68b2-2d8a95ab11e6.png)

6. Webhook が追加されます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269159/9122d030-4370-4416-0a1d-d91e59c3e222.png)

## 3. Backlog APIの取得

Power Automate でタスク状態を変更するユーザーの API キーを取得します。

1. ユーザーアイコンから、個人設定をクリックします
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269159/ff0c2319-de30-1e79-2f79-6fe1e2b67845.png)

2. API から メモを入力し、登録をクリックします
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269159/6f6313ca-954d-ba1a-3d6b-c0615a635db2.png)

3. API キーが取得できますので、キーをメモ帳にコピーしておきます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269159/c6c3bf16-aedd-c148-6017-8bd9577d768b.png)

## 4. Power Automate の続き

承認処理を実施し、承認されたときとそうじゃないときとの処理を以下のように作成します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269159/18acfcd4-f405-6161-5555-fa4b63fd8f99.png)

### 4.1. 承認部分

このような設定にします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269159/39074760-4010-f911-4a9c-a0cb08cd9d66.png)

タイトル
```
@{triggerBody()?['project']?['name']} プロジェクト課題終了通知
```

詳細
```
@{triggerBody()?['project']?['name']} プロジェクトの課題 
@{triggerBody()?['content']?['summary']} の状態が 処理済みになりました。    
内容を確認してください。
```

アイテムリンク
```
https://<テナントID>.backlog.com/view/@{triggerBody()?['project']?['projectKey']}-@{triggerBody()?['content']?['key_id']}
```

アイテムリンクの説明
```
@{triggerBody()?['content']?['summary']}
```

### 4.2. True部分

承認された時の動作（状態を完了にする）を設定します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269159/8d61ea7f-fada-6701-7d72-e2dcf3e5cd92.png)


URL
```
https://<テナントID>.backlog.com/api/v2/issues/@{triggerBody()?['project']?['projectKey']}-@{triggerBody()?['content']?['key_id']}
```

Body

```
{
  "statusId": 4
}
```

### 4.3. False部分

却下された時の動作（状態を差し戻しにし、コメントを付記）を設定します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269159/9532f733-3fb6-ed81-a20c-2cfd678ea0d3.png)


URL
```
https://<テナントID>.backlog.com/api/v2/issues/@{triggerBody()?['project']?['projectKey']}-@{triggerBody()?['content']?['key_id']}
```

Body

```
{
  "statusId": <追加した状態ID>,
  "comment": @{items('For_each')?['comments']}
}
```

## 5. 動作確認

実際にタスクを処理済みにすると以下のようになります

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269159/55aab6b8-3715-3c66-8e97-d62b6d91a35f.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269159/63d66611-8249-d1b6-2220-c6f8b7ca53c6.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269159/f3d17722-0285-faa3-1021-9fbaa7f48d09.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269159/a05524a3-dd35-c658-70fd-6a81861ff042.png)

## まとめ

Power Automate と Backlog API を組み合わせることで、より実業務運用に近いカスタマイズを自分たちで行うことができるようになります！
Backlog API 自体も様々な機能があるので、ぜひいろいろ試してみてはいかがでしょうか？