Open13

GASをgit管理してうまくやる

oratakeoratake

公式のreadmeを見ながら設定まわり

とりあえずnpmでグローバルにインストール

$ npm install -g @google/clasp

loginする

$ clasp login

提示されたURLからログインすると、ホームディレクトリに .clasprc.json が生成される

oratakeoratake

Claspをwrapしているasideというのがあるので、そちらに乗り換え
https://github.com/google/aside
デフォでTSになっていたり、Jestのテストが入っていたりとモリモリになっている。
これはGoogleAppsScript向けの型定義をちゃんと調べねばならなさそう。
doPostのeventですらこう

const doPost = (e: GoogleAppsScript.Events.DoPost) => { /** hogePiyo */ }
oratakeoratake

Slack App側で設定しておくところ
https://api.slack.com/apps/
上記の作成したアプリ内で設定。どちらもFeatures内。

  • Event Subscriptions
    Slackのイベント(投稿、ユーザ作成、チャンネル作成など)を送ってもらうURLの設定
  • Incoming Webhooks
    Add New Webhooks to WorkspaceってとこでSlackにつぶやくためのWebhook URLがある
oratakeoratake

doPostでSlackのeventを受けるとき

最初にSlackのEvent Subscriptionが本当に所有しているかの確認のためにchallengeリクエストを飛ばすので、それの反応をさせる

const doPost = (e: GoogleAppsScript.Events.DoPost) => {
  const params = e.parameters;

  // SlackのEvent SubscriptionsでURL確認のためのリクエスト用
  if('challenge' in params){
    return ContentService.createTextOutput(params.challenge);
  }
  // 省略...

とおもったらparamsの型で.challengeとかねぇぞって怒られたので、
slack apiとかの型定義っぽいものを入れてみる。本当にこれであってるかは不明

$ npm i -D @slack/web-api @slack/webhook

型についてはslackのsdkのドキュメントがあったのでこれで
https://slack.dev/node-slack-sdk/typescript

で、これに対して何を返せばいいかはこちら
https://api.slack.com/apis/connections/events-api#challenge
レスポンスでオウム返しすればよいっぽい

ContentService.createTextOutput(params.challenge);
これが何を返しているかだが、ContentServiceクラスはGASのクラス。似てるものにHtmlServiceもある。
https://iwb.jp/google-apps-script-contentservice-htmlservice/
ただ、今回だとJSONを返してもよいっぽいのでJSONを返す。
JSONで返す参考
https://qiita.com/tfuruya/items/3c306ee03d1ac290bcef

二転三転してplaneテキストを返すように。あとe.parametersの挙動があまりよくなさそう。どこかでlogを表示したい。Logger.logではGASの実行からは確認できなかった。スプシーに吐き出そうかな
https://zenn.dev/shuuuuuun/articles/9de830ec37de30

oratakeoratake

コンパイル時にdoPostとかは使ってないのに書くんじゃねぇとeslintに怒られるので回避
一旦はアンダーバーを不可した場合無視とした
https://madogiwa0124.hatenablog.com/entry/2022/05/07/154628

上記、GASでは_doPostではPOST時にフックしなかったので、doPostに戻す。
代わりにeslintの設定を一瞬相殺するコメントを使う

// eslint-disable-next-line @typescript-eslint/no-unused-vars
const doPost = (e) => { /** 処理 */ }
oratakeoratake

Could not read API credentials. Are you logged in globally?

npm run deployで上記。多分プロジェクト直下にしか .clasprcが無いからと思われる
homeにも.clasprcを置く

oratakeoratake

doPostだけ置いておくと使われていないfunctionだと怒られるので、eslintの除外用にコメントを置く

// eslint-disable-next-line @typescript-eslint/no-unused-vars
const doPost = (e: GoogleAppsScript.Events.DoPost) => { /** 処理 */ }
oratakeoratake

Github Actions でデプロイ にpushする参考
https://zenn.dev/yumechi/articles/5dd115924f81bc

デプロイについてはこちらが参考になりそう
GASはデプロイの度にIDが変わるので、IDを変えずにデプロイするためにオプション付きでdeployする必要がある
https://www.aruse.net/entry/2022/10/09/130019

$ clasp deploy --deploymentId <ここにデプロイID>

このデプロイIDについてはSecretsにいれておいてActionsでCDするようにできるかも。

oratakeoratake

ログを吐かせるときにスプシーに吐かせるのがよさそう。
以下、event_logsというシートにタイムスタンプとLogを吐く場合。
LoggerのgetLog()でそこまでの全ログを吐くっぽい

  // スプシーにログを排出
  let sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('event_logs');
  const timestamp = new Date();
  Logger.log(e.postData.contents);
  sheet.appendRow([timestamp, Logger.getLog()]);

https://developers.google.com/apps-script/reference/base/logger?hl=ja