-
Notifications
You must be signed in to change notification settings - Fork 1
/
deploy.sh
executable file
·286 lines (222 loc) · 7.92 KB
/
deploy.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
#!/bin/bash
set -E
trap '[ "$?" -ne 20 ] || exit 20' ERR
# trap finalize EXIT
args=("$@")
if [ $# -lt 1 ]
then
printf "Usage: \n$0 run|backup|restoredb <Vars>\n"
exit 20
fi
# Make sure name matches name used on git and branches being deployed
APP_NAME="DIwebsite-redesign"
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
APP_DIR=$SCRIPT_DIR'/'$APP_NAME
DATABASE_BACKUP=$SCRIPT_DIR'/database_backup'
DATABASE_NAME='di_website'
DOCKER_STORAGE='diwebsite_db;index_db'
REPOSITORY="[email protected]:devinit/"$APP_NAME".git"
ACTIVE_BRANCH=$BRANCH
ENVIRONMENT=$ENVIRONMENT
STAGING_IP=
ENVIROMENT_VARIABLES='ENVIRONMENT;SECRET_KEY;DEFAULT_FROM_EMAIL;EMAIL_HOST;EMAIL_BACKEND;EMAIL_HOST_USER;EMAIL_HOST_PASSWORD;DATABASE_URL;BRANCH;GITHUB_TOKEN;SITE_URL;WWW_SITE_URL;DATA_SITE_URL;USE_SPACES;AWS_S3_ENDPOINT_URL;AWS_STORAGE_BUCKET_NAME;AWS_ACCESS_KEY_ID;AWS_SECRET_ACCESS_KEY'
OIFS=$IFS
IFS=';'
function finalize {
$IFS=$OIFS
}
function start_new_process {
printf "\n===================================================================\n"
printf "$1"
printf "\n===================================================================\n"
}
function log {
printf "$1\n"
}
function setup_docker_storage {
start_new_process 'Setting up new docker storage for postgres'
docker_volumes="$( docker volume ls )"
for storage in $DOCKER_STORAGE
do
if echo $docker_volumes | grep -q $storage ; then
log "Docker volume $storage already exits. Skipping ...."
else
docker volume create $storage > /dev/null
log "Created new docker volume $storage with status "$?
fi
done
}
function setup_docker_networks {
start_new_process 'Setting up new external consul network'
docker_networks="$( docker network ls )"
if echo $docker_networks | grep -q "consul"; then
log "Docker network already exists. Skipping ..."
else
docker network create consul > /dev/null
log "Created new docker network consul with status "$?
fi
}
# This can only happen after project clonning has been done
function export_travis_enviroment {
start_new_process 'Exporting enviroment variables defined in Travis to .env file'
rm $APP_DIR'/'.env > /dev/null && touch $APP_DIR'/'.env
for env in $ENVIROMENT_VARIABLES
do
log "Creating $env"
eval echo $env"="\${$env} >> $APP_DIR'/'.env
done
}
function backup_database {
start_new_process "Creating a backup of working database to location $DATABASE_BACKUP"
mkdir -p $DATABASE_BACKUP && cd $DATABASE_BACKUP
current_date=`date '+%F'`
file_name=$DATABASE_BACKUP'/'$current_date'.backup'
label="$(($(ls -v | grep $current_date | cat -n | wc -l) + 1))"
if [ -r $current_date'.backup' ];
then
log "Moving file old backup to new location $label.$current_date.backup"
mv -n $current_date'.backup' $label'.'$current_date'.backup'
fi
cd $APP_DIR
log "Starting backup from remote docker machine $(docker compose ps -q db)"
docker compose exec -T db pg_dump -U di_website -d di_website > $file_name
log "Database backup completed..."
if [ -r $file_name ];
then
:
else
log "Database backup failed, exiting process ... If this is a fresh deployment, delete $APP_DIR folder"
exit 20;
fi
}
function search_reindex {
start_new_process "Re-indexing search"
cd $APP_DIR
sleep 60s
docker compose exec -T ${new_state} python manage.py update_index
}
function perform_git_operations {
start_new_process "Performing git operation on branch $ACTIVE_BRANCH of repository $REPOSITORY"
if [ -d $APP_DIR ]; then
cd $APP_DIR
if [[ $ACTIVE_BRANCH == *"refs/tags"* ]]
then
{
log "Cloning new content from a release tag "$ACTIVE_BRANCH
git fetch --tags -f
git stash
git checkout $ACTIVE_BRANCH
} || {
log "Failed to update from git repository"
exit 20;
}
else
{
log "Cloning new content from active branch "$ACTIVE_BRANCH
git fetch
git stash
git checkout $ACTIVE_BRANCH
git reset --hard origin/$ACTIVE_BRANCH
} || {
log "Failed to update from git repository"
exit 20;
}
fi
else
{
git clone -b $ACTIVE_BRANCH $REPOSITORY
} || {
log "Failed to perform git clone on $REPOSITORY with branch $ACTIVE_BRANCH "
exit 20;
}
fi
}
function enable_https_configs {
https_content="listen 443 ssl;"
if [[ "$ENVIRONMENT" == "production" || "$ENVIRONMENT" == "staging" ]]
then
if grep -q "${https_content}" $APP_DIR"/config/nginx/django.conf.ctmpl"; then
echo "ssl config already exists"
else
cat "$APP_DIR/config/nginx/django_https.ctmpl" >> $APP_DIR"/config/nginx/django.conf.ctmpl"
fi
fi
}
function setup_blue_green_deployment {
# build the new Image
echo 'Build the new image'
docker build . -t diwebsite-redesign_web:new
# check the current container state
echo 'Check the current state'
blue_is_run=$(docker exec blue echo 'yes' 2> /dev/null || echo 'no')
state='blue'
new_state='green'
new_upstream=${green_upstream}
if [[ ${blue_is_run} != 'yes' ]]
then
state='green'
new_state='blue'
new_upstream=${blue_upstream}
fi
# create the new state image
docker tag diwebsite-redesign_web:new diwebsite-redesign_web:${new_state}
# install JS dependencies
echo "Update JS dependencies"
npm ci
npm run build
# Attempt to stop new container. Sometimes there is a hanging one still running...
docker compose stop ${new_state}
# update the new state container
echo "Update the ${new_state} container"
docker compose up -d ${new_state}
# Check the new state container is ready
echo "Check the ${new_state} container is ready"
docker compose run --rm --entrypoint /bin/bash ${new_state} ./scripts/wait-for-it.sh ${new_state}:8090 --timeout=60
chmod +x ./scripts/activate.sh
./scripts/activate.sh ${new_state} ${state} ${new_upstream} ${key_value_store}
echo "Set the ${new_state} image as ${state}"
docker tag diwebsite-redesign_web:${new_state} diwebsite-redesign_web:${state}
echo 'Set the old image as previous'
docker tag diwebsite-redesign_web:latest diwebsite-redesign_web:previous
echo 'Set the new image as latest'
docker tag diwebsite-redesign_web:new diwebsite-redesign_web:latest
echo "Stop the ${state} container"
docker compose stop ${state}
}
if [ ${args[0]} == 'run' ]
then
perform_git_operations
export_travis_enviroment
setup_docker_storage
setup_docker_networks
cp $SCRIPT_DIR"/box_config.json" $APP_DIR"/"
mkdir -p $APP_DIR"/assets"
mkdir -p $APP_DIR"/storage"
mkdir -p $APP_DIR"/ssl"
mkdir -p $APP_DIR"/certbot_logs"
enable_https_configs
start_new_process "Starting up services ..."
cd $APP_DIR
sudo chown -R di_website:di_website storage
sudo chown -R di_website:di_website ssl
cp certbot_success.sh ./ssl
chmod +x ssl/certbot_success.sh
sudo chown -R di_website:di_website certbot_logs
#run this script within this subprocess
chmod +x scripts/*
source scripts/init.sh
docker compose -f docker-compose-consul.yml up -d
setup_blue_green_deployment
search_reindex
start_new_process "Generating static assets"
docker compose exec -T ${new_state} python manage.py collectstatic --noinput
sudo chown -R di_website:di_website assets
exit 0
elif [ ${args[0]} == 'backup' ]
then
backup_database
exit 0
else
log "Failed to find operation; Usage: \n$0 run|backup|restoredb <Vars>"
exit 20
fi