コネヒト開発者ブログ

コネヒト開発者ブログ

サービスとシステムの健全性に保つためのAndroidチームの取り組み色々

こんにちは!2017年11月にAndroidエンジニアとしてjoinした関根です。気づけば入社4年目に突入しました。 さて今回は、弊社サービスのママリ改善を担当するAndroidチームでやっていることや始めていることを、年末の棚卸しを兼ねて紹介してみようと思います。

この記事はコネヒト Advent Calendar 2020 16日目の記事です。

やっていること

まずは今年までに既にやっていることの中から2つの動作チェックサポート対象のアプリバージョンやminSdkVersionの運用について紹介をさせていただきます。

2つ動作チェック

言わずもがなですが、サービスやシステムを健全に保つためには、意図した挙動が守られていることを事前に確認しておく必要があります。 Androidチームでは大きく分けて2つ動作チェックのタイミングがあります。

プルリクエストでの確認

ひとつめはプルリクエストを送るタイミングです。 下記のようなテンプレートを用意して、レビュアー/レビュイーの間の共通認識をとり、認識の齟齬を減らしミスを減らす工夫をしています。

## 目的
今回のPRの目的を書く。関連issueを貼ることが多い

## やったこと
このPRの作業内容を書く

## テスト項目
動作確認する内容や手順を書く

## チェック項目
- [ ] File Changedのセルフレビュー
- [ ] 6系で動作が問題ないこと
- [ ] 7系で動作が問題ないこと
- [ ] 8系で動作が問題ないこと
- [ ] 9系で動作が問題ないこと
- [ ] 10系で動作が問題ないこと
- [ ] デザインが崩れていないこと
- [ ] Activity破棄設定にして動作が問題ないこと
- [ ] 不要なリソース削除。`$ ./gradlew removeUnusedResources`

## その他
特に見てほしいポイントや、その他レビュワーに伝えたいことなどがあれば記載

テンプレートのチェック項目を全て確認をするのはレビュイーが多いですが、レビュアーも必要に応じて動作確認をしています。

リリース前チェック

もう一つはリリース前のリグレッションテストです。 こちらはプルリクエストの場合と違い、既にある機能を守れているかを確認するテストとなります。

確認する項目

サービスの重要な機能にしぼり、約70の項目を確認しています。 プロダクトマネジメントを担当するメンバーと相談し、ユーザーやクライアントに与える価値の大きいものを抜粋してテストをしています。

確認するタイミング

アプリリリース前に実施しています。かかる時間は一時間弱です。

機能が増えるタイミングで項目が追加されることも多いため不定期で棚卸しを実施しています。今は人力での動作確認をしていますが、今後は自動化検討して、効率化をしていきたいと考えています。

サポート対象のアプリバージョンやminSdkVersionの運用

Android開発ではminSdkVersionとの向き合い方に悩まされることが多いと思います。コネヒトでも長い間明確な運用ルールは決めていなかったのですが、2019年度のシステム安定化という部署の目標をきっかけにルールの整備が始まりました。

導入の背景

それ以前は、ルールがないことで全ての環境の全ての問題を同じように対応することが多く、サービス改善で起こるシステムの問題に対して「過度な萎縮」が起こり始めていました。 しかし、ユーザーに価値を提供し続けるにはシステム改修に萎縮せず気軽にリリースをし続けることが大事だと考えています。他方、ビジネス数値からみると、サポート範囲を狭めることはネガティブに捉えられがちでなので、「守るべき範囲」を明確に定義し過度な萎縮を防ぐことが「ユーザーに価値を提供し続ける」ことに繋がるという前提で議論を進め、導入に至っています。現在は以下のルールで運用されています。

基準

ルール名 対応内容 基準値
非推奨環境 設計や実装時の考慮から外してOK
不具合やエラー発生時に通常issueとして扱い対応可否を決める
DAU500人以下の環境
レガシーアプリver. バージョンアップを誘導する リリースから2年経過したアプリVer.
レガシーOS minSdkVersionの対象外にする
※2~3週間前にお知らせでアナウンスをする
OS毎MAUが2%以下のOS

見直し時期

  • クオータ毎
    • 3月、6月、9月、12月

見直し事項

  • サポートバージョンの基準値の見直し
  • サポートバージョンの環境の更新

実施ステップ

  1. 開発部でサポート対象外となる環境を計測する
    • 特定期間のMajorバージョンシェア
    • 特定期間でDAU1000以下のMajorバージョン
    • 2年前のバージョン番号
  2. 社内に共有してスケジュールを組む
    • ex). レガシーOS/レガシーアプリver対応:事前に対象ユーザーのお知らせに案内を掲出
  3. スケジュールに沿って遂行する

あくまでも一定の基準であるため、閾値を下回ったから直ぐに対応を実施するわけではなく、開発効率のバランスやサービスに与える影響をプロダクトマネジメントを担当するメンバーと相談しながら進められるように工夫をしています。

はじめている事

最後に、これからはじめていくことの中からrenovateの導入について紹介します。今月に入ってから着手し始めたもので、試行錯誤の真っ最中です。

依存ライブラリのアップデートを効率化

renovateを一言で紹介すると、依存ライブラリのアップデートを検知してPRを投げてくれるOSSです。 Androidの依存ライブラリは更新も早く、人力でアップデートしていくのは、至難の技だと感じており、 この課題を解決するために、renovateで自動化をし、運用を楽にすることを考えています。 余談ですが、以前は gradle-use-latest-versions-pluginをGithub Actionsで実行し、PRを出す運用の準備をしていましたが、別のプロジェクトで仕様していたrenovateでも同じことが実現できることがわかり乗り換えをしています。 この取り組みの中から1つの工夫を紹介します。

PRをまとめる

renovateではデフォルト設定だとパッケージごとにPRが送られてきます。 依存ライブラリが多いとPRが多くなりすぎることが懸念されたので、minorとpatchアップデートは1つにまとめるようにルールを決めています。 renovateの設定ファイルに下記の設定を追加することで実現ができます。

"packageRules": [
        {
            "packagePatterns": [
                "*"
        ],
            "updateTypes": [
                "minor",
                "patch"
        ],
            "groupName": "all non-major dependencies",
            "groupSlug": "all-minor-patch"
        }
]

なお、majorバージョンは変更が大きく、プロダクトへの影響も大きいため、個別のPRでしっかりと検証する必要があると判断し、対象をminor、patchのみにしぼっています。

最後に

いかがでしたでしょうか?コネヒトでは今回紹介したように、各々のメンバーが工夫をしながら業務改善を楽しんでいます。そんなコネヒトでは積極的にエンジニアを募集しているので、是非一度話を聞きにきてください!

hrmos.co

Bitrise を触ってみた所感

こんにちは!アプリケーションエンジニアのあぼです。

コネヒトでは iOS アプリの CI ツールとして Travis CI を使っていましたが、先日プランが変わったこともあり、定額の Bitrise に移行しました。元々 fastlane で自動化していたので、Bitrise ではキャッシングなどのワークフローを組み立ててメインの処理は fastlane のコマンドに任せるという感じで動かしています。ですので移行自体もそこまで苦ではなかったなという印象です。

今回ははじめて Bitrise を触ったので自分の所感を簡単に書いていこうと思います。コネヒト Advent Calendar 2020の記事です。

導入初期の色々試したいときに GUI でガリガリいじれる

Bitrise はワークフローの設定などが書かれた bitrise.yml を Bitrise.io で管理する方法とリポジトリ管理する方法が選べますし、後からでも変更可能です。個人的に導入初期は yml のこと考えずに一気にガリガリ弄って試したいので、その点でラクでした。そしてある程度動くことが確認できて正式にチームに展開する際に GitHub のリポジトリ管理に切り替えています。GUI で弄った bitrise.yml をそのままダウンロードしてリポジトリに追加すれば良いので切り替えも簡単にできました。

f:id:aboy_perry:20201214162452p:plain
bitrise.ymlの管理方法

bitrise.yml を自分で書く場合にドキュメントが必要なのですが、探してみた感じだと Bitrise CLI のドキュメントを参照すればだいたい網羅されてそうな気がします。CLI 自体 OSS なのでソースコードを読んで調べることもできますね。Go で書かれているようです。

devcenter.bitrise.io

スタック(イメージ)の更新・削除が早い

スタックの更新と削除ポリシーを見る限り、他の CI と比べて古いスタックが deprecated になるタイミングや、削除されるタイミングが早そうです。例えば直近だと Xcode11.x は 11.7 以外のマイナーバージョンが順次 deprecated になり、削除されていきます。Circle CI の場合 Xcode11.x は Xcode13 のリリースが始まってから順次 deprecated になっていきます。一方で、Bitrise は新しいバージョンのスタックが使えるようになるのも早い印象*1なので、そこは嬉しいですね。

Travis CI に関しては更新と削除ポリシーについてそれらしい記述が見つけられなかったのですが、現状用意されている環境一覧を見る限り Xcode7.3 があり、かなり古いバージョンまで保持しているようです。(ちなみに前述のリンク先のページでは Xcode11.7 が無い…のですが、チェンジログには対応したと書いてありました)

会社や個人の状況によって、スタックの更新・削除ポリシーが要件と合わず使いたくても使えないということも起こりそうですが、コネヒトの場合は運用していけそうと判断しました。

ビルドの結果がステップごとに表示されて見やすい

ステップごとに折り畳まれてたり、かかった時間が一覧で見れるのでパッと見で見やすいと感じます。ビルド時間を削減しようと思った時にステップを細かくわけてボトルネックを探ったりするのに使えそうですね。

f:id:aboy_perry:20201214165209p:plain
ビルドの結果がステップごとに表示される

キャッシュが便利

Bitrise のキャッシュはブランチごとに特定のディレクトリを保存しておけるもので、Bitrise.io Cache:PullステップとBitrise.io Cache:Pushステップを組み込んで簡単に使うことができました。該当のブランチに有効なキャッシュが無ければ Bitrise 上でデフォルトブランチに指定しているブランチのキャッシュを取りに行く仕様です。Travis CI ではプルリクエストトリガーの際にターゲットブランチのキャッシュを取りにいく点が違っていますが、ほとんど同じ感覚で使うことができそうですね。

コネヒトでは現在 ruby (rbenv)、Gem、CocoaPods で管理しているライブラリ、Swift Package Manager 管理しているライブラリをキャッシュしています。

devcenter.bitrise.io

おわりに

というわけで今回は Bitrise を触ってみて感じたことを書きました!まだ細かい課題ややりたいこともあるので色々試していきたいなと思います!


そして宣伝です!12/12 (火) に potatotips (iOS/Android のオンラインLT会) を開催予定です。空いている枠は先着順で入れるのでご予定合う方はぜひご参加ください〜!

potatotips.connpass.com

*1:Bitrise の Twitter をウォッチしているとそんな印象があります、あくまで印象

CakePHPを使った実装で悩んだときに見ている情報源

こんにちは! @fortkle です。
この記事は コネヒト Advent Calendar 2020 8日目 の記事です。

f:id:fortkle:20201208110038p:plain
https://cakephp.org/jp

はじめに

コネヒトではサーバーサイドの言語として主にPHP、フレームワークでいうとCakePHPが採用されています。 公式のドキュメントにもある通り、CakePHPは「設定より規約」的な思想が随所に感じられるフレームワークです。

私たちは「設定より規約」(convention over configuration) という考え方に賛成です。 CakePHP の規約を習得するには少し時間がかかりますが、長い目で見ると時間を節約していることになります。 規約に従うと自由に使える機能が増えますし、設定ファイルを調べまわってメンテナンスするという悪夢からも 開放されます。 規約によって開発が統一感を持つため、開発者が加わってすぐに手伝うということがやりやすく なります。
CakePHP の規約 - 4.x

日々の実装の中で「どうやって書けばスマートかな?」や「Cakeだとどうやって書くのがCakeWayっぽいかな?」だったりを考えながら手を動かすことが多いため、今日はそういった際に役に立つ情報源をまとめてみます。

ちなみに私が探しに行く順番で、上から順に紹介していきます。

情報源

公式ドキュメント(Cookbook)

最初というか、実装に悩む以前にCakePHPを触るのであれば一通り公式ドキュメントを流し見しておくことをおすすめします。 「設定より規約」という思想のフレームワークにおいて、「知っていること」が何よりも重要になるからです。

CakePHPの公式ドキュメントは内容の充実度もさることながら、ボランティアベースで行われている日本語への翻訳作業も継続的に実施されていて大変素晴らしい・・というかお世話になっております。

ドキュメントはcakephp/docsで管理されています。翻訳に興味がある人は以下の記事を参考にしてみてください。

公式APIリファレンス

CakePHPは公式のドキュメントであるCookbookの他に、APIリファレンスをHTMLの形で公開しています。これも実装に悩む以前に読んでいてほしいものですね。英語で言えばAPIは英単語、英会話を楽しむ前に最低限の語彙力を鍛えましょう!

エンジニアなら全員読んだことがありそうな『リーダブルコード』にも以下のような記述があります。

 プログラマというのは、既存のライブラリで問題を解決できることを知らないことが多い。あるいは、ライブラリで可能なことを忘れていることが多い。ライブラリの機能を熟知して、実際に活用することが大切だ。
 ここでささやかな提案だ。たまには標準ライブラリのすべての関数・モジュール・型の名前を15分かけて読んでみよう。標準ライブラリというのは、C++標準テンプレートライブラリ(STL)やJavaのAPIやPythonの組み込みモジュールなどのことだ。
13.4 身近なライブラリに親しむ 『リーダブルコード』 P.172

厳密にはフレームワークのAPIリファレンスよりは低いレイヤーの話だと思いますが、伝えたいことは同じです。全てを覚えるのではなく、頭の中にインデックスを作り、実装で悩んだときに参照できるようにしておきましょう、ということです。

社内の類似技術スタックのリポジトリ

(全員が参考にできないのでサクッといきますが)社内に同じような技術スタックのリポジトリがある場合はそちらの実装も参考にしてみましょう。 大抵の悩みは先行しているリポジトリで解決されていたりします。

cakephp/cakephpリポジトリ

特におすすめなのは「テストコードを読むこと」です。
公式ドキュメントを読んでも使い方が分からなかったり、自分たちがやりたいカスタマイズ方法が分からなかったりする場合はあると思います。 そんなときにテストコードを読むと、テスト対象であるSUTが「一体何を目的に実装されたコードなのか?」を明示されながら使い方まで理解することができるからです。

個人的には、テストコードのスマートな書き方を求めてコアコードを見に行くことが多いです。

(コラム) 思想を理解する

フレームワークの思想を理解するにはより詳細にissueなど実装当時の情報を深ぼるのもおすすめです。特にlabel:RFCだけでも見ておくとよいかもしれません。
例えば、CakePHP3でガラッと変わったバリデーション周りの変更はこのissueに背景が書いてありますし、Traitの使い方の見直しについてもこのissueで議論を垣間見ることができます。

他にもwikiにあるロードマップを見たり、コアコントリビューターのmark storyのwikiには実装の草案・アイデアが公開されていたりします。

FriendsOfCake/awesome-cakephp リポジトリ

CakePHPの良さそうなライブラリやシステムのリンク集です。
用途別に分類されているので、関係がありそうなセクションのリポジトリを眺めにいくことが多いですね。 弊社に関係するライブラリもいくつか記載されています💪

ちなみに、 FriendsOfCake はCakePHPの中の人達が中心となっている開発者グループで、品質の比較的高いCakePHPプラグインやリソースが提供されているため、比較的安心して実装を参考にできるかなと思います。

CakePHP Slackグループ

これまで紹介した情報源を調べても分からなかったり、数時間悩んだりするなら「人に聞く」というのもおすすめです。
周りに詳しい人がいない場合は、CakePHPコミュニティのSlackグループがあるのでそちらを活用してみるのはどうでしょうか。

#japanese チャンネルがあるので日本語で相談もできますね!
CakePHP Slack から誰でもjoinできます。

コアデベロッパーの関連サイト(2020/12/08 追記)

CakePHPのコアデベロッパーが個人でCakePHPに関する情報発信をしているケースが多々あるのでそちらも参考になります。いくつか例をあげます。

おわりに

ここまで参考になりそうな情報源を紹介してきました。
実際にはもちろんQiitaやZenn、個人ブログなども参考に見ることが多いですが、参考に値する確かな情報源を持っておくことは重要です。 いろいろなコードを読み、理解して、よりスマートな実装ができるように鍛錬していきましょう!

宣伝! イベントやります!

コネヒトでは12/17にオンラインイベント開催予定です。 サービス開発が大好きなエンジニアはもちろん、事業会社で働いてみたいエンジニアやtoC向けサービスに興味がある方はぜひご参加ください〜!

connehito.connpass.com

iOS14からはaddTargetじゃなくてaddAction

こんにちは、コネヒトでiOSエンジニアをやっていますyanamuraです。

これは iOS Advent Calendar 2020 の 4日目の記事です。

TL;DR

UIKitのUIControl系のView(UIButtonなど)ではタップ時のアクションをコードで実装するときは、標準のAPIだとaddTargetを用いる必要がありました。addTargetだとclosureが使えずいちいち関数を定義しなければならなかったり、@objcをつける必要があったりと面倒でした。

// addTargetでやるパターン
@IBOutlet weak var button: UIButton!

override func viewDidLoad() {
    super.viewDidLoad()

    button.addTarget(self, action: #selector(doSomething), for: .touchUpInside)
}

@objc func doSomething() {
    print("do something")
}

iOS14でついにUIControlにaddActionという新しいAPIが追加されこの面倒くささが解決しました!(SwiftUIがでているこの状況では今更感がありますが・・)

このようにシュッとかけるようになっています。

button.addAction(.init { _ in print("do something") }, for: .touchUpInside)

(ちなみにコネヒトでは現在RxSwift(RxCocoa)を使っているので正直addActionの恩恵にあずかることはなさそうです

詳細

UIControlの新しいAPIのaddActionではactionをselectorではなくUIActionを受け取るようになっています。

// UIControl
func addAction(_ action: UIAction, for controlEvents: UIControl.Event)

UIActionはinitializerで多くの引数を指定できますが、必須なのはhandlerだけです。

// UIAction
convenience init(
    title: String = "",
    image: UIImage? = nil,
    identifier: UIAction.Identifier? = nil,
    discoverabilityTitle: String? = nil,
    attributes: UIMenuElement.Attributes = [],
    state: UIMenuElement.State = .off,
    handler: @escaping UIActionHandler)

UIActionHandlerは単なるaliasです。

// UIActionHandler
typealias UIActionHandler = (UIAction) -> Void

UIControlにはaddAction以外にもinitializerでactionを設定することもできるようになっています。https://developer.apple.com/documentation/uikit/uicontrol/3600494-init

// UIControl
convenience init(frame: CGRect, primaryAction: UIAction?)

使い方

わかりやすく書くとこうなります。

let action = UIAction(handler: { _ in print("do something")})
button.addAction(action, for: .touchUpInside)

省略して書くとこのようになります。

button.addAction(.init { _ in print("do something") }, for: .touchUpInside)

addActionが使えるView

addActionはUIControlのAPIなのでUIControlとUIControlを継承しているクラスでは使えます。

ですので、UIButtonをはじめ、UIDatePicker, UIPageControl, UISegmentedControl, UISwitch, UIStepper, UISlider, そして新たに追加されたUIColorWellでaddActionが使えるはずです。

参考

WWDC2020: Build with iOS pickers, menus and actions https://developer.apple.com/videos/play/wwdc2020/10052/

Lambdaのコンテナサポートに関する考察

こんにちは。インフラエンジニアの永井(shnagai)です。

AWS re:Invent今年も大豊作ですごいですね。まだ全部は追えてないんですが、良さそうなものがあればサービスに取り入れていこうと思いわくわくしています。

この記事はコネヒト Advent Calendar 2020 - Qiita 3日目の記事です。

今回は、試してみてる方は結構いそうなので、ざっとLambdaのコンテナサポートを触ってみた感じの所感を中心に書いていきます。

うれしいポイント

  • 今想像してる一番うれしいポイントは、lambdaがサポートしてる数多のAWSインテグレーションをトリガに好きな処理が動かせるところ(lambdaRuntimeAPIの存在を知りそう甘くないことを理解した)
  • ローカルの開発がやりやすくなるなー
    • SAMとか使って出来るけど。個人的にはlambdaの管理は煩雑
    • dockerで検証出来た方が楽
  • lambdaの設定とアプリケーションコード(コンテナ)を分離して管理出来るようになるので、コード化しやすいなとか

vs 既存のLambda

  • Lambdaの一番かゆいところは、チーム開発しようとするとデプロイフローがやや面倒という点があると思っている(AWS SAMとかをうまく使っていけば出来なくはないが、チーム全員で回すにはやや複雑と感じている)

pros

  • 今回、アプリケーションコードをDockerコンテナ内に閉じ込めることで、既存の開発フローに乗せてLambdaを開発出来るようになる未来が見えた
  • ハンドラがDockerのCMD句に置き換わるので、共通のイメージで開発して、Function毎にCMD句だけ上書きすることで管理コストが大幅に下げれそうな気がしている

cons

  • しいて言うなら、Lambdaのメリットにマネコン上からコード閲覧出来たりサクッと変えてお試しみたいなのが出来るのがあると思うが、それは出来ない(手軽さは少し落ちるかなというところ)

vs Fargate

  • サーバレスでコンテナを動かせると考えると、Fargateの代替になりえるなと考えるのは当然の流れだと思う

pros:

  • AWSのインテグレーションを簡単に使えるというLambdaの強みを享受
    • 例えば、下のサンプルでやったSQSトリガのワーカーの仕組みなんかは、Fargateでやる場合は、ポーリングの処理を書かないといけないがそれが不要になるのはうれしい
  • Fargateでコンテナ動かすには、ECSなりEKSのオーケストレーターも必要なわけなので、スポットで単発の処理動かしたいみたいな時はLambdaはより簡単で良い

cons:

  • LambdaRuntimeAPIをコンテナ側で実装しなければいけないので、どんなイメージでも動くわけではない。
    • AWSである程度の言語については、すでに用意されてはいる
    • インターフェースを統一しなきゃいけないのはそれはそうだな
    • 既存のアプリケーションの一部をLambda+コンテナで動かすのはちょっとハードルあるなというのが正直な印象ではある

ちょっとイメージと違ったところ

これは触ってみて感じたことなので、実は違う可能性もある。

  • コンテナイメージは都度pullではなく、イメージ設定時に固定されそう
    • 同一タグでECR更新して、起動時に最新のイメージ取得みたいな構成は出来なさそう(何回か試したけど、lambdaを更新した時にイメージがずっと使われてそうだった)
    • 「新しいイメージをデプロイ」する時にpullしてるように見える
    • 起動速度維持するために、キャッシュしてるのかなと想像
    • コンテナビルドとLambdaの更新をセットでやらないとダメそう

で試してみる

今回は、SQSをイベントソースとして、SQSキューが入ったら中身を出力するという簡単な内容(疑似的なワーカー)

こちらのチュートリアルをベースに実行

docs.aws.amazon.com

コードはこちら

github.com

コンテナの準備

$ docker build -t [アカウントID].dkr.ecr.ap-northeast-1.amazonaws.com/tst-shnagai:test .

## 手元で動作確認
$ docker run --rm [アカウントID].dkr.ecr.ap-northeast-1.amazonaws.com/tst-shnagai:test

hogehoge

## ECRへのpush(ログイン込)
$ aws ecr get-login-password --region ap-northeast-1 | docker login --username AWS --password-stdin [アカウントID].dkr.ecr.ap-northeast-1.amazonaws.com && docker push [アカウントID].dkr.ecr.ap-northeast-1.amazonaws.com/tst-shnagai:test


Lambdaの設定

作成(コンテナイメージを選ぶ)

f:id:nagais:20201203100953p:plain

  • 手元にあった適当なpython動くコンテナで最初試したけど、それをただ実行させるとかは出来ないみたい(lambdaRuntimeAPIが必要で、呼び出しI/FもLambdaにそる)

f:id:nagais:20201203100356p:plain

  • IAM Roleとして AWSLambdaSQSQueueExecutionRole を追加するのを忘れずに。

SQSの準備

aws-cliでサッと作る

$ aws sqs create-queue --queue-name lambda-test
{
    "QueueUrl": "https://ap-northeast-1.queue.amazonaws.com/[アカウントID]/lambda-test"
}

先程作ったLambdaのイベントソースに上記のSQSを登録

テスト

$ aws sqs send-message --queue-url https://ap-northeast-1.queue.amazonaws.com/[アカウントID]/lambda-test --message-body "lambda-containerのテスト"

無事に動いた。

f:id:nagais:20201203100305p:plain

クラメソさんの記事が概要理解するのにめちゃ役立ちました!!

dev.classmethod.jp

TravisCIの料金体系の変更によるmacOSでのビルドへの影響(有料ユーザー向け)

2020/11/02からTravis CIの料金体系が変わりました。 blog.travis-ci.com

影響があるのは以下の4つ場合です。

  • Building on the macOS environment
  • Building with more than 10 concurrent builds
  • Building on a Trial Plan
  • Building on a public repositories only

コネヒトでは月額$249(5 concurrent job)のplanでweb, iOS, Androidで使っています。

このエントリーでは、コネヒトで影響のあった Building on the macOS environment についてのみふれていきます。

(注:TravisCIを無料でpublic repositoryでのみmacOSでビルドするのに使われている方には参考にならないです🙇🏻‍♂️)

macOS環境でのビルドへの影響

Travis CIではこれまではOSに関係なく同じプラン内で使えていましたが、今後はmacOSの場合はビルド時間に応じて追加料金が必要となります。 料金は以下の通りです。

  • $15で25000 creditを購入
  • macOSだと1分で50 credit

CircleCIとそろえているようでした。

いつから?

現在のプランの有効期限が切れると次回から新しいプランに移行するようでした。

Beginning on Monday the 2nd of November 2020, customers impacted by pricing changes listed above will be gradually upgraded to the new pricing scheme upon their plan expiration date.

他のCIとのコストの比較

追加料金必要になるなら他のCIに乗り換えることも検討するかと思いますのでコストを比較してみました。

月にどれくらい使うか、チームの規模、iOS以外の開発での利用などによって最適なものは異なってくるのでどれが一番良いとは一概に言えません。

ビルド時間 Travis CI Circle CI bitrise GitHub Actions
2000min $60 + $69/$129/$249 ※1 $60+$15 ※2 $100/$300 ※3 $136
2500min $75 + $69/$129/$249 ※1 $75+$15 ※2 $100/$300 ※3 $176
3000min $90 + $69/$129/$249 ※1 $90+$15 ※2 $100/$300 ※3 $216
3500min $105 + $69/$129/$249 ※1 $105+$15 ※2 $100/$300 ※3 $256

※1 Travis CIはconcurrent planによってベースの料金が異なります

※2 Circle CIはユーザー数によって料金が異なります

※3 bitriseはプランによって料金が異なります

2020/11/11時点の情報です。

コネヒトでの今後の方針

コネヒトのiOS開発でのCIの利用状況は月に3000分くらいで、コスト的には他のCIと遜色なさそうでした。

ただTravis CIを使っている上で ログが最大4MBまでしか保存されない というところが結構不便に感じていたので、同じくらいのコストで定額で使えるbitriseに乗り換えようかと検討しています。

potatotips #71 で Mixpanel について LT してきたのでその補足や失敗談の共有

こんにちは!コネヒトでアプリケーションエンジニアをしているaboです。

先日開催された potatotips #71 iOS/Android 開発 Tips 共有会で、コネヒトでも活用しているプロダクト分析ツールの Mixpanel について話してきました。コネヒトでは、エンジニアもプロダクトをより良くする開発チームの一員として仮説検証や施策を考えるために Mixpanel や Redash などの分析ツールを触ります。Mixpanel は GUI で比較的かんたんに分析できたり、レポートのビジュアライズが強力で、コネヒトでも分析ツールのひとつとして役立っています。

potatotips.connpass.com

今回は、発表内容の補足や失敗談の共有をします。当日の発表資料はこちらです。

GUI でかんたんに分析できる

発表で出さなかった例として、「Compare to previous year」を選択すると、前年の値と比べられたり(点線が前年、実線が今年)

f:id:aboy_perry:20201028160221p:plain
前年との比較

Annotation という、レポートの日付に注釈をつけられる機能があったりします。下の画像の例だと、機械学習のモデルを更新したんだな、ということがレポート上でわかりやすくなります。

f:id:aboy_perry:20201028184839p:plain
Annotation をつけてやった施策をわかりやすくする

ユーザーの Activity Feed をエラー調査に活用する

ユーザーの行動を時系列で確認できる Activity Feed も便利です。実際にアプリケーションのエラーを調査するときに、Activity Feed で該当のエラーが発生した時刻の前後の行動をみたりします。そして「通常のユースケースで起きてそう」「いや何か変だぞ」みたいなコミュニケーションをしたりしています。

f:id:aboy_perry:20201028181426p:plain
ユーザーの行動を時系列で確認できる Activity Feed

Cohorts も便利

発表では触れられませんでしたが、Cohorts というユーザーをグループ化できる機能があります。つくった Cohorts は分析の条件に入れたり、ユーザーリストを CSV としてエクスポートできたりして便利です。例えば「過去7日間に10回以上起動した Android ユーザー」などです。

f:id:aboy_perry:20201028170603p:plain
Cohorts の作成画面

エンタープライズプランであれば Cohorts はファネル分析やリテンション分析のレポートからも作成できます。ファネルであれば「施策で追加したバナーから購読画面を開いたが購読せず離脱したユーザー」や「ディープリンクから投稿画面を開いてそのまま投稿してくれたユーザー」など。リテンションであれば「投稿した次の日に起動しなかったユーザー」のようなユーザーのリストを、レポートからポチポチするだけで作成できます。

f:id:aboy_perry:20201028164022p:plain
ファネル分析のレポート上で選択するだけで Cohorts がつくれる

コネヒトでは使っていませんが、Cohorts に対してメッセージを送ることもできます。

help.mixpanel.com

MTU が想定以上に増えた

最後に失敗談です。Mixpanel は MTU (Monthly Tracked User) という方法で費用が計算されます。 MTU は対象の月にイベントを実行したユーザー数のことで、Mixpanel では distinct_id という識別子でユーザーが一意に決定されます。

コネヒトではアプリ (Native と WebView) からのみ Mixpanel にイベントを送信しており、distinct_id にはママリのユーザー ID が設定されるようになっていました。なので MTU はアプリ版ママリの月間ユニークユーザー数と近しい値になっていました。

しかし新たに Mixpanel へのトラッキングを追加した際、ママリにログインしていなくても見ることができるブラウザも対象にしました。すると distinct_id には Mixpanel で生成されたユニークな ID が設定されたことによってそれぞれが別のユーザーとしてカウントされてしまい MTU が想定以上に増えてしまいました。

f:id:aboy_perry:20201027231719p:plain
MTU が爆増した2週間

このときは、(1)コスト増のインパクトが大きいこと(2)トラッキングの目的であったデータ分析が終わっていたため消しても問題ない、という理由から該当のコミットをリバートする対応をしました。

公式ドキュメントには、集計対象外のイベントや MTU の計算方法の例外、MTU に大きな影響を与えているイベントの調べ方なども書かれてあります。

help.mixpanel.com

おわりに

LT で話せなかったことや、失敗談を共有しました。プロダクト分析ツール選びの際に参考のひとつになれば幸いです!


コネヒトではプロダクトを一緒に成長させられるエンジニアを絶賛募集中ですので、まずはお話だけでも聞きにきてください!

hrmos.co