エンジニア

2017.09.07

HandsPOSゆるふわ開発フロー

HandsPOSゆるふわ開発フロー

最近はTypeScriptが楽しい、駒場です。

東急ハンズの内製iPadPOSアプリHandsPOSのゆるふわ開発フローについて書いてみたいと思います。

issue tracker

課題管理には社内全体で Backlog を利用しています。Backlogの課題に対応したGitHubのプルリクエストが作成された場合、Open時にはPRのURLをコメントしマージされた時にはBacklogの課題をCloseするBOTが運用しています。BOTはGitHubのWebHook, API Gateway, Lambdaで出来ています。コードと絡まないようなタスクもこちらに登録しています。

git workflow

developブランチからforkしてfeatureブランチやbugfixブランチをローカルで作成してプルリクを作成しレビュー後にdevelopブランチにマージするフローで、GitHub Flowに近いです。リポジトリにはGitHubを使っています。最近はRebase mergeが好きです。

git commit-hook + lint

lintにはSwiftLintを利用し警告も出ないようにしています。lintで警告が出るコードをコミットしたくないので、gitのpre-commit hookにswiftlintを実行し警告が出ない事をチェックして警告があるようであればエラーにしてコミットを防止しています。commit hookは.gitディレクトリ配下となりコード管理しにくいため、npmの pre-commit を利用してチーム内で共有しています。また、個々人のインストールしているSwiftLintのバージョンが古く、新規ルールを追加しても必要な警告がその人の環境では出ない事も考えられるため、そこは後述のCI(CI環境のSwiftLintは最新を利用)で実行されるDangerで警告されるようにしています。

CI

developブランチへのコミット及びプルリクされているブランチへのコミット時にはCIを走らせてテスト等を実行しています。

  • DEBUGビルド及びUnit Test
  • Releaseビルド
  • プルリクの場合はDangerの実行

CIサービスは最初は無料だったbuddybuildを利用していたのですが、有料化に伴いビルドの早かったCircleCIを現在は利用しています。Travis, CircleCI, Bitrise, Nevercode, buddybuildを試した結果として最近のCircleCIはマシンパワーが上がってCIサービスの中ではちょっぱやです。でも1コミットに対して並列で何か処理させる事は出来ないので、タスクがいくつもあってMatrixをうまく使えれば総合時間ではTravisが速いかもしれません。

Danger

Dangerはいまのところこんなルールで動かしています。Storyboardファイルを変更していたらスクリーンショットのせてねルールが独特でしょうか。あまり使いこなせている感がないです。

# Git
warn "Big PR" if git.lines_of_code > 5000
# GitHub
warn "Please add labels to this PR" if github.pr_labels.empty?
warn "PR is classed as Work in Progress" if github.pr_labels.include? "WIP"
warn "PR is classed as Work in Progress" if github.pr_title.include? "WIP"
can_merge = github.pr_json["mergeable"]
warn("This PR cannot be merged yet.", sticky: false) unless can_merge
hasImage = github.pr_body.match /!\[.*\]\(.*\.png\)/
warn "Please provide screenshots." if git.modified_files.include?("*.storyboard") && !hasImage
fail "Please provide a summary in the Pull Request description" if github.pr_body.length < 5
# swiftlint
github.dismiss_out_of_range_messages
swiftlint.config_file = '.swiftlint.yml'
swiftlint.lint_files inline_mode: true

Carthage自動PullRequest

アプリで利用しているライブラリはなるべくCocoaPodsではなくCarthageに寄せています。Carthageはcarthage outdated で新しいバージョンがリリースされていないかチェックでき、carthage update –no-checkout コマンドで実際にはframeworkをビルドせずにCartfile.resolveをアップデート出来ます。これらを利用して週に1回CIをスケジュール実行(CircleCIはスケジュール実行の機能がないためLambdaのスケジュール実行でCircleCIのAPIで実行)させ、新しいバージョンがあればCartfile.resolveをアップデートするPullRequestを自動作成するようにしてライブラリは定期的にアップデートしています。

GitHub Releases

新しいバージョンを作成する際はgitのタグを作ります。タグのプッシュイベントの場合はCIは通常のタスクの他にxcarchiveを作成しGitHub Releasesにアップロードするタスクを追加で実行させています。現在はタグの作成後にCHANGELOG.mdの生成のために github-changelog-generator を手動で実行していますがこれもCIのタスクに持っていきたいですね。ただ、このgemですとまだdevelopブランチにはマージされていないけれど、featureブランチに向けたPRのマージも、バージョン間にマージされたものとして載ってきてしまうため、もうちょっと良いものはないかと検討中。

deploy

HandsPOSはEnterpriseアプリなので、AppStoreへの登録はありません。代わりにMDMと呼ばれる管理サービスにipaファイルをアップロードし各端末に配信する形です。弊社では CLOMO をMDMに利用していますが、CLOMOに外部向けのAPIがないため現在は作成したipaを手動でアップロードしています。このあたりの自動化は課題の一つ。最近個人的なサイドプロジェクトでpuppeteerを使い始めたので、それで出来たらいいなと構想しています。また、プロビジョニングプロファイルを1年間更新せずに危うく有効期限切れになる事があったため、現在は定期的に再作成しているが新しいバージョンを作る度に再作成しても問題はないため、そこもspaceship等で再作成->ダウンロードした新しいプロビジョニングプロファイルでipaを作成…と出来ると新しいバージョンを作成するとそこから1年有効なipaが作成出来るので嬉しいですね!

まとめ

書いていくうちに後回しにしている改善がそこそこある事に気付かされました。まだまだ改善していこうと思います!
 
「iOSDC 2017」に本ブログの著者 駒場と、黒岩が登壇します!
https://www.hands-lab.com/news/seminar-events/770
マイナビニュース掲載「エンタープライズの世界で挑戦! ハンズラボのiOSアプリ開発現場に迫る」
http://news.mynavi.jp/kikaku/2017/09/01/002/

一覧に戻る