-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdeploy.bash
executable file
·307 lines (288 loc) · 8.97 KB
/
deploy.bash
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
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
#!/usr/bin/env bash
##
# Description:
# Deploys CAFPE site to its FTP server destination
# Arguments:
# - S1 -> Host
# - $2 -> Username
# - $3 -> Password
# - $4 -> Development DB location
# - $5 -> Production DB location
##
# Global variables
HOST=$1
USERNAME=$2
PASSWORD=$3
DEV_DB=$4
PROD_DB=$5
FTP_ACCESS="ftp://$USERNAME:$PASSWORD@$HOST"
TRANSFERRED_LOG="lftp_transferred.log"
DEBUG_LOG="lftp_debug.log"
LFTP_OPTIONS="set ftp:list-options -a;
set cmd:fail-exit yes;
set ftp:ssl-allow no;
set ssl:verify-certificate no;
set xfer:log true;
set log:file/xfer $TRANSFERRED_LOG;
set log:show-time/xfer false;
set ftp:use-site-utime false;
set ftp:use-site-utime2 false;
set net:timeout 5;
set dns:fatal-timeout 5;
set dns:max-retries 3;
debug 4 -o $DEBUG_LOG -T;"
##
# Activates maintenance mode in CI
# $1 - new status (string -> 'true' or 'false')
##
function set_maintenance_mode() {
if [[ $1 != 'true' && $1 != 'false' ]]; then
echo "CHANGING MAINTENANCE MODE [INFO]: '$1' is not a valid parameter. Only 'true' or 'false' are valid."
return 1
fi
MAINTENANCE_FILE="application/config/maintenance.php"
echo "CHANGING MAINTENANCE MODE TO $1 [INFO]: Editing '$MAINTENANCE_FILE'"
if [[ ! -f $MAINTENANCE_FILE ]]; then
echo "CHANGING MAINTENANCE MODE TO $1 [ERROR]: '$MAINTENANCE_FILE' doesn'exist"
return 1
fi
sed -i "s/\(^\s*\$config\['site_under_maintenance'\]\s*=\s*\).*;/\1$1;/i" $MAINTENANCE_FILE
echo "CHANGING MAINTENANCE MODE TO $1 [INFO]: Uploading '$MAINTENANCE_FILE'"
if ! ftp_upload_file $MAINTENANCE_FILE $MAINTENANCE_FILE; then
return 1
fi
echo "CHANGING MAINTENANCE MODE TO $1 [INFO]: Done"
}
##
# Looks for error codes in LFTP debug log
##
function check_ftp_errors() {
echo "FTP TRANSFER CHECK DEBUG [INFO]: Checking errors in debug log"
if ! tail -1 $DEBUG_LOG| grep -q '221 Goodbye'; then
echo "FTP TRANSFERS CHECK DEBUG [ERROR]: Connection wasn't finished properly. Transfer could have not been completed."
return 1
fi
# Get FTP server return codes (second column) and check for errors (4XX, 5XX or 6XX)
awk '$2~/^[4-6]/ { print "FTP TRANSFER CHECK DEBUG [ERROR]: " $0; errors++; } END { if(errors){ exit errors; } }' $DEBUG_LOG
ERRORS=$?
if [[ $ERRORS > 0 ]]; then
echo "FTP TRANSFER CHECK DEBUG [INFO]: Done, $ERRORS error(s)"
return 1
fi
echo "FTP TRANSFER CHECK DEBUG [INFO]: Done, no errors"
}
##
# Checks if sizes of files in local storage are the same as logged size
# Return values:
# 1 - Error
# -1 - No files tranferred
##
function check_ftp_transfers() {
FTP_URL="ftp://$USERNAME@$HOST"
echo "FTP TRANSFERS CHECK [INFO]: Checking transferred files log"
# error if nothing was uploaded
if [[ ! -f $1 ]]; then
echo "FTP TRANSFERS CHECK [WARNING]: No files were transferred, check FTP log above"
return -1
fi
ERRORS=0
# check if each file size is the same as bytes uploaded, using the log file created by LFTP
while IFS="|" read TRANSFERRED_FNAME TRANSFERRED_FSIZE; do
ACTUAL_FSIZE=$(ls -nl $TRANSFERRED_FNAME | awk '{print $5}')
if [[ $ACTUAL_FSIZE != $TRANSFERRED_FSIZE ]]; then
echo "FTP TRANSFERS CHECK [ERROR]: Possible corrupted file: $TRANSFERRED_FNAME $ACTUAL_FSIZE $TRANSFERRED_FSIZE SS"
((ERRORS++))
fi
# process transfers log so it has two columns: local file name|transferred size
done <<< `sed 's/\(^ftp.* -> \(\/.*\)\|\(\/.*\) -> ftp.*\) [0-9]\+-\([0-9]\+\) .*/\2\3|\4/g' $TRANSFERRED_LOG`
if [[ $ERRORS > 0 ]]; then
echo "FTP TRANSFERS CHECK [INFO]: Done, $ERRORS error(s)"
return 1
fi
echo "FTP TRANSFERS CHECK [INFO]: Done, no errors"
}
##
# Deletes LFTP logs if present
##
function remove_lftp_logs() {
if [[ -f $TRANSFERRED_LOG ]]; then
rm $TRANSFERRED_LOG
fi
if [[ -f $DEBUG_LOG ]]; then
rm $DEBUG_LOG
fi
}
##
# Renames a file in ftp server
#
# $1 - Current file name
# $2 - New file name
function ftp_rename_file() {
echo "FTP RENAME [INFO]: Renaming '$1' to '$2'"
remove_lftp_logs
lftp -c "$LFTP_OPTIONS
open '$FTP_ACCESS';
mv $1 $2"
if ! check_ftp_errors $DEBUG_LOG; then
return 1
fi
echo "FTP RENAME [INFO]: Done"
}
##
# Downloads a file from ftp server
#
# $1 - Remote file name
# $2 - Destination file name
function ftp_download_file() {
echo "FTP DOWNLOAD [INFO]: Downloading '$1' from FTP server"
remove_lftp_logs
lftp -c "$LFTP_OPTIONS
open '$FTP_ACCESS';
get $1 -o $2"
echo "FTP DOWNLOAD [INFO]: Done"
if ! check_ftp_errors $DEBUG_LOG; then
return 1
fi
if ! check_ftp_transfers $TRANSFERRED_LOG; then
return 1
fi
}
##
# Uploads a file to ftp server
#
# $1 - Local file name
# $2 - Destination file name
# $3 - (optional) permissions in octal format. If present, updated file
# will be chmoded accordingly
function ftp_upload_file() {
echo "FTP UPLOAD [INFO]: Uploading '$1' to FTP server"
if [[ $# > 2 ]]; then
CHMOD="chmod $3 $2"
fi
remove_lftp_logs
lftp -c "$LFTP_OPTIONS
open '$FTP_ACCESS';
put $1 -o $2;
$CHMOD;"
echo "FTP UPLOAD [INFO]: Done"
if ! check_ftp_errors $DEBUG_LOG; then
return 1
fi
if ! check_ftp_transfers $TRANSFERRED_LOG; then
return 1
fi
}
##
# Uploads whole site to ftp server
##
function ftp_upload_site() {
echo "FTP UPLOAD [INFO]: Uploading site to FTP server"
remove_lftp_logs
# Change html folder name to public_html
mv html public_html
lftp -c "$LFTP_OPTIONS
open '$FTP_ACCESS';
mirror --reverse --ignore-time \
--delete \
--verbose \
--exclude-glob='*' \
--include='public_html/' \
--exclude='public_html/assets/src' \
--include='vendor/' \
--exclude-glob='vendor/*/' \
--exclude-glob='vendor/?*' \
--include='vendor/codeigniter/' \
--exclude-glob='vendor/codeigniter/*/' \
--include='vendor/codeigniter/framework' \
--exclude-glob='vendor/codeigniter/framework/*/' \
--exclude-glob='vendor/codeigniter/framework/?*' \
--include='vendor/codeigniter/framework/system' \
--include='application/' \
--exclude-glob='application/cache/ci_session*' \
--exclude-glob='application/logs/*.php' \
--exclude='application/config/development/' \
--exclude='application/config/production/' \
--exclude='application/config/testing/' \
--exclude='application/database/' \
--exclude='application/migrations/' \
--exclude='application/tests/'"
echo "FTP UPLOAD [INFO]: Done"
if ! check_ftp_errors $DEBUG_LOG; then
return 1
fi
check_ftp_transfers $TRANSFERRED_LOG
# ignore if return value is -1 (no tranfers)
if [[ $? == 1 ]]; then
return 1
fi
mv public_html html
}
##
# Returns 0 if migrations were run, 1 if there were no pending migrations
##
function run_migrations() {
CURRENT=`php cli migrate version|grep database|awk '{ print $2 }'`
LATEST=`php cli migrate version|grep latest|awk '{ print $2 }'`
if [[ $CURRENT < $LATEST ]]; then
php cli migrate $LATEST
return 0
fi
return 1
}
##
# Updates db if there are pending migrations
##
function update_db() {
echo "DB MIGRATIONS [INFO]: Updating DB"
echo "DB MIGRATIONS [INFO]: Downloading DB from FTP server"
# CLI that runs migrations uses current environment DB
# So download production DB naming it as development DB
if [[ -f $DEV_DB ]]; then
rm $DEV_DB
fi
if ! ftp_download_file $PROD_DB $DEV_DB; then
return 1
fi
echo "DB MIGRATIONS [INFO]: Running migrations"
# if migrations were run
if run_migrations; then
# rename production db with date appended to name (backup)
echo "DB MIGRATIONS [INFO]: Backing up DB"
if ! ftp_rename_file $PROD_DB ${PROD_DB}`date +"%d%m%Y"`; then
return 1
fi
# upload db as production db
echo "DB MIGRATIONS [INFO]: Uploading DB"
if ! ftp_upload_file $DEV_DB $PROD_DB 666; then
return 1
fi
else
echo "DB MIGRATIONS [INFO]: No pending migrations"
fi
echo "DB MIGRATIONS [INFO]: Done"
}
echo
echo "-------------------------- DEPLOYMENT [BEGIN] --------------------------"
if ! set_maintenance_mode 'true'; then
echo "[FATAL] Fatal error enabling maintenance mode, script halted"
exit 1
fi
# Upload site
if ! ftp_upload_site; then
echo "[FATAL] Fatal error uploading site, script halted"
exit 1
fi
# Update DB
if ! update_db; then
echo "[FATAL] Fatal error updating DB, script halted"
exit 1
fi
if ! set_maintenance_mode 'false'; then
echo "[FATAL] Fatal error disabling maintenance mode, script halted"
exit 1
else
echo "[INFO] Deployment done correctly"
echo
echo "-------------------------- DEPLOYMENT [END] --------------------------"
exit 0
fi