※このストーリーは、noteで発信した記事を転載しています。
株式会社カンリー、エンジニア部の小泉です。 2023年1月中旬ごろに入社し、現在カンリー開発の保守を担当しています。 現在カンリー開発チームでは
タスク管理→Backlog コミュニケーションツール→Slack 社内ドキュメント→Google Document、Notion を使用しています。 今回はこの3つのアプリを連携し他チームの業務の効率化に取り組んだので、そのナレッジを共有したいと思います。
目次 連携ってなに?どうやるの? 手順 0. 環境 1. backlogのAPI利用準備 2. google formの準備 3. SlackAPI利用準備 4. Slackのチャンネル情報の取得 5. Google App Scriptコーディング さいごに 連携ってなに?どうやるの? さて、「3つのアプリを連携し、他チームの業務改善に取り組んだ」と書きましたが、もう少し詳しく見ていきましょう。
具体的な流れは「 Google Formを送信すると、その内容で自動的にBacklogの課題が新規作成され、Slackに課題が作成されたことを投稿する 」ことです。 これらを実現するためにGoogle App Script(以降、GAS)を使って、BacklogとSlackのそれぞれのAPIにリクエストを送ります。
手順 0. 環境 PC: MacBook Pro(16インチ、2021) チップ: Apple M1 Pro メモリ: 16 GB OS: macOS Monterey 12.5
1. backlogのAPI利用準備 まずはBacklogのAPIを利用する準備から始めていきます。 Backlogのアカウント登録、プロジェクト作成はしてある前提なので、まだの場合は作成してから次に進んでください。 1-1. 個人アクセストークンを取得 APIを利用する際には、個人アクセストークンが必要なので取得します。
右上の自分のアイコンをクリックし、さらに個人設定をクリック ↓
↓
↓
アクセストークンを発行 発行したトークンは次から使うのでどこかにメモしておきましょう。
1-2. 新規課題作成時に必要な情報を取得 Backlog上に課題を作成するEPにリクエストする際には、必須となる項目があるので、早速アクセストークンを使ってそれらの情報を取得していきます。
1. projectId ( 課題を登録するプロジェクトの ID ) 2. issueTypeId ( 課題の種別の ID ) 3. priorityId ( 課題の優先度の ID ) 1. projectId ( 課題を登録するプロジェクトの ID ) 2. issueTypeId ( 課題の種別の ID ) 3. priorityId ( 課題の優先度の ID )
copy
BacklogAPIへのリクエストはApiKeyでの認証となります。
リクエストパラメーターにユーザーごとに発行された API キーを付加して認証する方式です。 リソースへのアクセス時に、発行された API キーをパラメータ名 “apiKey” として付加することで認証が行えます。 リクエスト例 < https : / / xx . backlog . jp / api / v2 / users / myself ? apiKey = abcdefghijklmn > URL がbacklog . comの場合は次のようになります。 < https : / / xx . backlog . com / api / v2 / users / myself ? apiKey = abcdefghijklmn > 参照) [ < https : / / developer . nulab . com / ja / docs / backlog / auth / # > ] ( < https : / / developer . nulab . com / ja / docs / backlog / auth / # > ) リクエストパラメーターにユーザーごとに発行された API キーを付加して認証する方式です。 リソースへのアクセス時に、発行された API キーをパラメータ名 “apiKey” として付加することで認証が行えます。 リクエスト例 < https : / / xx . backlog . jp / api / v2 / users / myself ? apiKey = abcdefghijklmn > URL がbacklog . comの場合は次のようになります。 < https : / / xx . backlog . com / api / v2 / users / myself ? apiKey = abcdefghijklmn > 参照) [ < https : / / developer . nulab . com / ja / docs / backlog / auth / # > ] ( < https : / / developer . nulab . com / ja / docs / backlog / auth / # > )
copy
これに倣って、3つのIDを取得していきましょう。 今回はAPIにリクエストを送る際には、PostManなどのツールではなく、ターミナルからcurlコマンドを叩いてみます。その際、レスポンスのjsonが見やすいようにjqというツールを入れています。
1.projectId {}の中身は適宜書き換えてください
curl https : / / { xx . backlog . com } / api / v2 / projects\\ ? apiKey = { abcdefghijklmn } | jq curl https : / / { xx . backlog . com } / api / v2 / projects\\ ? apiKey = { abcdefghijklmn } | jq
copy
2.issueTypeId 1で取得したprojectIdを使用していきます。 {}の中身は適宜書き換えてください
curl https : / / { xx . backlog . com } / api / v2 / projects / { 1 で取得したprojectId } / issueTypes\\ ? apiKey = { abcdefghijklmn } | jq curl https : / / { xx . backlog . com } / api / v2 / projects / { 1 で取得したprojectId } / issueTypes\\ ? apiKey = { abcdefghijklmn } | jq
copy
3.priorityId {}の中身は適宜書き換えてください
curl https : / / { xx . backlog . com } / api / v2 / priorities\\ ? apiKey = { abcdefghijklmn } | jq curl https : / / { xx . backlog . com } / api / v2 / priorities\\ ? apiKey = { abcdefghijklmn } | jq
copy
2. google formの準備 次に、GoogleFormを新規作成します。Backlogに連携する内容を入力してもらいます。
ここには、backlogに登録したい タイトル 、 詳細 を入力します。 Backlogの画面上でいうと以下の場所です。
3. SlackAPI利用準備 3-1.アプリの作成 Slack APIのページにアクセスし、「Create an App」をクリックします(すでに作成済みの場合は、右上に表示される「Create New App」)。
アプリの作成方法を選びます。 From an app manifest をクリックすると、アプリの構成を YAML 形式で記述できるようですが今回は「From Scratch」を選択。
「アプリ名(App Name)」と「利用するSlackワークスペース名(Development Slack Workspace」を入力し、「Create App」ボタンをクリックします。
これでSlackAPIで利用するアプリの作成ができました。
3-2. 必要な権限を付与する 左側の OAuth & Permissions をクリックします。
下の方にスクロールすると、Scopesという欄があるので、そこで権限を付与していきます。
User Token Scopesの「 Add an OAuth Scope 」というボタンをクリックします。
投稿するときにchat.postMessageというEP、 BacklogにSlackのURLを記載する際にchat.getPermalinkというEP を使用するため chat:write を登録します。
次に、ワークスペースにアプリをインストールします。 ページの1番上に戻り、「 Install to Workspace 」をクリックしてください。
すると、 Slack の連携確認画面へ遷移するので、「許可する」ボタンを押してください。
これで連携が完了し、 User OAuth Token が発行されています。 これは後ほど GASで使用しますので、どこかにコピーしておきましょう。
4. Slackのチャンネル情報の取得 次に、課題作成時の投稿をするチャンネルと、エラーが起きた時の通知をするチャンネルを準備し、それらの情報を取得します。 チャンネルが作成できたら、それぞれのチャンネルIDを取得します。 作成したチャンネル名の上に移動し、右クリックします。 すると「チャンネル詳細を表示する」という項目があるのでそこを選択します。
一番下にチャンネルIDが表示されるのでそちらをメモしておきます。
5. Google App Scriptコーディング さて、ここまで来てやっと準備が整いました。 GASにコードを書いて、BacklogのAPIとSlackのAPIと連携していきます。
5-1. GASを開く 2で作成したGoogle formの編集画面を開き、右端の 3つの丸のボタン をクリックすると、 スクリプトエディタ という項目があるのでそこを開きます。
すると、このような画面になるので、ここにコードを書いていきます。
5-2. Google Formから値を取得する
function handle ( e ) { const form_items = ( e !== undefined ) ? e . response : FormApp . getActiveForm ( ) . getResponses ( ) [ 0 ] ; const items = form_items . getItemResponses ( ) ; } function handle ( e ) { const form_items = ( e !== undefined ) ? e . response : FormApp . getActiveForm ( ) . getResponses ( ) [ 0 ] ; const items = form_items . getItemResponses ( ) ; }
copy
form_itemsに三項演算子を使っているのは、FormApp.getActiveForm().getResponses()[0] はデバッグ時にすでに入力された過去のデーターを参照する時のために設定しています。 5-3. BacklogAPIにリクエストする 各種ID、URL、apiKeyは取得したものに書き換えてください。
var canlyDevelopmentProjectId = "xxxxxxxxxx" ; var reportIssueTypeId = "xxxxxxxxxx" ; var defaultPriorityId = "xx" ; var backlogBaseUrl = "<https://xxxxx.backlog.com/api/>" ; var backlogApiKey = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" ; function handle ( e ) { : : var title = '' ; for ( let i = 0 ; i < items . length ; i ++ ) { if ( items [ i ] . getItem ( ) . getTitle ( ) == 'タイトル' ) { title = items [ i ] . getResponse ( ) ; break ; } } const createIssueUrl = ` ${ backlogBaseUrl } v2/issues?apiKey= ${ backlogApiKey } ` ; const data = { "projectId" : canlyDevelopmentProjectId , "summary" : title , "issueTypeId" : reportIssueTypeId , "priorityId" : defaultPriorityId , } ; const createIssueOptions = { "method" : "post" , "contentType" : "application/x-www-form-urlencoded" , "muteHttpExceptions" : true , "payload" : data } ; const backlogResponse = UrlFetchApp . fetch ( createIssueUrl , createIssueOptions ) ; const parsedBacklogResponse = JSON . parse ( backlogResponse ) ; } var canlyDevelopmentProjectId = "xxxxxxxxxx" ; var reportIssueTypeId = "xxxxxxxxxx" ; var defaultPriorityId = "xx" ; var backlogBaseUrl = "<https://xxxxx.backlog.com/api/>" ; var backlogApiKey = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" ; function handle ( e ) { : : var title = '' ; for ( let i = 0 ; i < items . length ; i ++ ) { if ( items [ i ] . getItem ( ) . getTitle ( ) == 'タイトル' ) { title = items [ i ] . getResponse ( ) ; break ; } } const createIssueUrl = ` ${ backlogBaseUrl } v2/issues?apiKey= ${ backlogApiKey } ` ; const data = { "projectId" : canlyDevelopmentProjectId , "summary" : title , "issueTypeId" : reportIssueTypeId , "priorityId" : defaultPriorityId , } ; const createIssueOptions = { "method" : "post" , "contentType" : "application/x-www-form-urlencoded" , "muteHttpExceptions" : true , "payload" : data } ; const backlogResponse = UrlFetchApp . fetch ( createIssueUrl , createIssueOptions ) ; const parsedBacklogResponse = JSON . parse ( backlogResponse ) ; }
copy
5-4. Slack APIにリクエストする こちらもアクセストークンやチャンネルIDは取得したものに書き換えてください。
: : var slackUrl = "<https://slack.com/api/>" ; var slackAccessToken = 'xoxp-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' ; var noticeErrorsChannel = "xxxxxx" ; var reportChannel = "xxxxxx" ; function handle ( e ) { : : const postSlackUrl = slackUrl + "chat.postMessage" ; const slackHeader = { 'Authorization' : 'Bearer ' + slackAccessToken } ; const payload = { "channel" : reportChannel , "text" : ` チケットを新規作成しました。\\ \\nタイトル: ${ parsedBacklogResponse [ "summary" ] } \\ \\nURL: ${ backlogUrl } \\ \\nご確認よろしくお願いします! ` , "unfurl_links" : true , "as_user" : true } ; const postSlackOptions = { 'method' : "post" , 'headers' : slackHeader , 'payload' : payload } ; const postSlackMessageResponse = UrlFetchApp . fetch ( postSlackUrl , postSlackOptions ) ; const parsedSlackMessageResponse = JSON . parse ( postSlackMessageResponse ) ; } : : var slackUrl = "<https://slack.com/api/>" ; var slackAccessToken = 'xoxp-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' ; var noticeErrorsChannel = "xxxxxx" ; var reportChannel = "xxxxxx" ; function handle ( e ) { : : const postSlackUrl = slackUrl + "chat.postMessage" ; const slackHeader = { 'Authorization' : 'Bearer ' + slackAccessToken } ; const payload = { "channel" : reportChannel , "text" : ` チケットを新規作成しました。\\ \\nタイトル: ${ parsedBacklogResponse [ "summary" ] } \\ \\nURL: ${ backlogUrl } \\ \\nご確認よろしくお願いします! ` , "unfurl_links" : true , "as_user" : true } ; const postSlackOptions = { 'method' : "post" , 'headers' : slackHeader , 'payload' : payload } ; const postSlackMessageResponse = UrlFetchApp . fetch ( postSlackUrl , postSlackOptions ) ; const parsedSlackMessageResponse = JSON . parse ( postSlackMessageResponse ) ; }
copy
このようにAPIを叩き、Slackのリンク取得とBacklogの課題の更新もしていきます。
コードを書き終えたら、左上の「保存」ボタンを押します。
5-5. トリガーを設定する Google Formを送信した時にhandleメソッドが動くように設定します。
左横の「トリガー」をクリックします。
「+トリガーを追加」ボタンを押し、そのまま「保存」ボタンを押します。
トリガーができていたら、完成です。
これでGoogle formとBacklog、Slackの連携できました🎉
さいごに 今回はGASを使ってGoogleのツールとAPIを公開してるサービスを連携して、他チームの業務の効率化をしてみました。 この記事には載せられなかったですがPostManを使ってAPIにリクエストすることで、より簡単に連携ができると思います。 Google Formで作成するまでは「Backlogに課題を新規作成」→「Slackに課題を作成したことを投稿」→「BacklogにSlackのURLを追記」という3ステップが必要だったのが、「Google Formを送信する」という1ステップになり、実際に使ってみた人からも「手間が減りました、ありがとうございます!」といった声を聞きました。 ぜひいろんなサービスを使って、自分も周りもよりよい環境で仕事ができるように整えていきましょう!
株式会社カンリーでは一緒に働く仲間を募集しています!カンリーのバリューに共感できる方、ちょっと話を聞いてみたいという方、ぜひご応募ください!