LoginSignup
1
1

More than 5 years have passed since last update.

GithubのissueをSlackに通知する方法2(AzureFunctions+WebHook)

Last updated at Posted at 2018-06-27

初めての投稿につき、やさしい心で見て頂けると嬉しいです。
自分のメモ用を再編集したもので、不備が多いかと思いますが、誰かの役に立てば幸甚です。
細かい部分は覚えていない 初期設定など情報が多々ある部分は、所々省略しています。

やりたいこと

  • Githubのissueを横断的にSlackで見たい
    • ID、タイトル、author、URL、reactionの数(投票などをするため)
  • せっかくなので、RESTAPIではなくGraphQLを使ってみたい

方法1でやったことと問題点

イメージ

方法1(前回の方式)
shg.png

方法2(今回の方式)
sag.png

動作環境

  • MacOS 10.13.5
  • git-graphql-client 1.0.0
  • AzureFunctions 無料プラン
  • Slack 無料プラン
  • Github 無料プラン

STEP1 Azureにアカウントを作る

  • Microsoft Azureはクラウドサービスの集合体です。
  • 今回は、サーバーレスでファイルをあげるだけでURLを呼ぶとプログラムが実行されるAzureFuctionsを利用します。
  • 類似するサービスに AmazonWebService Lambda があります。
  • 今回は、無料枠 で行います。
  • アカウントの作成や資材のアップロードは様々な先人の方がノウハウを残しているので省略します。

STEP2 SlackからWebHookのURLを設定する

  • 日本語化している場合は、slackをカスタマイズ ⇒ App管理 ⇒ カスタムインテグレーション ⇒ 発信/着信Webフックからいけます
  • 発信WebフックがAzureFunctionsを呼び出すもの
    • 引き金となる言葉とazureの関数のURLを設定します。
    • azure Functions側のソースコードが表示されている画面で、関数のURLの取得 で表示されるものを設定
  • 着信WebフックがAzureFUnctionsから投稿されるもの
    • どこのチャンネルに投稿されるのかを指定します
    • WebhookURLは、azureFunction側の送信先のURLに指定します(詳しくは後述するソースを参照)

STEP3 GithubのPersonalAccessTokenを払いだす

  • 細かい手順は、こちらも様々な先人の方がノウハウを残しているので省略します。
  • 公開しているプロジェクトであれば、なにも権限がなくて大丈夫です

STEP4 GraphQLのクエリを作成する

作成したリクエスト

  • owner,name,labelsは自分の条件に合わせて使ってください
    • 今回は、ステータスがOpenで特定のラベルが付いたissueを集めました
    • 条件の追加をする場合は、()内を公式APIドキュメントをみてカスタマイズしてください
{
  repository(owner: "xxx", name: "yyy") {
    issues(last: 100, states: OPEN, labels: "zzz") {
      edges {
        node {
          number
          title
          url
          author {
            login
          }
          reactions(last: 100) {
            nodes {
              content
            }
          }
        }
      }
    }
  }
}

応答イメージ

{
  "data": {
    "repository": {
      "issues": {
        "edges": [
          {
            "node": {
              "number": 1,
              "title": "タイトル",
              "url": "https://github.com/XXX/YYY/issues/1",
              "author": {
                "login": "user"
              },
              "reactions": {
                "nodes": [
                  {
                    "content": "THUMBS_UP"
                  }
                ]
              }
            }
          }
        ]
      }
    }
  }
}

STEP5 package.jsonを書く

  • 最低限の名前とバージョン、依存関係のgithub-graphql-clientを記述したpackage.jsonをファイルのアップロードでサーバに置く
    • 下記のサンプルを参照
    • あるいは、プラットフォームの構成でコンソールからnpmでインストールしてもOKです
{
  "name": "topic-bot",
  "version": "1.0.0" ,
  "dependencies": {
    "github-graphql-client": "1.0.0"
  }
}

STEP6 プログラム本体を記述する

  • 関数の+ボタンで新規作成⇒HTTPtriggerで新しい関数を作る
    • 許可されているHTTPメソッド:All methods
    • モード:Standard
    • 要求パラメータ名:req
    • ルートテンプレート:ルートテンプレート
    • 承認レベル:Function
  • アプリケーションの設定で、Githubのトークンを設定する

プログラム本体

module.exports = function (context, req) {
    context.log('JavaScript HTTP trigger function processed a request.');

    // 準備
    if (!process.env["GITHUB_TOKEN"]) {
       context.res = {
            status: 400,
            body: "please set API token environment value."
        };
        context.done();
    }

    var request = require('request');
    var myquery =
        `{
        repository(owner: "xxx", name: "yyy") { 
            issues(last: 100, states: OPEN, labels: "zzz") { 
                edges { 
                    node { 
                    number 
                        title 
                        url 
                        author { 
                            login 
                        } 
                        reactions(last: 100) { 
                            nodes {  
                                content 
                            } 
                        } 
                    }
                } 
            }
        }  
    }`;
    var githubToken = process.env["GITHUB_TOKEN"];

    var issues = [];
    var client = require('github-graphql-client');
    // githubに問い合わせ
    client({token: githubToken,query: myquery}, function (err, res) {
        if (err) {
            context.log("error");
            context.log(err);
        } else {
            // 成功した場合
            var resData = res.data.repository.issues.edges;
            for (i = 0; i < resData.length; i++) {
                var issue  = {};
                issue.number = resData[i].node.number;
                issue.title = resData[i].node.title;
                issue.url = resData[i].node.url;
                issue.author = resData[i].node.author.login;
                issue.reaction = resData[i].node.reactions.nodes.length;
                issues.push(issue);
            }
            function compareReaction(a,b){
                return b.reaction - a.reaction;
            }
            issues = issues.sort(compareReaction);

            // チャットに返信
            var result = ""
            for (i = 0; i < issues.length; i++) {
                var resultLine = "#" + issues[i].number + ":" + issues[i].title + " :studio_microphone: " + issues[i].author + " :+1: " + issues[i].reaction + "pt " +
                "<" + issues[i].url + "|詳細>\n\n";
                result += resultLine;
            }

            var options = {
                url: {着信Webフックで表示されているURL} ,
                form: 'payload={"text": " '+ result +'"}',
                json :true
            };
            request.post(options, function(error, response, body){
            if (!error && response.statusCode == 200) {
                    context.log('ok');
                } else {
                context.log('error');
                }
            });
        }
    })
    context.done();
};
  • reactionsはtotalCountを使ってもOK
    • 今回は、個別の合計や特定の要素は不要で、全体数がほしいのでこのようにしています。

上手くいかなかったこと

  • botkitを使っても最初はうまくいくのですが、15-30分たつと接続が切れて、再接続のオプションを設定してもダメでした
  • 内容にバグやセッションの維持?があると、正しく切り替えが行われないのか、多重に応答するようになりました。

STEP7 AzureFunctionsにあげて動作確認

  • Slackで実際に呼ぶ

af.png

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1