読者です 読者をやめる 読者になる 読者になる

be-hase blog

主にプログラミングについて書くんだよ

LINE Notifyでたのでちょっと試してみる。ついでにGithub Enterpriseのwebhookを通知するやつを作ったぞ!!

LINE Notifyがリリースされたぞ!!

2016/09/29にLINE DeveloperDay 2016が開催され、いくつかの新機能などが発表されました。
http://developers.linecorp.com/blog/ja/?p=3779

その中のひとつに、LINE Notifyというものがあります。
一言でいうと、簡単にLINEにメッセージを送信することができるサービスです。
messaging APIと違って"LINE Notifyアカウント"からしか送信できないといった制限はありますが、その制限に耐えうるメリットがあるように思えます。

ちょっと試しにcurlから実行してみるぞ!!

なにはともあれ、ちょっと試しにcurlから実行してみます。

LINE Notifyにログインして、マイページにいきます。
https://notify-bot.line.me/my/

ここからPersonal Tokenを発行することができます。

f:id:hsbrysk:20161001170805p:plain

tokenの名前と、送り先を選択するだけです。

f:id:hsbrysk:20161001173948p:plain

発行したPersonal Tokenを用いて、

curl https://notify-api.line.me/api/notify -H 'Authorization: Bearer MY_TOKEN' -d 'message=hello'

とシェルで実行するだけでメッセージを送信することができます。

f:id:hsbrysk:20161001174244p:plain

こういったことが使えるだけでも色々な用途が思いつきます。
(王道っぽいですが)例えば、

  • depoyなどにフックさせて実行してみたり、
  • process downしてるのを検知したら送るようにしてみたり、
  • cron処理結果を送ったり、
  • Jenkinsのビルド後の処理に上記コマンドをいれてみたり、

...どれも手軽に使えて便利っぽい雰囲気を感じます。

すでにこんな使い方もされているようですね。真似してみよう。

YappoLogs: LINE Notify で line command 作ると便利

OAuth認証を実装することで、webサービスとも連携することができるぞ!!

Personal Tokenだけでも便利なんですが、OAuth認証を実装することでwebサービスとも連携することができます。
WEBサービスでメール通知などをしていることが多いと思いますが、同じスキームでLINEに送信することができます。

実際にすでにIFTTT, Mackerel, Githubで連携が実装されています。

IFTTTと連携してみるぞ!!

例えば自分は、同居人と家事等をTrelloで管理して分担している。
いままではIFTTTの送り先をslackにして通知していたのですが、同居人はslackは使用していません。
わざわざこのためにslackをインストールさせてアカウントを作らせるのは面倒なので、自分だけで通知を享受して便利!って感じでした。

LINEだと、すでに同居人も使用しているのでちょっとこのgroupに入ってくれい!という感じで自然に誘導できて簡単便利だぞ、と思いました。

これでトイレットペーパーを買い忘れて冷や汗をかくこともなくなります。

IFTTT連携の仕方は、すでに他の方が記事が書かれているので参考になると思います。
netafull.net

Githubと連携してみるぞ!!

Github連携もしてみます。

LINE Notifyのtop pageにいくと、Githubのアイコンがあるのでそれをクリックします。
https://notify-bot.line.me/github/repos/select

すると、LINE NotifyとのGithub連携する画面が出てきますので、許可します。
許可をすると、このページに遷移します。

f:id:hsbrysk:20161001171822p:plain

連携したrepositoryを選択し、LINEの通知先を選択するだけで完了です。カップヌードルができるよりも早くて楽チン!!

githubのwebhook eventを利用しているので、もしもこのeventは不要だなと思うのがあればGithubのwebhool設定ページのチェックを外しても良さそう。

f:id:hsbrysk:20161001172244p:plain

ちなみに対応しているeventは、

  • create
  • delete
  • commit_comment
  • issues
  • issue_comment
  • push
  • pull_request
  • pull_request_review_comment

とのこと。

Mackerelと連携してみるぞ!

と、簡単に書こうと思ったのですがこちらのHelpページが参考になるので参考にしてください。

mackerel.io

グラフとかも送られてくるの、すごい良さそう!

せっかくだし、なにかLINE Notifyを利用して作るぞ!!

さて、せっかくだしなにを作るぞ!
OAuthを実装するのはちょっとサクッと作るには面倒なので、Personal Tokenを利用するくらいが今回は無難そう。

考えた結果、Github Enterprise用のやつを作ってみようと思った。
LINE Notifyからはgithub.comとは手軽に連携できるのですが、Github Enterpriseとはできません。
会社の業務ではGithub Enterprise使っているので、Github Enterpriseでも使いたいぞ!というのがモチベーションです。

ghe-line-notify

そんなわけで、作ったやつがこれです。
https://github.com/be-hase/ghe-line-notify

Github Enterprise用ではありますが、github.comでも使用できます。

使い方

インストール/起動の仕方などは後述。

1. LINE NotifyでPersonal Tokenを発行する

LINE Notifyのマイページから作れます。
https://notify-bot.line.me/my/

tokenの名前(ghe-line-notifyとかで良い)と、送り先を選びます。

2. Personal TokenとWebhook Message Templateをghe-line-notifyに登録する

ヘッダーの"Add Token"をクリックすると、こんなform pageが表示される。

f:id:hsbrysk:20161001172404p:plain

まずはBasicsの情報を入力する。
Github webhookのSecretを利用したい場合は、Secretも入力する。そしたら同じSecretをGithub Webhookにも設定すれば良いです。
例えば違う部署を跨いで複数人でghe-line-notifyを利用する場合は、勝手にwebhookを利用されないようにSecretを使っておくと良いと思います。

次にWebhook Message Templateを入力する。

f:id:hsbrysk:20161001172449p:plain

各webhook eventで送られてるくるpayload jsonを使って、Jinja2テンプレートの記法で書けばです。
なんでJinja2なのかというと、ghe-line-notifyはPythonで実装しているからです。

ちなみに、webhook eventやpayload jsonはこのページを見ればわかります。
https://developer.github.com/webhooks/#events

各textareaには、とりあえず汎用的で便利そうなやつを予め入力してあるので、このまま登録しても良いです。

例えば、commit eventでは次のようなpayload jsonGithubから送られてきます。(一部省略)

{
  "ref": "0.0.1",
  "ref_type": "tag",
  "master_branch": "master",
  "description": "",
  "pusher_type": "user",
  "repository": {
    "id": 35129377,
    "name": "public-repo",
    "full_name": "baxterthehacker/public-repo",
    "owner": {
      "login": "baxterthehacker",
      "id": 6752317,
      ....
      "type": "User",
      "site_admin": false
    },
    "private": false,
    "html_url": "https://github.com/baxterthehacker/public-repo",
    ....
    "watchers": 0,
    "default_branch": "master"
  },
  "sender": {
    "login": "baxterthehacker",
    "id": 6752317,
    ....
    "site_admin": false
  }
}

このcreate eventに対して次のようなtemplateを登録しているとします。

{{ sender.login }} created {{ ref_type }} {{ ref }} at {{ repository.full_name}}

{{ repository.html_url }}

そうすると、LINEには次のようなテキストで送られるわけです。

baxterthehacker created tag 0.0.1 at baxterthehacker/public-repo

https://github.com/baxterthehacker/public-repo

ちなみに、Jinja2でレンダリングした結果が、空文字である場合はLINEには送信しません。 これを応用することで、次のようなif Statementsをいれることで、ref_typeがbranch以外のやつはLINEには送信しないことも可能です。

{%- if ref_type == 'branch' -%}
{{ sender.login }} created {{ ref_type }} {{ ref }} at {{ repository.full_name}}

{{ repository.html_url }}
{%- endif -%}

push eventのときはmaster branchのときだけ通知したり、pull request eventのactionが"opened"のときだけ送るなどといったカスタマイズが自由にできます。
自分自身もまだこの辺どうするのかは手探りなので、ちょっと手間はかかるけど自由にいろいろカスタマイズできるようにしています。

templateの挙動はヘッダーにある"Template Playground"ページから確認できます。

3. Githubのwebhookに登録する

Tokenの登録が完了すると、次のような画面が表示されます。

f:id:hsbrysk:20161001172625p:plain

一意なcodeが生成され、Github webhookに登録するPayload URLが表示されるので、Github上に登録します。
Content-typeはapplication/jsonにします。
Secretを使った場合は、Secretも入力しましょう。

f:id:hsbrysk:20161001172741p:plain

なお、登録したTokenは"Token List"に表示され、随時編集もできる。
やっぱりmessageを変えたいぞ!!ってときは変更できます。

インストール/起動方法とか

READMEに書いてあります。
https://github.com/be-hase/ghe-line-notify

すぐに動かして見たい場合は、READMEにあるherokuボタンを押せば完了です。

しかし、Github Enterpriseを使うような環境ではHerokuとは接続できないでしょう。
その場合は、READMEに書いてあるようにpython3をinstallしたサーバで、

git clone https://github.com/be-hase/ghe-line-notify
cd ghe-line-notify

pip install -r requirements/common.txt

python manage.py db upgrade

gunicorn -c gunicorn_config.py app:app

とかすれば良いです。
なお、python3.5.xでしか動作確認はしていないので、うまくいかなかったら最新版にあげてみてください...。

もしくは、Dockerfileも置いてあるのでDockerで動かしても良さそうです。

alembicを使ってDB migrateをしています。
デフォルトだと、sqliteを使用します。
失ったら死ぬ!といったデータでもないですし、sqliteで十分なのでは...と思っていますが、もしも変えたい場合は環境変数GHE_LN_DATABASE_URIを指定すればいいです。

heroku上で立ち上げるときは、herokuのaddonで用意されているpostgresqlを使用するようにしています。

今後修正実装しようかなと思っていること

「gheのOAuth2連携できるようにして!」って同僚から言われたので、あとで作ってみようかなと思っている。

まとめ

  • Personal Token発行するだけでサクっとcurlからでも使えるので便利!
    • 今回紹介したghe-line-notifyみたいなツールもサクっと作ることができる!
  • OAuth2実装すれば、自分のWEBサービスとかからも通知できる!

なにか他にも面白そうなのがあれば、githubとかにあげてこうかなと思っています。

Reluminでslowlog見れるようにした

Relumin Redis

やったこと

ReluminっていうRedis Cluster Admin Toolでslowlog見れるようにしてくれい!という依頼があったので、実装してみた。
こんな感じになります。

f:id:hsbrysk:20160624010805p:plain

GitHub - be-hase/relumin: Redis cluster admin tool

横軸に時間とって、縦軸にslowlogの実行時間(micro seconds)をノードごとに色分けしてscatter plotしていっている。
hoverするとツールチップでslowlogのコマンドとかも見れる感じ。

graphの下には、tableで羅列している。

Redisみたいにシングルスレッドでイベントループしてるやつで長い実行時間のcommandあると危険なので、
頻発するようだったら対処してあげてみてください。

今後

時間と気合があったらやることリスト

  • INFOコマンドで取得したmetricsに対してはalertできる機能あるので、slowlogもalertしてあげても良いかもしれない。
  • Redis3.0.6くらいから付属しているredis-trib.rbには良い感じに均等にリバランシングする機能がついたので、Relumin上でも実装してワンクリックでリバランシングできるようにしても良いかもしれない。
    • 今だとRelumin上でノードごとに複数回リシャードしないといけないので、少し面倒くさい。
  • Jedis2.9からclusterでもpassword設定できるようになるので、その対応しておこうかな。
    • でも他の言語のclientはまだpasswordのサポートしてなさそうだからあとでいいかな。
  • React(SPA)で書いてるフロント部分、Typescriptで書きなおそうかな。
  • metricsとかメタデータ保存しているstorage, RDBで実装するの面倒だったのでRedis使ってるんだけど明らかにお金もったいないのでRDBも使用できるようにしようかな。
    • チーム内でこじんまりと使うぶんにはよかったけど...

Java(Maven) + Docker + CircleCI + CodecovなCI環境にしたメモ

Java Docker CircleCI

1年位前に個人で開発していたReluminというRedis Cluster Admin Toolがあるんですが、
久しぶりに新しい機能いれるかってなって、ついでにtest + local env周りのちょっと残念な部分というか手抜きしていた部分を刷新してみた。

github.com (気が向いたら、Relumin自体のエントリもそのうち書こう)

以前の環境

個人で作っていたものだったので雑にVagrantでRedis cluster構築して、開発時とかunit testのときはそのVagrantのRedisに接続してごにょごにょとやっていた。

特にCI toolとかも回さず、手元でmvn testしてそれでいいや、みたいな感じ。

今の環境

Docker

Vagrantを捨てて、Dockerにした。 やっぱり起動早いし、使い捨てとかしやすいし、そのままCircleCIでも動かせたりするっていうのが理由。

Dockerfileはこんな感じ。
relumin/Dockerfile at develop · be-hase/relumin · GitHub

ちなみにやたらとEXPOSEしているけど、

  • 9000
    • meta data保存する用のRedis
  • 10000 ~ 10005
    • Redis Clusterのnode 6台
  • 20000 ~ 20005
    • Redis Clusterのnode間通信用 (gossip通信)
    • これもちゃんとやらないとcluster作れないので注意。ついつい忘れがち。
  • 10010 ~ 10015
    • 普通のRedis。いまのところ使っていない。

という用途です。

慣れでそのままsupervisord使ってしまったが、centos7にしてsystemdとかで良いと思う。

CircleCI

最初は慣れているtravisを使用していたのだけどDocker imageのcacheがうまく出来なくて、途中からCircleCIにした。
毎回docker buildするのは時間かかって辛い。
最近会社でCircleCI Enterpriseが導入されそうっていうのも理由のひとつであったりするし、なによりもsshできるのは良い。

circle.ymlはこんな感じ。
relumin/circle.yml at develop · be-hase/relumin · GitHub

Docker imageのcacheはこのあたりでやっている。

dependencies:
  cache_directories:
     - "~/docker"
  override:
    - if [[ -e ~/docker/image.tar ]]; then docker load -i ~/docker/image.tar; fi
    - docker build -t relumin/relumin-test .
    - mkdir -p ~/docker; docker save relumin/relumin-test > ~/docker/image.tar

参考 : Continuous Integration and Delivery with Docker - CircleCI

ちなみに、
dependencies:overrideでmvn install -DskipTestsしているのは、mavenをcacheさせるため。
もう少し適切なgoalがある気はする。

Codecov

Coverage toolは色々あるけど、Codecovを使ってみた。

Codecovにした理由は、
documentの量とか他のものより多かったし、こっちのほうがUIが好みだったのと、カバレッジサービスのための依存lib(uploadするためのlib)がなかったから。

mavenの場合は、pomにjacocoのpluginを入れるだけで良い。 (jacoco自体は、javaで一般的なカバレッジツール)

<plugin>
    <groupId>org.jacoco</groupId>
    <artifactId>jacoco-maven-plugin</artifactId>
    <version>0.7.7.201606060606</version>
    <executions>
        <execution>
            <goals>
                <goal>prepare-agent</goal>
            </goals>
        </execution>
        <execution>
            <id>report</id>
            <phase>test</phase>
            <goals>
                <goal>report</goal>
            </goals>
        </execution>
    </executions>
</plugin>

circle.ymlにこんな風に書いている。

test:
  override:
    - docker run -d --net="host" -p 9000:9000 -p 10000:10000 -p 10001:10001 -p 10002:10002 -p 10003:10003 -p 10004:10004 -p 10005:10005 -p 20000:20000 -p 20001:20001 -p 20002:20002 -p 20003:20003 -p 20004:20004 -p 20005:20005 -p 10010:10010 -p 10011:10011 -p 10012:10012 -p 10013:10013 -p 10014:10014 -p 10015:10015 relumin/relumin-test
    - mvn test jacoco:report -DargLine="@{argLine} -Dspring.profiles.active=ci"
  post:
    - mkdir -p $CIRCLE_TEST_REPORTS/junit
    - find . -type f -regex ".*/target/surefire-reports/.*xml" -exec cp {} $CIRCLE_TEST_REPORTS/junit/ \;
    - cp -r ./target/site/* $CIRCLE_TEST_REPORTS/
    - bash <(curl -s https://codecov.io/bash)

mvn test jacoco:report -DargLine="@{argLine} -Dspring.profiles.active=ci"でテストレポートが諸々作成される。
CircleCI上では、Spring bootの"ci" profileで実行したいので-DargLine="@{argLine} -Dspring.profiles.active=ci"を付与している。

jacoco自体もargLineを利用しているため、@{argLine}をつけないと上書きされてしまってjacocoが上手く動かないので注意。 ハマった。

test reportを
find . -type f -regex ".*/target/surefire-reports/.*xml" -exec cp {} $CIRCLE_TEST_REPORTS/junit/ \
cp -r ./target/site/* $CIRCLE_TEST_REPORTS/
でCIRCLE_TEST_REPORTSに移動することで、CircleCI上のArtifactsで見れるようにしている。こんな感じ。
Continuous Integration and Deployment

最後にbash <(curl -s https://codecov.io/bash)を実行することで、Codecovにtest reportを送信している。

test code自体もがっつり書き直した。
Mockitoで済むところはMocktioだけでいい。全部springかましたtestでやると遅くて辛い。
( springかますのは、最終的なintegrateなtestと、DAOくらいでいいかなと。 )

所感

仕事だとJenkinsでこういったことやってるけど、やっぱりこの手のツールのほうが楽だし簡単。UIも綺麗で嬉しい。

Prometheusのfluentd_monitor_agent_exporter書いた

Prometheus

最近身の回りでPrometheusが使われていて、僕も色々と試してみようと思い昨晩ビールでも飲みながらdocumentを眺めてた。

ほほう...なるほどと思い、次は適当になんかexporterでも書いてみっか!ってなって、ちょうど昨日fluentd meetupやってたのでfluentdのmonitor agentの情報をexportするやつ書いてみた。

github.com

fluentd monitor agent plugin使うと、buffer_queue_length, buffer_total_queued_size, retry_countが取得できるのでそれをexportしてる。 Monitoring Fluentd | Fluentd

各自のoutput pluginの設定に応じて、適切なalertとか飛ばしてあげるといいかなって感じです。

(Java) Lambda使っていい感じにMapとかClass生成できるやつ書いた

Java

MapとかPOJO作るのに疲弊してきた

疲弊しすぎて、イライラして書いた。

https://github.com/be-hase/lamtils

Lambda使ってこんな感じで、さっくりと作れる。

例) HashMap :

Map<String, Object> map = Lamtils.newHashMap(
    one -> "one",
    two -> 2,
    three -> new Date(),
    four -> 4.0
);

よっしゃ!なんかLL言語っぽい感じになったぞ!

例) POJO(JavaBeans) : setter実装していないと駄目

public static class TestPojo {
    private String one;
    private int two;
    private Date three;
    private double four;
    private boolean five;
    
    // setter, getterは省略 
}

TestPojo pojo1 = Lamtils.newClass(
    TestPojo.class,
    one -> "one",
    two -> 2,
    three -> now,
    four -> 4.0,
    five -> true
);

// もちろん指定したやつだけセットできる
TestPojo pojo2 = Lamtils.newClass(
    TestPojo.class,
    one -> "one"
);

よっしゃ!なんかGroovyとかScalaのあれっぽくなったぞ!
でもTestPojo.classって指定するのがダルい。 本気でやるならlombokみたいにしたい。

注意(重要)

結論

冷静に頭を冷やした結果、これからもGuavaのImmutableMap.of(...)とか、lombokの@Builderとか@Accessorsのfluentとか使って頑張る。

でも、こういう記法ができるってのはなんだか可能性を感じた。
なんか他にも応用できるといいなぁ。

Jenkins2.0のPipelineを触ってみたら便利だった

Jenkins2.0でてた

f:id:hsbrysk:20160428172413p:plain

Jenkins2.0がでてた。
https://jenkins.io/2.0/

ざっくりと概要を見ると、主な変更点は次の3つらしい。

  1. Built-in support for delivery pipelines.
  2. Improved usability.
  3. Fully backwards compatible.

2に関しては、単純に見た目が良くなったよってこと。嬉しい。
3に関しては、後方互換性あるよってこと。幸せ。アップデートしない理由は理由ありませんということ。

1が気になる。

続きを読む

ブログ放置してた

2年位前に"書くことに集中するなら、自分でサーバーを持つよりも良さそうです。"とか言っておきながら放置してた。

放置しすぎててアレなので、 明日から本気だす。