Flutter Starter Project
Generated by the Nero Lab CLI ?
A Nero Lab Project created by Nero Lab CLI.
Getting Started?
This project contains 3 flavors:
- development
- staging
- production
To run the desired flavor either use the launch configuration in VSCode/Android Studio or use the following commands:
# Development
$ flutter run --flavor development --target lib/main_development.dart
# Staging
$ flutter run --flavor staging --target lib/main_staging.dart
# Production
$ flutter run --flavor production --target lib/main_production.dart
Before you push your local branch to remote branch always do this steps:
$ flutter format lib test
$ flutter analyze lib test
*Flutter Starter Project works on iOS, Android, and Web.
Setup GitLab?
Git Branchs
- master as development branch (protected)
- staging (protected) : for QA to testing App
- production (protected) : for production, deploy to Play Store or App Store
- features branch
GitLab Flow
Principles
-
Create a new local branch for the task and periodically push a branch of the same name on the server
-
When the task is finished, request a Merge Request for the master branch
-
When the submitted changes were reviewed/approved, merge them with the master branch
-
Once in the master, the code must be integrated into the company’s internal environments branches, until reaching the production branch.
-
When being merged into the master, delete the branch where the task was developed leaving the repository more organized.
Features Branch > Master > Staging > Production
Read this for more information GitHub – jadsonjs/gitlab-flow: Shows the Gitlab flow workflow
CI Variables
In your project open settings > CI/CD > Variables , and this variabel:
- Encode the keystore:
base64 key.jks
- Copy the base64 output and create a variable called
STORE_FILE
- Save the store password as
STORE_PASSWORD
variable - Save the key password as
KEY_PASSWORD
variable - Save the key alias as
KEY_ALIAS
variable
To make the deployment via Fastlane working, you need to to get API access to Google Play console. To get an api key json file, follow the steps of the Collect your Google credentials section of the Fastlane guide
- Save the content of the key.json file as
JSON_KEY_DATA
variable.
To deploy to Firebase App Distribution via Fastlane, follow the steps Firebase App Distribution.
- Save the Firebase app id as
FIREBASE_APP_ID
variable - Save the firebase cli token as
FIREBASE_CLI_TOKEN
variable, to get firebase cli token follow this steps
GitLab CI/CD
This is Gitlab pipeline visualize for this project:
Stages
There are 4 stages:
- Test
- Build
- Staging
- Internal_test
- Production
1. Test
Test stage will run in all branchs and do this scripts
- flutter format --set-exit-if-changed lib test
- flutter analyze lib test
- flutter test --coverage
- lcov --remove coverage/lcov.info 'lib/*/*.g.dart' 'lib/core/**' -o coverage/lcov.info
- genhtml coverage/lcov.info --output=coverage
If when run flutter format --set-exit-if-changed lib test
must no file changed or Gitlab CI will return fail, and make sure no error or warning in this project. So before you push the project to remote you need run this in your local branch
$ flutter format lib test
$ flutter analyze lib test
2. Build
Build stage have two jobs build_android_staging
will run when master merge to staging branch and build_android_production
will run when merge to production branch.
3. Staging
Staging stage only run in staging branch and will distribute app to Firebase App Distribution for testing by QA to testing the app in staging flavor. In Firebase App Distribution make group with name Tester and add tester’s emails.
4. Internal Test
Internal test stage will distribute production app to internal test in Playstore
5. Production
Production stage will promote app from internal test to production. You need run this manually after internal test app passed from testing in Gitlab CI/CD.
Running Test?
To run all unit and widget tests use the following command:
$ flutter test --coverage
To view the generated coverage report you can use lcov.
# Remove core file and generated file to get actual coverage
$ lcov --remove coverage/lcov.info 'lib/*/*.g.dart' 'lib/core/**' -o coverage/lcov.info
# Generate Coverage Report
$ genhtml coverage/lcov.info -o coverage/
# Open Coverage Report
$ open coverage/index.html
Integration Testing?
Firebase Test Lab
Go to the Firebase Console, and create a new project if you don’t have one already. Then navigate to Quality > Test Lab:
Uploading an Android APK
Create an APK using Gradle:
$ pushd android
# flutter build generates files in android/ for building the app
$ flutter build apk --flavor staging -t lib/main_staging.dart
$ ./gradlew app:assembleAndroidTest
$ ./gradlew app:assembleDebug -Ptarget=integration_test/<name>_test.dart
$ popd
Where <name>_test.dart
is the file created in the Project Setup section.
Drag the “debug” APK from <flutter_project_directory>/build/app/outputs/apk/debug
into the Android Robo Test target on the web page. This starts a Robo test and allows you to run other tests:
Click Run a test, select the Instrumentation test type and drag the following two files:
<flutter_project_directory>/build/app/outputs/apk/debug/<file>.apk
<flutter_project_directory>/build/app/outputs/apk/androidTest/debug/<file>.apk
If a failure occurs, you can view the output by selecting the red icon
For more information read Flutter Integration Firebase Test Lab or from flutter doc Integration Testing.
Flutter integration tests on Firebase Test Lab
Integration Testing in Real Device
flutter drive --driver=test_driver/integration_test.dart --target=integration_test/app_test.dart
QA Testing Staging App
We will use Firebase App Distribution to distribute staging app to Tester.
To add tester add emails in folder firebase_app_distribution/testers.txt, or add groups in folder firebase_app_distribution/groups.txt, add emails or groups divided by comma.
Example add testers:
Example add groups:
Testers, QA
Group tester need set up in Firebase Console go to App Distribution > Testers & Groups and add tester to the group.
Working with Translations?
This project relies on flutter_sheet_localization and read documentation of flutter_sheet_localization_generator. for more information.
Usage
1. Create a Google Sheet
Create a sheet with your translations (following the bellow format, an example sheet is available here) :
Make sure that your sheet is shared :
Extract from the link the DOCID
and SHEETID
values : https://docs.google.com/spreadsheets/d/<DOCID>/edit#gid=<SHEETID>
) :
2. Declare a localization delegate
Declare the following AppLocalizationsDelegate
class with the SheetLocalization
annotation pointing to your sheet in a lib/l10n/localization.dart
file :
import 'package:flutter/widgets.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter_sheet_localization/flutter_sheet_localization.dart';
part 'localization.g.dart';
@SheetLocalization("DOCID", "SHEETID", 1) // <- See 1. to get DOCID and SHEETID
// the `1` is the generated version. You must increment it each time you want to regenerate
// a new version of the labels.
class AppLocalizationsDelegate
extends LocalizationsDelegate<AppLocalizationsData> {
const AppLocalizationsDelegate();
@override
bool isSupported(Locale locale) => localizedLabels.containsKey(locale);
@override
Future<AppLocalizationsData> load(Locale locale) =>
SynchronousFuture<AppLocalizationsData>(localizedLabels[locale]!);
@override
bool shouldReload(AppLocalizationsDelegate old) => false;
}
3. Generate your localizations
Run the following command to generate a lib/l10n/localization.g.dart
file :
$ flutter packages pub run build_runner build
4. Display your labels
import 'package:flutter_starter_project/core/l10n/localizations.dart';
final labels = context.localizations;
print(labels.dates.month.february);
print(labels.templated.hello(firstName: "World"));
print(labels.templated.contact(Gender.male, lastName: "John"));
Generate Icon Android IOS
Generate launcher icon for android and ios
$ flutter pub run flutter_launcher_icons:main -f flutter_launcher_icons*
Generate Splashscreen Android IOS
Generate splashscreen for android and ios
$ flutter pub run flutter_native_splash:create