clasp + GitHub + CodeBuild で Google Apps Script の継続的デプロイをやってみた

clasp+GitHub+CodeBuildでGoogleAppsScript(GAS)の継続的デプロイメント(CD)をやってみました
2020.04.03

こんにちは、大前です。

以前、Clasp という Google Apps Script をローカル管理できる CLI ツールを紹介しましたが、今回はこれを使った CD の仕組みを作ってみましたので、ブログを書いていきます。

claspを使ったGoogle Apps Scriptのソース管理を試してみた

構成

下記の構成となります。

  1. GitHub 上の特定の操作が発生
  2. CodeBuild が起動
  3. CodeBuild から EC2 上のシェルスクリプトを実行
  4. EC2 上で最新のソースを GitHub からクローン
  5. Clasp を利用して GAS にデプロイ

 

何だかまわりくどい構成になっていますが、Clasp を使用するために叩く「clasp login」で必ずブラウザでの操作が必要となってしまい、ログイン状態を保持するために EC2 上で処理を行う形になっています。

GitHub Actions 等でうまくやる方法もあるのかもしれませんが、現時点では見つけられませんでした。

これより良い方法があれば教えてください。。。

 

とはいえ、上記構成でも GAS の CD という目的は達成できますので、実際にやっていきたいと思います。

やってみた

前準備

Google Apps Script プロジェクトの用意

GAS のプロジェクトを作成しておきます。今回は下記の様な「clasp-test」プロジェクトを用意しました。

 

プロジェクトの作成方法はこちら

Git リポジトリの用意

GAS のソースを管理するリポジトリを用意します。

今回は、下記の様なディレクトリ構造にしました。/gas 配下が GAS にデプロイされる様にする予定です。

$ tree
.
├── README.md
├── buildspec.yml
└── gas
    ├── appsscript.json
    └── main.js

1 directory, 4 files

CodeBuild と連携するため、buildspec.yml のみ必須です。あとはお好みで。

EC2 の構築

まずは EC2 を構築します。細かい手順は省きますが、以下の様な構成を作成しました。

 

EC2 上で git や clasp を叩く必要があるため、色々とインストールをしていきます。

今回は、SSM を使える様に設定をし、セッションマネージャーにて行いました。

yum アップデート

sh-4.2$ sudo su ec2-user
[ec2-user@ip-10-10-2-163 bin]$ cd ~
[ec2-user@ip-10-10-2-163 ~]$ sudo yum update -y

nodejs インストール

clasp を npm でインストールするため、nodejs をインストールします。

チュートリアル: Amazon EC2 インスタンスでの Node.js のセットアップ

[ec2-user@ip-10-10-2-163 ~]$ curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.34.0/install.sh | bash
[ec2-user@ip-10-10-2-163 ~]$ . ~/.nvm/nvm.sh
[ec2-user@ip-10-10-2-163 ~]$ nvm install node
[ec2-user@ip-10-10-2-163 ~]$ node -e "console.log('Running Node.js ' + process.version)"
[ec2-user@ip-10-10-2-163 ~]$ npm -v
6.14.4

git インストール

[ec2-user@ip-10-10-2-163 ~]$ sudo yum install -y git
[ec2-user@ip-10-10-2-163 ~]$ git --version
git version 2.23.1

git clone

ssh で git clone 等を行うため、鍵の生成を行なっています。

生成した公開鍵は GitHub に登録しておきます。

[ec2-user@ip-10-10-2-163 ~]$ ssh-keygen -t rsa
Generating public/private rsa key pair.
Enter file in which to save the key (/home/ec2-user/.ssh/id_rsa):(Enter)
Enter passphrase (empty for no passphrase):(Enter)
Enter same passphrase again:(Enter)
Your identification has been saved in /home/ec2-user/.ssh/id_rsa.
Your public key has been saved in /home/ec2-user/.ssh/id_rsa.pub.
[ec2-user@ip-10-10-2-163 ~]$ git clone git@github.com:xxxxxxxx/clasp-test.git
[ec2-user@ip-10-10-2-163 ~]$ ls
clasp-test

clasp インストール

[ec2-user@ip-10-10-2-163 ~]$ npm install -g @google/clasp
[ec2-user@ip-10-10-2-163 ~]$ clasp -v
2.3.0

clasp login

clasp の初期化作業になります。

clasp login を実行すると「https://accounts.google.com/〜〜」といったリンクが表示されるので、そのリンクをブラウザで開きます。

画面の指示にしたがって認証を進めるとコードが表示されるので、そちらを入力するとログイン成功となります。

[ec2-user@ip-10-10-2-163 ~]$ mkdir ~/clasp
[ec2-user@ip-10-10-2-163 ~]$ cd ~/clasp
[ec2-user@ip-10-10-2-163 clasp]$ clasp login --no-localhost
Logging in globally...
Authorize clasp by visiting this url:
https://accounts.google.com/xxxxx.....

Enter the code from that page here: xxxxxxxxxx
Authorization successful.

Default credentials saved to: ~/.clasprc.json (/home/ec2-user/.clasprc.json).

clasp clone

「xxxxx」部分には、対象の Google Apps Script プロジェクトID を指定してください。

ID の確認方法はこちら

[ec2-user@ip-10-10-2-163 clasp]$ clasp clone xxxxxxxx
Warning: files in subfolder are not accounted for unless you set a '.claspignore' file.
Cloned 2 files.
└─ appsscript.json
└─ main.js
Not ignored files:
└─ appsscript.json
└─ main.js

Ignored files:
└─ .clasp.json

シェルスクリプト配置

CodeBuild から実行させるスクリプトを配置します。

[ec2-user@ip-10-10-2-163 clasp]$ cd ..
[ec2-user@ip-10-10-2-163 ~]$ vi ~/release.sh

スクリプトの内容は下記です。

  1. GitHub から最新のソースを pull
  2. clasp で GAS の最新ソースを pull
  3. GitHub から pull したソース(今回は/gas配下)を clasp ソースに上書き
  4. clasp で GAS に push
#!bin/sh

echo "[release] start"

echo "[git pull] start"
cd ~/clasp-test
git checkout master
git pull
echo "[git pull] finish"

echo "[clasp pull] start"
cd ~/clasp
clasp pull $1
echo "[clasp pull] finish"

echo "[clasp push] start"
cp ~/clasp-test/gas/*.js .
clasp push
echo "[clasp push] finish"

echo "[release] finish"

Security Group の設定

CodeBuild から EC2 に SSH できる様に Security Group を設定します。

CodeBuid 用

EC2 用

パラメータストアの設定

CodeBuild に EC2 の秘密鍵と GAS のプロジェクトID を渡す必要があるため、SSM パラメータストアでパラメータを作成しました。

Clasp-Test-SSHKey(EC2秘密鍵)

Clasp-Test-ProjectId(GASプロジェクトID)

CodeBuild の設定

最後に、CodeBuild の設定を行います。

 

ビルドプロジェクトの作成より、プロジェクト名は「Clasp-Test-AutoDeploy」とします。

 

送信元は、ソースプロバイダを GitHub、GitHub リポジトリに対象のリポジトリを指定します。

GitHub への接続がまだの方は、画面の指示にしたがって接続を行なってください。

 

プリマリソースへのウェブフックイベントを有効にし、イベントタイプは「プッシュ」、HEAD_REF に「^refs/heads/master$」を指定しました。

こうすることで、master ブランチへのプッシュ時のみビルドがトリガーされます。

 

環境イメージは Amazon Linux2 のマネージドイメージを指定します。カスタムイメージでも良いと思います。

 

サービスロールは新しいものを作成しますが、パラメータストアから Get を行う権限を後ほど追加してあげる必要があります。

 

VPC を指定します。サブネットは EC2 が存在するプライベートサブネット、SG は先ほど作成した CodeBuild 用の SG を指定します。

「VPC 設定の確認」をクリックし、問題なければおkです。

 

環境変数に先ほど作成したパラメータストアを指定します。「名前」が buildspec.yml で参照される値で、「値」がパラメータストアで作成したパラメータ名です。

 

ここまで設定したら、ビルドプロジェクトの作成をします。

 

また、buildspec.yml は以下になります。「xx.xx.xx.xx」には構築した EC2 のプライベートIP を記載してください。

version: 0.2

phases:
  pre_build:
    commands:
      - echo "${SSH_KEY}" > ~/.ssh/ssh-key.pem
      - chmod 0700 ~/.ssh
      - chmod 0400 ~/.ssh/ssh-key.pem
  build:
    commands:
      - ssh -i ~/.ssh/ssh-key.pem -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null ec2-user@xx.xx.xx.xx -p 22 "sh ~/release.sh ${GAS_PROJECT_ID}"

IAM ロールへのポリシー追加

ビルドプロジェクト作成時に作成された IAM ロールに、パラメータストアへのアクセス権限を追加します。

今回は「AmazonSSMReadOnlyAccess」を追加しました。

動作確認

全ての設定が完了したので、動作確認をしてみます。

今回は、既存の main.js を編集するのと、新規ファイル(add.js)を追加してみました。

$ vi gas/main.js
$ cat gas/main.js
function myFunction() {
	// add comment
}
$ vi gas/add.js
$ cat gas/add.js
// add file
$ git add gas/.

push します

$ git commit -am 'test'
$ git push

 

push されると、CodeBuild のコンソールにて、ビルドが実行されているのが確認できます。

 

少し待つと、ビルドが成功しました!(一度失敗してやり直したため、上記スクショとビルド番号が異なっています。。)

 

GAS プロジェクトを更新してみると、GitHub にプッシュした内容が反映されていることも確認できます。

おわりに

clasp + GitHub + CodeBuild を組み合わせた Google Apps Script の CD を試してみました。

もっとうまくできるかもしれませんが、やりたかった clasp での CD が実現できたので、とりあえず満足です。

 

以上、AWS 事業本部の大前でした。