RAS Syndrome

冗長。

GASで何らかのWebhook通知を受け取ってログに書き出すまで

Scrapbox の Slack 通知の中身を調べたかったので、GAS で受け取ってログに吐いてみることにした。
GAS 触るのは初めてだったので色々ハマったり色々調べたりした。以下、分かったこととかをつらつらと。

GAS の種類

Sheets や Docs に紐付いてるパターン(コンテナバウンド)とそうでないパターン(スタンドアローン)がある。
"Google Apps Script" でググって出てきたページから流れで作っていくとスタンドアローンタイプになる。
紐付いてるやつ作りたかったらまず Sheet とかを作って、そこからスクリプトを作成するという手順を踏む必要がある。
特に Sheet は DB みたいに使えるのでよく使いそう。*1

GCP プロジェクト

1 つの GAS には 1 つの GCP(Google Cloud Platform) プロジェクトが必ず紐付いてるもんらしい。
何も考えず作ってると、自動で作られた「デフォルト GCP プロジェクト」に自動で紐付いてる状態になる。
しかしこの状態では使えない機能がいくつかある。それらを使いたければ「スタンダード GCP プロジェクト」に紐付ける必要がある。
「スタンダード GCP プロジェクト」は、GAS ではなく GCP のページを開いて、そこで自分で作ったプロジェクトのことを指すっぽい。
これを作ったら後は GAS 側の設定画面で GCP プロジェクト ID を指定すれば紐付けできる。

……と思いきや、「OAuth 同意画面を設定する必要があります」と怒られて紐付けに失敗してしまった。
仕方ないので、GCP プロジェクトの設定画面から「OAuth 同意画面」という項目を見つけ、よしなに設定していく。
User Type は「内部」と「外部」があるが、「Google Workspace ユーザーではない」とか言われて「内部」は選べなかった。
正直意味を何も理解してないので、選択肢が勝手に限られてくれるのはありがたい。
他の設定項目もよくわからないので全部テキトーに設定したが、これで GAS に紐付けることができるようになり、Cloud Logging 機能(後述)が無事使えるようになった。
どうやら設定した内容は今回使いたい機能(Cloud Logging)と関係無かったっぽい。
なんでこの作業必須なんだろう。

デプロイの種類

スクリプトをデプロイしようとすると、

  • ウェブアプリ
  • 実行可能 API
  • アドオン
  • ライブラリ

の4つの中からデプロイの種類を選べと言われる。

ウェブアプリは doGet(e)doPost(e) という関数を定義しておく必要があるやつ。
それぞれ GET 時や POST 時に実行される。
ちなみにこれらの関数は HTMLOutputTextOutput オブジェクトをリターンする必要がある。(ContentService を使う。)

ライブラリは他のプロジェクトで使うための関数群。
ちなみにライブラリを取り込む際にはスクリプト ID を指定する形式となる。ライブラリを検索できるプラットフォームとかは特にないっぽい。
ちなみにちなみに、ライブラリは取り込むと実行が遅くなってしまうらしい。公式ガイドにわざわざ警告文が書いてあった。あんま使わないほうが良さそう。

公式ガイドから読み取れたのはここまで。
実行可能 API もアドオンも特に説明が見つからない。
なんでなんだ。

実行可能 API が一番わかんない。ウェブアプリとどう違うのか。あと実行不可能な API も果たしてあるのか。
まあ多分だけど、実行可能 API だと doGet(e) とか doPost(e) を動かす感じではなく、トップレベルの関数を名前指定して実行する感じになるっぽい。

アドオンは多分 GMail とか Google Calendar とかでインストールできるやつ。
アドオンストアに登録することになるっぽい。

実行可能 API とアドオンは、前述の「スタンダード GCP プロジェクトへの紐付け」が必要なようだった。

とりあえず今回の「Webhook 通知を受け取ってログに書き出す」という目的に対してはウェブアプリで良さそう。

エディタ画面

デフォルトではコード.gsという 1 ファイルのみがあるが、複数ファイルあっても良いらしい。

デフォルトでは appsscript.json というマニフェストファイルが非表示になっている。
設定で表示させることも可能。
依存ライブラリとかはここで管理されてるっぽい。
まあ自動で管理されてるし、あんま自分で触る必要は無さそう。

エディタにはコードのリストの他に、取り込んでるライブラリのリストとサービスのリストが表示されている。
ライブラリは前述の通り。
サービスは多分 Google が用意してくれてるやつで、他サービスの API 叩くためのやつが多そう。

エディタ画面でコードを書いたらちゃんと保存する必要がある。
ブラウザ上のエディタって自動保存されるパターンが多いので、この仕様に気付くまでかなり時間かかったし、知った今でも油断すると忘れる。
せめてデプロイ時ぐらいは自動保存とか、あるいは「保存されていないコードをデプロイしようとしています。よろしいですか?」って警告ぐらいはしてほしい。
ちなみに command + S みたいなショートカットは使える。

ロガー

ログ出力には consoleLogger の 2 種類がある。
特に出力先とかが変わるわけではなさそう。
undefined を渡した時に後者は null って出力してきた。怪しげ。

console には log, info, warn, error とかがある。
console.log の severity は DEBUG。
一方で Logger にあるログ出力関数は log のみで、severity は INFO。
かわりに Logger の方には getLog とかがある。

console の方は GAS じゃない JavaScript とも互換性ありそうだし、こっちの方が良さそう。

コード

function doPost(e) {
  console.info('post data type:', e.postData.type);
  console.info('post data:', e.postData.contents);
  
  var output = ContentService.createTextOutput('received POST');
  return output;
}

とりあえずこれで動いたしログも見れた。
postData.typeMIME のこと。

追記:const 使ってよかったらしい。
現在のGoogle Apps Scriptはアロー関数やlet, constが使用可能に | iwb.jp

デプロイ設定

デプロイの種類「ウェブアプリ」を指定したら、具体的な設定をいくつか求められる。

「次のユーザーとして実行」については「自分」か「ウェブアプリケーションにアクセスしているユーザー」を選べる。
後者だと Google アカウント持ってる人がブラウザで叩かないと動かない気がする。

「アクセスできるユーザー」については「自分のみ」か「Google アカウントをもつ全員」か「全員」を選べる。
今回はやはり「全員」じゃないとダメそう。

「説明」はデプロイバージョンのタイトルに使用されてるので、変更内容についての説明が求められてる気がする。

変更があれば都度、「新しいデプロイ」を選んでデプロイし直す。
URL は変わらない。
「デプロイを管理」で過去のデプロイ履歴が見れる。
「デプロイを管理」で最新のデプロイ設定を変更できるが、変更して「デプロイ」を押しても全く反映されなかった。もちろん設定だけじゃなく、コードの変更も反映されない。これ何のためにあるんだ。謎。

マルチアカウントで運用している際の罠

デプロイした URL にアクセスしてみると、「ファイルを開くことができません。」と表示された。
調べてみると原因は、「デフォルトの Google アカウント」でデプロイしなかったかららしい。
どうやら 1 番目にログインしたアカウントがデフォルトになるらしい。
デフォルトを変えるには他のアカウントをログアウトさせるしかないっぽい。
クソめんどくさい。
とりあえず GAS 書く時は普段使ってないブラウザを使い、1 アカウントだけでログインすることにした。

叩き方

curl の際には -L--location)(Follow redirects)をつける必要がある。

ログを見る

ログには Apps Script execution log と Cloud Logging(と Error Reports)があるらしい。
前者はちょっとの間残る、後者は結構な日数残る、らしい。
また、後者は GCP プロジェクトで見るもののようで、前述の「スタンダード GCP プロジェクトへの紐付け」が必要になる。
出力の仕方はどちらも変わらず。前述のように Loggerconsole を使えば良い。
閲覧インターフェースが 2 種類あるって感じだろうか。

ちょっとした関数をエディタ上でデバッグ実行してみると、exectuion log の方でログを見ることができた。
しかし、実際にデプロイしたウェブアプリの doPost(e) 内で吐かせたログは、 execution log ではなぜだか見れなかった。
しょうがないので、スタンダード GCP プロジェクトへの紐づけを済ませ、Cloud Logging の方で確認したら見れた。

ローカル開発

「GAS のコードはクラウド上にあるから、git で管理したりとかできなくて嫌だな〜」とずっと思っていた。
しかしどうやら Apps Script API という口があって、ローカルで書いたコードもこの API を通してデプロイしたりできる様子。
んでもって、その辺をよしなにやってくれる clasp というコマンドツールがあるらしい。
次からはローカルで開発し、GitHub 上でちゃんとソースを管理しつつ、clasp でデプロイ、みたいな流れで書きたいなぁ。

おわり。

*1:データ保存に関しては Properties Service という機能もあってキー・バリュー式にデータを管理できる。この場合にどれぐらい永続してくれるかはよく分からない。