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
update_instance() {
#Read arguments and set variables
coop=$1
instance=$2
repo=$3
now=$4
send_mails=$5
ci_dir=$6
ci_data_dir=$7
if [[ ${repo} == "third-party" ]]; then
user="django"
service="django"
elif [[ ${repo} == "Odoo" ]]; then
user="odoo"
service="odoo"
else
echo "Incorrect repo name : ${repo}"
if ${send_mails}; then
python3 "${ci_dir}/send_error_mail.py" "${coop} ${instance} ${repo} : incorrect repo name"
fi
exit 1
fi
if [[ "${instance}" == "prod" ]]; then
target="${coop}_prod"
else
target="dev_cooperatic"
fi
#Move to repository directory, fetch all and make sure coop_prod branch exists
cd /home/${user}/${repo}
su ${user} -c "git fetch --all"
branch_found_str=$( su ${user} -c "git ls-remote origin ${coop}_prod" ) #seems that git ls-remote is not "failing" so we need to check output
if [ -z "${branch_found_str}" ]; then
#branch prod does not exist, cannot go on
echo "${coop} ${instance} ${repo}: branch ${coop}_prod does not exist"
if ${send_mails}; then
python3 "${ci_dir}/send_error_mail.py" "${coop} ${instance} ${repo} : branch ${coop}_prod does not exist"
fi
exit 1
fi
#Make sure config file exists if repo is third-party
if [[ ${repo} == "third-party" ]]; then
if ! test -f "coops_configurations/config_${coop}.py"; then
echo "${coop} ${instance} ${repo}: coops_configurations/config_${coop}.py does not exists"
if ${send_mails}; then
python3 "${ci_dir}/send_error_mail.py" "${coop} ${instance} ${repo} : coops_configurations/config_${coop}.py does not exists"
fi
exit 1
fi
fi
#Save filepaths of files that are going to be updated if repo is odoo
if [[ ${repo} == "Odoo" ]]; then
echo "git diff --name-only origin/${target}.."
updated_filepaths="$( git diff --name-only origin/${target}.. )"
echo "${updated_filepaths}"
fi
#Update code if needed
new_commits="$( git log origin/${target}... )"
if [ -z "${new_commits}" ]; then
echo "${coop} ${instance} ${repo} : already up to date"
else
#Stop instance
/etc/init.d/${service} stop
#One could argue that git stash is risky on prod,
#but it's way easier to go that way to get rid of template file changes generated on django service restart
if ! su ${user} -c "git stash"; then
#We can not finish the update : restart the system
/etc/init.d/${service} start
echo "${coop} ${instance} ${repo}: could not git stash"
if ${send_mails}; then
python3 "${ci_dir}/send_error_mail.py" "${coop} ${instance} ${repo} : could not git stash"
fi
exit 1
fi
#Make script robust to any branch change : switch to target !
if ! su ${user} -c "git checkout ${target}"; then
#We can not finish the update : restart the system
#TODO : detect if we have stashed something on previous step to revert it (git stash pop)
/etc/init.d/${service} start
echo "${coop} ${instance} ${repo}: could not git checkout ${target}"
if ${send_mails}; then
python3 "${ci_dir}/send_error_mail.py" "${coop} ${instance} ${repo} : could not git checkout ${target}"
fi
exit 1
fi
#Pull
if ! su ${user} -c "git pull"; then
#We can not finish the update : restart the system
#TODO : detect if we have stashed something on previous step to revert it (git stash pop)
#TODO : undo previous git checkout if necessary
echo "${coop} ${instance} ${repo}: could not git pull"
if ${send_mails}; then
python3 "${ci_dir}/send_error_mail.py" "${coop} ${instance} ${repo} : could not git pull"
fi
exit 1
fi
#Additionnal update actions
#push tags to remember this prod update point (only on prod)
if [[ "${instance}" == "prod" ]]; then
#TODO : handle errors
su ${user} -c "git tag -a ${coop}_${now} -m autotag"
su ${user} -c "git push origin ${coop}_${now}"
fi
if [[ ${repo} == "third-party" ]]; then
#Replace config file by proper one only if required
if ! cmp "outils/config.py" "coops_configurations/config_${coop}.py"; then
#Config files are different, go for it
mv "outils/config.py" "${ci_data_dir}/ci_old_cfg_file_${now}.py"
cp "coops_configurations/config_${coop}.py" "outils/config.py"
else
echo "config files are identical"
fi
fi
if [[ ${repo} == "Odoo" ]]; then
#Loop on updated_filenames, for each filename, look for the directory of __openerp__.py file
#Ff found, just store the parent directory
SAVEIFS=$IFS
IFS=$'\n'
if [[ ${updated_filepaths} == "" ]]; then
updated_filepaths_array=()
else
read -rd '' -a updated_filepaths_array <<<"${updated_filepaths}"
fi
IFS='/'
l=${#updated_filepaths_array[@]}
declare -A modules #Modules to update
modules_str=""
for (( i=0; i<l; i++ ));
do
read -rd '' -a one_path_array <<<"${updated_filepaths_array[$i]}"
j=0
accu_path="${one_path_array[0]}"
pathlen=${#one_path_array[@]}
while [[ $j -lt ${pathlen} ]] && ! test -f "${accu_path}/__openerp__.py"; do
((j++))
accu_path="${accu_path}/${one_path_array[j]}"
done
#Update key of modules if (we have found openerp.py (j<path) + module has not been added already),
#so that we do not add twice same module in modules_str
#and add module in modules_str
if [[ $j -lt ${pathlen} ]] && [[ ! -v modules["${one_path_array[$j]}"] ]]; then
modules["${one_path_array[$j]}"]=
if [[ ${modules_str} == "" ]]; then
modules_str="${one_path_array[$j]}"
else
modules_str="${modules_str},${one_path_array[$j]}"
fi
fi
done
IFS=$SAVEIFS
echo "${modules_str}"
restart_odoo_cmd="/home/odoo/Odoo/odoo/odoo.py -c /home/odoo/odoo-server.conf"
if [[ -n "${modules_str}" ]]; then
echo "restart odoo service with module update"
su odoo -c "${restart_odoo_cmd} -u${modules_str} --stop-after-init"
fi
fi
#Restart service
echo "Starting ${service} service"
/etc/init.d/${service} start
fi
}