update_instance.sh 6.16 KB
Newer Older
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
}