Chào các bạn, để tiết kiệm thời gian build app rồi phải deploy thủ công thì hôm nay mình sẽ viết 1 bài về Continuous delivery (from local machine) android phục vụ cho deploy Flutter app. Vì là bài viết đầu tay nên có gì thiếu sót mọi người thông cảm và góp ý để nâng cao chất lượng bài viết sau này nhé.
Các cách để setup Continuous delivery cho Flutter app
Chúng ta có thể dễ dàng tìm được những giải pháp hỗ trợ cho việc deploy Flutter dễ dàng trên Docs của Flutter, về cơ bản có 2 giải pháp chính:
- Sử dụng dịch vụ bên thứ 3 như: Codemagic, Bitrise, Appcircle. (mình có dùng qua Codemagic, khá tiện lợi).
- Cấu hình thủ công bằng fastlane (trong bài viết này mình sẽ tập trung vào giải pháp này).
Điều kiện tiên quyết
- Cần có tài khoản Google Play Console Developer.
- Đã cài đặt môi trường cần thiết để phát triển Flutter App.
- Cài đặt môi trường phát triển và build file .aab (android app bundle).
Cài đặt và cấu hình fastlane.
1 2 3 4 5 | brew <span class="token function">install</span> fastlane flutter create —org com.example projectname <span class="token builtin class-name">cd</span> android fastlane init |
Sau khi chạy lệnh “fastlane init” terminal sẽ yêu cầu cung cấp 1 số thông tin:
- Cung cấp package name của app (ví dụ: my.package.name).
- Cung cấp json secret file: nhấn “n” (bước này mình sẽ thiết lập sau).
- Nhấn ‘n’ khi được hỏi “liệu bạn có định tải thông tin lên Google Play qua fastlane hay không?” (mình sẽ thiết lập sau).
Sau khi hoàn tất “thủ tục” fastlane init fastlane sẽ khởi tạo 2 file Appfile (cấu hình thông tin cho app) và Fastfile (cấu hình các lệnh deploy) trong thư mục android/fastlane.
Cấu hình trên Google Play Console và Google Cloud Platform để lấy “Json secret file” đã đề cập trước đó.
Các bước sẽ như sau:
- Mở Google Play Console
- Ở Sidebar bên trái, click vào Account Details, chú ý Developer Account ID.
- Click vào Setup ⇒ API access
- Chuyển tới Google Cloud Platform
- Click vào nút Create new service account. để chuyển tới Google Cloud Platform.
- Click nút CREATE SERVICE ACCOUNT ở đầu trang Google Cloud Platform Console.
- Xác minh dùng đúng Developer Account ID trong IAM & Admin → Service Account.
- Cung cấp Service account name và click Create.
- Click Select a role, chọn Service Account User và nhấn tiếp tục → Nhấp DONE.
- Click Actions ở icon 3 chấm của service account vừa tạo → Chọn Manage keys.
- Click ADD KEY → Create New Key
- Chọn kiểu JSON → nhấp CREATE.
- Download file và lưu trữ nơi cần thiết trên máy tính.
- Quay về Google Play Store click nút DONE để đóng popup
- Click nút Grant Access → Refresh service accounts để cập nhật những thay đổi từ bước 4.
- Cấp quyền cho tài khoản này. Gợi ý Admin (all permissions).
- Click Invite user để hoàn tất.
Run những lệnh fastlane đầu tiên.
Sau khi đã cấu hình những thứ cần thiết, chúng ta sẽ viết những lệnh phục vụ cho deploy.
- Đầu tiên kiểm tra xem thử đã kết nối với Google Play Store thành công chưa, chạy lệnh:
1 2 | fastlane run validate_play_store_json_key json_key:/path/to/your/downloaded/file.json |
- Khi mọi thứ đã ok hết thì mở file android/fastlane/Appfile để thêm đường dẫn file json secret.
1 2 3 | json_key_file<span class="token punctuation">(</span><span class="token string">"path/to/your/play-store-credentials.json"</span><span class="token punctuation">)</span> package_name<span class="token punctuation">(</span><span class="token string">"my.package.name"</span><span class="token punctuation">)</span> |
- Chạy lệnh sau để bắt đầu cấu hình.
1 2 | fastlane supply init |
Lưu ý: Google Play Store yêu cầu phải có 1 bản build đầu tiên (version code: 1) đã upload lên Google Play Store trước mới có thể deploy những bản build sau này.
Cấu hình build android appĐể tránh bài viết dài dòng, các bạn có thể làm theo hướng dẫn của Flutter để build bản android app đầu tiên: https://docs.flutter.dev/deployment/android.
Thay đổi 1 số config để tránh việc chạy lệnh fastlane deploy bị lỗi.
- Thêm lintOptions:
android/app/build.gradle
.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | android { //.... lintOptions { checkReleaseBuilds false } // Đổi versionName, versionCode để phục vụ cho việc tăng version build bằng plugin defaultConfig { // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). applicationId "my.package.name" minSdkVersion flutter.minSdkVersion targetSdkVersion flutter.targetSdkVersion // versionCode flutterVersionCode.toInteger() // versionName flutterVersionName versionCode 2 // Đổi về dạng tiêu chuẩn để khi chạy lệnh increment_version_code không bị lỗi versionName 1.0.0 } //... } |
- Ở file android/gradle.properties thêm dòng lệnh sau:
1 2 | org.gradle.jvmargs=-Xmx1536M --add-exports=java.base/sun.nio.ch=ALL-UNNAMED --add-opens=java.base/java.lang=ALL-UNNAMED --add-opens=java.base/java.lang.reflect=ALL-UNNAMED --add-opens=java.base/java.io=ALL-UNNAMED --add-exports=jdk.unsupported/sun.misc=ALL-UNNAMED |
- Ở file android/gradle/wrapper cài đặt project chạy trên gradle 7.5 thay vì 6.7 như hiện tại.
1 2 3 4 5 6 7 8 | #Fri Jun 23 08:50:38 CEST 2017 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists // distributionUrl=https://services.gradle.org/distributions/gradle-6.7-bin.zip distributionUrl=https://services.gradle.org/distributions/gradle-7.5-bin.zip |
- Chạy lệnh sau để cập nhật gradle 7.5
1 2 3 | cd android ./gradlew --refresh-dependencies |
Viết các lệnh cần thiết cho việc Deploy
Sau khi đã hoàn tất các bước trên. Mở file android/fastlane/Appfile.
1 2 3 4 5 6 7 8 9 | # Increment version code - Lệnh này để tăng version code trước mỗi lần build desc "Increment version code" lane :increment_vc do increment_version_code( gradle_file_path: "./app/build.gradle", version_code: 2 // Thay đổi version code ở đây 2 -> 3 -> 4 -> ... cho mỗi lần deploy mới. ) end |
Cấu hình việc build & deploy
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | desc "Deploy a new version to the Internal Google Play" lane :deploy do // lane deploy gradle(task: "clean bundleRelease") // Lệnh này để clean bundleRelease (làm sạch project trước mỗi lần build mới). gradle( task: 'bundle', build_type: 'Release' ) // Lệnh này để build file .aab upload_to_play_store( track: 'internal', // Chúng ta thử nghiệm trên Internal tester. Thay đổi track cho những bản build production, beta, alpha, internal,... release_status: 'draft', skip_upload_changelogs: true, aab: '../build/app/outputs/bundle/release/app-release.aab', // Lệnh này để trỏ đường dẫn bản build file .aab (dùng file .aab này để upload lên Google Play Console). ) end |
Hoàn tất các lệnh cần thiết. Bắt đầu deploy thôi nào!
1 2 3 4 | cd android fastlane increment_vc // Chạy lệnh tăng version code trước mỗi lần deploy fastlane deploy // Chạy lệnh để build & deploy trên lane :deploy |
Tận hưởng thành quả.
Sau khi đã hoàn tất các bước trên thì ta đã hoàn thành việc Continuous delivery (local machine) cho android app. Các bản build sau chỉ cần nâng version code và chạy lệnh sau là đã upload file lên Internal Tester (tương tự cho các trường hợp beta, production,…)