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

SonarQubeを使ってみた #sonarqube

概要

Javaで作ってるリポジトリにSonarQubeを適用してみました。

SonarQubeとは?

SonarQubeは、ソースコードの静的解析ツールです。

www.sonarqube.org

今回はオープンソースであれば無料で使えるSonarQube.comを利用します。

about.sonarqube.com

アカウント

GitHubアカウントがあれば、それを利用してログインできます。

https://sonarqube.com/sessions/new

トークンの発行

適当な名前を付けて、トークンを発行します。

トークンはどこかに退避しておきます。

https://sonarqube.com/account/security

Organizationsの確認

Organizationsを確認します。

デフォルトで personal organization が作られているはずです。

※自分の場合は su-kun1899-github でした。

https://sonarqube.com/account/organizations

実行してみる

自分のプロジェクトはMavenを使っているので、mvnコマンドから実行します。

mvn sonar:sonar \
    -Dsonar.host.url=https://sonarqube.com \
    -Dsonar.organization=<あなたのorganization> \
    -Dsonar.login=<あなたのトークン>

Maven周りの設定の詳細は下記を参照

Analyzing with SonarQube Scanner for Maven - Scanners - Doc SonarQube

結果を確認してみる

ビルドログに下記のようなURLが出ているのでアクセスしてみます。

[INFO] ANALYSIS SUCCESSFUL, you can browse https://sonarqube.com/dashboard/index/red.sukun1899:shishamo

いい感じです。

CIに組み込む

CircleCIを使っているのでymlファイルに追加ます。

トークンは環境変数に入れておきました。

test:
  override:
    - mvn integration-test
    - mvn sonar:sonar -Dsonar.host.url=https://sonarqube.com -Dsonar.organization=su-kun1899-github -Dsonar.login=${SONAR_QUBE_TOKEN}

まとめ

get-started に従ってやったら簡単にできました。

静的解析をかけて修正すべきポイントも見つかりました。

https://about.sonarqube.com/get-started/

実際に適用したプロジェクトはこちら。

https://sonarqube.com/dashboard?id=red.sukun1899%3Ashishamo

github.com

GitHubのAPIを使って、Releaseコンテンツを取得する

概要

GitHubAPIも触らないまま大人になってしまった。

せっかくなのでモブプロにお世話になっているMobsterをAPI経由でダウンロードしてみます。

Releaseコンテンツ

リリースページからDownloadできるやつらのことです。

APIの表現だとassetsというようです。

Release 0.0.30 · dillonkearns/mobster · GitHub

GitHub API

Release関連のAPIがあるのでそれを使います。

Releases | GitHub Developer Guide

Releaseの取得

APIcurlで叩いてみます。

一覧取得は下記のような感じです。

curl https://api.github.com/repos/dillonkearns/mobster/releases

レスポンスがたくさん出てきてうんざりしました。

最新を取得するAPIもあるようです。

curl -v https://api.github.com/repos/dillonkearns/mobster/releases/latest

上記で返ってくる url がrelease取得用です。

{
  "url": "https://api.github.com/repos/dillonkearns/mobster/releases/6174887",
  "assets_url": "https://api.github.com/repos/dillonkearns/mobster/releases/6174887/assets",
  "upload_url": "https://uploads.github.com/repos/dillonkearns/mobster/releases/6174887/assets{?name,label}",
 ・・・以下略
}

なので、下記でも同じ結果が取得できます。

curl -v https://api.github.com/repos/dillonkearns/mobster/releases/6174887

Assetsの取得

assets_url を叩くと、releaseに紐づくAssetsの一覧が取得できます。

※release取得のAPIでもレスポンスに含まれています

curl -v https://api.github.com/repos/dillonkearns/mobster/releases/6174887/assets

今回はMac用のファイルを対象にしてみたいと思います。

[
・・・略
  {
    "url": "https://api.github.com/repos/dillonkearns/mobster/releases/assets/3728974",
    "id": 3728974,
    "name": "Mobster-0.0.30.dmg",
    ・・・略
    }
・・・略
]

url を叩けば対象のAssetsの情報だけ取得できます。

curl -v https://api.github.com/repos/dillonkearns/mobster/releases/assets/3728974

Assetsのダウンロード

Assetsをダウンロードするには、HTTPヘッダに Accept: application/octet-stream を付けます。

curl -vLJO -H 'Accept: application/octet-stream' https://api.github.com/repos/dillonkearns/mobster/releases/assets/3728974
  • リダイレクトされるので、Lオプションを付けてます
  • ファイル名そのままで保存するためにJOオプションを付けてます

TOKENを使う

TOKENを使って認証付きでAPIを叩けます。

対象がprivateリポジトリである場合などに有効です。

またAPIは時間あたりの呼び出し回数に制限があります。

認証付きの方が上限ゆるく設定されています。

GitHub API v3 | GitHub Developer Guide

認証なしでAPI上限越えると下記のようなレスポンスが返ってきます。

{
  "message": "API rate limit exceeded for XXX.XXX.XXX.XXX. (But here's the good news: Authenticated requests get a higher rate limit. Check out the documentation for more details.)",
  "documentation_url": "https://developer.github.com/v3/#rate-limiting"
}

TOKENを発行する

[Personal access tokens]から新しいトークンを発行します。

https://github.com/settings/tokens/

privateリポジトリの場合、scopeはrepoだけあれば大丈夫でした。

TOKENを使ってAPIを叩く

uオプションでトークンを渡してあげればOKです。

curl -vLJO -u :07381d41a0f3f0a313dd26c75bb721e71cdd1809 -H 'Accept: application/octet-stream' https://api.github.com/repos/dillonkearns/mobster/releases/assets/3728974

まとめ

自動化とかは簡単にできそうです。

今回はcurlで愚直にやりましたが、自分でスクリプト組むより Octokit とか使ったほうが便利らしいので、機会があったら使ってみようと思います。

参考

nodebrewでNode.jsをインストールしてHello World

nodebrewのインストール

インストール

$ curl -L git.io/nodebrew | perl - setup

bash_profileにPATHを追加

export PATH=$HOME/.nodebrew/current/bin:$PATH

$ source .bash_profile

Node.jsのインストール

7.9.0をインストール

$ MAKE_OPTS="-j 2" nodebrew install-binary v7.9.0

無事インストールできました。

$ nodebrew use 7.9.0
use v7.9.0
$ node -v
v7.9.0

Hello World

ディレクトリを作ってinit。

$ mkdir ~/hello-node-js/
$ mkdir ~/hello-node-js/
$ cd ~/hello-node-js/
$ npm init -y

app.jsを直下に作成

'use strict';

function main(){
   console.log('Hello Node.js!');
}

main();

実行。

$ node app.js
Hello Node.js!

参考

ローカルで作成したブランチがリモート追跡されない #git

ローカルで新規にブランチを作成してpush

git push origin [ブランチ名]

リモートのブランチを追跡してくれない。

git branch -vv しても追跡ブランチが出てこない。

set-upstream-toを使う

git git branch --set-upstream-to=origin/[ブランチ名]

これで git branch -vv で見られるようになる。

pushするときに set-upstream-to 付けといてもよい

git push --set-upstream origin [ブランチ名]

–set-upstreamは-uと一緒

git branch -u origin/[ブランチ名] git push -u origin [ブランチ名]

-uでもOK。

Javaで期間の日数を計算する #java

概要

2016年1月7日から2017年4月27日みたいな期間の日数を数える方法。

Period…惜しい

日付の期間を扱うには java.time.Period クラスがあるが、悲しいことに日数をカウントするAPIがない。

getDays() は日付だけで計算をするため、月をまたいだ日数のカウントにはならない。

Period period = Period.between(LocalDate.of(2017, 1, 1), LocalDate.of(2017, 2, 1));
int count = period.getDays(); 
System.out.println(count); // 31ではなく、0が返ってくる

ちなみに月は getMonths() とは別に期間の合計月数を取得できる toTotalMonths() がある。

なぜ toTotalDays() はないのだ。。

Durationならいける

時間ベースの期間を表す java.time.Duration クラスであれば、日数をカウントできる。

Duration duration = Duration.between(LocalDate.of(2017, 1, 1).atTime(0, 0, 0), LocalDate.of(2017, 2, 1).atTime(0, 0, 0));
long count = duration.toDays();
System.out.println(count); // 31!

※LocalDateTimeで最初からインスタンスを作っても良いが、日付の意図を示すためにあえて atTime() を使用

ChronoUnitでもOK

期間を表現する必要がなくて、本当に日数をカウントするだけなら java.time.temporal.ChronoUnit でよさそう。

long count = ChronoUnit.DAYS.between(LocalDate.of(2017, 1, 1), LocalDate.of(2017, 2, 1));
System.out.println(count); // 31!

参考

CircleCIでjacocoのカバレッジレポートをとる #circleCi #jacoco #java

概要

SpringBoot + Spock + maven で開発をしているんだけれど、せっかくテストも書いているのでカバレッジレポートをCI時に取得するようにする。

pom.xmlにjacocoプラグインを追加

...
<build>
    ...
    <plugins>
        ...
        <plugin>
            <groupId>org.jacoco</groupId>
            <artifactId>jacoco-maven-plugin</artifactId>
            <version>0.7.9</version>
            <executions>
                <execution>
                    <id>prepare-agent</id>
                    <goals>
                        <goal>prepare-agent</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
        ...
    </plugins>
</build>
...
<reporting>
    <plugins>
        <plugin>
            <groupId>org.jacoco</groupId>
            <artifactId>jacoco-maven-plugin</artifactId>
            <reportSets>
                <reportSet>
                    <reports>
                        <report>report</report>
                    </reports>
                </reportSet>
            </reportSets>
        </plugin>
    </plugins>
</reporting>
...
  • execution を設定しておけば、test時に自動で prepare-agent を実行してくれる
  • reporting は必要なのかどうか実はよく分かっていない。。
  • これで mvn clean test jacoco:report とかやると、target配下にレポートが出力されるようになる

circle.ymlの修正

test:
  override:
    - mvn integration-test
    - mvn jacoco:report
  post:
    - mkdir -p $CIRCLE_ARTIFACTS/site/jacoco
    - mv target/site/jacoco/ $CIRCLE_ARTIFACTS/site/jacoco
  • testブロックでカバレッジレポートを出力するようにする
  • testのpostブロックで $CIRCLE_ARTIFACTS のレポート成果物を配置する

そうすると、下記のような感じでレポートが参照できるようになる。

https://26-80196016-gh.circle-artifacts.com/0/tmp/circle-artifacts.RCejr3V/site/jacoco/jacoco/index.html

なお、test-postブロックはtestの成否に関わらず実行されてしまうので非効率であるのだが、とりあえずはこのままでよしとしている。

まとめ

実際に適用したプロジェクトは下記。
GitHub - su-kun1899/mysql-visualizer: Mysql Metadata Viewer

jacocoのレポート、UIはパット見時代を感じさせるのだけれど、見やすく分かりやすくて良い。

f:id:su-kun1899:20170417232708p:plain

f:id:su-kun1899:20170417232642p:plain

参考

flywayで差し込みバージョンを適用する #flyway

こんな感じの時、間に差し込みバージョンを作る。

+------------+-----------------+---------------------+---------+
| Version    | Description     | Installed on        | State   |
+------------+-----------------+---------------------+---------+
| 1.0        | init            | 2017-01-01 10:00:00 | Success |
| 2.0        | add2            | 2017-01-02 10:00:00 | Success |
| 3.0        | add3            | 2017-01-03 10:00:00 | Pending |
+------------+-----------------+---------------------+---------+

flyway:infoすると、ignoredとして認識される。

+------------+-----------------+---------------------+---------+
| Version    | Description     | Installed on        | State   |
+------------+-----------------+---------------------+---------+
| 1.0        | init            | 2017-01-01 10:00:00 | Success |
| 1.1        | patch1          | 2017-01-02 10:00:00 | Ignored |
| 2.0        | add2            | 2017-01-02 10:00:00 | Success |
| 3.0        | add3            | 2017-01-03 10:00:00 | Pending |
+------------+-----------------+---------------------+---------+

この状態でflyway:migrateすると、エラーになる。

下記はMavenプラグインで実行した場合。

[ERROR] Failed to execute goal org.flywaydb:flyway-maven-plugin:3.2.1:migrate (default-cli) on project shotaki: org.flywaydb.core.api.FlywayException: Validate failed. Detected resolved migration not applied to database: 1.1 -> [Help 1]

outOfOrderオプションをtrueにして実行すると、Ignoredも含めて実行してくれる。

Mavenプラグインコマンドラインで直接指定だと下記のような感じ。

mvn flyway:migrate -Dflyway.outOfOrder=true

この方法で実行すると、当該バージョンとそれ以降で適用済だったバージョンのStateがOutOrdrになる。

+------------+-----------------+---------------------+---------+
| Version    | Description     | Installed on        | State   |
+------------+-----------------+---------------------+---------+
| 1.0        | init            | 2017-01-01 10:00:00 | Success |
| 1.1        | patch1          | 2017-01-02 10:00:00 | OutOrdr |
| 2.0        | add2            | 2017-01-02 10:00:00 | OutOrdr |
| 3.0        | add3            | 2017-01-03 10:00:00 | Success |
+------------+-----------------+---------------------+---------+

参考

FlywayでDBスキーマのマイグレーションをしてみたsiguniang.wordpress.com