Files
ZERO_CODE/scripts/deploy.sh
vermouth789 fe39320977 123
123
2026-01-11 00:11:34 +08:00

379 lines
13 KiB
Bash

#!/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