How to safely add environment variables using Bitbucket Pipelines with automated Google App Engine deployments
Published in
4 min readNov 12, 2020
This article is translated based on a medium article written by modolee. You can check out the original article here: bitbucket-pipelines로-google-app-engine에-자동-배포-시-안전하게-환경변수-추가하기
Today, I want to introduce a safe way to add environmental variables using Bitbucket Pipelines with automated Google App Engine deployments.
Dev/Deployments Environment setup
- Server : Google App Engine
- runtime : custom
- env: flex - Source code management: Bitbucket
- CI/CD: Bitbucket Pipelines
Issues
- Typically, we add environmental variables to the Google App Engine configuration file (
app.yaml
) by storing them inkey:value
form in theenv_variables
entry. - Sensitive data such as API key, Auth Token, etc is directly exposed to
app.yaml
file. env_varibles
- You need a solution which dynamically add them at the point when you deploy it, not directly store it to
app.yaml
file. - You need to store and access the environmental variables from either place: Bitbucket or GCP.
Trying to find solutions…
- I’ve Googled various ways but I couldn’t find a suitable way to apply it.
- I excluded the following option: store it to Google Datastore and calling API directly from source code, because it seemed to be too dependent on GCP.
- An option to create .env file during the deployment process was working only when App Engine is in a
standard
environment, it was not working withflex
environment. - It seemed like this option is the most suitable solution: which is to manually add environment variables to the
app.yaml
file during the bitbucket pipelines execution period before deploy it to the App Engine.
Solutions
- Store env variables in Bitbucket
- Create a file that manages names of the env variables, and add it to the project
- Create a script to load the names of the env variables then add them to the
app.yaml
file - Run the script right before you deploy to Goolge App Engine through Bitbucket pipelines
Storing env variables in Bitbucket
- Store all env variables in Bitbucket which were previously stored in
app.yaml
file in plain text format - Go to Bibucket
Repository settings > PIPELINES > DEPLOYMENTS
page, and add env variables - Select
secured
option. The saved value cannot be revisited after, so please save it in a safe place.
Add env variables-list file
- Create
.env.array
file in project root - Add each env variable’s name line by line on the created file that needs to be included on deployment
TEST_ENV1
TEST_ENV2
TEST_ENV
Add script to add env variables
- Create
add-env-to-gae-conf.sh
file in project root - Copy and paste the script code below
#!/bin/bash# Set default file input/output name
FILE_INPUT_NAME=.env.array
FILE_OUTPUT_NAME=app.yaml# Set file input/output name, when user add options
while getopts "i:o:" opt; do
case $opt in
i)
FILE_INPUT_NAME=$OPTARG ;;
o)
FILE_OUTPUT_NAME=$OPTARG ;;
*) echo "usage: $0 [-i] [-o]" >&2
exit 1 ;;
esac
done# Read all environment variables that have to be copied from input file
declare env_array=()while IFS= read -r line || [[ "$line" ]]; do
env_array+=("$line")
done < "${FILE_INPUT_NAME}"# Print all environment variables to output file
if [ "${#env_array[@]}" -eq 0 ]; then
echo "There is no environment variables";
else
{ printf "\n\n"; printf "env_variables:"; printf "\n"; } >> "${FILE_OUTPUT_NAME}";for i in "${env_array[@]}";
do
printf " %s\n" "${i}: ${!i}" >> "${FILE_OUTPUT_NAME}";
done
fi;
- Link to the source code repo: https://github.com/modolee/add-env-to-gae-conf
- Default input file (
.env.array
), default output file (app.yaml
) are configured, and you can modify it with-I, -o
option - Read the input file (read the list of the env variables) then add them to the bottom of the output file in the form of `env_variable_name: value`
- Here we are adding the whole block of
env_variables
, so if there is a pre-definedenv_variables
, then you need to remove it. - Dynamically add the stored env variables to the
app.yaml
file app.yaml
file will appear like below:
env_variables:
TEST_ENV1: test string 1
TEST_ENV2: test string 2
TEST_ENV3: test string 3
Check script to add env variables
- Run the command below on your local machine to see that the env variables are added to the
app.yaml
file
Update Bitbucket Pipelines deployment configuration: add env variables, add script
- From
bitbucket-pipelines.yml
, run add-env-variables script with Google App Engine deployment script - Install the bash separately using the
node:alpine
image as a default - Grant the ability to run the script and try to output it to verify that it has been added with no error after running the script
image: node:alpinerun-test: &run-test
step:
name: Run jest unit test
caches:
- node
script:
- yarn
- yarn testdeploy-dev: &deploy-dev
step:
name: Deploy Develop Branch to App Engine
deployment: gcp-dev
script:
- apk add bash
- chmod +x ./add-env-to-gae-conf.sh
- bash ./add-env-to-gae-conf.sh
- cat ./app.yaml
- pipe: atlassian/google-app-engine-deploy:0.7.3
variables:
KEY_FILE: $KEY_FILE
PROJECT: $PROJECT
STOP_PREVIOUS_VERSION: 'true'
DEBUG: 'true'pipelines:
branches:
master:
- <<: *run-test
develop:
- <<: *run-test
- <<: *deploy-dev
Test it on the source code
- To check it from the source code, try console.log or return in JSON format:
process.env.TEST_ENV1, process.env.TEST_ENV2, process.env.TEST_ENV3
- If you see the values you stored in Bitbucket, that means it is working well.
Possible Improvements
- As mentioned above, it is not working if you already have
env_variables
inapp.yaml
file - It would be better if we improve it to use pre-existing env variables.