Tech Blog

グローバルな家族アプリFammを運営するTimers inc (タイマーズ) の公式Tech Blogです。弊社のエンジニアリングを支える記事を随時公開。エンジニア絶賛採用中!→ https://timers-inc.com/engineering

Famm iOSにおけるBitriseのワークフローを大公開 #bitrise

f:id:bboykk:20190509100944p:plain

iOSチームのかっくん(@fromkk)です。
TimersのiOSチームでは2016年頃からBitriseを利用しています。当初はただビルドしてバイナリを社内に配布するだけだったのですが、月日が経つにつれてBitriseの役割も増えてきました。
そこで2019年5月時点でのFamm iOSアプリにおけるBitriseのワークフローを公開します!

Bitriseとは

iOS/AndroidアプリのCI/CDに特化したウェブサービス(PaaS)です。最近はBitrise社の人達もよく来日したり、色んな会社に訪問して精力的に日本での意見のヒアリングや勉強会への参加・登壇を行なっています。
また、資料の日本語化にも力を入れていますので、困った時にも情報がすぐに見つかると思います。 1
弊社のワークフローの説明の前にステップワークフローという単語を抑えておきましょう。既にご存知の方は飛ばして下さい。

ステップ

1つの処理を記述した物です。公式に配布さている物と、独自に配布されているものがあります。2

ワークフロー

複数のステップをまとめて1つの流れにしたものです。ビルドのタイミングによって選択が可能で、様々なステップを組み合わせる事で独自の処理を作っていきます。

トリガー

Bitriseではワークフローを実行する方法として、

  • 手動(GUIから直接実行)
  • WebHook経由(GitHubなど、手動で叩くことも可能)
  • 時限設定(beta)

が可能です。弊社で設定しているトリガーを以下に記述します。

ブランチのプッシュ時

通常

f:id:bboykk:20190513164827p:plain

f:id:bboykk:20190510122617p:plain:h480
Gist

GitHubにブランチがプッシュされたら動作するものです。一番よく動いています。ワークフローは長いですがやっていることはシンプルで、開発環境のアーカイブを作成して、Bitrise、DeployGateにアップロードしています。 3

リリースブランチ作成時

f:id:bboykk:20190513164924p:plain

f:id:bboykk:20190513182530p:plain:h480
Gist

リリースブランチがプッシュされたら動作するものです。
Auto Provisionで証明書を解決し、バイナリをAppStore Connectへアップロードを行っています。

PR

f:id:bboykk:20190513153211p:plain:h480
Gist
Gemfile
Dangerfile

GitHubでPRを作成したら動作します。Unit Testの実行とDangerを実行しています。

Tag

f:id:bboykk:20190513163216p:plain:h480
Gist

タグが作成(新バージョンを新たにリリース)されたら動作します。 Change logを作成してGitHubにリリースページを作成しています。

f:id:bboykk:20190513183210p:plain

1つ前のタグと最新のタグの差分を表現するURLを作成している部分のスクリプトはこんな感じです。

#!/usr/bin/env bash
# fail if any commands fails
set -e
# debug log
set -x

BEFORE=`git describe --abbrev=0 --tags $(git rev-list --tags --skip=1 --max-count=1)`
LATEST=`git describe --abbrev=0 --tags $(git rev-list --tags --skip=0 --max-count=1)`

COMPARE_URL="https://github.com/YYYY/XXXXX/compare/${BEFORE}...${LATEST}"

envman add --key COMPARE_URL --value $COMPARE_URL

時間をトリガーとして動作するもの

f:id:bboykk:20190510175435p:plain

Bitriseには時間をトリガーとして動作する Schedule this build(beta) という機能があります。時間が掛かったり、開発と同期的に実行する必要が無い物を定期実行にしています。
まだベータ版なので正式リリースされる際には変更が入るかも知れません。

UIテスト(毎晩深夜24時)

f:id:bboykk:20190513171001p:plain:h480
Gist

UIテストは実行に時間が掛かるのと、変更頻度が低いので定期実行にしています。
結果をまとめてS3にアップロードしています。

Magic Pod(毎週金曜日深夜25時)

f:id:bboykk:20190513171130p:plain:h480
Gist

BitriseとMagic PodでiOSアプリのCI & 自動テスト | 品質向上ブログという記事を参考にしました。
最近はQAの人たちが自主的にテストケースを作れる様にトライしており、その週で対応した部分のテストが週末に走り、翌週に結果が見れる様にしています。

ライブラリの自動更新(毎週日曜日深夜25時)

f:id:bboykk:20190513171156p:plain
Gist

TravisCIでiOSの依存ライブラリの更新を自動化する - Speee DEVELOPER BLOGという記事を参考にしてスクリプトを作成しました。
日曜日の深夜に行う事で月曜日の午前中はライブラリの更新に失敗した場合などの作業を行う様にしています。こまめにアップデートする事で、何かあっても少ない差分で対応出来ています。

#!/usr/bin/env bash
# fail if any commands fails
set -e
# debug log
set -x

pod install

POD_OUTDATED=`pod outdated`
CARTHAGE_OUTDATED=`carthage outdated --use-ssh`

POD_UPDATES=""
CARTHAGE_UPDATES=""

if echo "${POD_OUTDATED}" | grep "No pod updates are available." ; then
  echo "cocoapods no updates"
else
  POD_UPDATES=`echo "$POD_OUTDATED" | grep '(latest version'`
fi

if echo "${CARTHAGE_OUTDATED}" | grep "All dependencies are up to date." ; then
  echo "carthage no updates"
else
  CARTHAGE_UPDATES=`echo "$CARTHAGE_OUTDATED" | grep '(Latest'`
fi

if [ ${#CARTHAGE_UPDATES} -eq 0 -a ${#POD_UPDATES} -eq 0 ]; then
  echo "No update"
  exit 0
fi

if [ ${#CARTHAGE_UPDATES} -eq 0 ]; then
  echo "empty"
else
  carthage update --platform iOS --use-ssh --new-resolver
fi

if [ ${#POD_UPDATES} -eq 0 ]; then
  echo "empty"
else
  pod update
fi

if which hub >/dev/null; then
    echo "hub installed!"
else
    echo "hub not installed..."
    brew install hub
fi

CREDENTIAL_FILE="$HOME/.config/git-credential"
mkdir -p $HOME/.config

GH_TOKEN=$GITHUB_ACCESS_TOKEN
GH_USER=$GITHUB_USER_NAME

echo "https://${GH_TOKEN}:@github.com" > $CREDENTIAL_FILE
echo "github.com:
- oauth_token: $GH_TOKEN
  user: $GH_USER
  protocol: https
" > "$HOME/.config/hub"

git config --global user.name "${GH_USER}"
git config --global user.email "${GH_USER}@users.noreply.github.com"
git config --global credential.helper "store --file=$CREDENTIAL_FILE"

touch pr.txt
echo "Detected outdated dependencies." > pr.txt

BRANCH_NAME="refactor/library_"`date "+%Y-%m-%d_%H-%M-%S"`
git checkout -b $BRANCH_NAME
git add Cartfile.resolved
git add Podfile.lock
if git commit -m "[Auto generated] Update dependencies" ; then
  git push origin $BRANCH_NAME
  hub pull-request -F pr.txt -b develop
fi

まとめ

弊社で実行しているBitriseの環境をほぼ全て公開してみました。
他にも「こういう事を自動化するといいよ」とか「うちではこうやってるよ」などあれば色々教えて欲しいです。
弊社ではCI/CD環境を各プラットフォームのエンジニアが整備しています。この様に様々な事を自動化する事に興味があるエンジニアの人がいましたら、是非お声がけ頂ければと思います!

積極採用中!!

子育て家族アプリFammを運営するTimers inc.では、現在エンジニアを積極採用中!
急成長中のサービスの技術の話を少しでも聞いてみたい方、スタートアップで働きたい方など、是非お気軽にご連絡ください!
採用HP: http://timers-inc.com/engineerings


  1. まだ日本語化されて無い資料はGitHubからPRを出せば貢献出来るかもしれません。

  2. 独自に作成する方法も公開されています。

  3. DeployGateを公式のものを利用していない理由としては、インストール用のURLがうまく取得出来なかったので独自のスクリプトを書いています。

Timersでは各職種を積極採用中!

急成長スタートアップで、最高のものづくりをしよう。

募集の詳細をみる