Supporting Ruby 3 in fastlane

先日Ruby 3に正式に対応したfastlane v2.183.0を無事リリースすることができた。昨年末にCore Contributorになって勢いでRuby 3サポートやるぞと宣言して、約半年弱かかったがようやく達成することが出来た。 https://github.com/fastlane/fastlane/releases/tag/2.183.0 今回の記事ではどのようにしてRuby 3サポートを進めていったについて知見を紹介したいと思う。ここ最近、賃貸の家の退去と日本への一時帰国などで少々忙しかったためリリースしてから1ヶ月弱後と少し遅れてしまった。一般的に、Ruby 3サポートは、他の小・中規模のgemではそこまで難しい作業ではないことが多いし、もしくはRuby 2.7がリリースされたタイミングでwarningsに対応ちょっとやって終わりというところがほとんどだと思う。しかしfastlaneというgemは規模も大きいし、依存しているgemの数もかなりあったため作業を進めるのが少々困難だった。 Ruby 3.0サポートそのものの価値としては、fastlane自体がモバイルアプリ開発者向けにDSLとして使われるのがメインと考えるとfastlaneがRuby3.0で受ける恩恵はそこまで多くはない。だけど、ソフトウェアは時間と共に劣化していく(そのうち主流の環境で実行できなくなる)ので、常に最新の環境に対応しておくのはソフトウェアの寿命を伸ばすという点でとても意味があるし、実際に誰か手を動かしてやらないといけない。今回はその誰かが見当たらなかったので自分から手をあげてプロジェクトを1人でリードしてみたという感じ。自分はもともとWebエンジニアとしてもRubyを書いていてRuby言語そのものが好きだし、モバイルアプリの開発もそこそこやっていて仕事でfastlaneも触っていたので、fastlaneへのcontributionはちょうど自分にマッチしていると思った。何より、今所属している会社にRubyのコミッターの方々がいるので最悪Ruby 3対応で困ったら質問できるという安心感・福利厚生があったのが良かった。 段階的・継続的な修正のリリース まず初めに決めていたのが、いわゆる作業用ブランチを切ってマイグレーションを続けて日々リベースをして完成したらビックバンリリースみたいなリスクの高いやり方はしないということ。fastlaneは今でこそ新機能が毎日追加されるということはないものの、依然としてかなりのPRが送られてきてマージし続けているし大体週1回はリリースしているので、一つの作業ブランチを作ろうものなら日々コンフリクトが発生してしまうので避けたかった。 そこで、Ruby 3.0サポートのための計画をGitHubのissueにまとめて、TODOリストを書き、そこから順番に実行して少しづつリリースしていった。またこのissueを早めに用意することによって気軽にRuby 3.0環境でfastlaneを試したユーザーたちが無駄にissueを無限に立て続けるのを防ぐ効果を期待していた。 https://github.com/fastlane/fastlane/issues/17931 その結果、最終的なリリースの2.183.0はgoogle-api-client gemのバージョンをあげてRuby 2.4のサポートを切りつつ3.0のサポートを正式に行う修正+漏れていたURI.escapeの修正ぐらいしか入ってなくてほとんどの修正はそれよりも前のバージョンでリリースしていた。2.183.0では修正漏れが多少あったものの大きな問題は発生せずにRuby 3.0サポートを達成することが出来た。 要件の洗い出し 最初にissueを書く際に、Ruby 3サポートを達成するために何が必要なのかを一通り洗い出す必要があった。Ruby 3での破壊的な変更は公式のブログなどを読めば明らかで、これをやれば良いのだなということは真っ先にわかったし、実際にRuby 3環境でgem installしてみたときにそもそも最新のfastlaneがインストール出来ないことなどを元にやらなきゃいけないことをissueにまとめていった。一番大きな変更はキーワード引数の分離というもので詳細は以下のブログを読むのが良いので割愛する。出現箇所が分かってさえいれば修正は割と簡単ではあるが、Rubyが動的型付け言語なため実行するまでエラーが発生するか分からないという問題はある。 キーワード引数の分離について https://www.ruby-lang.org/en/news/2019/12/12/separation-of-positional-and-keyword-arguments-in-ruby-3-0/ またこのブログもRubyコミッター自身による解説でとても勉強になる https://techlife.cookpad.com/entry/2020/12/25/155741 この段階で全ての修正箇所が明らかになるわけではないので必要に応じてissueを更新したが、大まかな計画には最初に立てた通りで進行していった。 Ruby 2.7サポート 要件を洗い出してる最中にそもそも現状のfastlaneの対応Rubyバージョンもあやふやだということが分かったので、Ruby 2.7に対応しているというのをまず最初に明確にする必要があった。具体的には利用しているCircleCIでRuby 2.7に対するテストを実行できるようにした。 Ruby 2.7でテストを実際に実行してみると、非互換な変更があるわけでもないのに一部のテストが落ちたりしてめちゃくちゃ細かい対応をせざるを得なかった。 https://github.com/fastlane/fastlane/pull/17861 具体的にはSyntax errorが起きた時のエラーメッセージをテスト中に確認している箇所があって、そこのformatがちょっとだけ変わったことで落ちたり、Shellwords.escapeの挙動にあったバグが治ったことで、テスト中の期待値がマッチしなくなったので正しい値に直したり、巨大プロジェクトならではの大変さがあった。 ユニットテストでdeprecation warningsの収集 Ruby 2.7に正式に対応することでRuby 2.7が出力するdeprecationのwarningsをCI上で確認することが出来るようになった。実行するまで分からないエラー・警告ならばユニットテストを実行していけばいい。Ruby 2.7.3ではデフォルトでdeprecationは出力されないのでRUBYOPT=-W:deprecatedを設定してRubyを実行する必要がある。RSpecの実行時にこの環境変数を設定すればログにwarningsが残るのでテストでカバーされている範囲で修正が必要な箇所を洗い出し、一気に修正した。 https://github.com/fastlane/fastlane/pull/18021 https://github.com/fastlane/fastlane/pull/18395 また、CircleCI上でwarningsがこれ以上増えないようにrspecの実行後にチェックする仕組みを入れたことでこれ以上のdeprecation warningsが増えないようになった。fastlaneのCIはfastlaneのコマンドからrakeを経由してrspecを実行しているためwarningsを集めるための処理がちょっと複雑になってしまった。 Rubyのwarningsはstderrに出力される stderrはCircleCI上で引き続きログで閲覧したいがファイルにも書き出したい という要件を満たすためにstderrをstdoutにリダイレクトしてからteeを利用してwarningsを集めるという感じになった。 task(:test_all) do formatter = "--format progress" formatter += " -r rspec_junit_formatter --format RspecJunitFormatter -o #{ENV['CIRCLE_TEST_REPORTS']}/rspec/fastlane-junit-results....

Setting Time Limit at Table

今日は子育ての話題。今現在子供が2歳10ヶ月、1歳0ヶ月で、運よく2人とも睡眠まわりは全く問題がなくてどちらかというと比較的楽な子育てをしていると思う。 そんな中でここしばらく大変だなぁという気持ちがあったのがご飯と歯磨きの時間(ロックダウンで外出がまともに出来ないという問題も別にあるけど)で、特にご飯の時間は兄のイヤイヤ期と合わさってかなり時間がかかるようになってしまった。 具体的には ご飯の準備が終わって子に呼びかけてもテーブルまで来ないで遊び続ける 無理やり連れてきても椅子に座らない 椅子に座っても食べない 好きな物だけ摘んでおもちゃに戻ってしまう 上記を繰り返して1時間ぐらいしたら真にお腹空き始めるも父母どちらかの膝の上に座りにきて口に入れてもらおうとする 口の中に食べ物を入れても噛もうとしないか飲み込もうとしなくて一向に食べ進められない テーブルにおもちゃを持ってくきて遊ぶ 持ってきたおもちゃを片付けても、スプーン・フォーク・コップだけで遊び続ける 絶対にエプロンをしたがらないのでご飯をこぼしまくるが自分自身が汚れるのは嫌で汚れるごとに新たなティッシュを消費し続けて散らかる 床に食べ物が大量にこぼれる ご飯じゃなくて水とか牛乳ばかり飲んでおかわりを要求し続ける etc… こういうったことが日常茶飯事で、改めて書き並べるとすでに絶望的な状況に聞こえるけど、実際にはさらに同時に1歳弱の娘にも同時に離乳食をあげているのでもっと大変。娘も娘で、気に入らない物は食べない、手にスプーンを握らせないと怒るなどなどあるけどまぁそれでも赤ちゃん用の椅子で固定されているし楽な部類。 そんなわけで去年の秋ぐらいからご飯の度に食べ始めてから1時間半は軽くかかるようになってしまったし自分たちが平穏に食べ始めるのも難しくてあんまりご飯を食べた気持ちにならなくなってしまった。あとは幸か不幸か毎日リモートワークなのでこれが昼と夜両方に起きるが、その分も昼も父が食事に同席できるのは妻にとっては良かったと思う。朝はおやつも食べるタイミングないためお腹が空くのでそこそこ食べる。 あまりにも大変なのでいろいろ少しずつ試行錯誤してきて最近ようやく改善してきた。 テーブルの上にご飯の前に持ち込まれたおもちゃを必ず一掃してからご飯を始めるようにした(以前は端に寄せているだけだった) 気を散らすティッシュ箱をテーブルに置くのをやめた 1歳の時から使い続けていた使いづらいプラスチックのスプーン・フォークから先が金属製のものを常に使うようにした 兄用の赤ちゃん向けの椅子を妹に流用してたため、兄はテーブルに合わない大人向けの椅子でしばらくご飯食べていたので、改めてご飯を食べるのに高さが合う椅子を買った(高さが調整できるやつ) おかずを切って一口サイズにするのがまだ苦手なので食べている間に都度手伝うのではなく、事前に小さく切ってあげるようにした 会議などで使える卓上のアナログのタイマーを買って30分測るようにして都度時間がなくなっていく事を伝えてご飯を食べるのを促した ↑これとほぼ同じやつをUKのストアで買ったのだけどこのタイマーが特に効果的で、残り時間が赤い領域で示されているため3歳弱の子供がみても何か時間が減っているというのを理解しやすいらしく、親があおると”大変だ!大変だ!”って言い出すし、タイマーの音がなったらご飯を取り上げるしデザートもおやつも無しという旨を毎回伝える事で以前よりも遥かに集中して食べるようになった。ただタイマーが全てではなく上に書いた施策はどれも意味があって子供がご飯を食べるために集中するための環境を作るというのは大事だなと思った。あとはあれこれ試行錯誤しているうちにイヤイヤ期が終わってきていたというのもあるかもしれない。 30分という制限を設けた事で強制的に親自身も時間を気にするようになったし、以前のように子がだらだらしている間に諦めて自分たちが先に食べて後から無理やり兄に食べさせる、みたいな無駄が減ってご飯の時間が1時間以内に収まるようになってきた。子供たちが何もしなくても自立してパクパクご飯を食べていくまでこの習慣はしばらく続けてみようと思う。子供が3歳手前まで育って意味不明ながらそれなりに喋れるようになってきてさらに可愛さが増したので早く家族で食事中に平和に会話が楽しめるようになりたいなと思った。...

Annoying crack sound from MacBook Pro

MacBook Proを使用中に音楽などを再生していると音割れが発生する現象がiOS開発している人たちの中で起きている(同僚でも2、3人同じことを言っていた)らしいけど、これはどうやらiOS Simulatorが原因らしい。 自分のMacBook Proでも昨年からいつの間にかこの現象が現れ始めて、OSを再起動しても治ったり治らなかったりで本体の故障かと思って諦めていたのだけど最近なぜかずっと調子がよくて不思議だった。しかし今日久しぶりにiOS Simulatorを起動してみたら、さっきまで調子良くYouTubeを再生してくれていたのに急にノイズが混じるようになってこの現象に気づいた。直近ではRubyを書いていることが多かったからiOS Simulatorを起動してなくて調子良かったのだと思う。 Twitterで聞いてみたら他にも同じ現象に遭遇している人iOS開発者の人たちがいたので正しいのだと思う。 MacBookのスピーカー、iOSシュミレーター起動してるときに音が割れたりする?? — Satoshi Namai (@ainame) January 13, 2021 シミュレータ起動していると他の音がおかしくなりますね。シミュレータ終了するか、シミュレータの音のアウトプットをMacのスピーカ以外にするか、くらいしか解決方法はなさそうです。 — kishikawa katsumi (@k_katsumi) January 13, 2021 スピーカーは分からないですけど、Bluetoothヘッドフォンしてると断続的にブチブチ切れることあります。zoomしてるときもシミュレーター起動したらめっちゃノイズ乗ったりとかありましたね。 — y_koh (@y_koh) January 13, 2021 追記 自分もよくこの現象に直面していたので情報助かります。自分の場合はSimulator起動中というよりも、Simulatorでキーボードのinput操作をしたときに突然音が悲惨なことになるケースが多かったです。 — su-🐈 Flutter, iOS, Firebase (@_sgr_ksmt) January 13, 2021 他にもフォーラムに投稿している人が。 https://discussions.apple.com/thread/251814420 ひとまずワークアラウンドとしてiOS SimulatorのメニューからAudio OutputをMacBook Pro本体のスピーカー意外にすると良いらしい。(まだ試して数分だけど一旦治ったかもしれない。) Audio Output settings on iOS Simulator この音割れ現象、原因がわかりづらい上に普段ずっとiOS開発していて一日8時間以上MacBook Proを触っている人には相当ストレスが溜まると思うので周知のためにこの記事を書きました。自分もこれ気づくまでにいろいろググって試したけど全然解決に至れなかった。...

Google Translate menu is now supported

My blog will primarily be written in Japanese. So this blog has now supported Google Translate for English speakers on each article at the top. You can give it try if you want to read my blog. For the convenience, blog title will only be in English as much as possible as well. At least you can get some ideas from it at first. The translation quality of Google Translate for Japanese to other languages is not good enough....

I became a Fastlane core contributor

fastlane's logo and the description というわけで2020年の振り返り記事にも書いたけど、業務内外でfastlaneをいじる機会が多かったので、昨年末に勢いでfastlaneのCore Contributorやらせてとリクエストしたらアクセプトされた。 fastlaneを知らな人向けに一言で説明すると、Ruby製のモバイルアプリ開発向けのCI/CDをサポートするツール群だ。世の中ではそれなりに使われているはず。fastlane以前では毎回手作業で各個人のMacからビルドしてアプリをiTunes Connectというサイトにアップロードして、コンソールから必要なメタデータの更新をして…みたいな感じだったのがほとんど作業がfastlaneによって自動化出来る時代になっている。昔はprivateなAPIを呼び出して実装されていて動作していたので重宝されていたけど、去年からAppleも公式にそれらの作業を自動化するためのAPIを公開し始めたので必ずしもfastlaneが必須ではなくなって来ているものの、依然として各種ワークフローを実装するための豊富な機能がそなわっているので、すぐに要らなくなることはない。 これまではfastlane/deliverをやっていて、具体的にはスクリーンショットのアップロードの高速化/安定化や、ローカルの画像のロード処理のリファクタとエラーハンドリングの改善 + スクリーンショットのアップロード前のバリデーションの追加でユーザー体験向上、iPhone 12シリーズによる新しい解像度の対応などをした。最近はCircleCIでRuby2.7系でテストを実行するために壊れたテストを直したり、.circleci/config.ymlの壊れているところを直したりした。 今後は元々やりたいなぁと思っていたfastlaneのRuby 3.0の対応のプロジェクトを個人的にリードしてやっていく、というのをさっきアナウンスした。やっていくぞ。こういうった作業は昔からRubyをWeb開発の仕事でも使ってて最近はiOSエンジニアを仕事にしている自分のスキルと経験がマッチしていると思う。 https://github.com/fastlane/fastlane/issues/17931 もし何かfastlaneで困りごとなどがあればTwitrerのDMなどからご相談ください(全ての機能に詳しいわけでは無いけど)。 Core Contributorのチーム全体は現在そこまでアクティブでは無いけど、直近Core Contributorになった他のメンバーなどとお互いにレビューしあったりしながらワイワイやっていて楽しい。数年前まで元々英語は全く読み書きダメだったけど、直近3年間ほど仕事と生活先を英語圏に置くことで強制的に毎日英語を使ったおかげで、難なくこういうことも出来るようになってよかったなぁとしみじみ感じている。 ちなみにタイトルだけ英語にしてみた今後もそうすると思う。基本的に本文は日本語でブログを書きたいけど(そのほうが早いので)、タイトルだけでも英語にしたら誰か翻訳ツールで読むかもしれないと思った。もしかしたらそのうち英語でも記事を書くかもしれない。 実際Twitterは同僚に翻訳して読まれている。...

og:imageをつけるのやった

昨日ブログをシュッと作ったけどtheme以外のデコレーション以外は何もやってなかったので試しにTwitterでシェアした時に良い感じになるようにog:imageを付けようとしてみた。Twtiter Cardsはthemeがデフォで対応していなかったのでいったん見送りで。 og:image自体はHugoの持っているテンプレートで簡単に対応出来るようになっているらしく自分が使っているPaperというthemeも既に対応済みだった。あとは各記事のFront matterでimagesでファイル名を指定してあげるだけっぽい。 画像を置くディレクトリもassets, data, staticとそれっぽい名前のやつが何個かあるけど、Pipelineで処理するならassetsでそうじゃなければstaticに置くべきっぽい。 assets Stores all the files which need be processed by Hugo Pipes. Only the files whose .Permalink or .RelPermalink are used will be published to the public directory. Note: assets directory is not created by default. static Stores all the static content: images, CSS, JavaScript, etc. When Hugo builds your site, all assets inside your static directory are copied over as-is. A good example of using the static folder is for verifying site ownership on Google Search Console, where you want Hugo to copy over a complete HTML file without modifying its content....

新しくブログを作った

2021年になったので新しく個人サイト・ブログを作ってみた。ブログを書き始めるために環境構築とかで手間取りたくなかったためbrew install hugoだけで始められるHugoと定番のNetlifyを使ってみた。Hugoはとても簡単に始められて、30分程度でデプロイまで出来たけど、選んだpaperというthemeにおいてトップページへ余計なリンクが出現しないようにする設定とかディレクトリ構成とかを把握するまでに少々時間がかかった。 これまではてなブログを使っきていて満足していたけど、編集画面が現在住んでいるイギリスからアクセスすると(日本からでも?)少々重い気がしていて(特にプレビュー)、Emacsでさくっとブログを書けるようになったらしたかった。ドメインは昔.tokyoが公開された時になんとなく取得したIDと紐づいたやつだけど、今となっては東京に住んでいるわけでもないのでいまいちかもしれない。 とりあえずお正月中に最初の記事を書くことが出来たので満足。明日から仕事始め。...