-
Notifications
You must be signed in to change notification settings - Fork 3
Environments
Each project should have the following environments:
- Development is used by the developers. Testing should not be done in this environment since it is always changing.
- Test will be used by your testers to ensure that the software is error free.
- UAT ensures that your software is working as expected in the hands of your intended users.
- Production contains the latest version of your software that passed all testing and is generally available to your intended user.
Under .secrets
folder, we can find the different variables used for each environments:
We use Command Variable extension in order to select which environment to run locally. Pressing F5
will show a picker before debugging the application:
Read more about this setup in this article and here.
A specific .json
file per environment is passed to Flutter's build arguments as Dart defines. Checkout our .vscode/launch.json
file to see how we pass the environment file to the build arguments.
Below are sample values of a secret file for the development environment:
{
"appEnvironment": "dev",
"appServerUrl": "https://jsonplaceholder.typicode.com/",
"appId": "com.mycompany.starterkit.app",
"appIdSuffix": ".dev",
"appName": "Starterkit App (Dev)",
"iOSDevelopmentTeam": "XXXXXXXXXX",
"iOSDevelopmentProfile": "Your Development Profile Name",
"iOSDistributionProfile": "Your Distribution Profile Name",
"iOSExportMethod": "ad-hoc"
}
❗ IMPORTANT
- The secrets file should be kept in a secure location that is not accessible to the public. And should be given only to the developers who need it. For CI purposes, the secrets files should be stored in a secure location in the CI server (like GitHub Secrets) and should be re-created for each build depending on the environment.
- The secrets file are added to this repository by default. Be sure to remove them on yours once you updated the values.
- For iOS, you need to add the necessary provisioning profiles and signing certificates to your local machine. You also need to supply the correct
iOSDevelopmentTeam
value in the secrets file and in theDartDefine-Defaults.xcconfig
file. - The secrets file are also used in Fastlane. See
Fastfile
for more details.
The Android and iOS native projects are already configured to update their current configurations based on the environment file we will use. For example, the provisioning profile used for running the app on an iPhone device are automatically selected (given that the profile is available in your local machine).
You can access other Dart defines in the native projects by referencing the key directly.
An example of this can be found in iOS' Info.plist
:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
...
<key>CFBundleName</key>
<string>$(appName)</string>
...
</dict>
</plist>
and in Android's build.gradle
:
def dartDefines = [:]
if (project.hasProperty('dart-defines')) {
// Decode dart-defines, which are comma-separated and encoded in Base64, and store them in a variable.
dartDefines = dartDefines + project.property('dart-defines')
.split(',')
.collectEntries { entry ->
def pair = new String(entry.decodeBase64(), 'UTF-8').split('=')
[(pair.first()): pair.last()]
}
}
def appIdSuffix = dartDefines.appIdSuffix != 'appIdSuffix' ? dartDefines.appIdSuffix : ''
def appIdComplete = "${dartDefines.appId}${appIdSuffix}"
println "Building: ${dartDefines.appName} (${appIdComplete}) for ${dartDefines.appEnvironment} environment"
android {
...
defaultConfig {
println "Building $appIdComplete"
applicationId $appIdComplete
if (appIdSuffix?.trim()) {
applicationIdSuffix appIdSuffix
}
minSdkVersion 31
targetSdkVersion 34
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
resValue "string", "app_name", "${dartDefines.appName}"
}
}