はじめに
日常生活でGASとLineBotを連携したサービスを使っていますが、更新のたびにソースコードをローカルからプッシュしWeb上でデプロイをかけていました。
これが面倒だと感じてきたのでせっかくだし特に調べもせず自動化をしようと思い立ち自動化をすることにしました。
結論から言うとタイトルの通りデプロイごとに存在するIDを指定して更新する形をとることにしました。
最初の目論見
当初は以下のような順序で考えていました。
- とりあえずざっくりGitHubActionsを利用して更新をかけたらいいのではないか
- 更新をかけると新しくデプロイのURLが発行されてこれをMesseging APIのwebhookに登録するのは面倒だ
- Proxyプロジェクトを作成してこのProxyのURLだけwebhookに登録してProxy側の変数にbot側のURLを埋め込めばいいのでは
- (IDを指定して更新できることを知らなかったため)
とりあえず実装
甘い考えでとりあえず実装を進めてみることにしました。
proxy側にパラメータとしてnewUrlというパラメータを用意し、この値をpropertiesに登録するような形にしてみました。
proxyの実装
function doPost(e) {
const props = PropertiesService.getScriptProperties();
if (e.parameter.newUrl) {
props.setProperty('ACTIVE_DEPLOY_URL', e.parameter.newUrl);
return ContentService.createTextOutput("Proxy target updated to: " + e.parameter.newUrl);
}
const activeUrl = props.getProperty('ACTIVE_DEPLOY_URL');
if (!activeUrl) return ContentService.createTextOutput("Error: No URL set.");
// LINEからのWebhook転送
const contents = (e.postData && e.postData.contents) ? e.postData.contents : "{}";
const response = UrlFetchApp.fetch(activeUrl, {
method: 'post',
contentType: 'application/json',
payload: contents,
muteHttpExceptions: true
});
return ContentService.createTextOutput(response.getContentText()).setMimeType(ContentService.MimeType.TEXT);
}
ぶつかった壁
デプロイをしながら検証をしていたところデプロイの上限にあたりました。
どうやら20個がリミットのようでした。
デプロイ上限のことを考えるのが面倒だなぁと思い世の中はどうしているのかと調べてみるとidを指定して更新することができるということを知りました。
強引にやらずにまずは調べるということはやっぱり大事なんですね。
実装方針を変更して再実装
idを更新するだけなら構成は非常にシンプルになります。
webhookとして登録しているurlのデプロイIDを指定して実行すればよいだけでした。
それに合わせてGitHubActionsのymlを書きました。
自動デプロイ用のyml
name: Deploy Bot
on:
push:
branches: [ main ]
jobs:
deploy:
runs-on: ubuntu-latest
env:
CLASP_CREDENTIALS: ${{ secrets.CLASP_CREDENTIALS }}
steps:
- uses: actions/checkout@v5
- uses: actions/setup-node@v5
with: { node-version: '24' }
- run: npm install -g @google/clasp
- run: echo $CLASP_CREDENTIALS | base64 --decode > ~/.clasprc.json
- name: Deploy to GAS
run: |
# ビルド&デプロイ
npm ci
npm run build
sed -i 's/export //g' budget_book.js
clasp push -f
# 固定IDを指定して更新
clasp deploy -i ${{ secrets.BOT_DEPLOY_ID }}
ほかの方のを見るとclaspの認証情報をそれぞれ丁寧に保存していたりしたのですが、手間だなぁと感じたので
base64 -w 0 ~/.clasprc.json
という形で丸っとエンコーディングしてしまいGitHubActions内でデコードするようにしました。
暗号化はせずデータ形式のみ変更した形です。
セキュリティを考えるとちゃんと暗号化(KMSを使うなど)したほうが良いと思うのですがやりたいことに対して仰々しすぎるかなと思いエンコーディングだけにしてしまっています。
あと特筆すべき点があるとすれば、
- tscでビルドするとjsにexportがついてpushできないのでsedで無理やりexportをとった
- GASはグローバルスコープで関数を呼び出す必要があるらしくexportがあるとダメ見たいです
- clasp push にフォースプッシュのオプションを付けた
- どうも差分を検知しないようなので…
まとめ
あれこれ考えてproxyという形をとろうとしましたが結果的には不要な仕組みとなりました。
まだまだ取り回しが微妙なところは多々ありますが、一旦自動でデプロイできるようになったため以前と比べると改善が楽になったと思っています。
追加で気になっていること
webhookが全員に公開していないとLineから連携できないことも気になっています。
URLさえ知っていればリクエストは投げられる状態になっているのはやや微妙な気もしました。
特にproxyを挟んで今回の浅い目論見であるような更新手段をとる場合悪意のある更新もできてしまうんだろうなと。
headerを見るようにするような感じでパラメータとして特定の文字列を渡すようにしたり、LINE公式が提供している署名検証(X-Line-Signature のチェック)を実装するなど打てる手はいろいろあるのかなと考えています。
それはまた今度書いてみようと思います。