【Netlify functions】Netlifyでデプロイ成功したらSlackにメッセージを投稿する

`Netlify functions`でSlackにメッセージを投稿するAPIを作成した際の忘備録です。

## やりたい事
NetlifyでホスティングしているWebページのデプロイが成功したら、Slackにメッセージを投稿する。

ちなみに、Netlifyの有料プランなら[Slack notifications](https://docs.netlify.com/site-deploys/notifications/#slack-notifications)で簡単に設定できるようです。
（以前は無料プランでも使えていた…？）


## Netlify functionsとは
- AWS LambdaをNetlify上で使えるようにしたもの（AWSアカウント不要）
- JavaScript または Go で書ける。
- 無料プランでは、**リクエスト数125,000／月**と制限がある

:warning: リクエスト数の上限を越えると、自動的に次のレベルまたはパッケージにアップグレードされるようなので注意！

## 構成
- ホスティング： Netlify
- SSG： Next.js
- ソース管理： Github

フローとしては、次の通りです。
1. Next.jsで静的出力したソースをGithubリポジトリへプッシュ
2. Githubへのプッシュをトリガーに、Netlifyが自動ビルド＆デプロイ
3. デプロイが成功したら、Slackに「デプロイが成功しました」とメッセージ投稿

## 前提条件
- NetlifyとGitリポジトリの連携設定が完了している
- メッセージを投稿したいSlackチャンネルが既に用意されている

## 環境
- macOS Mojave 10.14.6
- Next.js 9.4.4
- Node.js v12.12.0


## 実装
### 1. Slackでの設定
Slackの`Incoming Webhook URL`を取得します。

##### Incoming Webhook URL作成方法
1. Slackにログインした状態で
   https://slack.com/services/new/incoming-webhook にアクセス
2. 通知を送りたいチャンネルを選択し、「Incoming Webhookインテグレーションの追加」ボタンを押す
3. 作成されたWebhook URLをコピーして控えておく

### 2. APIの作成
※今回はNext.jsを使用しているので、ディレクトリ構成などはNext.jsの仕様に従っています。

#### 2-1. 必要なnpmパッケージのインストール

```terminal:ターミナル
yarn add node-fetch
yarn add netlify-lambda
```

#### 2-2. `/functions/slack.js`を作成

先ほど作成したWebhook URLへPOSTリクエストを投げるAPIを作ります。
  
```javascript:slack.js
import fetch from "node-fetch";

exports.handler = async (event, context) => {

  if (event.httpMethod !== "POST") {
    return { statusCode: 405, body: "Method Not Allowed" };
  }

  return fetch(process.env.SLACK_WEBHOOK_URL, {
    headers: {
      "content-type": "application/json"
    },
    method: "POST",
    body: JSON.stringify({ text: `デプロイが成功しました` })
  })
    .then(() => ({
      statusCode: 200,
      body: `Your message has been sent to Slack.`
    }))
    .catch(error => ({
      statusCode: 422,
      body: `Oops! Something went wrong. ${error}`
    }));
};
```

#### 2-3. Netlify functionを生成するnpmコマンドの追加
以下のように`lambda-build`コマンドを追加します。

```package.json
"scripts": {
  "dev": "next dev",
  "build": "next build && next export",
  "start": "next start",
  "export": "next export",
  "lambda-build": "netlify-lambda build functions/"
}
```

コマンドを追加したら、`lambda-build`を叩きます。

```terminal:ターミナル
yarn lambda-build
```

すると、先ほど作成した`/functions/slack.js`がビルドされ、`/api`に吐き出されます。

#### 2-4. APIディレクトリの設定
どのディレクトリに格納されているファイルをNetlifyがAPIとして認識するかを`netlify.tml`ファイルで設定します。（この設定は恐らくNetlifyダッシュボードからでも可能）
今回だと`api`ディレクトリを指定します。

```toml:/netlify.tml
functions = "api"
```



### 3. Netlifyダッシュボードでの設定
#### 3-1. 環境変数の設定
Netlifyダッシュボードから`Settings > Build & Deploy > Build environment variables`と進み、SlackのWebhook URLを環境変数として設定します。
![スクリーンショット 2021-01-21 16.52.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274280/c9c556c3-9d56-9fe8-6bb0-1bef83aa0d5f.png)



#### 3-2. Netlifyのイベント設定
このイベントが発生したら、このサーバーレス関数呼んでね！という設定をします。

1. 「Site settings」を開き、<br>メニューから`Build & deploy` > `Deploy notifications` を選択

2. 「Add notification」のプルダウンから`Outgoing webhook`を選択
3. 「Event to listen for」でイベント発火のトリガーを選択<br>今回はデプロイ成功時（`Deploy succeeded`）

4. 「URL to notify」にはAPIのエンドポイントを設定します。
![スクリーンショット 2021-01-21 16.55.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274280/6fe3de05-4d67-f187-acd0-853432e3d65a.png)

##### :bulb: Netlify functionsのエンドポイントについて
**`https://ドメイン/.netlify/functions/APIファイル名`**

例）
サイトのURLが`https://hoge-hoge.netlify.app`
APIプログラムのファイル名が`slack.js`だとすると、

APIエンドポイントは
`https://hoge-hoge.netlify.app/.netlify/functions/slack` となる。


## 動作確認
Gitリポジトリへpushし、Netlifyでのビルド・デプロイが成功すると…
![スクリーンショット 2021-01-21 17.02.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274280/dbfc3f9b-ebd9-462e-71c5-30a047123f8f.png)
無事に通知がきました〜！



## 参考
https://docs.netlify.com/functions/overview/
https://functions-playground.netlify.app/