GASをgit管理してうまくやる
Google謹製のClaspでgit管理
公式のreadmeを見ながら設定まわり
とりあえずnpmでグローバルにインストール
$ npm install -g @google/clasp
loginする
$ clasp login
提示されたURLからログインすると、ホームディレクトリに .clasprc.json
が生成される
Claspをwrapしているasideというのがあるので、そちらに乗り換え
これはGoogleAppsScript向けの型定義をちゃんと調べねばならなさそう。
doPostのeventですらこう
const doPost = (e: GoogleAppsScript.Events.DoPost) => { /** hogePiyo */ }
Slack App側で設定しておくところ
上記の作成したアプリ内で設定。どちらもFeatures内。- Event Subscriptions
Slackのイベント(投稿、ユーザ作成、チャンネル作成など)を送ってもらうURLの設定 - Incoming Webhooks
Add New Webhooks to WorkspaceってとこでSlackにつぶやくためのWebhook URLがある
Apps Scriptのドキュメント。doGetだけどeventの戻り値の例がある
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のドキュメントがあったのでこれで
で、これに対して何を返せばいいかはこちら
レスポンスでオウム返しすればよいっぽいContentService.createTextOutput(params.challenge);
これが何を返しているかだが、ContentServiceクラスはGASのクラス。似てるものにHtmlServiceもある。
ただ、今回だとJSONを返してもよいっぽいのでJSONを返す。
JSONで返す参考
二転三転してplaneテキストを返すように。あとe.parametersの挙動があまりよくなさそう。どこかでlogを表示したい。Logger.logではGASの実行からは確認できなかった。スプシーに吐き出そうかな
コンパイル時に至るとこにライセンスつけてきよるのでlicense-config.jsonでignore
↓参考
コンパイル時にdoPostとかは使ってないのに書くんじゃねぇとeslintに怒られるので回避
一旦はアンダーバーを不可した場合無視とした
上記、GASでは_doPostではPOST時にフックしなかったので、doPostに戻す。
代わりにeslintの設定を一瞬相殺するコメントを使う
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const doPost = (e) => { /** 処理 */ }
Could not read API credentials. Are you logged in globally?
npm run deployで上記。多分プロジェクト直下にしか .clasprcが無いからと思われる
homeにも.clasprcを置く
doPostだけ置いておくと使われていないfunctionだと怒られるので、eslintの除外用にコメントを置く
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const doPost = (e: GoogleAppsScript.Events.DoPost) => { /** 処理 */ }
Github Actions でデプロイ にpushする参考
デプロイについてはこちらが参考になりそう
GASはデプロイの度にIDが変わるので、IDを変えずにデプロイするためにオプション付きでdeployする必要がある
$ clasp deploy --deploymentId <ここにデプロイID>
このデプロイIDについてはSecretsにいれておいてActionsでCDするようにできるかも。
Slackでイベントがあった時、Event Subscriptionで設定したURLに送られてくるデータ仕様はこれ?っぽい
ログを吐かせるときにスプシーに吐かせるのがよさそう。
以下、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()]);
Geminiにコードを吐かせたらApps Scriptのライブラリ(UrlFetchApp)とかを使うときに一旦anyで定義して回避しておくハックを出してきた
追記: 自分で導入したライブラリも行けるらしい。スクレイピング用のCheerioとか。
// Apps Scriptライブラリから提供されるグローバル変数をTypeScript用に宣言しておくと、
// 型チェックや開発時のオートコンプリートの恩恵を受けやすくなります。
// @types/cheerio のような型定義ファイルが適切に設定されていれば不要な場合もありますが、
// Apps Scriptのグローバルライブラリに対しては 'any' 型で宣言するのが安全な場合があります。
declare const Cheerio: any; // Cheerioライブラリ用の型宣言
declare const UrlFetchApp: any; // UrlFetchAppはApps Scriptの組み込みサービス
追記: UrlFetchAppはaside導入時に入る? @types/google-apps-script
google-apps-script.url-fetch.d.ts
ですでに詳細の定義があるっぽい
今日時点でのpackage.jsonのdependenciesは "@types/google-apps-script": "^1.0.97",
ライブラリを導入した場合、aside(clasp)の自動デプロイで消滅することがあるので、appsscript.jsonで定義しておく。
以下、CheerioとParserの例
versionについてはわからなかったのでGASでライブラリを検索したあと最新のものを拾って入れた。
{
"timeZone": "Asia/Tokyo",
"dependencies": {
"libraries": [
{
"userSymbol": "Cheerio",
"version": "16",
"libraryId": "1ReeQ6WO8kKNxoaA_O0XEQ589cIrRvEBA9qcWpNqdOP17i47u6N9M5Xh0",
"developmentMode": true
},
{
"userSymbol": "Parser",
"version": "8",
"libraryId": "1Mc8BthYthXx6CoIz90-JiSzSafVnT6U3t0z_W3hLTAX5ek4w0G_EIrNw",
"developmentMode": true
}
]
},
"exceptionLogging": "STACKDRIVER",
"runtimeVersion": "V8"
}