リリースプルリクを gh-release-pr-generator で自動作成しよう!
誕生! gh-release-pr-generator
ステージング環境と本番環境があるWeb開発において、git-flow に沿って、
developブランチにマージがあったらステージング環境のリリースが走って、
masterブランチ(最近ではmainブランチ)にマージがあったら本番環境にリリースが走る。
そういう作りになっていることはよくあると思います。
その関係で、master ブランチに develop ブランチからマージするための、
いわゆるリリースプルリクを作るということはあると思います。
そんなリリースプルリクをカンタンにぃ!
作れるぅ!
CLIアプリケーションを作りましたぁ!!!
動機
……と言っても、実はすでに先行者の方がいまして、
というものがありました。
git-pr-release は使っている方も多く、「良さそうだなあ……」と最初はこれを使う予定でいたんですが、
1つ大きな問題がありまして、この issue にある通り、
develop ブランチに「Squash and merge」をしている場合、そのプルリクが差分として出てこないのです!
develop や master ブランチのコミットログが大量にならないよう「Squash and merge」で、リリースプルリク以外のプルリクをマージしていたので、
「これは困ったぞ」となりました。
オプションで切り替えられるような仕組みのプルリクを作るよりも、
このくらいだったら自分で作っちゃおうかな、と思って作成しました。
Go言語で作るとワンバイナリにできるぶん、CI で使うときに都合がいいですからね。
作成にあたっては、github-pr-release の GitHub API をバリバリ使う実装が参考になりました。
ありがとうございます。
使い方
こちらの README でも書いていますが、おおまかな使い方について日本語でも書いておきます。
1. GitHub API Token を取得する
GitHub Actions で動かすだけだったら、GitHub Actions 自体がAPIトークンを持っているため必要ありませんが、
ローカルで動かす場合には必要になります。
『個人アクセストークンを使用する - GitHub Docs』を読んで用意してください。
「repo」のところにチェックを入れたAPIトークンがあれば大丈夫です。
2. インストール
Go 1.16 以上であれば、
go install github.com/nekonenene/gh-release-pr-generator@latest
でインストール可能です。1.16 未満には go install
コマンドがないので
go get github.com/nekonenene/gh-release-pr-generator@latest
でおこないます。
また、 https://github.com/nekonenene/gh-release-pr-generator/releases にはバイナリファイルが置いてありますので、
そこから最新バージョンのバイナリを wget
などで取得して実行する方法もあります。
CIなどでおこなう場合はそちらのやり方がオススメです。
3. gh-release-pr-generator の実行
gh-release-pr-generator --token 123456789abcd123456789abcd --repo-owner nekonenene --repo-name my-repository-name --dev-branch staging --prod-branch production
のように実行します。
パラメーター | 指定するもの | 必須か |
---|---|---|
-token | 1. の手順で取得した GitHub API Token | YES |
-repo-owner | リポジトリのユーザー名・組織名 | YES |
-repo-name | リポジトリの名前 | YES |
-prod-branch | 本番リリース用ブランチ名(デフォルト: main ) |
|
-dev-branch | 開発用ブランチ名(デフォルト: develop ) |
|
-template-path | 後述するテンプレートファイルのPATH | |
-limit | 取得するクローズ済みプルリク数(デフォルト: 100 ) |
|
-enterprise-url | GitHub Enterprise の URL (例: https://github.your.domain ) |
-limit
オプションは大きくすると、GitHub API のリクエスト数制限に引っかかる可能性があるのでご注意を。
ふつうはデフォルトの100もあれば充分かと思います。
最後の -enterprise-url
オプションについては、GitHub Enterprise を契約していなくて動作確認できないので、
もし動いた方いらっしゃったら教えてくださるとうれしいです!
4. テンプレートファイル
gh-release-pr-generator で作られるリリースプルリクのタイトルや本文を変えたい場合は、
テンプレートファイルを作って、それの場所を指定することでカスタマイズできます。
デフォルトは以下のようになっています。
カスタマイズするにはある程度 Go 言語の知識が必要な部分もありますが、
日付は知らない人でもいじりやすいようにパラメーターを用意しましたので、
README のこちらを読みつつ設定してみてください。
Release {{ .Year }}-{{ .Month }}-{{ .Date }} {{ .Hour }}:{{ .Minute }} # Pull Requests {{ range $i, $pull := .Pulls }} * {{ $pull.Title }} (#{{ $pull.Number }}) @{{ $pull.User.Login }} {{- end }}
.release-pr-template.tmpl
など、それっぽい名前で保存して、
gh-release-pr-generator の実行時に --template-path .release-pr-template.tmpl
と書いてあげれば読んでくれるはずです。
5. GitHub Actions での使用
.github/workflows/release_pr.yml
など、適当な場所に GitHub Actions 用のファイルを 置いて、
develop ブランチにマージがあるたびにリリースプルリクエストが作られるようにしておくと楽です。
ファイル例は README に載せていますので、ご活用ください。
バージョン指定を README に書きたくなかったので、例では go install
をしていますが、
wget でバイナリファイルをダウンロードして実行、ってやり方のほうがもう少し実行速度が上がると思います。
作ってみての感想
久しぶりに Go 言語をさわれて楽しかったです。
(前回作った YouTube の概要欄を更新するやつ は 2020年4月作成だったので、約1年ぶりだったみたい)
おもしろかったのが release-it という CLI ツールを知れたことで、
これによって、master ブランチへのマージ時に
バイナリファイルをアタッチしたリリースページが自動で作成されるようになり、
go install github.com/nekonenene/gh-release-pr-generator@latest
をしたときにしっかり最新版がインストールされる仕組みに出来たのでとてもよかったです。
Go言語のCLIアプリケーションを作ることがあるときには
また活用させてもらおうと思います。
そういえば Rust をいつかさわろうと思っていたのに、また Go で作ってしまっていた。
次こそは……!
Rails の Mountable Engine 側の _path や _url をメインアプリから呼び出す
1. 前提
まず config/routes.rb
に
# config/routes.rb Rails.application.routes.draw do mount Admin::Engine, at: "/admin" end
は書かれていることと思う。
今回はその Admin::Engine の配下にある /admin/users
を呼び出したいとする。
つまり、 admin/config/routes.rb
には以下が定義済みとする。
# admin/config/routes.rb Admin::Engine.routes.draw do resources :users end
2. controller から呼び出すぶんにはカンタン
/admin
は admin_path
で呼び出せるし、
/admin/users
は admin.users_path
で呼び出せる。
_url
側は後述する設定をおこなわないとまだダメかもしれない。
3. as 設定を入れておく
この設定は必要ではないのだけれど、
Admin app からメインアプリを呼び出すときの routing が
main_app.mypage_path
のようなものなので、そこと対称性を持つためと、
あとで文字列でのファイル検索がしやすいように、 admin_app
と名付ける。
# config/routes.rb Rails.application.routes.draw do mount Admin::Engine, at: "/admin", as: :admin_app end
この変更により、
admin_path
→admin_app_path
admin_url
→admin_app_url
admin.users_path
→admin_app.users_path
が正しい path になるので、 as 設定を入れる場合は、現在の記載を変更するようお忘れなく。
4. admin_app.xxx_url を使えるようにする
admin_app.users_path
は使えるが、
admin_app.users_url
を使おうとすると以下のようにエラーが出るはず。
ArgumentError: Missing host to link to! Please provide the :host parameter, set default_url_options[:host], or set :only_path to true from /bundle/ruby/2.7.0/gems/actionpack-6.0.3.4/lib/action_dispatch/http/url.rb:63:in `full_url_for'
というわけで、警告通り、
admin_app.users_url(host: "localhost:3000")
のようにオプション付きで呼び出すか、
default_url_options の設定をする必要がある。
今回は、メインアプリ側の config/environments
で環境ごとの
default_url_options
を指定してあるので、それを呼び出すものとする。
# config/environments/development.rb 内の記載 Rails.application.routes.default_url_options[:host] = "localhost:3000" # config/environments/production.rb 内の記載 Rails.application.routes.default_url_options[:host] = "prod.example.com"
上のような設定が各ファイルに書かれているとして、
以下のように admin/config/routes.rb
には書いてあげて Rails.application.routes.default_url_options[:host]
を再利用する。
# admin/config/routes.rb Admin::Engine.routes.draw do default_url_options host: Rails.application.routes.default_url_options[:host] resources :users end
これで admin_app.users_url
のような呼び出しも可能になったはずだ。
5. Job から Mountable Engine 側の path や url を呼び出す
Controller はカンタンだけど、では Job や Model から呼ぶにはどうするか。
特に Slack 通知なんかで管理画面側の URL 表記をしたい場合があるだろう。
また、 Rails console から routing を確認したいときもあるだろう。
メインアプリ側であれば include Rails.application.routes.url_helpers の記載があれば
mypage_path
などを呼び出せた。
Engine 側はこれだけでは呼び出せない。
NameError: undefined local variable or method `admin_app' for main:Object Did you mean? admin_app_url
などと言われてしまうことだろう。
どうするか。 include Rails.application.routes.mounted_helpers を呼び出せばいい。
というわけで、Job は例えばこうなる。
class MountedEngineTestSlackNotificationJob include Rails.application.routes.url_helpers include Rails.application.routes.mounted_helpers include Sidekiq::Worker sidekiq_options queue: :slack, retry: 3 def perform blocks = [] blocks.push({ type: :section, text: { type: :mrkdwn, text: "リンク → <#{admin_app.users_url}|ユーザー一覧管理画面>", }, }) notifier = Slack::Notifier.new("https://hooks.slack.com/services/ABCDEF/GHIJKL/MNOPQRSTUVWXYZ") notifier.post(attachments: { blocks: blocks, color: "#2eb886" }) end end
gem入れてること前提のコードなので、上のはあくまで参考程度に。
Mountable Engine 周りの話はネットに情報少なめなので、情報探すの苦労しました。
最終的には Rails 本体のテスト周りのコードを読むことで解決しました。
やはり https://github.com/rails/rails は神……。
顔画像認識周りのメモ
手っ取り早いのは Haar-like
OpenCV に分類器が同梱されていてすぐに使えるので、試してみるのはとっても簡単です。
これらの記事が詳しいです。
上の記事ではそれぞれの分類器ファイルの説明が書いてあってとてもありがたいのですが、
『haarcascade_profileface.xml : 顔(証明写真)』のとこだけ、
Profile face は「横顔」の意味が正解ですので、そこだけ注意です。
実際に試してみるとこんな感じ。
処理が1秒未満で終わるのは良いのですが、(2841 x 2200 px の画像で 0.74s 程度)
やはりこの手法は画像の白黒パターンの一致から判定しているだけなので、
顔が傾いているとダメだったり、必要以上の場所を認識してしまって、なかなか実用は難しそうです。
英語ですが、「テンプレートマッチング」と「畳み込みニューラルネットワーク」の違いの説明記事は
以下がいい感じでした。
What’s the Difference Between Haar-Feature Classifiers and Convolutional Neural Networks?
CNN(畳み込みニューラルネットワーク)か~
というわけで、実用可能な方向を考えると、
CNN(Convolutional Neural Networks=畳み込みニューラルネットワーク)か~。
なんですけど、ここはまだあれこれ試してないので、メモ程度にリンクをまとめときます。
使えそうなライブラリやアプリケーション
- FaceNet : https://github.com/davidsandberg/facenet
- OpenFace : https://github.com/cmusatyalab/openface
- MTCNN : https://github.com/ipazc/mtcnn
実装してみた記事に関しては、このあたりがわかりやすそうでした。
まだ試せていませんが、実装してみるときはここらへんの記事を読みながらやってみようと思います。
IBMの学習済みモデルを使ったAPIが簡単に作れる Model Asset Exchange なんかも便利だなーと思って読んでましたが、
IBMは2020/06に顔画像認識は肌の色の偏見に基づく可能性があるため撤退しているようで、
現在は Facial recognization は一覧にありませんでした。
【2019/4月更新】学習済みの様々なディープラーニング・モデルをメチャ簡単に利用できる! Model Asset Exchange(MAX)をご紹介します - Qiita
畳み込みニューラルネットワークがなんなのか、どうやって処理しているのかとか、
勉強しないといけないことが多いですが、時間あるときに調べていきたいと思います。
画像処理の基礎:フィルタリング,パターン認識から撮像過程モデルまで | Udemy
この Udemy の講座も、せっかく買ったのにまだほぼ見られてないので、
早く学びたいです。