Help us understand the problem. What is going on with this article?

GAS用のCLIツール clasp を使ってGASをローカルで開発して実行するの巻。

claspを使ってローカルでGASを書く

基本的にGASの開発はブラウザで行う必要があります。
スクリーンショット 2019-07-07 15.03.29.png
これは面倒ですね。
単純なプログラムであればブラウザでも十分ですが、ある程度複雑な開発になるとこんな不満が出そうです。

  • Gitでのバージョン管理がしたい
  • 使い慣れたエディタで開発したい

この不満を解消するべくGoogleが開発したのが google/claspです。
clasp はローカルで書いたコードをGitHub感覚でpush、オンラインからpullできるCLIツールです。

今回はこのclaspを使ってローカルでGASの開発、一歩踏み込んでデバッグまでできるようにしてみます。
ついでにローカルではTypeScriptを使うことにします。

ローカル環境で快適なGAS開発を行う手順

GAS API の設定をオンにする

はじめにG Suite ユーザー設定画面からGoogle Apps Script APIをオンにして下さい。
スクリーンショット 2019-07-07 16.03.02.png

claspのインストールとログイン

既にnpmをインストールしているものとして準備を進めていきます。
はじめにclaspをグローバルインストールしてください。

ターミナル
$ npm install -g @google/clasp

次にclaspコマンドからGoogleアカウントのリソースを扱えるように認証を通します。

ターミナル
$ clasp login
> Logging in globally...
> Authorization successful
> Default credentials saved to: ~/.clasprc.json

ブラウザが立ち上がるのでポチポチっと認証を許可します。
.clasprc.jsonファイルの有無でログイン状態を判断しているようですね。

claspプロジェクトの作成

好きな場所にワークディレクトリを作成してnpm initしてください。今回はTypeScriptで開発を行うため型の定義ファイルもインストールします。

$ npm init -y
$ npm install -D @google/clasp
$ npm install -S @types/google-apps-script

続いて clasp create コマンドでclaspプロジェクトを作成します。今回はgas-sundayという名前でclaspプロジェクトを作成しました。

ターミナル
$ clasp create gas-sunday

? Create which script? (Use arrow keys)
❯ standalone 
  docs 
  sheets 
  slides 
  forms 
  webapp 
  api 

:warning: 既存のGASからclaspプロジェクトを作成する時はclasp clone スクリプトIDコマンドを使えばOKです :warning:


コマンドを実行するとスクリプトの種類を問われますので必要に応じて選択しましょう。
standaloneは他のアプリに依存しないスクリプト、docssheetsはドキュメントやスプレッドシートに結びついたスクリプトです。アプリと結びつけると独自クラスが使えます。
基本的にはstandaloneでほぼ対応できます。アプリベースのTriggerもコードでセットすれば良いので〜〜。

設定ファイルの編集、オンラインからpullする

clasp createコマンドでワークディレクトリ内に.clasp.jsonappsscript.jsonが作成されました。

ターミナル
$ ls -a
.                       .clasp.json             node_modules            package.json
..                      appsscript.json         package-lock.json       tslint.json

名前の通り.clasp.jsonは claspプロジェクトの設定、 appsscript.jsonはGASの設定ファイルです。

.clasp.jsonに以下の設定を追加するとclasp pushの対象ディレクトリを指定することができます。ついでにTypeScriptの設定も書いておきます。

.clasp.json
{
  "scriptId":"##################################",
  "rootDir": "./src",
  "fileExtension": "ts"
}

設定した通りにsrcディレクトリを作成しておきましょう。

ターミナル
$ mkdir src

ここで一度clasp openコマンドを叩いてオンラインにスクリプトが作成させていることを確認しておきます。

ターミナル
$ clasp open

コマンドを実行すると自動的にブラウザが開かれます。
スクリーンショット 2019-07-07 16.37.52.png
問題なくスクリプトが作成されているようです!
しかし、オンライン上のCode.gsファイルはローカルにはありませんね。
そこでclasp pullコマンドを使います。

ターミナル
$ clasp pull
Cloned 2 files.
└─ ./src/appsscript.json
└─ ./src/Code.ts

これでローカルにオンライン(リモート)のCode.jsappsscript.jsonをsrc配下にpullすることができました。
今回はTypeScriptを指定しているためCode.jsCode.tsへと変換されています。

ここまでで環境がだいぶ整ってきました!

コードを記述してpushする

ではローカルでGASを書いてclasp pushしてみます。
今回はとってもシンプルなTypeScript。

Code.ts
function myFunction() {
  var greeting: string = 'hello, GAS'
  Logger.log(greeting);

  var aisatsu: string = 'こんにちは、GAS'
  console.log(aisatsu);
}

Logger.logはオンラインエディタ上でログを出力させる命令です。
それではさっそくこのコードをclasp pushしてみましょう。

ターミナル
$ clasp push

ブラウザでスクリプトを確認すると.tsファイルが上手いこと.gasファイルに変換されてpushされていることが分かります。
スクリーンショット 2019-07-07 17.01.39.png

再生ボタンみたいなボタンを押してコードを実行してみるとログにhello, GASと吐き出されています。
スクリーンショット 2019-07-07 17.04.50.png
console.logのログはSTACKDRIVERのLoggingに吐かれるためここには出ないです。

ここまででローカル環境での開発が可能になりました:sunny:

ここからはさらに一歩踏み込んでローカル環境でログの確認(デバッグ)を行えるようにしてみます。
GASでそこまでする必要あるのか?って内容ですので気になる人だけ見てください。

ローカルからGASを叩く

「 ローカルでログの確認(デバッグ)ができる == GAS APIを叩いてローカルでログを取得できる 」ことです。
これを行うためにはGASをGCPプロジェクトへと関連付ける必要があります。

GASを Cloud Platformプロジェクト と関連付ける

まずはGCPのコンソールを開いて新しいプロジェクトを作成しましょう。
スクリーンショット 2019-07-07 17.29.04.png
今回はgas-sunday-gcpというプロジェクトを作成しました。プロジェクトのダッシュボードからプロジェクト番号を確認しコピーしておきます。

次にGASのオンラインエディタに戻って 「リソース」 → 「Cloud Platform プロジェクト」を開いてコピーしておいたプロジェクト番号をペーストして「プロジェクトを設定」をクリックします。
スクリーンショット 2019-07-07 17.37.52.png
さらに確認のモーダルを進めると「プロジェクトに切り替えるには、OAuth 同意画面を設定する必要があります。 同意画面を設定するには、こちらをご覧ください。」と怒られます。
スクリーンショット 2019-07-07 17.39.41.png
それでは怒られた通りに こちら をクリックしてOAuthの設定を行います。
OAuth同意画面で「アプリケーション名」を入力して保存します。(必要な場合はスコープの設定も行なって下さい。)

保存をクリックすると「API 認証情報」タブへとリダイレクトされます。
スクリーンショット 2019-07-07 17.46.27.png
次に認証情報を作成 → OAuthクライアントID と進みます。

進んだ画面で その他 を選択し 作成 をクリックします。名前は何でも良いです。
クライアントIDが作成されるとモーダルで「クライアントID」と「クライアントシークレット」が表示されますが今回は特に気にする必要はありません。
スクリーンショット 2019-07-07 17.55.21.png

ここでクライアントIDの一番右にあるダウンロードボタン(画像の赤丸)を押してjsonファイルをダウンロードします。
ダウンロードしたjsonファイルは後ほど(claspプロジェクトのローカルログインで)使用します。ファイル名をcreds.jsonに変更して保存しておきましょう。

これでOAuthの設定ができました。
再びGASのオンラインエディタに戻り、「プロジェクトの設定」を押すと今度は怒られることなくGASを Cloud Platformプロジェクト に関連付けることができます。
スクリーンショット 2019-07-07 18.02.52.png

GASを実行可能APIとして公開する

GASのオンラインエディタから 公開 → 実行可能APIとして導入をクリックします。
スクリーンショット 2019-07-07 18.14.05.png
スクリプトにアクセスできるユーザーは自由に選んで下さい。今回は「全員」に設定し、配置をクリックします。

次に、GCPのプロジェクトページからAPIとサービス → ライブラリへと進みます。
そこでApps Script APIを検索し、有効にするをクリックします。
スクリーンショット 2019-07-07 19.15.33.png

これでスクリプトを実行可能APIとして公開できました。

creds.json で localログイン する

ここからはコマンドラインからの操作に戻ります。オンライン(リモート)でAPI公開設定を行なったのでローカルでも設定を反映させるためにclasp pullを実行しておきます。

ターミナル
$ clasp pull

appsscript.jsonに実行可能APIとして公開した設定が反映されているのが分かります。

appsscript.json
{
  "timeZone": "America/New_York",
  "dependencies": {
  },
  "exceptionLogging": "STACKDRIVER",
  "executionApi": {
    "access": "ANYONE"
  }
}

次に.clasp.jsonにGCPのプロジェクトIDを設定しておきます。
以下のコマンドを実行しましょう。

ターミナル
$ clasp setting projectId <PROJECT_ID>

上記のコマンドで.clasp.jsonprojectIdが追加されたことが確認できると思います。

続いてダウンロードしておいたjsonファイルcreds.jsonをワークディレクトリgas-sunday配下に入れます。creds.jsonには先ほど設定APIのクライアント情報が書かれてます。
このAPIクライアント情報を元に claspプロジェクトとしてワークディレクトリのlocalログイン を行います。

ターミナル
$ clasp login –creds creds.json

コマンドを実行すると自動的にブラウザに飛ばされます。

そしてボタンをポチポチして認証を進めます。

スクリーンショット 2019-07-07 18.44.43.png
警告を乗り越えて、許可ボタンを押していきます。

ターミナルに戻って以下のログが出れば完了です!

Authorization successful.
Local credentials saved to: ./.clasprc.json

globalログインしたときと似たように、今回はワークディレクトリ内にlocalログイン情報の入った.clasprc.jsonが作成されました。

clasp run で関数を実行する

ここまでできれば準備万端です。
ローカル環境でスクリプトを実行するにはclasp runコマンドを使います。

ターミナル
$ clasp run

コマンドを実行すると実行する関数を選択できます。

Running in dev mode.
? Select a functionName (Use arrow keys or type to search)
❯ myFunction 

初めからclasp run 関数名として実行することも可能です。

ターミナル
$ clasp run
? Select a functionName myFunction
No response.

myFunctionを実行すると返り値が表示されます。今回は特に関数の帰り値がないためNo response.となっています。

次にログを確認してみます。使うコマンドはclasp logsです。

ターミナル
$  clasp logs
DEBUG      2019-07-07T09:47:49.555Z myFunction      こんにちは、GAS   

実行された関数のログが吐き出されています。

おさらいですが、以下が今回実行した関数です。

function myFunction() {
    var greeting = 'hello, GAS';
    Logger.log(greeting);
    var aisatsu = 'こんにちは、GAS';
    console.log(aisatsu);
}

console.logで出力されたログが確認できます。なぜならSTACKDRIVERのLoggingのログを出力してるからです。
Logger.logのログは出ないので一応注意してください。

これでGASをローカル環境で開発,デバッグすることが可能になりました :star:

トラブルシューティング

上手く clasp runが実行できなかった方は以下を確認してください。

パターン① appsscript.jsonに実行APIとしての公開設定が反映されていない

appsscript.json
{
  "timeZone": "America/New_York",
  "dependencies": {
  },
  "exceptionLogging": "STACKDRIVER",
  "executionApi": {
    "access": "ANYONE"
  }
}

↓ ここがポイントです。

  "executionApi": {
    "access": "ANYONE"
  }

上記のような設定がない場合はGASを実行可能APIとして公開するをもう一度確認して下さい。

パターン② ローカルログインできない

clasp login –creds creds.jsonが上手くいかず、何故かglobalログインになってしまうパターン。
creds.jsonファイルをワークディレクトリ配下に置いていることを確認して下さい。

creds.jsonをバッチリ配置しているのにlocalログインできない!という方。APIクライアントの有効化にラグがあることが原因かと思われます。1~6時間待って再度ログインを試してみて下さい。

パターン③ 公開可能APIのバージョンが最新ではない

GASを実行可能APIとして公開するを繰り返し行なった場合はAPIのバージョンが変わります。思いがけない挙動とならないようにGASのオンラインエディタからバージョンは最新のものを指定しておきましょう。

おわりに

気軽な気持ちで書きはじめた記事でしたが、思ったより長くなり途中で後悔しました。
GASとTypeScriptの勉強頑張ります...!😭
それではまた!

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした