GitHubのActionsを使って、Twilio Functionのテストとデプロイを自動化する

:::note alert
2023年5月1日を持ちまして、株式会社KDDIウェブコミュニケーションズのTwilioリセール事業が終了したため、本記事に記載されている内容は正確ではないことを予めご了承ください。
:::

# はじめに

みなさん、こんにちは。
KDDIウェブコミュニケーションズのTwilio事業部エバンジェリストの高橋です。

今回は、先日USサイト上で公開された以下のブログの記事をベースに、GitHub の Actions を使って Twilio Functions のテストとデプロイを自動化させてみます。
[An Introduction to CI/CD for Twilio Functions Using GitHub Actions](https://www.twilio.com/blog/an-introduction-to-ci-cd-for-twilio-functions-using-github-actions)

この記事では上記の記事の内容に加えて、**テストの自動化**も行っていきたいと思います。

# 何をするのか

Twilio CLI を使うと、コマンドベースで Functions のデプロイが実行できますが、今回は GitHub の Actions を使って、main ブランチにコミットされるのをトリガーに、デプロイまでを GitHub 上で自動的に実行する仕組みを作ります。

GitHub Actions については、以下の記事を御覧ください。
https://github.co.jp/features/actions

main ブランチがコミットされると、具体的には以下の作業が自動的に GitHub 上で実行されます。すべてのステップが正常に完了したときにデプロイが行われ、いずれかのステップが失敗するとデプロイはされません。

1. デプロイ用の環境（ubuntu）を用意します。
2. Node.js の準備をします。
3. 必要なライブラリをインストールします。
4. Twilio CLI のインストールと、Serverless Plugins のインストールをします。
5. <font color='blue'>GitHub 上でローカルサーバーを起動します。</font>
6. <font color='blue'>Function のテストを行います。</font>
7. Twilio 上にデプロイします。

上記ステップの5と6が今回の記事で追加された項目になります。こちらについては後ほど解説します。

# 準備

以下の準備をお願いします。

- Twilio アカウント
- GitHub アカウント

ローカルでテストをしてから実行したい場合は、さらに以下の環境が必要です。

- Node.js(v.12.x）
- Twilio CLI
- Twilio CLI Serverless Plugins

CLI については、以下の記事を参考にしてください。
[Twilio CLI（セットアップ編）](https://qiita.com/mobilebiz/items/456ce8b455f6aa84cc1e)
[Twilio CLI（サーバーレス開発編）](https://qiita.com/mobilebiz/items/fb4439bf162098e345ae)

# ハンズオン

ではさっそく始めましょう。

## サンプルリポジトリをコピー

まずは、GitHubにログインした状態で、以下のサイトに移動します。
https://github.com/mobilebiz/twilio-runtime-github-actions

次に、画面右上にある **Fork** ボタンを押して、このリポジトリをフォークします。
![GItHubAction_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/86046/0b78c4ff-9215-b7aa-88e9-62b77d79919f.png)

しばらくすると、ご自分の環境内に先程のリポジトリがコピーされます。

## 環境変数の設定

Actions を利用して一連の作業を行うために、ご自分の Twilio アカウントに関する設定が必要になります。
まずは以下の内容を調べておいてください。

- **AccountSid**: [こちらのページ](https://jp.twilio.com/console)に記載されている AC から始まる文字列
- **API Key**: [こちらのページ](https://jp.twilio.com/console/project/api-keys)で、新規にキーを発行します
- **API Secret**: 上記、API Key の作成時に自動的に作られた文字列です

GitHub の **Settings** タブに移動し、さらに **Secrets** を選択します。
右上の **New repository secret** ボタンを使って、以下の項目名で環境変数を設定しましょう。

|Name|Value|
|:--|:--|
|TWILIO_ACCOUNT_SID|先程調べた AccountSid|
|TWILIO_API_KEY|先程調べた API Key|
|TWILIO_API_SECRET|先程調べた API Secret|

![GitHubAction_2 (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/86046/f85cb434-9439-36f4-7b41-501a24d7cd29.png)

## Actions の有効化

設定の最後は、Actions の有効化です。今回は、私のリポジトリをフォークして作成したため、デフォルトで GitHub Actions が無効になっています。有効にするには、**Actions** タブに移動し、中央の緑のボタンを押します。

![GitHubAction_3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/86046/882f2fae-2f85-5eb3-2238-fcc99a0697b9.png)

<font color='red'>＜注意＞
GitHub の Actions で指定されたワークフローについては、GitHub にてセキュリティチェックがされているわけではないので、実行するためにはワークフローが引き起こす内容について十分に理解する必要があります。</font>

# 実行してみる

ではまず、この状態で一度 Actions を実行してみましょう。

**Code** タブに移動し、**functions** ディレクトリ内にある **hello-world.js** を開きます。

![GitHubAction_4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/86046/fe4a4add-2be6-0f8a-a73e-a7be065681fb.png)

このサンプルプログラムは非常にシンプルなもので、実行すると以下のJSONを返却します。

```json
{ message: "Hello World!" }
```

では、コードを少しだけ修正してみます。
鉛筆アイコンを押して修正モードに切り替えて、3行目の`Hello World!`を、`Hello World!!`に変更します。

![GitHubAction_5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/86046/b9563095-a927-7b89-d0fe-3d794c18ae2c.png)

画面を下にスクロールして、緑色の **Commit change** ボタンを押して変更をコミットします。

![GitHubAction_6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/86046/ae6ddc5a-3229-2dd1-d17f-9661ffc7945c.png)

**Actions** タブに移動すると、main ブランチがコミットされたために、ワークフローが自動的に走り出すことが確認できます。
**Update hello-world.js**（コミット名）をクリックすると詳細が表示されます。

今回は、以下のような画面が表示されてワークフローが途中で失敗していることがわかります。

![GitHubAction_7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/86046/f68752cf-76c9-52ea-3de7-ea9160698a8e.png)

赤い点線で囲っていたところがテストの失敗原因となります。テストコードでは、`Hello World!`が戻ることを期待していましたが、実際には、`Hello World!!`が戻ったことが失敗の原因です（先程修正したので、この結果が正しいです）。

では、テストコードを修正しましょう。
再び、**Code** タブに移動し、今度は`__tests__`ディレクトリにある`hello-world.test.js`ファイルを開きます。

![GitHubAction_8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/86046/8014c47c-3dab-40bf-65d2-6478540c8b7e.png)

このテストコードは今回の記事で新しく追加したものです。今回はテストフレームワークに [Jest](https://jestjs.io/ja/) を利用しましたが、Jest では、`__tests__`フォルダにテストコードを入れておくと、テスト開始時に自動的に読み込まれるようになっています。
今回のテストコードでは、`axios` を使って `http://localhost:3000/hello-world` を呼び出し、その結果である JSON から`message`というキーに対する Value をチェックするようにしています。

**<font color='red'>重要</font>**
Node.js を使って、Jest のテストをする場合は、`package.json`に以下の記述がないとエラーが出ることがありますのでご注意ください。

```json
  "jest": {
    "testEnvironment": "node"
  }
```


では、このテストコードを変更したいと思います。鉛筆アイコンを押して編集モードに入ります。
10行目にある`Hello World!`を`Hello World!!`に変更します。

では変更をコミットします。
画面を下にスクロールして、緑色の **Commit changes** ボタンを押します。

**Actions** タブに移動します。
自動的にワークフローが実行されます。

以下の画面のように、今度はうまくデプロイまで成功しているようです。

![GitHubAction_10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/86046/ba79bb43-15a7-37b6-c46d-1d702fc50c41.png)

また、デプロイまでにかかった時間が1分28秒だったこともわかります。GitHub Actions の課金は時間単位です。フリープランでは、毎月2,000分までの Actions が利用できます。これを超える場合は、別途料金が必要です。料金については、[こちら](https://docs.github.com/ja/free-pro-team@latest/github/setting-up-and-managing-billing-and-payments-on-github/about-billing-for-github-actions)をご覧ください。

実際にデプロイされた Function は、[Twilio 管理コンソール](https://jp.twilio.com/console/functions/overview/services)内から確認が可能です。

![スクリーンショット 2020-11-16 14.37.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/86046/7ad9b293-9af7-ed41-a240-6188dafdb323.png)


# 解説

では、今回のしくみを解説しましょう。
今回のActions のワークフローで最も重要なファイルが、`.github/workflows`ディレクトリ内にある`main.yml`ファイルです。

```yml:main.yml
# This is a basic workflow to publish a Twilio function with Github Actions

name: Twilio CI

# Controls when the action will run. Triggers the workflow on push or pull request
# events but only for the master branch
on:
  push:
    branches: [ main ]

# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
  # This workflow contains a single job called "build"
  build:
    # The type of runner that the job will run on
    runs-on: ubuntu-latest

    # Steps represent a sequence of tasks that will be executed as part of the job
    steps:
      # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
      - uses: actions/checkout@v2
      - name: Use Node.js
        uses: actions/setup-node@v1
        with:
          node-version: '12.x'
      # Runs a single command using the runners shell
      - name: Install dependencies for the twilio function
        run: npm ci
      - name: Install twilio cli and run deploy command
        env:
         TWILIO_ACCOUNT_SID: ${{ secrets.TWILIO_ACCOUNT_SID }}
         TWILIO_API_KEY: ${{ secrets.TWILIO_API_KEY }}
         TWILIO_API_SECRET: ${{secrets.TWILIO_API_SECRET}}
        # Install the Twilio CLI and the serverless plugin then deploy the function
        # run: npm install twilio-cli -g && twilio plugins:install @twilio-labs/plugin-serverless && twilio serverless:deploy --service-name=example-deployed-with-github-actions --environment=dev --force
        run: npm install twilio-cli -g && twilio plugins:install @twilio-labs/plugin-serverless 
      - name: Start local http server in background
        run: npm start &
      - name: Test the function
        run: npm test
      - name: Deploy the function
        env:
         TWILIO_ACCOUNT_SID: ${{ secrets.TWILIO_ACCOUNT_SID }}
         TWILIO_API_KEY: ${{ secrets.TWILIO_API_KEY }}
         TWILIO_API_SECRET: ${{secrets.TWILIO_API_SECRET}}
        run: twilio serverless:deploy --service-name=example-deployed-with-github-actions --environment=dev --force
```

7〜9行目で、どのブランチがコミットされたら動作するかが指定されています。今回は、`main`ブランチがトリガーとなっています。
19行目の`step`以降が、実際に GitHub 上で実行される部分となります。
今回実行するように設定しておいたステップをもう一度記載しておきます。

1. デプロイ用の環境（ubuntu）を用意します。
2. Node.js の準備をします。
3. 必要なライブラリをインストールします。
4. Twilio CLI のインストールと、Serverless Plugins のインストールをします。
5. <font color='blue'>GitHub 上でローカルサーバーを起動します。</font>
6. <font color='blue'>Function のテストを行います。</font>
7. Twilio 上にデプロイします。

本来はステップ4で、Twilio CLI、Serverless Plugins のインストールと併せて、ステップ7のデプロイまでを一括で実行するようになっていたのですが、今回はまずステップ4ではプラグインのインストールまで済ませたあと、`npm start`を使ってローカルサーバーを起動しています。
これによって、GitHub 上で Functions をテストする環境が構築されるので、先程のテストコードを実行して想定した結果が戻るかどうかをテストしています。

# まとめ

今回は非常に簡単な Function のテストとデプロイでしたが、基本的な使い方が分かればあとは応用で色々とできそうです。
ぜひ、Twilio CLI と GitHub Actions を組み合わせた CI/CD の実現を試してみてください。

---
### Twilio（トゥイリオ）とは

https://cloudapi.kddi-web.com
Twilioは音声通話、メッセージング（SMS/チャット）、ビデオなどの 様々なコミュニケーション手段をアプリケーションやビジネスへ容易に組み込むことのできるクラウドAPIサービスです。初期費用不要な従量課金制で、各種開発言語に対応しているため、多くのハッカソンイベントやスタートアップなどにも、ご利用いただいております。

自己紹介|　
:--|:--
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/86046/b51a8b88-abd5-ce5e-195a-de3564ba2ae6.png" height='200' width='150'/>|高橋克己（Katsumi Takahashi） 自称「<font color='red'>赤い芸人</font>」<br />グローバル・インターネット・ジャパン株式会社　代表取締役<br />株式会社KDDIウェブコミュニケーションズ　Twilio事業部エバンジェリスト<br /><br />2001年より大手通信事業者の法人サービスの教育に携わり、企業における電話のしくみや重要性を研究。2016年よりTwilio事業部にジョインし、Twilioを使ったスマートコミュニケーションの普及活動を精力的に行っている。<br />2019 Twilio Champions