$shibayu36->blog;

クラスター株式会社のソフトウェアエンジニアです。エンジニアリングや読書などについて書いています。

git-pr-releaseでリリースPRの変更ファイルの情報を扱えるようになりました

git-pr-releaseというgithub上でリリース用の手順をまとめたPull Requestを簡単に作成できるツールがあります。

このリリースの手順を作る時に、そのリリースPRの変更ファイルの情報を使いたくなったので、そのようなプルリクを送った所mergeされたのでご紹介です。

github.com

やりたかったこと

今やっているプロジェクトでは

  • DBのマイグレーションツールとかは特に利用せず、db/migrations/以下にALTER TABLE文の書いたファイルを置いておき、手で実行する
  • 本番用に一時的に実行したいスクリプトとかをscript/onetime/以下に置いておく

などのことをしているのですが、これを本番リリース時に忘れてしまうことがあります。そういうことをしないために、それらのファイルが変更されたらリリースフローにチェックリストを追加したいと思っていました。

やり方

今回の変更で、erbのテンプレートにリリースPRの変更ファイルの情報が入ったchanged_filesという変数が渡ってくるようになったのでこれを利用します。例えばdb/migrations/以下にファイルが追加された場合にのみチェックリストを作りたいときは

- [ ] masterにmerge
<% if changed_files.any?{|f| f.filename =~ %r{\Adb/migrations/} } # DB系の変更をチェックリストに -%>
- [ ] alter table (`db/migrations/*` が変更されていました)
<% changed_files.select{|f| f.filename =~ %r{\Adb/migrations/} }.each do |file| -%>
    - [ ] `<%= file.filename %>`
<% end -%>
<% end -%>
- [ ] `cap deploy`

のようにテンプレートに書いておくと、db/migrations/以下のファイルが変更された時だけチェックリストを追加することが出来ます。これで忘れないはず!

ちなみにchanged_filesに入ってくるのは https://developer.github.com/v3/pulls/#list-pull-requests-filesAPIから取れる情報なので、変更行数とかも取ることができます。

まとめ

今回はchanged_filesという変数を利用してリリース手順にフローを動的に追加する方法について紹介しました。本当はデプロイコマンド一発で全て解決出来るといいのですが、様々な事情によりできなかったりするので、こういうのである程度バランスを取ってます。

「ドミトリーともきんす」という本を読んだ

ふとしたきっかけでこの本を知ったので読んだ。非常に良かった。

いろんな科学の現象や研究者の言葉を漫画形式でさらっと紹介してくれる本で、30分くらいで読めて楽しめる。僕は特にこの本の中の球面世界の話が面白かった。地球は球面なので実際にはここで書かれていることが起こってそうなんだけど、実際には非常に大きいから自分は近くできないことがなんとなく分かるので良かった。

またこの本の中で紹介されている湯川秀樹さんの「宇宙と人間 七つのなぞ 」という本もめちゃくちゃおもしろかった。この本もまた次の機会で感想を書きたいと思う。

[asin:B00PQDJL1U:detail]

git-pr-releaseのjsonオプションを利用してリリース情報のサマリーをSlackに投稿する

git-pr-releaseには--jsonオプションがあって、これはリリースPRを作り、その情報を標準出力にJSONで出力してくれる。これを利用することでgit-pr-releaseと連携していろんな用途に利用できる。

例えばこれを利用すると、以下のようにリリースPRのサマリー情報をSlackに投稿する、などの事ができる。下のものは適当にPerlスクリプトを書いてるけど、Pull RequestのAPIから取得された情報がJSONで渡ってくるので、いろんな言語から使えると思う。

use URI;
use JSON::XS qw(encode_json decode_json);
use List::UtilsBy qw(max_by);
use List::Util qw(sum);
use LWP::UserAgent;

# リリース用PRを作った後、その情報をSlackに投稿する

# git-pr-releaseしてjsonでデータを受け取る
my $release_json = `git-pr-release --json`;

my $data = decode_json($release_json);
my $release_pull_request = $data->{release_pull_request}; # リリースPRの情報
my $merged_pull_requests = $data->{merged_pull_requests}; # そのmergeされているPRの情報

# 追加行と削除行の合計が多いPRのタイトルを代表として表示する
my $max_merged_pr = max_by {
    $_->{data}->{additions} + $_->{data}->{deletions};
} @$merged_pull_requests;
my $max_merged_pr_title = $max_merged_pr->{data}->{title};

# 追加の合計行数を表示する
my $additions = sum map { $_->{data}->{additions} } @$merged_pull_requests;

# 削除の合計行数を表示する
my $deletions = sum map { $_->{data}->{deletions} } @$merged_pull_requests;

my $release_text = sprintf(
    "【リリース】 %s (%d件, +%d, -%d) %s",
    $max_merged_pr_title,
    scalar @$merged_pull_requests,
    $additions,
    $deletions,
    $release_pull_request->{data}->{html_url},
);

my $payload = {
    username => 'releasekun',
    text  => $release_text,
};

my $ua = LWP::UserAgent->new;
my $res = $ua->post('https://hooks.slack.com/services/...', {
    payload => encode_json($payload),
});