When you develop an app you usually do it locally, then deploy it to a test environment, and once QA signs off you go ahead and release it to the production environment. It is usually the case that the API, the app runs on, also has a test and a production environment. So, how can you ensure that the test app is calling the test API and the production app is calling the production API?
There are a lot of ways that you can achieve that, but I am used to putting environment bound parameters into environmental variables and pick them up in CI/CD pipeline when building my software for a specific environment. What follows is a very simple approach that worked for me, but may not work for others.
Head over to this gist to see all the files.
Let’s say that you have a typical Repository implementation where you have hardcoded the base URL. This will not cut it if you have multiple environments.
The next obvious step is to create a config file to hold the values of the variables in each environment.
Well, this is better. You could even get away without using environmental variables if you just have a runtime resolution of the environment and use the appropriate configuration.
Now you can use this configuration in your Repository.
Based on the previous example, there is no need to use any env vars at build time; so why do it? The answer is sensitive information such as API credentials and/or secrets.
Let’s say that your API requires some sort of secret credentials to be passed in order to authorize your app’s calls. In this case, putting this information into a file and storing it in your version control server is very much frowned upon. So you have to insert them in your application from your build environment.
You have to define appropriate environment variables for your
credentials variable, let’s say
APP_CREDENTIALS. The problem now is that this variable is defined in the built environment and not in the runtime.
An idea is to generate this config file built time so that you can have access to the env vars. So, you have to create a script that will read certain env vars and put them in the config file.
According to the official docs of pub, such scripts need to be in a
tool folder at the root of your app directory. The simplest way to write such a script is by creating a map with all the variables and their values and then just pass them into a template string.
Of course, this script can be more elaborate than this, but you are not trying to build a dedicated library here. You can put all of your environment configurations into env vars so that a change in them will not have to cause code changes.
How to use it
In order to use this facility now, all you have to do is to define the env vars in your CI/CD environment and to make sure to run the following command before you build the application.
$: dart tool/env.dart
There are a lot of ways to achieve env var insertion into a flutter build and by no means do I claim that this is the best, but this was something I came up with in order to solve this problem for me. Another option could have been to use a
build_runner and build the
.env.dat in a more structured way than a simple
Either way, I would be really happy if anyone else with the same problem gets some inspiration for his or her solution from this article.