🐣

GoogleフォームからGithubのissueを立てる(2022/03)

2022/03/18に公開

初めまして。Taroです。表題のようなことをしたのですが、調べても現在の仕様に合致したやり方が出てこなかったので、備忘録がてら残しておきます。

GASをちゃんと使うのは初めてだったので、GAS周りは初心者向けに手取り足取りで書きます。

全体の手順

  1. フォームとレポジトリを用意する
  2. GASを書く
  3. トークンを取得してスクリプトにコピペ
  4. トリガーの設定
  5. 完成!
  6. カスタマイズ
  7. ちょっと解説

1. フォームとレポジトリを用意する

特別なことはないので、やり方は省略します。用意してください。

2. GASを書く

フォームが提出されたときに実行する関数を定義します。
フォーム作成画面の右上からメニューを開き、「スクリプトエディタ」をクリック。
左の歯車をクリックして設定画面を開き、「appsscript.json」マニフェスト ファイルをエディタで表示するにチェックを入れます。
エディタに戻ると、appsscript.jsonが表示されています。oauthScopesという項目に以下の2つを追加してください。

appsscript.json
{
  "oauthScopes": [
    "https://www.googleapis.com/auth/forms",
    "https://www.googleapis.com/auth/script.external_request"
  ],
}

コード.gsに戻り、以下のように書きます。

コード.gs
const TOKEN = 'ここにトークンをコピペ'
const URL = 'https://api.github.com/repos/AccountName/RepositoryName/issues'

function onFormSubmit(e) {
  const answers = e.response.getItemResponses().map(ir => ir.getResponse())

  const options = {
    "method": "post",
    "headers" : {
      "Authorization": "token " + TOKEN, 
      "accept": "application/vnd.github.v3+json"
    },
    "payload" : JSON.stringify({
      "title": 'ここにissueタイトルを書く',
      "body": 'ここにissue本文を書く',
    }),
  }
  const res = UrlFetchApp.fetch(URL, options)
  // Logger.log(res)
}

2行目のconst URL = ...のところは、アカウント名とレポジトリ名をいい感じに書き換えてください。
answersは配列型で、フォームに対する回答が格納されています。これを適当に操作して、issueのタイトルと本文を錬成してください。

3. トークンを取得する

GithubのSettings > Developer settings でトークンを取得します。権限は、repoにチェックを入れればOK。作成時にしか見れないので、忘れずにコピーしてください(忘れた場合は再発行する羽目になります)。これを、GASの1行目に書き込みます。

4. トリガーの設定

フォーム提出時に、さっき作った関数を自動で実行してくれるようにします。
左端のタイマーアイコンをクリックして、トリガーの設定画面を開きます。右下のボタンでトリガーを追加し、

  • 実行する関数を選択: onFormSubmit
  • デプロイ時に実行: Head
  • イベントのソースを選択: フォームから
  • イベントの種類を選択: フォーム送信時

で設定します。エラー通知設定はよくわからんので適当。

5. 完成!

もしかしたら、これでフォームを提出するとエラーを吐くかもしれません。その場合は、エディタ画面で一度「実行」を押す必要があったかもしれないです。たぶん。

6. カスタマイズ

自動でラベルをつけたりassignしたりもできます。その辺は公式ドキュメントを見てください。

7. ちょっと解説

フォームの回答を取得するやつ

コード.gs
const answers = e.response.getItemResponses().map(ir => ir.getResponse())

e.responseFormResposeのインスタンスです(公式リファレンス)。
getItemResponses()ItemResposeの配列を返します。(公式リファレンス)。
ItemResponseは質問一つ一つに相当する情報を持っていて、getItem()で質問を取得したり、getResponse()で回答を取得したりできます。

APIにPOSTするやつ

コード.gs
const res = UrlFetchApp.fetch(URL, options)
// Logger.log(res)
}

UrlFetchAppは、http通信をしてくれるやつ(だと思っている)。どういう仕組みか知りませんが、async awaitとかは要らず、同期関数みたいに扱えます。
Logger.log()は、console.log()みたいなやつです。

Discussion