GASのコードをローカルで管理する。claspで「エディタを開かずに更新」する運用

エディタで直接書き換えるのが怖くなってきた
Google Apps Scriptのコードは、ブラウザのエディタで書きます。最初はそれで何の問題もありませんでした。
困りはじめたのは、1つのプロジェクトが育ってきてからです。
うちの社内通知用のプロジェクトは、ファイルが3つに増えました。お弁当の発注アプリ用、音声記録の受け取り用、そして共通の通知部分。ウェブアプリとしてのデプロイも2つあります。
この状態でエディタの画面で直接コードを書き換えるというのは、なかなかスリルがあります。
- 保存した瞬間に反映されるので、書きかけで保存すると壊れる
- 1つ前の状態に戻したくても、履歴は残っていない
- バックアップは「コードを全選択してテキストファイルに貼る」という原始的な方法
- デプロイが2つあるので、片方だけ更新して気づかない
特に最後のものは厄介です。コードは直したのに、片方のデプロイが古いままで動き続けるということが起きます。しかもエラーは出ないので、気づくのが遅れます。

claspを使うと、ローカルのフォルダが本体になる
claspはGoogleが出しているコマンドラインツールです。できることは単純で、Apps Scriptのコードをパソコンのフォルダに落としてきて、書き換えて、また送り返す。これだけです。
この「フォルダで管理できる」というのが大きい。
- いつものエディタやメモ帳でコードを書ける
- フォルダごとコピーすればバックアップになる
- Googleドライブの中に置けば、勝手に世代管理もされる
- 書き終わるまで反映されないので、書きかけで壊れない
フォルダをGoogleドライブの中に置いておけば、PCが壊れてもコードは残ります。

GASでは「.gs」だったファイルが「.js」になっていますが、これはclaspの仕様です。送り返すときに自動で戻るので、気にしなくて大丈夫です。
準備:スクリプトIDを調べてログインする
必要なのはNode.jsだけです。入っていなければ公式サイトからインストールしてください。
スクリプトIDを調べる
GASエディタの左下にある歯車アイコン、「プロジェクトの設定」を開きます。「スクリプト ID」という項目があるので、これをコピーします。

setup.batを作る
毎回コマンドを打つのは面倒なので、バットファイルにしています。フォルダの中に setup.bat という名前で、以下の内容を保存してください。
@echo off
chcp 65001 > nul
cd /d %~dp0
set CLASP=npx -y @google/clasp@2.4.2
set /p SID=スクリプトIDを貼り付けてEnter:
echo.
echo ブラウザが開きます。GASを使っているGoogleアカウントを選んで許可してください。
call %CLASP% login
echo { "scriptId": "%SID%" } > .clasp.json
call %CLASP% pull
echo.
echo 完了しました
pause
ダブルクリックするとスクリプトIDを聞かれるので貼り付け、ブラウザが開いたらアカウントを選んで許可。これでフォルダにコードが落ちてきます。

許可が終わると、ブラウザに「Logged in! You may close this page.」と出ます。「ログインできたので閉じてOK」という意味なので、そのタブは閉じて構いません。

バージョンを固定しているのはなぜか
コマンドの中で @google/clasp@2.4.2 とバージョンを指定しています。
npx は何も指定しないと毎回その時点の最新版を取りに行きます。便利そうに見えますが、ある日突然コマンドの挙動が変わって動かなくなることがある。業務で使うものなので、動いているバージョンに固定しておくほうが安心です。
日々の更新:deploy.batを叩くだけ
コードを直したあと、これを実行します。
@echo off
chcp 65001 > nul
cd /d %~dp0
set CLASP=npx -y @google/clasp@2.4.2
echo [1/2] このフォルダのコードを Apps Script に送ります...
call %CLASP% push -f
if not errorlevel 1 goto pushed
echo.
echo ログインの期限が切れている可能性があります。ログインし直します。
echo ブラウザが開くので、使っているアカウントを選んで許可してください。
call %CLASP% login
if errorlevel 1 goto err
echo もう一度送ります...
call %CLASP% push -f
if errorlevel 1 goto err
:pushed
echo.
echo [2/2] ウェブアプリのデプロイをすべて新バージョンにします...
set N=0
for /f "tokens=2" %%i in ('%CLASP% deployments ^| findstr /b /c:"- " ^| findstr /v "@HEAD"') do (
echo 更新: %%i
call %CLASP% deploy -i %%i -d "deploy.bat"
set /a N+=1
)
echo.
echo 完了しました(更新したデプロイ: %N% 件)
pause
exit /b
:err
echo.
echo エラーで止まりました。上のメッセージを確認してください
pause
ダブルクリックするだけで、コードの送信からデプロイの更新まで終わります。

実際に踏んだ3つの落とし穴
ここからが本題です。普通に使うだけなら上の内容で足りますが、運用していると必ずぶつかるものがあります。
① ログインの期限が切れる
しばらく使わないでいると、clasp push が invalid_grant というエラーで止まります。ログイン情報の有効期限切れです。
毎回ログインし直せばいいだけなんですが、エラーが出てから原因を調べる時間が無駄です。だから最初から仕込んであります。
call %CLASP% push -f
if not errorlevel 1 goto pushed
echo ログインの期限が切れている可能性があります。ログインし直します。
call %CLASP% login
call %CLASP% push -f
送信に失敗したら自動でログイン画面を出して、もう一度送る。これだけで、期限切れを意識しなくて済みます。
② pushだけではウェブアプリに反映されない
ここが一番ハマりやすいところです。
clasp push でコードは送られます。でもウェブアプリとして公開しているURLの中身は変わりません。デプロイを新しいバージョンに更新する必要があります。
しかもうちはデプロイが2つあるので、両方やらないと片方だけ古いまま動きます。手でやると必ずどちらかを忘れます。
for /f "tokens=2" %%i in ('%CLASP% deployments ^| findstr /b /c:"- " ^| findstr /v "@HEAD"') do (
call %CLASP% deploy -i %%i -d "deploy.bat"
)
デプロイの一覧を取ってきて、1つずつ順に新バージョンにしています。数が増えても自動で全部まわるので、更新漏れが起きません。
③ @HEADを除外する
上のコマンドで findstr /v "@HEAD" という部分があります。これを外すと失敗します。
@HEAD はテスト用の特殊なデプロイで、常に最新のコードを指しています。バージョンを固定する対象ではないので、ここだけ除外する必要があります。
一覧にしれっと混ざっているので、知らないとエラーの原因が分かりません。
おまけ:日本語が文字化けする
バットファイルの2行目に chcp 65001 > nul と書いてあります。これがないと、コマンドプロンプトの日本語が文字化けします。
エラーメッセージを日本語で出しておかないと、慌てているときに読めません。地味ですが入れておく価値があります。
運用のルール:フォルダ側が正本
1つだけ決めごとが要ります。
コードを直すときは、必ずフォルダのファイルを直す。 GASエディタで直接書き換えない。
理由は単純で、次に push したときにエディタ側の変更が消えるからです。フォルダの内容で上書きされるので。
「ちょっとだけだから」とエディタで直して、あとで原因不明の巻き戻りに悩む。これは実際にやりかねないので、最初にルールとして決めておくことをおすすめします。
まとめ
- claspを使うと、GASのコードをパソコンのフォルダで管理できる
- フォルダごとコピーすればバックアップになり、書きかけで壊れる心配もない
- setup.batとdeploy.batを作っておけば、ダブルクリックだけで運用できる
- ログインは切れるので、自動で入り直す処理を入れておく
- pushだけではウェブアプリに反映されない。デプロイの更新まで自動化する
- @HEADは除外する。chcp 65001で文字化けを防ぐ
- フォルダ側を正本にして、エディタでは直接書き換えない
GASのプロジェクトが1ファイルのうちは、エディタで十分です。ただファイルが増えてデプロイも複数になってくると、どこかで必ず事故ります。
そうなる前に移しておくと、あとがラクです。






