Here is my current scenario.
- I am using AWS Elasticbeanstalk along with the eb cli 3.x tools for deployment.
- I have created 2 environments (development and production). and one branch in my git repo for each environment (i.e. master , production)
- I have created .ebextensions and .elasticbeanstalk folders in my git repo
- the .ebextensions folder has config files that are specific to each environment (e.g. setups, files changes, environment variables . . etc)
I wish to work on each environment in its own git branch.
My difficulty
if i have to deploy to development env, it gets really simple
// make config changes in master branch
// git add, commit
// eb deploy
// thus development environment is updated
But if i have to deploy to production is where the problem begins
git checkout production
git merge master // pulls config that is meant for development environment only
eb deploy
I want that when i merge changes from the master branch, all my code updates with the latest changes. But the .ebextensions and .elasticbeanstalk directories remain untouched
How do tell git to ignore the whole .ebextensions folder while merging into production branch ?
Using EB CLI 3.x
For this version it's relatively simple. For example:
This doesn't save
ENV_NAME
anywhere in the local filesystem. The EB CLI changes the live EB instance directly. You may useeb config save
(as suggested by Nick Humrich) to save the environment configuration settings for the current running environment to.elasticbeanstalk/saved_configs/<env-name>.cfg.yml
. Since each environment has its own file, you shouldn't have any conflicts, unless you change one of them in both branches. Another option (see Protecting sensitive informations) would be to add them to.gitignore
.Using EB CLI 2.x
Q: How did you create your environments?
One way is to have distinct optionsettings files for each environment (branch). The EB CLI can help you with that :-)
Run
eb init
from each branch (see below) and choose a different environment name for each one, so you'll end up with 2 distinct.elasticbeanstalk/optionsettings.<env-name>
files. This way you avoid the conflicts on.elasticbeanstalk/
.1. Create the project directory
2. Initialize Git repository
3. Setup the development environment (master branch)
NOTE: When it asks you to provide an environment name, choose a name that identifies whether it's a development or production environment.
4. Create a new branch for production
5. Setup the production environment
Repeat step 3 but pick a different environment name. This will create distinct
.elasticbeanstalk/optionsettings.<env-name>
file.Q: What about my .ebextensions?
You should use the same
app.config
for both environments. The only thing that may diverge between environments is theoption_settings
section. But as far as I know, you can't have differentoption_settings
per environment, so how can we do it?Well, that's something I don't have an optimal solution yet, but I'll tell you how I do it. I add all
option_name
's I need and use placeholder values, for example:Then later I change their values manually through the AWS Elastic Beanstalk admin panel. Go to
Application > Configuration > Software Configuration > Environment Properties
.Another possibility would be to have a custom script which is run by your
container_commands
. This script could identify the EC2 instance by its hostname (or another unique value) and automatically load the environment variables (e.g.source <hostname>.env
).Protecting sensitive informations
The only rule you need to obey is this: Your repository MUST NOT contain sensitive informations like credentials, unless you don't care.
For example, an application expects to read RDS credentials via environment variables, so you put them in
option_settings
. But you don't want other contributors to see them, do you? The solution I propose using placeholder is convenient on this aspect.You can merge master to production and production to master. However, after every merge, you have to reset the working tree of the folders in question. Here is how you can do this.
Also, you may forget to reset after every merge so I suggest you set up a
post-merge
hook to do this automatically for the respective branches after every merge.