Update devbox/cli/devbox

This commit is contained in:
ryanyao 2025-07-15 00:59:23 +00:00
parent 38f5671cd0
commit d7aec36cf2

View File

@ -948,6 +948,145 @@ compile_backend_service() {
echo "[BACKEND] $(date '+%Y-%m-%d %H:%M:%S') Start backend service from $DEVBOX_NAME."
docker exec -i "$DEVBOX_NAME" bash <<EOF
# Define the install_and_verify_packages function inside the container
install_and_verify_packages() {
local requirements_file="\$1"
if [[ -z "\$requirements_file" ]]; then
echo "[ERROR] Requirements file path is required" >&2
return 1
fi
if [[ ! -f "\$requirements_file" ]]; then
echo "[ERROR] Requirements file '\$requirements_file' does not exist" >&2
return 1
fi
if [[ ! -r "\$requirements_file" ]]; then
echo "[ERROR] Requirements file '\$requirements_file' is not readable" >&2
return 1
fi
echo "[INFO] Starting package installation and verification for: \$requirements_file"
# Create temporary directory for hash verification
local temp_dir=\$(mktemp -d)
local hash_file="\$temp_dir/package_hashes.txt"
# Function to get package hash from PyPI
get_package_hash() {
local package_name="\$1"
local version="\$2"
local pypi_url="https://pypi.org/pypi/\${package_name}/\${version}/json"
local hash_value=""
if command -v curl &>/dev/null; then
hash_value=\$(curl -s "\$pypi_url" | grep -o '"sha256":"[^"]*"' | head -1 | cut -d'"' -f4 2>/dev/null || echo "")
elif command -v wget &>/dev/null; then
hash_value=\$(wget -qO- "\$pypi_url" | grep -o '"sha256":"[^"]*"' | head -1 | cut -d'"' -f4 2>/dev/null || echo "")
fi
echo "\$hash_value"
}
# Function to verify installed package
verify_package() {
local package_name="\$1"
local expected_hash="\$2"
if [[ -z "\$expected_hash" ]]; then
echo "[INFO] No hash available for \$package_name, skipping verification"
return 0
fi
local package_location=""
if command -v python3.11 &>/dev/null; then
package_location=\$(python3.11 -c "import \$package_name; print(\$package_name.__file__)" 2>/dev/null || echo "")
fi
if [[ -z "\$package_location" ]]; then
echo "[ERROR] Package \$package_name not found, verification failed" >&2
return 1
fi
local actual_hash=\$(find "\$(dirname "\$package_location")" -name "*\$package_name*" -type f -exec sha256sum {} \; 2>/dev/null | head -1 | cut -d' ' -f1)
if [[ "\$actual_hash" == "\$expected_hash" ]]; then
echo "[INFO] Package \$package_name verification successful"
return 0
else
echo "[ERROR] Package \$package_name verification failed - Expected: \$expected_hash, Got: \$actual_hash" >&2
return 1
fi
}
# Step 1: Install all packages
echo "[INFO] Installing all packages from \$requirements_file"
if ! pip install --no-cache-dir -r "\$requirements_file"; then
echo "[ERROR] Failed to install packages" >&2
rm -rf "\$temp_dir"
return 1
fi
# Step 2: Collect hashes for verification
echo "[INFO] Collecting package hashes for verification"
while IFS= read -r line; do
[[ "\$line" =~ ^[[:space:]]*# ]] && continue
[[ -z "\$line" ]] && continue
local package_name=\$(echo "\$line" | cut -d'=' -f1 | cut -d'[' -f1 | tr -d ' ')
local version=\$(echo "\$line" | grep -o '[=<>!][=<>!]*[^;]*' | head -1 | sed 's/[=<>!]*//' || echo "")
if [[ -n "\$package_name" ]]; then
echo "[INFO] Getting hash for \$package_name\${version:+:\$version}"
local hash_value=\$(get_package_hash "\$package_name" "\$version")
if [[ -n "\$hash_value" ]]; then
echo "\$package_name:\$hash_value" >> "\$hash_file"
fi
fi
done < "\$requirements_file"
# Step 3: Verify each package and reinstall if failed
echo "[INFO] Verifying installed packages"
local failed_packages=()
while IFS=: read -r package_name hash_value; do
if [[ -n "\$package_name" && -n "\$hash_value" ]]; then
if ! verify_package "\$package_name" "\$hash_value"; then
failed_packages+=("\$package_name")
echo "[WARN] Package \$package_name failed verification, will reinstall"
fi
fi
done < "\$hash_file"
# Reinstall failed packages
if [[ \${#failed_packages[@]} -gt 0 ]]; then
echo "[INFO] Reinstalling \${#failed_packages[@]} failed packages"
for package in "\${failed_packages[@]}"; do
echo "[INFO] Reinstalling \$package"
if ! pip install --no-cache-dir --force-reinstall "\$package"; then
echo "[ERROR] Failed to reinstall \$package" >&2
rm -rf "\$temp_dir"
return 1
fi
# Verify again after reinstall
local package_hash=\$(grep "^\$package:" "\$hash_file" | cut -d: -f2)
if ! verify_package "\$package" "\$package_hash"; then
echo "[ERROR] Package \$package still failed verification after reinstall" >&2
rm -rf "\$temp_dir"
return 1
fi
done
fi
echo "[INFO] All packages installed and verified successfully"
rm -rf "\$temp_dir"
return 0
}
# Check if /home/devbox/.backend.pid exits
if [ -f /home/devbox/.backend.pid ]; then
backend_pid=\$(cat /home/devbox/.backend.pid)
@ -1020,7 +1159,7 @@ compile_backend_service() {
# Check if it's the first time by verifying if the backend dependencies have been installed
if [ ! -f "/home/devbox/.backend_deps_installed" ]; then
echo "[BACKEND] \$(date '+%Y-%m-%d %H:%M:%S') Install backend dependencies..."
pip install --no-cache-dir -r /home/devbox/freeleaps/apps/freeleaps/requirements.txt
install_and_verify_packages /home/devbox/freeleaps/apps/freeleaps/requirements.txt
if ! pip show async_timeout; then
echo "[BACKEND] \$(date '+%Y-%m-%d %H:%M:%S') async_timeout is missing. Installing..."
pip install async_timeout
@ -1066,7 +1205,7 @@ compile_backend_service() {
if [ \$IS_NEW_REQ_ADDED -eq 1 ]; then
echo "[BACKEND] \$(date '+%Y-%m-%d %H:%M:%S') Reinstalling dependencies..."
pip install --no-cache-dir -r /home/devbox/freeleaps/apps/freeleaps/requirements.txt
install_and_verify_packages /home/devbox/freeleaps/apps/freeleaps/requirements.txt
fi
# Undo update for /home/devbox/freeleaps/apps/requirements.txt
rm /home/devbox/freeleaps/apps/freeleaps/requirements.txt
@ -1080,7 +1219,7 @@ compile_backend_service() {
# Check if all dependencies are installed, if not, install them
if ! pip check; then
echo "[BACKEND] \$(date '+%Y-%m-%d %H:%M:%S') Some dependencies are missing. Reinstalling..."
pip install --no-cache-dir -r /home/devbox/freeleaps/apps/freeleaps/requirements.txt
install_and_verify_packages /home/devbox/freeleaps/apps/freeleaps/requirements.txt
fi
# pip install async_timeout if not installed
@ -1126,7 +1265,7 @@ compile_backend_service() {
if [ \$IS_NEW_REQ_ADDED -eq 1 ]; then
echo "[BACKEND] \$(date '+%Y-%m-%d %H:%M:%S') Reinstalling dependencies..."
pip install --no-cache-dir -r /home/devbox/freeleaps/apps/requirements.txt
install_and_verify_packages /home/devbox/freeleaps/apps/requirements.txt
fi
# Undo update for /home/devbox/freeleaps/apps/requirements.txt