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

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が使われていて、僕も色々と試してみようと思い昨晩ビールでも飲みながら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生成できるやつ書いた

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が気になる。

続きを読む