🕌

15分でGASのローカル開発環境を構築しデプロイするためのboilerplateを作りました

2024/03/05に公開
2

リポジトリ公開してます!
https://github.com/Taichiro-S/gas_local

2024/3/9追記
Github actionsでGASの認証情報をコマンドライン引数からファイルに書き込んでいましたが、セキュリティ的な観点[1]からenvsubsetを使用する方法に変更しました

追加予定項目

  • TypeScript化する

こんな人におすすめ

  • GASをローカルで開発したい
  • テスト環境と本番環境を作りたい
  • Github Actionsで自動テスト、ビルド、デプロイしたい

そもそもなんでローカルで開発するの?

とりあえず動かしてみたい、という場合はブラウザで開発した方がスピーディにできますが、プロジェクトが大きくなったり、複数人で開発するとなると、いろいろ不便なことが出てきます。

  • ブラウザ上で変更したコードがそのまま本番環境にデプロイされてしまう
    👉 テストせずに誤ってデプロイしてしまう可能性
  • ブラウザ上のエディタでしか開発できない
    👉 フォーマットや静的解析できない、複数人で開発できない
  • Chromeの拡張機能でGithubと連携はできるが、機能が限定される
    👉 拡張機能依存になってしまう、Github Actionsが使えない

上記の問題点はローカルのエディタを使って開発を行い、Github Actionsで自動テスト、ビルド、デプロイすることで解決できます!

前提

  • claspでログイン済み
  • GAS作成済
  • Github CLIインストール済み

使用するライブラリ

これらのライブラリについては説明は省きます

  • clasp:ローカルでのGAS開発環境構築
  • ESLint:静的解析
  • prettier:フォーマット
  • esbuild:複数ファイルをGAS用にビルドする
  • Jest:ユニットテスト

使い方

  1. このリポジトリをforkしてローカルにcloneします
    git clone https://github.com/Taichiro-S/gas_local

  2. プロジェクトディレクトリに移動し、npm installを実行します

  3. srcディレクトリでclasp clone GASのスクリプトIDを実行します

  4. プロジェクトルートにdistディレクトリを作成し、srcからappscript.jsonを移動します

  5. コード.jsをindex.jsに名前を変更します

  6. index.jsで定義されている関数(GASで直接呼び出したい関数)をglobal関数にします

    + global.myFunction = myFunction
    function myFunction() {
     console.log('Hello World')
     }
    

ここまで終わったら、一旦ローカルで以下のコマンドを実行してみてください

  • npm test : サンプルのテストが実行されます
  • npm run test:coverage : サンプルのテストが実行され、coverageというフォルダが生成します
  • npm run build : distにmain.jsが生成します(確認できたら削除してください)

Github Actionsの設定

  1. GithubリポジトリのSettings > Actions > general > Workflow permissions で Read and write permissions にして保存します(test coverageをPRに書き込むために必要です)
  2. Githubの Settings > Environments からclaspという名前でNew environmentで環境を作成します
  3. .envファイルを作成し、~/.clasprc.jsonの中身とスクリプトIDを書き込みます(env.exampleを参考にしてください)。※テスト環境を作らない場合はSTAGINGは不要です。※デプロイしない場合はDEPLOY_IDは不要です。
  4. gh secret set --env clasp --env-file .env --repo Githubのユーザー名/リポジトリ名を実行します(.envに書き込まれた認証情報等が "clasp" environment の secrets に登録されます)
  5. template_clasprc.jsonのexpiry_dateを~/.clasprc.jsonからコピペします
  6. Github に push します(テスト用の GAS を作成している場合は、stgブランチに pushします)

GASエディタでpushされていることを確認できればOKです

GASをwebアプリとしてデプロイしたい場合

  1. GASエディタからから新しいデプロイを作成し、デプロイIDを控えておきます
  2. エディタ上でappscript.jsonが変更されるので、ローカルのファイルにコピペします
  3. デプロイIDをGithub secretsに登録します(テスト用はなくても良いです)
  4. cd_workflow.ymlでpush時にdeployするように修正します
        - name: Push
            run: |
            clasp push -f
    
    +    - name: Set up environment variables for deployment
    +        run: |
    +        if [[ ${{ github.ref }} == 'refs/heads/main' ]]; then
    +            echo "DEPLOY_ID=${{ secrets.PRODUCTION_DEPLOY_ID }}" >> $GITHUB_ENV
    +        elif [[ ${{ github.ref }} == 'refs/heads/stg' ]]; then
    +            echo "DEPLOY_ID=${{ secrets.STAGING_DEPLOY_ID }}" >> $GITHUB_ENV
    +        fi
    +   - name: Deploy
    +        run: |
    +       clasp deploy --deploymentId ${{ env.DEPLOY_ID }}
    
    

つまったところ

ローカルやGASエディタ上でappscript.jsonを変更すると、pushの際に? Manifest file has been updated. Do you want to push and overwrite? (y/N)という質問が出てきてしまい、pushできていないにも関わらず、Github Actions ではエラーを出してくれません。
正攻法ではないような気がしますが、cd_workflow.ymlのpushコマンドをecho y | clasp pushとすることで、上記の質問にyesで答えて処理を進めています。

コメントで教えていただきました!
clasp push -fでoverwriteできるようです

慣れれば10分切ります!
頑張ってください!(?)

こちらも読んでみてください!
https://zenn.dev/xcter/articles/5eee9451ae25f6

参考にさせていただいた記事

https://qiita.com/Syuparn/items/80c4f48c66ca53ef12b8
https://zenn.dev/rena_h/articles/29b8203db2299f
https://qiita.com/shunexe/items/fdf0def390a160d044c3

脚注
  1. 理由や対処法はこちらの記事で詳しく述べられています ↩︎

Discussion

sinskysinsky

clasp pushにはforceオプションがあるので、
clasp push -fを使うといいと思います。

      - name: Push
        run: |
-           echo y | clasp push
+           clasp push -f
> clasp push --help
Usage: clasp push [options]

Update the remote project

Options:
  -f, --force  Forcibly overwrites the remote manifest.
  -w, --watch  Watches for local file changes. Pushes when a non-ignored file changes.
  -h, --help   display help for command
XCTERXCTER

それでいけるんですね。
ありがとうございます!