dart_define
is an all-in-one tool to handle secrets and launch configurations
both locally and in CI/CD pipelines super easily. Say goodbye to .env
files
or any other tedious and error-prone ways. With this package you can access
your secrets in dart code as well as platform specific configurations.
Flutter supports adding compile-time variables with --dart-define
option,
and using them in both dart code and native configurations. However, with
many variables, the commands become quite long quite fast. A workaround for
that would be to create a custom launch shell scripts, or storing variables
in a JSON file and using it with --dart-define-from-file
option.
Hovewer, that raises a ton of other issues within CI/CD pipelines. You'd have to gitignore the launch config files, so you don't leak any secrets unwantedly. Then you'd have to create some custom script to initialize and fill those files with proper values in your CI/CD environments. Even after working your way around those issues, you'd have to be very careful to always remember update those pipelines when new values are added (missing values are not recognized at compile-time, leading to possible run-time errors in production).
With dart_define
, you'll get easy ways of handling secrets and configurations
in both local development environment as well as CI/CD pipelines. You can specify
which variables are required, so the CLI tool will throw an exception if those
are missing. This way missing values will result in failed pipeline run, not
run-time error in production.
When the generator is run, dart_define
reads the values from
- CLI option override
You can override values from system environment or yaml config defaults with CLI options, like so
--MY_VARIABLE=MY_VALUE
- System environment
dart_define
tries to read values from system environment for smooth integration with CI/CD pipelines - Default values
You can specify default values within
pubspec.yaml
configuration, which will be used as fallback values if none of the above are provided. Note that ifrequired
istrue
(default), the generator will fail if 1 or 2 are not provided and the default value will be ignored.
-
Install the CLI tool, OR add it into dependencies
# activate the CLI tool dart pub global activate dart_define
OR
# add the tool to dependencies flutter pub add --dev dart_define # If you chooce this method, you'll have to add `pub run` # in from of all of the `dart_define` commands. # Eg. `pub run dart_define generate`
-
Define your variables in
pubspec.yaml
dart_define: # OPTIONAL: Whether to generate the dart boilerplate or not. # Defaults to true dart: true # OPTIONAL: Whether to generate the json boilerplate or not. # Defaults to true json: true # OPTIONAL: The path to the json file to generate. # Defaults to dart_define.json json_path: dart_define.json # OPTIONAL: The path to the dart file to generate. # Defaults to lib/dart_define.gen.dart dart_path: lib/dart_define.gen.dart # OPTIONAL: The name of the generated class. # Defaults to dart_define class_name: dart_define # REQUIRED: The variables to add to the generated config files variables: # REQUIRED: The name of the variable - name: STRING_VALUE # REQUIRED: The description of the variable description: An example String value # REQUIRED: If `required` is false, this field is mandatory. # Otherwise, it is ignored. default: hello world! # OPTIONAL: If this is set to true, the CLI tool will # throw an exception if the variable is not provided # as an argument. This is handy when using the tool # in CI/CD pipelines. # Defaults to true. required: false - name: INT_VALUE description: An example int value default: 3 required: false - name: BOOL_VALUE description: An example bool value required: true # OPTIONAL: The flavors to use within the app flavors: # REQUIRED: The name of the flavor - name: production # REQUIRED: The description of the flavor description: The production flavor - name: staging description: The staging flavor - name: development description: The development flavor
-
Generate boilerplate
# If you activated the CLI tool dart_define generate
NOTE: You can override values and variables from pubspec.yaml config with CLI arguments
NOTE: This will generate a json file with the given secretes / configurations. It is recommended to gitignore that file.
-
Use your variables in dart code
This tool generates dart boilerplate, so you can access the values very easily.
/// This is the code this tool creates class DartDefine { /// An example String value static const stringValue = String.fromEnvironment('STRING_VALUE'); /// An example int value static const intValue = int.fromEnvironment('INT_VALUE'); /// An example bool value static const boolValue = bool.fromEnvironment('BOOL_VALUE'); } /// With this you can access the variables like so: String testValue = DartDefine.stringValue;
-
Access the values in platforms native configurations (see this article)
Within android build.gradle
// In app/build.gradle defaultConfig { applicationId STRING_VALUE // This allows us to access the value in eg. AndroidManifest.xml resValue "string", "STRING_VALUE", STRING_VALUE }
Within AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="@string/STRING_VALUE"> </manifest>
Within iOS config files
$(STRING_VALUE)
-
Run the app from the configuration file
flutter run --dart-define-from-file=dart_define.json
dart_define
is designed to integrate smoothly into your CI/CD pipelines.
-
Add variables to pipelines secrets
Since
dart_define
reads the values from environment secrets, you don't have to reference the variables later on. All you've got to do is to add them to the environments secrets! -
Run the generator
# If you have dart_define as (dev) dependecy, simply run dart run dart_define generate # If you activated dart_define as CLI tool locally dart pub global activate dart_define dart_define generate
Alternatively, you can also specify the variables when running the command. This way you can fetch them from wherever you want.
dart run dart_define generate --force --BOOL_VALUE=${BOOL_VALUE} --STRING_VALUE=${STRING_VALUE} --INT_VALUE=${INT_VALUE}
NOTE: If your CI/CD pipeline caches the codebase (does not always start from fresh clone), you MUST add the
--force
flag. Otherwise the values in the config.json
file won't update, even if they are changed in their source. -
Use the configuration in the actual build commands
flutter build apk --dart-define-from-file=dart_define.json flutter build ios --dart-define-from-file=dart_define.json
dart_define
allows you to create multiple configurations, for different
environments or white labels of your app. This means you can easily generate
config files for all of the environments or white labels and launch your app
with the configurations. To set these up
-
Add flavors to
dart_define
config inpubspec.yaml
dart_define: variables: - name: APP_NAME description: The apps name default: My App required: false - name: APP_ID description: The apps unique id default: com.my.app required: false flavors: - name: production description: The production flavor - name: staging description: The staging flavor - name: development description: The development flavor
-
Generate the config file for all of your flavors
dart_define generate --json_path=config/production.json --FLAVOR=production dart_define generate --json_path=config/staging.json --FLAVOR=staging dart_define generate --json_path=config/development.json --FLAVOR=development
-
Use the flavor in your app
/// `dart_define` generates this enum based on the flavors in your configurations /// You can access the current flavor used to launch the application by calling /// DartDefine.flavor enum Flavor { /// The production flavor production, /// The staging flavor staging, /// The development flavor development, }
-
Run application from specific flavor
flutter run --dart-define-from-file=config/development.json
By default, dart_define
will look for the configurations under the
pubspec.yaml
file in the project root. To change this behavior,
you can specify a new yaml file with the --yaml_path
flag.