【Flutter】アプリのバージョンニングの自動化方法と運用について考える
概要
CI/CDを組んでいるとアプリのバージョンも自動化してインクリメントしたくないでしょうか?
Flutterプロジェクトはアプリのバージョン(と内部的なバージョン)の更新はpubspec.yamlに記載されているversion
フィールドを
name: flutter_playground
description: A new Flutter project.
publish_to: 'none'
version: 1.0.0+1 # ←これ
各OS用プロジェクトファイルにデフォルトでそのまま適用してくれる仕組みになってます
各バージョンをCI/CDのワークフローの一部に取り入れる際に自動でインクリメントできないかの手段を考えたいと思います
結論(忙しい人向け)
先に結論です
どちらかというとpackage開発向けですが、cider packageが一番柔軟にアプリバージョンとビルドバージョンをインクリメントまた指定のバージョンにアップデートがしやすいかなと考えてます
前提知識と各バージョンの統一性
pubspec.yamlの version
フィールドはセマンティックバージョンニングで記載します
+の左側,右側で以下のように実行時にデフォルトで参照する仕組みになってます
pubspec.yaml | Android(local.properties) | Android記述 | iOS(Generated.xcconfig) | iOS記述 |
---|---|---|---|---|
左 | versionName | セマンティックバージョニング | CFBundleShortVersionString | セマンティックバージョニング |
右 | versionCode | 整数値(最大値 2100000000) | CFBundleVersion | セマンティックバージョニング(マイナーバージョン以降省略可) |
アプリのバージョンはAndroid・iOSと同じ記載方法で統一できますが、内部的に使う各versionCodeとCFBundleVersionで記述方法が異なります
ただ、Apple公式ドキュメントを確認すると
You can also abbreviate the build version by using only one or two integers, where missing integers in the format are interpreted as zeros. For example, 0 specifies 0.0.0, 10 specifies 10.0.0, and 10.5 specifies 10.5.0.
整数として省略できるのでAndroidと同じ整数値として統一した方が管理しやすいと思います
(プロジェクト要件によっては記載したい方法が変わるかもしれないので、管理しやすい一つの例ぐらいでの参考でお願いします🙏)
またAndroidは上限値がドキュメントに記載されていますが、iOSの方は特に公式ドキュメントでは言及されていません
余談レベルとして調べてみると以下サイトより↓
Careful with the length of CFBundleVersion as it has not to exceed 18 characters (including dot separators).
という注意書きがあり18文字以内にするよう何かしらの警告が出るようです?
アプリ実行時に試した際は特に出なかったので、時間あった時にはアップロード時に試してみたいと思います
手段
自分が調べていて現状可能なパッケージも含めて4種類あるかなと思います
- Flutter CLI
- 自作シェルスクリプトを用意する
- pub_version_plus パッケージ
- cider パッケージ
Flutter CLI
Flutterのbuildコマンドのオプションにそれぞれのバージョン指定オプションが用意されてます
- --build-name・・・アプリバージョン(
version
フィールドだと+左側) - --build-number・・・内部的なバージョン(
version
フィールドだと+右側)
# 例
$ flutter build ios --build-name=2.0.0 --build-number=3
上記のような形でそれぞれのバージョンを更新できるのですが、pubspec.yamlの更新ではなく
Android → local.properties
iOS → Generated.xcconfig
各プロジェクトファイルで用意される設定値の上書きなので、pubspec.yamlのversion
フィールドと統一できなくこの方法で運用するとあとでpubspec.yamlファイルを手動更新するスタイルになるのかなと思います
自作シェルスクリプトを用意する
他手段がない場合はこれを検討してもいいですが、yamlファイルの読み書きが少々めんどくさいので最終手段になるかなと思います。。。
pub_version_plus パッケージ
pubspec.yamlのversion
フィールドを更新してくれるパッケージです
ドキュメントに書いてある通りに <version-type>
と書いてある箇所にそれぞれのどのアップデートの仕方か
- major
- minor
- patch
- build
を指定して記載するとそれに適したバージョンでインクリメントしてくれます
※ 以下使用パッケージバージョン: pub_version_plus 1.1.0
# Before 1.2.1 → After 1.3.0
$ dart pub global run pub_version_plus:main minor
# Before 1.2.1 → After 1.2.2
$ dart pub global run pub_version_plus:main patch
ただ、パッケージ運用の場合は問題ないですが build
の箇所は0としてリセットしてしまいます
アプリ運用の場合は内部的なバージョンは各ストアへアップロードする際に前回より大きい値にしないと弾かれてしまうため、pub_version_plusだとちょっと要件が満たせれないのが惜しいです
cider パッケージ
パッケージ開発向けですが、アプリ開発でも柔軟にバージョニングができるコマンドがいくつか用意されています
※ 以下使用パッケージバージョン: cider 0.2.3
直指定の方法
# 例
$ dart pub global run cider version 1.0.1+12
どういうアップデートをするかを指定した自動インクリメントの方法
# 例
$ dart pub global run cider bump minor --bump-build
major
, minor
, patch
, build
に合わせた該当箇所に対する現状の値からインクリメントしつつ
--keep-build will retain the existing build part.
--bump-build will increment the build part (see below).
という内部的なバージョンの扱いをどうするかというオプションコマンドも用意されているので柔軟にアップデートできます
まとめ
プロジェクト状況によっては適切なバージョンニング手法は異なるかもしれませんが、pubspec.yamlのバージョンをAndroid/iOSそれぞれのバージョンへそのまま適用する場合はciderパッケージだと、CI/CDのワークフローの一部に導入しやすいかなと考えてます
何か不適切な内容の記載だったり、別手法も検討できる等あれば気軽にご指摘くださいませ🙏
Discussion