#!/usr/bin/env bash set -e BASE_DIR="$(cd "$(dirname "$0")"/.. && pwd)" LOG_DIR="$BASE_DIR/logs" mkdir -p "$LOG_DIR" PY_BIN="" PIP_BIN="" if command -v python3 >/dev/null 2>&1; then ver="$(python3 -c 'import sys;print("{}{}".format(sys.version_info.major,sys.version_info.minor))')" if [ "$ver" -ge 37 ]; then if [ ! -d "$BASE_DIR/.venv" ]; then python3 -m venv "$BASE_DIR/.venv" fi PY_BIN="$BASE_DIR/.venv/bin/python" PIP_BIN="$BASE_DIR/.venv/bin/pip" fi fi if [ -z "$PY_BIN" ]; then CONDA_DIR="$BASE_DIR/.miniconda" if [ ! -d "$CONDA_DIR" ]; then url="https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh" tmp="$BASE_DIR/miniconda.sh" if command -v wget >/dev/null 2>&1; then wget -qO "$tmp" "$url" else curl -fsSL -o "$tmp" "$url" fi bash "$tmp" -b -p "$CONDA_DIR" rm -f "$tmp" fi ENV_DIR="$BASE_DIR/.conda-env" if [ ! -d "$ENV_DIR" ]; then "$CONDA_DIR/bin/conda" create -y -p "$ENV_DIR" python=3.8 fi PY_BIN="$ENV_DIR/bin/python" PIP_BIN="$ENV_DIR/bin/pip" fi "$PIP_BIN" install -U pip REQ_MAIN="$BASE_DIR/ZeroCodeProject/apis/ZeroCodeMain/requirements.txt" REQ_TEMP="$BASE_DIR/ZeroCodeProject/apis/temp_api/requirements.txt" if [ -f "$REQ_TEMP" ]; then "$PIP_BIN" install -r "$REQ_TEMP" fi if [ "${INSTALL_MAIN_REQ:-0}" != "0" ] && [ -f "$REQ_MAIN" ]; then "$PIP_BIN" install -r "$REQ_MAIN" fi # Force urllib3 < 2 for OpenSSL 1.0.x/1.1.0 environments "$PIP_BIN" install 'urllib3<2' || true MYSQL_BIND="${MYSQL_BIND:-127.0.0.1}" # Default DB credentials DB_USER="${DB_USER:-test_user}" DB_PASSWORD="${DB_PASSWORD:-your_password}" DB_NAME="${DB_NAME:-zero_code_new}" DB_HOST="${DB_HOST:-127.0.0.1}" DB_PORT="${DB_PORT:-3306}" # Fix misplaced bind-address in client config and ensure mysqld picks correct bind if [ -f "/etc/mysql/conf.d/mysql.cnf" ]; then if grep -q "bind-address" "/etc/mysql/conf.d/mysql.cnf"; then if command -v sudo >/dev/null 2>&1; then sudo sed -i '/bind-address/d' /etc/mysql/conf.d/mysql.cnf || true else sed -i '/bind-address/d' /etc/mysql/conf.d/mysql.cnf || true fi fi fi SERVER_CONF_DIR="" if [ -d "/etc/mysql/mysql.conf.d" ]; then SERVER_CONF_DIR="/etc/mysql/mysql.conf.d" elif [ -d "/etc/mysql/mariadb.conf.d" ]; then SERVER_CONF_DIR="/etc/mysql/mariadb.conf.d" fi if command -v sudo >/dev/null 2>&1 && [ -n "$SERVER_CONF_DIR" ]; then sudo bash -c "printf '[mysqld]\nbind-address = %s\n' '$MYSQL_BIND' > '$SERVER_CONF_DIR/bind.cnf'" || true fi if command -v sudo >/dev/null 2>&1; then sudo mkdir -p /var/run/mysqld && sudo chown mysql:mysql /var/run/mysqld || true if command -v systemctl >/dev/null 2>&1; then sudo systemctl restart mysql || sudo systemctl restart mariadb || true else sudo service mysql restart || sudo service mariadb restart || true fi else mkdir -p /var/run/mysqld && chown mysql:mysql /var/run/mysqld || true service mysql restart || service mariadb restart || true fi DB_JSON="$BASE_DIR/ZeroCodeProject/apis/ZeroCodeMain/dependency/api_config/project_settings.json" export DB_JSON read_vars=$("$PY_BIN" - <<'PY' import json,sys,os p=os.environ.get('DB_JSON') try: with open(p,'r') as f: d=json.load(f) except Exception: d={} def val(k,default): return d.get(k,default) e=val('ENGINE','') h=val('HOST','127.0.0.1') port=val('PORT','3306') n=val('NAME','zero_code') u=val('USER','root') pw=val('PASSWORD','') print('\n'.join([ f"ENGINE={e}", f"HOST={h}", f"PORT={port}", f"NAME={n}", f"USER={u}", f"PASSWORD={pw}", ])) PY ) eval "$read_vars" # Normalize ZeroCodeMain DB config to MySQL env DB_JSON="$DB_JSON" "$PY_BIN" - <<'PY' import json,os p=os.environ['DB_JSON'] try: with open(p,'r') as f: d=json.load(f) except Exception: d={} e=d.get('ENGINE','') name=d.get('NAME','zero_code') host=d.get('HOST','127.0.0.1') port=d.get('PORT','3306') user=d.get('USER','zerocode') pw=d.get('PASSWORD','') if host=='localhost': host='127.0.0.1' if e!='django.db.backends.mysql': d['ENGINE']='django.db.backends.mysql' d['NAME']=name d['HOST']=host d['PORT']=port d['USER']=user d['PASSWORD']=pw with open(p,'w') as f: json.dump(d,f,indent=2,ensure_ascii=False) PY # Override from environment if provided (applies to ZeroCodeMain) if [ -n "${DB_USER:-}" ] || [ -n "${DB_PASSWORD:-}" ] || [ -n "${DB_NAME:-}" ] || [ -n "${DB_HOST:-}" ] || [ -n "${DB_PORT:-}" ]; then env new_user="${DB_USER:-$USER}" new_pass="${DB_PASSWORD:-$PASSWORD}" new_name="${DB_NAME:-$NAME}" new_host="${DB_HOST:-$HOST}" new_port="${DB_PORT:-$PORT}" DB_JSON="$DB_JSON" "$PY_BIN" - <<'PY' import json,os p=os.environ['DB_JSON'] u=os.environ['new_user'] pw=os.environ['new_pass'] n=os.environ['new_name'] h=os.environ['new_host'] pt=os.environ['new_port'] try: with open(p,'r') as f: d=json.load(f) except Exception: d={} d['ENGINE']='django.db.backends.mysql' d['USER']=u d['PASSWORD']=pw d['NAME']=n d['HOST']=h d['PORT']=pt with open(p,'w') as f: json.dump(d,f,indent=2,ensure_ascii=False) PY USER="${DB_USER:-$USER}" PASSWORD="${DB_PASSWORD:-$PASSWORD}" NAME="${DB_NAME:-$NAME}" HOST="${DB_HOST:-$HOST}" PORT="${DB_PORT:-$PORT}" fi if [ "$ENGINE" = "django.db.backends.mysql" ]; then if [ "$USER" = "root" ]; then new_user="${DB_USER:-zerocode}" if [ -n "${DB_PASSWORD:-}" ]; then new_pass="$DB_PASSWORD" else if command -v tr >/dev/null 2>&1; then new_pass="$(tr -dc 'A-Za-z0-9_@#%!' < /dev/urandom | head -c 20)" else new_pass="Zc$(date +%s)Pwd" fi fi env new_user="$new_user" new_pass="$new_pass" DB_JSON="$DB_JSON" "$PY_BIN" - <<'PY' import json,os p=os.environ.get('DB_JSON') try: with open(p,'r') as f: d=json.load(f) except Exception: d={} u=os.environ.get('new_user','zerocode') pw=os.environ.get('new_pass','ZcDefaultPwd') d['USER']=u d['PASSWORD']=pw d['HOST']='127.0.0.1' with open(p,'w') as f: json.dump(d,f,indent=2,ensure_ascii=False) PY USER="$new_user" PASSWORD="$new_pass" HOST="127.0.0.1" fi SQL_DB="CREATE DATABASE IF NOT EXISTS \`$NAME\` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;" SQL_GRANT_1="GRANT ALL PRIVILEGES ON \`$NAME\`.* TO '$USER'@'127.0.0.1' IDENTIFIED BY '$PASSWORD';" SQL_GRANT_2="GRANT ALL PRIVILEGES ON \`$NAME\`.* TO '$USER'@'localhost' IDENTIFIED BY '$PASSWORD';" SQL_FLUSH="FLUSH PRIVILEGES;" if command -v sudo >/dev/null 2>&1 && sudo -n true >/dev/null 2>&1; then sudo mysql --no-defaults -e "$SQL_DB CREATE USER IF NOT EXISTS '$USER'@'127.0.0.1' IDENTIFIED BY '$PASSWORD'; CREATE USER IF NOT EXISTS '$USER'@'localhost' IDENTIFIED BY '$PASSWORD'; CREATE USER IF NOT EXISTS '$USER'@'%' IDENTIFIED BY '$PASSWORD'; $SQL_GRANT_1 $SQL_GRANT_2 $SQL_FLUSH" || true elif [ -n "${MYSQL_ROOT_PWD:-}" ]; then mysql --protocol=TCP -h "${HOST:-127.0.0.1}" -P "${PORT:-3306}" -uroot -p"$MYSQL_ROOT_PWD" --no-defaults -e "$SQL_DB CREATE USER IF NOT EXISTS '$USER'@'127.0.0.1' IDENTIFIED BY '$PASSWORD'; CREATE USER IF NOT EXISTS '$USER'@'localhost' IDENTIFIED BY '$PASSWORD'; CREATE USER IF NOT EXISTS '$USER'@'%' IDENTIFIED BY '$PASSWORD'; $SQL_GRANT_1 $SQL_GRANT_2 $SQL_FLUSH" || true else mysql --protocol=TCP -h "${HOST:-127.0.0.1}" -P "${PORT:-3306}" -uroot --no-defaults -e "$SQL_DB CREATE USER IF NOT EXISTS '$USER'@'127.0.0.1' IDENTIFIED BY '$PASSWORD'; CREATE USER IF NOT EXISTS '$USER'@'localhost' IDENTIFIED BY '$PASSWORD'; CREATE USER IF NOT EXISTS '$USER'@'%' IDENTIFIED BY '$PASSWORD'; $SQL_GRANT_1 $SQL_GRANT_2 $SQL_FLUSH" || true fi fi TEMP_DB_JSON="$BASE_DIR/ZeroCodeProject/apis/temp_api/dependency/api_config/project_settings.json" export TEMP_DB_JSON temp_vars=$("$PY_BIN" - <<'PY' import json,os p=os.environ.get('TEMP_DB_JSON') try: with open(p,'r') as f: d=json.load(f) except Exception: d={} def val(k,default): return d.get(k,default) e=val('ENGINE','') h=val('HOST','127.0.0.1') port=val('PORT','3306') n=val('NAME','zero_code') u=val('USER','root') pw=val('PASSWORD','') print('\n'.join([ f"T_ENGINE={e}", f"T_HOST={h}", f"T_PORT={port}", f"T_NAME={n}", f"T_USER={u}", f"T_PASSWORD={pw}", ])) PY ) eval "$temp_vars" # Normalize temp_api DB config to MySQL env TEMP_DB_JSON="$TEMP_DB_JSON" "$PY_BIN" - <<'PY' import json,os p=os.environ['TEMP_DB_JSON'] try: with open(p,'r') as f: d=json.load(f) except Exception: d={} e=d.get('ENGINE','') name=d.get('NAME','zero_code') host=d.get('HOST','127.0.0.1') port=d.get('PORT','3306') user=d.get('USER','zerocode') pw=d.get('PASSWORD','') if host=='localhost': host='127.0.0.1' if e!='django.db.backends.mysql': d['ENGINE']='django.db.backends.mysql' d['NAME']=name d['HOST']=host d['PORT']=port d['USER']=user d['PASSWORD']=pw with open(p,'w') as f: json.dump(d,f,indent=2,ensure_ascii=False) PY # Override from environment if provided (applies to temp_api) if [ -n "${DB_USER:-}" ] || [ -n "${DB_PASSWORD:-}" ] || [ -n "${DB_NAME:-}" ] || [ -n "${DB_HOST:-}" ] || [ -n "${DB_PORT:-}" ]; then env new_user="${DB_USER:-$T_USER}" new_pass="${DB_PASSWORD:-$T_PASSWORD}" new_name="${DB_NAME:-$T_NAME}" new_host="${DB_HOST:-$T_HOST}" new_port="${DB_PORT:-$T_PORT}" TEMP_DB_JSON="$TEMP_DB_JSON" "$PY_BIN" - <<'PY' import json,os p=os.environ['TEMP_DB_JSON'] u=os.environ['new_user'] pw=os.environ['new_pass'] n=os.environ['new_name'] h=os.environ['new_host'] pt=os.environ['new_port'] try: with open(p,'r') as f: d=json.load(f) except Exception: d={} d['ENGINE']='django.db.backends.mysql' d['USER']=u d['PASSWORD']=pw d['NAME']=n d['HOST']=h d['PORT']=pt with open(p,'w') as f: json.dump(d,f,indent=2,ensure_ascii=False) PY T_USER="${DB_USER:-$T_USER}" T_PASSWORD="${DB_PASSWORD:-$T_PASSWORD}" T_NAME="${DB_NAME:-$T_NAME}" T_HOST="${DB_HOST:-$T_HOST}" T_PORT="${DB_PORT:-$T_PORT}" fi if [ "$T_ENGINE" = "django.db.backends.mysql" ]; then if [ "$T_USER" = "root" ]; then t_new_user="${DB_USER:-$USER}" [ -z "$t_new_user" ] && t_new_user="zerocode" t_new_pass="${DB_PASSWORD:-$PASSWORD}" [ -z "$t_new_pass" ] && t_new_pass="Zc$(date +%s)Pwd" env new_user="$t_new_user" new_pass="$t_new_pass" TEMP_DB_JSON="$TEMP_DB_JSON" "$PY_BIN" - <<'PY' import json,os p=os.environ.get('TEMP_DB_JSON') try: with open(p,'r') as f: d=json.load(f) except Exception: d={} u=os.environ.get('new_user','zerocode') pw=os.environ.get('new_pass','ZcDefaultPwd') d['USER']=u d['PASSWORD']=pw d['HOST']='127.0.0.1' with open(p,'w') as f: json.dump(d,f,indent=2,ensure_ascii=False) PY T_USER="$t_new_user" T_PASSWORD="$t_new_pass" T_HOST="127.0.0.1" fi SQL_DB_T="CREATE DATABASE IF NOT EXISTS \`$T_NAME\` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;" SQL_GRANT_T1="GRANT ALL PRIVILEGES ON \`$T_NAME\`.* TO '$T_USER'@'127.0.0.1' IDENTIFIED BY '$T_PASSWORD';" SQL_GRANT_T2="GRANT ALL PRIVILEGES ON \`$T_NAME\`.* TO '$T_USER'@'localhost' IDENTIFIED BY '$T_PASSWORD';" SQL_FLUSH_T="FLUSH PRIVILEGES;" if command -v sudo >/dev/null 2>&1 && sudo -n true >/dev/null 2>&1; then sudo mysql --no-defaults -e "$SQL_DB_T CREATE USER IF NOT EXISTS '$T_USER'@'127.0.0.1' IDENTIFIED BY '$T_PASSWORD'; CREATE USER IF NOT EXISTS '$T_USER'@'localhost' IDENTIFIED BY '$T_PASSWORD'; CREATE USER IF NOT EXISTS '$T_USER'@'%' IDENTIFIED BY '$T_PASSWORD'; $SQL_GRANT_T1 $SQL_GRANT_T2 $SQL_FLUSH_T" || true elif [ -n "${MYSQL_ROOT_PWD:-}" ]; then mysql --protocol=TCP -h "${T_HOST:-127.0.0.1}" -P "${T_PORT:-3306}" -uroot -p"$MYSQL_ROOT_PWD" --no-defaults -e "$SQL_DB_T CREATE USER IF NOT EXISTS '$T_USER'@'127.0.0.1' IDENTIFIED BY '$T_PASSWORD'; CREATE USER IF NOT EXISTS '$T_USER'@'localhost' IDENTIFIED BY '$T_PASSWORD'; CREATE USER IF NOT EXISTS '$T_USER'@'%' IDENTIFIED BY '$T_PASSWORD'; $SQL_GRANT_T1 $SQL_GRANT_T2 $SQL_FLUSH_T" || true else mysql --protocol=TCP -h "${T_HOST:-127.0.0.1}" -P "${T_PORT:-3306}" -uroot --no-defaults -e "$SQL_DB_T CREATE USER IF NOT EXISTS '$T_USER'@'127.0.0.1' IDENTIFIED BY '$T_PASSWORD'; CREATE USER IF NOT EXISTS '$T_USER'@'localhost' IDENTIFIED BY '$T_PASSWORD'; CREATE USER IF NOT EXISTS '$T_USER'@'%' IDENTIFIED BY '$T_PASSWORD'; $SQL_GRANT_T1 $SQL_GRANT_T2 $SQL_FLUSH_T" || true fi fi MYSQL_CHECK=0 env MYSQL_HOST="$HOST" MYSQL_PORT="$PORT" MYSQL_USER="$USER" MYSQL_PASS="$PASSWORD" "$PY_BIN" - <<'PY' && MYSQL_CHECK=1 || MYSQL_CHECK=0 import os import pymysql h=os.environ.get('MYSQL_HOST','127.0.0.1') p=int(os.environ.get('MYSQL_PORT','3306')) u=os.environ.get('MYSQL_USER','zerocode') pw=os.environ.get('MYSQL_PASS','') conn=pymysql.connect(host=h,port=p,user=u,password=pw,connect_timeout=3) conn.close() PY cd "$BASE_DIR/ZeroCodeProject/apis/temp_api" if [ -d "$BASE_DIR/main_package" ]; then export PYTHONPATH="$BASE_DIR/main_package:$PYTHONPATH" fi "$PY_BIN" manage.py migrate cd "$BASE_DIR/ZeroCodeProject/apis/ZeroCodeMain" if [ -d "$BASE_DIR/main_package" ]; then export PYTHONPATH="$BASE_DIR/main_package:$PYTHONPATH" fi # Resolve possible inconsistent history by migrating users before admin "$PY_BIN" manage.py migrate admin zero || true "$PY_BIN" manage.py migrate users || true # Ensure BaseApi base tables exist "$PY_BIN" manage.py makemigrations BaseApi || true "$PY_BIN" manage.py migrate echo ready