すでに存在するデータベースにFlywayを適用する(その2) #flyway

概要

下記記事の続き。

今度はbaselineの設定を活用して、SQLとFlywayの足並みを調整する。

su-kun1899.hatenablog.com

テスト用のデータベースを作る

create database if not exists flyway_sample character set utf8

flyway管理外のテーブルを追加する

mysql -u root -D flyway_sample_2
create table person (
    `person_id` int not null,
    `name` varchar(100) not null
);
create table hoge (
    `hoge_id` int not null,
    `name` varchar(100) not null
);

DDLを作成する

  • src/main/resources/db/migration
    • V1_0_0__create_person.sql
    • V1_0_1__create_hoge.sql
    • V1_2_0__create_fuga.sql
    • V1_2_1__create_piyo.sql

この場合、既にpesonテーブルとhogeテーブルは作成済のため、実際に適用したいのは V1_2_0 以降となる。

Baselineを設定する

pom.xmlにて、baselineOnMigratebaselineVersion を指定する。

baselineOnMigrateをtrueにして、baselineを有効化する。

baselineVersionは指定したバージョンがBaseline(適用済)となる。

つまり、1.0.1 を指定すると 1.2.0 移行のSQLがFlywayでMigrateされる

<build>
    <plugins>
        <plugin>
            <groupId>org.flywaydb</groupId>
            <artifactId>flyway-maven-plugin</artifactId>
            <version>4.0.3</version>
            <configuration>
                <url>
                    jdbc:mysql://localhost:3306/flyway_sample
                </url>
                <user>root</user>
                <!-- Baselineの設定 -->
                <baselineOnMigrate>true</baselineOnMigrate>
                <baselineVersion>1.0.1</baselineVersion>
            </configuration>
            <dependencies>
                <dependency>
                    <groupId>mysql</groupId>
                    <artifactId>mysql-connector-java</artifactId>
                    <version>5.1.6</version>
                </dependency>
            </dependencies>
        </plugin>
    </plugins>
</build>

flyway:migrate する

mvn flyway:migrate 
+---------+-----------------------+---------------------+---------+
| Version | Description           | Installed on        | State   |
+---------+-----------------------+---------------------+---------+
| 1.0.0   | create person         |                     | <Baseln |
| 1.0.1   | << Flyway Baseline >> |                     | <Baseln |
| 1.2.0   | create fuga           | 2017-06-08 09:51:07 | Success |
| 1.2.1   | create piyo           | 2017-06-08 09:51:07 | Success |
+---------+-----------------------+---------------------+---------+

注意事項

  • Baseline以前のDBの状態はユーザに委ねられるため、Flyway側では保証されない(当たり前だけど)
  • データベースが空の場合、Baselineが効かない?
    • 空なので、途中から流す必要ないので特に問題はないのだけれども

まとめ

flywayが好きだ。

すでに存在するデータベースにFlywayを適用する #flyway

概要

Baselineを使って、MySQL+Mavenで、FlywayによるDB構成管理を既に存在するデータベースに適用する。

Flyway by Boxfuse • Database Migrations Made Easy.

テスト用のデータベースを作る

create database if not exists flyway_sample character set utf8

flyway管理外のテーブルを追加する

mysql -u root -D flyway_sample
create table person (
    `person_id` int not null,
    `name` varchar(100) not null
);

pom.xmlにFlywayを追加する

<build>
    <plugins>
        <plugin>
            <groupId>org.flywaydb</groupId>
            <artifactId>flyway-maven-plugin</artifactId>
            <version>4.0.3</version>
            <configuration>
                <url>
                    jdbc:mysql://localhost:3306/flyway_sample
                </url>
                <user>root</user>
            </configuration>
            <dependencies>
                <dependency>
                    <groupId>mysql</groupId>
                    <artifactId>mysql-connector-java</artifactId>
                    <version>5.1.6</version>
                </dependency>
            </dependencies>
        </plugin>
    </plugins>
</build>

flyway:baselineを実行する

mvn flyway:baseline

schema_versionが作成される

mysql> show tables;
+-------------------------+
| Tables_in_flyway_sample |
+-------------------------+
| person                  |
| schema_version          |
+-------------------------+
2 rows in set (0.00 sec)

mysql> select * from schema_version;
+----------------+---------+-----------------------+----------+-----------------------+----------+--------------+---------------------+----------------+---------+
| installed_rank | version | description           | type     | script                | checksum | installed_by | installed_on        | execution_time | success |
+----------------+---------+-----------------------+----------+-----------------------+----------+--------------+---------------------+----------------+---------+
|              1 | 1       | << Flyway Baseline >> | BASELINE | << Flyway Baseline >> |     NULL | root         | 2017-06-08 09:27:41 |              0 |       1 |
+----------------+---------+-----------------------+----------+-----------------------+----------+--------------+---------------------+----------------+---------+

新しいDDLを追加する

src/main/resources/db/migration/V1_0_1__create_demo.sqlあたりに。

create table demo (
    `demo_id` int not null,
    `name` varchar(100) not null
);

flyway:migrateを実行する

mvn flyway:migrate

構成管理ができている

mysql> select * from schema_version;
+----------------+---------+-----------------------+----------+-------------------------+-------------+--------------+---------------------+----------------+---------+
| installed_rank | version | description           | type     | script                  | checksum    | installed_by | installed_on        | execution_time | success |
+----------------+---------+-----------------------+----------+-------------------------+-------------+--------------+---------------------+----------------+---------+
|              1 | 1       | << Flyway Baseline >> | BASELINE | << Flyway Baseline >>   |        NULL | root         | 2017-06-08 09:27:41 |              0 |       1 |
|              2 | 1.0.1   | create demo           | SQL      | V1_0_1__create_demo.sql | -1142022008 | root         | 2017-06-08 09:33:54 |            153 |       1 |
+----------------+---------+-----------------------+----------+-------------------------+-------------+--------------+---------------------+----------------+---------+
2 rows in set (0.00 sec)

まとめ

Flyway好きです。

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!

参考