Old Sunset Days

Netlifyのデプロイ完了をFirebase経由でLINEへ飛ばす

日付 タグ netlify line firebase hugo カテゴリ others

目次

Netlify Webhook + Firebase + LINE Notify

NetlifyのWebhookを利用する

本サイトは個人のブログサイトなので、Githubのmasterブランチと連携しているNetlifyへのデプロイは、masterブランチにマージした時なので、あえてLINEにまで通知を送る必要はない。

しかし、何人かのチームや会社でやっている場合はデプロイ完了などのイベントをLINEグループ等に通知したいことがあるだろう。そんな時はどうするのかちょっと考えてみた。

NetlifyにはWebhookという機能があるので、これをを使えば外部サイトにPost通知が可能。しかし、データフォーマットを整えないと、そのまま直にはLINEには送ることはできない。

今回は前回のLINE Notifyの機能をFirebaseのCloud Functionsでデータを整形した後で叩くことで、
( ==> LINEのNotify通知機能を使ってみる )

Netlify Webhook —> Firebase Cloud Functions —> LINE Notify

というパスでLINE Notifyに通知を送れるかどうかテストしてみたいと思う。

なお、NetlifyのProアカウントユーザーなら、SlackやEmailへなら直接の通知が可能なようだ。 https://www.netlify.com/pricing/ - Netlify Pricing

Netlify Webhookの設定

まずはそもそもNetlifyのWebhookによってどんな内容の通信が来るのかを観察したいので、 Firebase側でhttpsのPOSTで受けた内容をログに書き出すだけの簡単な実装を先にFirebaseにデプロイすることに。

functions/index.js

const functions = require('firebase-functions')

// NetlifyからのWebhook受け付け用
exports.receivePing = functions.https.onRequest(async (req, res) => {
  // NetlifyからのPostを受けつけ
  if (req.method !== 'POST') {
    res.status(405).send('Method Not Allowed');
    return;
  }

  console.log('req body =' + JSON.stringify(req.body));
  res.status(200).send('Hello from Firebase');
});

受け取った中身のJSONをただログに書き出して、成功200を返すだけのreceivePing関数を用意。
これをFirebaseにデプロイする。

$ firebase deploy --only functions
...
...(途中省略)
...
✔  functions[receivePing(us-central1)]: Successful create operation.
Function URL (receivePing): https://[ここはdeploy先のURLになる]/receivePing

ここでFirebaseのデプロイ先のURLをメモしておく。

Firebaseへのデプロイや初期セッティングに関しては、こちらの記事を参照して欲しい。
( ==> FirebaseのCloud FunctionsでHello World )

Firebaseで受け口のAPIができたので、NetlifyのWebhookでデプロイ完了時の通信の向け先をこのAPIのURLに設定する。

Netlifyのサイトにログインしたら、メニューの「Site settings」から
「Build & deploy」-> 「Deploy notifications」を選択。

「Add notification」 -> 「Outgoing webhook」

「Event to listen for」 -> 「Deploy succeeded」(デプロイ成功時)を選択して、
「URL to notify」に先ほどのFirebaseのAPIのURL。

設定を見るとWebhookが追加されているのが確認できる。

これで、デプロイが成功のたびにWebhookでFirebaseにデータが送信されるようになる。

NetlifyのWebhookで送られてくるデータの確認

適当なファイルなり記事を更新して、Netlifyでデプロイが走るようにしてFirebaseに来たログを観察してみる。

Firebaseのコンソールにログインして、Functionsのログを見てみると、先ほどのWebhookで設定した通知が来るようになる。

なお、試したところ、Github上でdevelopブランチからmasterブランチへPull Requestを出して、マージする場合、 Pull Requestの時点でpreview環境へデプロイされるDeploy Previewチェックでも、Webhookの通知が来るようだ。

1) masterブランチへPull Request
2) Deploy previewが走って成功するとWebhook通知が来る
3) Masterへマージする
4) ProductionへのDeployが成功するとWebhook通知が来る

previewかproductionかはWebhookの通知のbranch項目を見れば判別が可能そうだ。

そこでLINEに通知する際に、NetlifyからWebhook通知中のurl、branch、commit_urlをLINE Notifyへ渡してLINEに飛ばす事を考えてみる。

LINE NotifyにNetlifyのWebhookで来た情報を流す

テスト的に使っていたreceivePingを加筆修正して、以下のようにしてみる。

functions/index.js

const functions = require('firebase-functions')
const axios = require('axios')
const querystring = require('querystring')

const LINE_NOTIFY_TOKEN = functions.config().line.token;

// NetlifyからのWebhook受け付け用
exports.receivePing = functions.https.onRequest(async (req, res) => {
  // NetlifyからのPostを受けつけ
  if (req.method !== 'POST') {
    res.status(405).send('Method Not Allowed');
    return;
  }

  console.log('req body =' + JSON.stringify(req.body));
  console.log('url =' + req.body.url);
  console.log('branch = ' + req.body.branch);
  console.log('commit_url = ' + req.body.commit_url);

  // LINE Notify
  let post_message = 'Deployに成功したよ\n'
  + 'url =' + req.body.url
  + '\nbranch = ' + req.body.branch
  + '\ncommit_url = ' + req.body.commit_url + '\n';

  let config = {
    url: 'https://notify-api.line.me/api/notify',
    method: 'post',
    headers: {
      'Content-Type': 'application/x-www-form-urlencoded',
      'Authorization': 'Bearer ' + LINE_NOTIFY_TOKEN
    },

    data: querystring.stringify({
      message: post_message
    })
  }

  try {
    value = await axios.request(config);
    console.log(value.status);
  } catch (err) {
    console.log(err);
  }

  res.status(200).send(post_message);
});

Node.jsでapplication/x-www-form-urlencoded指定でaxiosを使ってPOSTする時はquerystringを使うのが便利なようなのでこれを利用。

LINEのアクセストークンはプログラム中に直接に書き込むのはあまりよろしくないので、通常はこういうものは環境変数にセットするのだが、Firebaseの場合、CLIのfunctions:config:setを使って環境変数をセットできる。

$ firebase functions:config:set line.token="ここには実際に発行されているトークンが入る"
✔  Functions config updated.

なお、この環境変数名は大文字は使えないようだ。最初LINE_NOTIFY_TOKENで変数をセットしようとしたら、

Error: Invalid config name LINE_NOTIFY_TOKEN, cannot use upper case.

としてエラーになった。それじゃ、ということで、line_tokenならどうだと思ったら、

Error: Invalid argument, each config value must have a 2-part key (e.g. foo.bar).

これまたエラーになった。結局、環境変数はline.tokenとした。

環境変数が実際にセットできたか確認。

$ firebase functions:config:get
{
  "line": {
    "token": "ここには実際に発行されているトークンが入る"
  }
}

問題なくセットできたようだ。これでプログラム中から

const LINE_NOTIFY_TOKEN = functions.config().line.token;

で参照できるようになっている。

環境変数がセットされたので、必要な追加パッケージaxios、querystringをインストールしてFirebaseにデプロイする。

$ npm install axios --save
$ npm install querystring --save
$ firebase deploy --only functions

なお、firebase serveでローカル環境でサーバーを起動してテスト時に、この環境変数が同じようにセットされた状態にするには、 ローカル環境にこれと同等の内容を含むファイル.runtimeconfig.jsonfunctionsディレクトリ下に置くことで、ローカル環境でも環境変数が同様に使えるようになる。

firebase functions:config:get > .runtimeconfig.json

ここにはトークン等の機密情報を設定しているので、取り扱いには注意が必要でGithubでコードを管理している場合は、.runtimeconfig.json.gitignoreに入れておいた方が良いだろう。

Netlify Webhook + Firebase + LINE Notifyの貫通テスト

それでは、今まで設定してきたのが通しで動作するのかチェックしてみる。

適当なファイルなり記事を更新してGithubのmasterブランチにマージして、Netlifyでビルド&デプロイが走るようにしてFirebaseに来たログ、およびLINEでの通知を確認する。

developブランチ=>masterブランチへのPull RequestのDeploy previewチェックで通知が1個
masterブランチへのmergeでNetlifyのproductionにDeployされた時に通知が1個

合計2個の通知を受け取ったので、これで通知は取得できてそうだ。

以上、前回わかったLINE Notifyを利用して、Netlifyのデプロイ成功時にFirebase経由でLINE Notifyで通知するようにしてみた。 他にもいろいろと使い方があるかもしれない。また、Firebaseはちょっとしたデータを加工して、別へデータを流すのには便利そうですね。