refactor: automate build.sh to clone modules, configure DB and init permissions

- Clone all reference and business modules to pkgs/
- Interactive DB config (host, port, user, password)
- Auto-create database, import schema, encrypt password in config.json
- Auto-run permission initialization
- Generate start.sh/stop.sh
This commit is contained in:
yumoqing 2026-04-29 13:26:34 +08:00
parent 2134a83738
commit f83dde78f9

308
build.sh
View File

@ -1,150 +1,261 @@
#!/bin/bash #!/bin/bash
# Integrated CRM Application Build Script # Integrated CRM Application - Automated Build & Deploy Script
# Uses local modules from ~/repos instead of cloning from git # Clones all dependencies, configures database, initializes tables and permissions
set -e set -e
APP_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" APP_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
REPOS_DIR="$HOME/repos" PKGS_DIR="$APP_DIR/pkgs"
GIT_BASE="git@git.opencomputing.cn:yumoqing"
echo "Building Integrated CRM Application at: $APP_DIR" echo "============================================"
echo "Using local modules from: $REPOS_DIR" echo " Integrated CRM Application Builder"
echo "============================================"
echo ""
# ============================================================
# Step 1: Create required directories # Step 1: Create required directories
mkdir -p "$APP_DIR/pkgs" # ============================================================
echo "[1/10] Creating directories..."
mkdir -p "$PKGS_DIR"
mkdir -p "$APP_DIR/logs" mkdir -p "$APP_DIR/logs"
mkdir -p "$APP_DIR/files" mkdir -p "$APP_DIR/files"
mkdir -p "$APP_DIR/wwwroot" mkdir -p "$APP_DIR/wwwroot"
mkdir -p "$APP_DIR/conf"
# ============================================================
# Step 2: Setup Python virtual environment # Step 2: Setup Python virtual environment
# ============================================================
echo "[2/10] Setting up Python virtual environment..."
if [ ! -d "$APP_DIR/py3" ]; then if [ ! -d "$APP_DIR/py3" ]; then
echo "Creating Python virtual environment..."
python3 -m venv "$APP_DIR/py3" python3 -m venv "$APP_DIR/py3"
fi fi
source "$APP_DIR/py3/bin/activate" source "$APP_DIR/py3/bin/activate"
pip install --upgrade pip --quiet
# ============================================================
# Step 3: Install core dependencies # Step 3: Install core dependencies
echo "Installing core dependencies..." # ============================================================
pip install --quiet git+https://git.opencomputing.cn/yumoqing/apppublic echo "[3/10] Installing core dependencies..."
pip install --quiet git+https://git.opencomputing.cn/yumoqing/sqlor pip install git+https://git.opencomputing.cn/yumoqing/apppublic --quiet
pip install --quiet git+https://git.opencomputing.cn/yumoqing/ahserver pip install git+https://git.opencomputing.cn/yumoqing/sqlor --quiet
pip install --quiet xls2ddl pip install git+https://git.opencomputing.cn/yumoqing/ahserver --quiet
pip install xls2ddl --quiet
pip install pymysql --quiet
pip install cryptography --quiet
# Step 4: Install local modules from ~/repos # ============================================================
echo "Installing local modules..." # Step 4: Clone all modules to pkgs/
# ============================================================
echo "[4/10] Cloning modules to pkgs/..."
MODULES="apppublic sqlor ahserver appbase rbac customer_management opportunity_management contract_management financial_management workflow_approval unified_dashboard bricks" REFERENCE_MODULES="apppublic sqlor ahserver appbase rbac"
BUSINESS_MODULES="customer_management opportunity_management contract_management financial_management workflow_approval unified_dashboard"
for module in $MODULES; do for module in $REFERENCE_MODULES $BUSINESS_MODULES; do
MOD_DIR="$REPOS_DIR/$module" MOD_DIR="$PKGS_DIR/$module"
if [ -d "$MOD_DIR" ]; then if [ -d "$MOD_DIR/.git" ]; then
echo " Installing $module from $MOD_DIR..." echo " Pulling latest $module..."
# Create symlink in pkgs for consistency cd "$MOD_DIR" && git pull --quiet 2>/dev/null
ln -sf "$MOD_DIR" "$APP_DIR/pkgs/$module"
pip install -e "$MOD_DIR" --quiet 2>/dev/null || echo " (pip install failed for $module, may be a non-package module)"
else else
echo " WARNING: Module $module not found at $MOD_DIR" echo " Cloning $module..."
git clone --quiet "$GIT_BASE/$module.git" "$MOD_DIR"
fi fi
# Install module
pip install -e "$MOD_DIR" --quiet 2>/dev/null || true
done done
# Step 5: Generate database DDL for all modules with models/ cd "$APP_DIR"
echo "Generating database DDL..."
# ============================================================
# Step 5: Generate database DDL and CRUD UI
# ============================================================
echo "[5/10] Generating database DDL..."
# Collect all DDL into a single file
> "$APP_DIR/integrated_crm_app_schema.sql" > "$APP_DIR/integrated_crm_app_schema.sql"
for module in appbase rbac customer_management opportunity_management contract_management financial_management workflow_approval unified_dashboard; do for module in rbac customer_management opportunity_management contract_management financial_management workflow_approval unified_dashboard; do
MOD_DIR="$APP_DIR/pkgs/$module" MOD_DIR="$PKGS_DIR/$module"
if [ -d "$MOD_DIR/models" ]; then if [ -d "$MOD_DIR/models" ]; then
echo " Processing models for $module..."
cd "$MOD_DIR/models" cd "$MOD_DIR/models"
# Check for .xlsx files first
if ls *.xlsx >/dev/null 2>&1; then if ls *.xlsx >/dev/null 2>&1; then
xls2ddl mysql . > "$MOD_DIR/mysql.ddl.sql" 2>/dev/null || true xls2ddl mysql . > "$MOD_DIR/mysql.ddl.sql" 2>/dev/null || true
# Check for .json files
elif ls *.json >/dev/null 2>&1; then elif ls *.json >/dev/null 2>&1; then
json2ddl mysql . > "$MOD_DIR/mysql.ddl.sql" 2>/dev/null || true json2ddl mysql . > "$MOD_DIR/mysql.ddl.sql" 2>/dev/null || true
fi fi
# Append to combined schema if DDL was generated
if [ -f "$MOD_DIR/mysql.ddl.sql" ] && [ -s "$MOD_DIR/mysql.ddl.sql" ]; then if [ -f "$MOD_DIR/mysql.ddl.sql" ] && [ -s "$MOD_DIR/mysql.ddl.sql" ]; then
echo "-- Module: $module" >> "$APP_DIR/integrated_crm_app_schema.sql" echo "-- Module: $module" >> "$APP_DIR/integrated_crm_app_schema.sql"
cat "$MOD_DIR/mysql.ddl.sql" >> "$APP_DIR/integrated_crm_app_schema.sql" cat "$MOD_DIR/mysql.ddl.sql" >> "$APP_DIR/integrated_crm_app_schema.sql"
echo "" >> "$APP_DIR/integrated_crm_app_schema.sql" echo "" >> "$APP_DIR/integrated_crm_app_schema.sql"
echo " Generated DDL for $module" echo " Generated DDL for $module"
else
echo " No DDL generated for $module (using existing mysql.ddl.sql if available)"
if [ -f "$MOD_DIR/mysql.ddl.sql" ] && [ -s "$MOD_DIR/mysql.ddl.sql" ]; then
echo "-- Module: $module" >> "$APP_DIR/integrated_crm_app_schema.sql"
cat "$MOD_DIR/mysql.ddl.sql" >> "$APP_DIR/integrated_crm_app_schema.sql"
echo "" >> "$APP_DIR/integrated_crm_app_schema.sql"
fi
fi fi
fi fi
done done
cd "$APP_DIR"
echo "Combined schema written to: $APP_DIR/integrated_crm_app_schema.sql" echo "[5/10] Generating CRUD UI..."
wc -l "$APP_DIR/integrated_crm_app_schema.sql" for module in rbac customer_management opportunity_management contract_management financial_management workflow_approval unified_dashboard; do
MOD_DIR="$PKGS_DIR/$module"
# Step 6: Generate CRUD UI for all modules with json/
echo "Generating CRUD UI..."
for module in appbase rbac customer_management opportunity_management contract_management financial_management workflow_approval unified_dashboard; do
MOD_DIR="$APP_DIR/pkgs/$module"
if [ -d "$MOD_DIR/json" ] && [ -d "$MOD_DIR/models" ]; then if [ -d "$MOD_DIR/json" ] && [ -d "$MOD_DIR/models" ]; then
echo " Generating UI for $module..." echo " Generating UI for $module..."
cd "$MOD_DIR/json" cd "$MOD_DIR/json"
# Get list of json files (excluding potential subdirectories)
for jsonfile in *.json; do for jsonfile in *.json; do
if [ -f "$jsonfile" ]; then if [ -f "$jsonfile" ]; then
xls2ui -m ../models -o ../wwwroot "$module" "$jsonfile" 2>/dev/null || echo " Warning: xls2ui failed for $jsonfile" xls2ui -m ../models -o ../wwwroot "$module" "$jsonfile" 2>/dev/null || true
fi fi
done done
fi fi
done done
cd "$APP_DIR"
# Step 7: Create symbolic links for wwwroot # ============================================================
echo "Creating wwwroot symbolic links..." # Step 6: Create wwwroot symbolic links
# ============================================================
echo "[6/10] Creating wwwroot symbolic links..."
mkdir -p "$APP_DIR/wwwroot" for module in rbac customer_management opportunity_management contract_management financial_management workflow_approval unified_dashboard; do
MOD_DIR="$PKGS_DIR/$module"
for module in appbase rbac customer_management opportunity_management contract_management financial_management workflow_approval unified_dashboard; do
MOD_DIR="$APP_DIR/pkgs/$module"
if [ -d "$MOD_DIR/wwwroot" ]; then if [ -d "$MOD_DIR/wwwroot" ]; then
ln -sf "$MOD_DIR/wwwroot" "$APP_DIR/wwwroot/$module" ln -sfn "$MOD_DIR/wwwroot" "$APP_DIR/wwwroot/$module"
echo " Linked $module/wwwroot" echo " Linked wwwroot/$module"
fi fi
done done
# Step 8: Setup Bricks framework # Link bricks framework
echo "Setting up Bricks framework..." if [ -d "$PKGS_DIR/bricks/dist" ]; then
ln -sfn "$PKGS_DIR/bricks/dist" "$APP_DIR/wwwroot/bricks"
BRICKS_DIR="$REPOS_DIR/bricks" elif [ -d "$PKGS_DIR/appbase/wwwroot/bricks" ]; then
if [ -d "$BRICKS_DIR" ]; then ln -sfn "$PKGS_DIR/appbase/wwwroot/bricks" "$APP_DIR/wwwroot/bricks"
if [ -f "$BRICKS_DIR/build.sh" ]; then
echo " Building bricks framework..."
cd "$BRICKS_DIR" && ./build.sh
fi
if [ -d "$BRICKS_DIR/dist" ]; then
ln -sf "$BRICKS_DIR/dist" "$APP_DIR/wwwroot/bricks"
echo " Linked bricks/dist to wwwroot/bricks"
else
echo " WARNING: bricks/dist not found"
fi
else
echo " WARNING: bricks module not found at $BRICKS_DIR"
fi fi
# Step 9: Create main app wwwroot links # ============================================================
echo "Setting up main app wwwroot..." # Step 7: Interactive database configuration
# ============================================================
echo ""
echo "[7/10] Database Configuration"
echo "--------------------------------------------"
# Link main app wwwroot files read -p " MySQL host [localhost]: " DB_HOST
if [ -d "$APP_DIR/wwwroot_main" ]; then DB_HOST=${DB_HOST:-localhost}
cp -r "$APP_DIR/wwwroot_main"/* "$APP_DIR/wwwroot/" 2>/dev/null || true
fi
read -p " MySQL port [3306]: " DB_PORT
DB_PORT=${DB_PORT:-3306}
read -p " MySQL admin user (needs CREATE DATABASE permission) [root]: " DB_ADMIN_USER
DB_ADMIN_USER=${DB_ADMIN_USER:-root}
read -sp " MySQL admin password: " DB_ADMIN_PASS
echo ""
read -p " CRM database name [crm_db]: " DB_NAME
DB_NAME=${DB_NAME:-crm_db}
read -p " CRM database user [hermes]: " DB_USER
DB_USER=${DB_USER:-hermes}
read -sp " CRM database password: " DB_PASS
echo ""
# ============================================================
# Step 8: Create database, import schema, configure app
# ============================================================
echo "[8/10] Initializing database..."
# Create database and user via MySQL admin
mysql -h "$DB_HOST" -P "$DB_PORT" -u "$DB_ADMIN_USER" -p"$DB_ADMIN_PASS" <<EOSQL
CREATE DATABASE IF NOT EXISTS \`$DB_NAME\` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER IF NOT EXISTS '$DB_USER'@'%' IDENTIFIED BY '$DB_PASS';
GRANT ALL PRIVILEGES ON \`$DB_NAME\`.* TO '$DB_USER'@'%';
FLUSH PRIVILEGES;
EOSQL
echo " Database '$DB_NAME' created."
# Import schema
mysql -h "$DB_HOST" -P "$DB_PORT" -u "$DB_USER" -p"$DB_PASS" "$DB_NAME" < "$APP_DIR/integrated_crm_app_schema.sql"
echo " Schema imported."
# Generate config.json with encrypted password
python3 <<PYEOF
import sys, json
sys.path.insert(0, '$PKGS_DIR/apppublic')
from appPublic.aes import aes_encode_b64
password_key = "!@#\$%^&*(*&^\$QWERTYUIqwertyui234567"
encrypted_pass = aes_encode_b64(password_key, "$DB_PASS")
config = {
"password_key": password_key,
"logger": {
"name": "integrated_crm_app",
"level": "info",
"file": "\$[workdir]\$/logs/app.log"
},
"filesroot": "\$[workdir]\$/files",
"databases": {
"crm_db": {
"driver": "mysql",
"kwargs": {
"host": "$DB_HOST",
"port": $DB_PORT,
"user": "$DB_USER",
"password": encrypted_pass,
"db": "$DB_NAME",
"charset": "utf8mb4"
}
}
},
"website": {
"paths": [
["\$[workdir]\$/wwwroot", "/main"],
["\$[workdir]\$/wwwroot/bricks", "/bricks"]
],
"processors": [
[".ui", "bui"],
[".dspy", "dspy"],
[".tmpl", "tmpl"]
],
"session_max_time": 3600,
"session_issue_time": 1800,
"client_max_size": 10485760
}
}
with open("$APP_DIR/conf/config.json", "w") as f:
json.dump(config, f, indent=2)
print(" config.json generated.")
PYEOF
# ============================================================
# Step 9: Initialize permissions
# ============================================================
echo "[9/10] Initializing permissions..."
cd "$APP_DIR"
python3 -c "
import asyncio, json, sys, os
os.chdir('$APP_DIR')
sys.path.insert(0, '$APP_DIR')
from appPublic.jsonConfig import getConfig
from appPublic.dictObject import DictObject
from sqlor.dbpools import DBPools
config = getConfig('$APP_DIR', {'workdir': '$APP_DIR'})
db_config = {}
for k, v in config.databases.items():
db_config[k] = DictObject(driver=v['driver'], kwargs=DictObject(**v['kwargs']))
DBPools(db_config)
from app.init_permissions import init_permissions_from_config
dbname = list(config.databases.keys())[0]
asyncio.run(init_permissions_from_config(dbname))
"
echo " Permissions initialized."
# ============================================================
# Step 10: Create start/stop scripts # Step 10: Create start/stop scripts
echo "Creating service scripts..." # ============================================================
echo "[10/10] Creating service scripts..."
cat > "$APP_DIR/start.sh" << 'STARTSCRIPT' cat > "$APP_DIR/start.sh" << 'STARTSCRIPT'
#!/bin/bash #!/bin/bash
@ -152,8 +263,10 @@ APP_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
cd "$APP_DIR" cd "$APP_DIR"
source "$APP_DIR/py3/bin/activate" source "$APP_DIR/py3/bin/activate"
export PYTHONPATH="$APP_DIR:$PYTHONPATH" export PYTHONPATH="$APP_DIR:$PYTHONPATH"
echo "Starting Integrated CRM Application on port 8080..." PORT="${1:-8080}"
python app/integrated_crm_app.py --port 8080 --root wwwroot/ echo "Starting Integrated CRM Application on port $PORT..."
echo "Access: http://localhost:$PORT/main/login.ui"
python app/integrated_crm_app.py --port "$PORT" --root wwwroot/
STARTSCRIPT STARTSCRIPT
cat > "$APP_DIR/stop.sh" << 'STOPSCRIPT' cat > "$APP_DIR/stop.sh" << 'STOPSCRIPT'
@ -164,18 +277,25 @@ STOPSCRIPT
chmod +x "$APP_DIR/start.sh" "$APP_DIR/stop.sh" chmod +x "$APP_DIR/start.sh" "$APP_DIR/stop.sh"
# ============================================================
# Done
# ============================================================
echo "" echo ""
echo "==========================================" echo "============================================"
echo "Build completed successfully!" echo " Build completed successfully!"
echo "==========================================" echo "============================================"
echo "" echo ""
echo "Next steps:" echo "Next steps:"
echo "1. Apply database schema:" echo " 1. Start the application:"
echo " mysql -u hermes -phermes123 < $APP_DIR/integrated_crm_app_schema.sql" echo " ./start.sh [port] (default: 8080)"
echo "" echo ""
echo "2. Start the application:" echo " 2. Register the first admin user:"
echo " ./start.sh" echo " http://localhost:8080/user/register.ui"
echo "" echo ""
echo "3. Access the application:" echo " 3. Assign admin_superuser role to your user:"
echo " http://localhost:8080/main/login.ui" echo " mysql -u $DB_USER -p $DB_NAME"
echo " INSERT INTO userroles (userid, roleid) VALUES ('<your_userid>', 'admin_superuser');"
echo ""
echo " 4. Access the application:"
echo " http://localhost:8080/main/login.ui"
echo "" echo ""