diff --git a/lib/common.sh b/lib/common.sh index 39529d9..1d94aef 100644 --- a/lib/common.sh +++ b/lib/common.sh @@ -14,7 +14,7 @@ readonly FILESTORE_SUBPATH="var/lib/odoo/filestore" check_required_commands() { local missing=() - for cmd in docker compose sudo rsync; do + for cmd in docker compose sudo rsync yq; do if ! command -v "$cmd" &>/dev/null; then missing+=("$cmd") fi @@ -100,7 +100,83 @@ exec_python_script_in_odoo_shell() { run_compose --debug run "$service_name" shell -d "$db_name" --no-http --stop-after-init < "$python_script" } +# Classifies missing modules into 4 categories based on the known_changes.yaml +# files from each traversed version (from ORIGIN_VERSION+1 to FINAL_VERSION). +# The following global arrays are populated: +# addons_obsolete : modules that became obsolete +# addons_core : modules merged into Odoo Core +# addons_renamed : renamed modules (format "old_name -> new_name") +# addons_truly_missing : modules that are genuinely missing +# +# Prerequisites: ORIGIN_VERSION and FINAL_VERSION must be exported. +classify_missing_addons() { + local missing_addons_raw="$1" + + addons_obsolete=() + addons_core=() + addons_renamed=() + addons_truly_missing=() + + # Convert the string into an array (one entry per line) + local -a missing=() + while IFS= read -r line; do + [[ -n "$line" ]] && missing+=("$line") + done <<< "$missing_addons_raw" + + if [[ ${#missing[@]} -eq 0 ]]; then + return 0 + fi + + # Build lookup tables from all known_changes.yaml files in traversed versions + local -A known_obsolete=() + local -A known_core=() + local -A known_renamed=() + + local versions_path="${PROJECT_ROOT}/versions" + local v + for v in $(seq $((ORIGIN_VERSION + 1)) "$FINAL_VERSION"); do + local yaml_file="${versions_path}/${v}.0/known_changes.yaml" + [[ -f "$yaml_file" ]] || continue + + local mod + while IFS= read -r mod; do + [[ -n "$mod" && "$mod" != "null" ]] && known_obsolete["$mod"]=1 + done < <(yq '.obsolete[]?' "$yaml_file" 2>/dev/null) + + while IFS= read -r mod; do + [[ -n "$mod" && "$mod" != "null" ]] && known_core["$mod"]=1 + done < <(yq '.merged_in_core[]?' "$yaml_file" 2>/dev/null) + + local count + count=$(yq '.renamed | length' "$yaml_file" 2>/dev/null) + if [[ "$count" =~ ^[0-9]+$ && "$count" -gt 0 ]]; then + local i + for ((i = 0; i < count; i++)); do + local old new + old=$(yq ".renamed[$i].old" "$yaml_file" 2>/dev/null) + new=$(yq ".renamed[$i].new" "$yaml_file" 2>/dev/null) + [[ -n "$old" && "$old" != "null" ]] && known_renamed["$old"]="$new" + done + fi + done + + # Classify each missing module + local mod + for mod in "${missing[@]}"; do + if [[ -n "${known_obsolete[$mod]:-}" ]]; then + addons_obsolete+=("$mod") + elif [[ -n "${known_core[$mod]:-}" ]]; then + addons_core+=("$mod") + elif [[ -n "${known_renamed[$mod]:-}" ]]; then + addons_renamed+=("${mod} -> ${known_renamed[$mod]}") + else + addons_truly_missing+=("$mod") + fi + done +} + export PROJECT_ROOT DATASTORE_PATH FILESTORE_SUBPATH export -f log_info log_warn log_error log_step confirm_or_exit export -f check_required_commands export -f query_postgres_container copy_database copy_filestore run_compose exec_python_script_in_odoo_shell +export -f classify_missing_addons diff --git a/scripts/prepare_db.sh b/scripts/prepare_db.sh index 76dc3d1..c8e5f0d 100755 --- a/scripts/prepare_db.sh +++ b/scripts/prepare_db.sh @@ -60,9 +60,31 @@ echo "Retrieve missing addons..." missing_addons=$(query_postgres_container "$SQL_MISSING_ADDONS" "$DB_NAME") log_step "ADD-ONS CHECK" -echo "Installed add-ons not available in final Odoo version:" -echo "$missing_addons" -confirm_or_exit "Do you accept to migrate with these add-ons still installed?" +classify_missing_addons "$missing_addons" + +if [[ ${#addons_obsolete[@]} -gt 0 ]]; then + log_info "Obsolete modules (${#addons_obsolete[@]}):" + printf "%s\n" "${addons_obsolete[@]}" + echo "" +fi +if [[ ${#addons_core[@]} -gt 0 ]]; then + log_info "Merged into Odoo Core (${#addons_core[@]}):" + printf "%s\n" "${addons_core[@]}" + echo "" +fi +if [[ ${#addons_renamed[@]} -gt 0 ]]; then + log_info "Renamed modules (${#addons_renamed[@]}):" + printf "%s\n" "${addons_renamed[@]}" + echo "" +fi +if [[ ${#addons_truly_missing[@]} -gt 0 ]]; then + log_warn "Truly missing modules (${#addons_truly_missing[@]}):" + printf "%s\n" "${addons_truly_missing[@]}" + echo "" + confirm_or_exit "Do you accept to migrate with these add-ons truly missing?" +else + log_info "No truly missing modules — all accounted for." +fi SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" PYTHON_SCRIPT="${SCRIPT_DIR}/lib/python/check_views.py" diff --git a/upgrade.sh b/upgrade.sh index 69a0921..0b2f7a2 100755 --- a/upgrade.sh +++ b/upgrade.sh @@ -31,8 +31,10 @@ fi check_required_commands -readonly ORIGIN_VERSION="$1" -readonly FINAL_VERSION="$2" +export ORIGIN_VERSION="$1" +readonly ORIGIN_VERSION +export FINAL_VERSION="$2" +readonly FINAL_VERSION readonly ORIGIN_DB_NAME="$3" readonly ORIGIN_SERVICE_NAME="$4" diff --git a/versions/13.0/known_changes.yaml b/versions/13.0/known_changes.yaml new file mode 100644 index 0000000..9a2252e --- /dev/null +++ b/versions/13.0/known_changes.yaml @@ -0,0 +1,10 @@ +# Modules that became obsolete in version 13.0 +obsolete: [] + +# Modules merged into Odoo Core in version 13.0 +merged_in_core: [] + +# Modules renamed in version 13.0 +renamed: [] +# - old: old_name +# new: new_name diff --git a/versions/14.0/known_changes.yaml b/versions/14.0/known_changes.yaml new file mode 100644 index 0000000..22d763f --- /dev/null +++ b/versions/14.0/known_changes.yaml @@ -0,0 +1,10 @@ +# Modules that became obsolete in version 14.0 +obsolete: [] + +# Modules merged into Odoo Core in version 14.0 +merged_in_core: [] + +# Modules renamed in version 14.0 +renamed: [] +# - old: old_name +# new: new_name diff --git a/versions/15.0/known_changes.yaml b/versions/15.0/known_changes.yaml new file mode 100644 index 0000000..2f2a3bb --- /dev/null +++ b/versions/15.0/known_changes.yaml @@ -0,0 +1,10 @@ +# Modules that became obsolete in version 15.0 +obsolete: [] + +# Modules merged into Odoo Core in version 15.0 +merged_in_core: [] + +# Modules renamed in version 15.0 +renamed: [] +# - old: old_name +# new: new_name diff --git a/versions/16.0/known_changes.yaml b/versions/16.0/known_changes.yaml new file mode 100644 index 0000000..0efaca1 --- /dev/null +++ b/versions/16.0/known_changes.yaml @@ -0,0 +1,10 @@ +# Modules that became obsolete in version 16.0 +obsolete: [] + +# Modules merged into Odoo Core in version 16.0 +merged_in_core: [] + +# Modules renamed in version 16.0 +renamed: [] +# - old: old_name +# new: new_name diff --git a/versions/17.0/known_changes.yaml b/versions/17.0/known_changes.yaml new file mode 100644 index 0000000..6d68470 --- /dev/null +++ b/versions/17.0/known_changes.yaml @@ -0,0 +1,10 @@ +# Modules that became obsolete in version 17.0 +obsolete: [] + +# Modules merged into Odoo Core in version 17.0 +merged_in_core: [] + +# Modules renamed in version 17.0 +renamed: [] +# - old: old_name +# new: new_name diff --git a/versions/18.0/known_changes.yaml b/versions/18.0/known_changes.yaml new file mode 100644 index 0000000..d7678ed --- /dev/null +++ b/versions/18.0/known_changes.yaml @@ -0,0 +1,10 @@ +# Modules that became obsolete in version 18.0 +obsolete: [] + +# Modules merged into Odoo Core in version 18.0 +merged_in_core: [] + +# Modules renamed in version 18.0 +renamed: [] +# - old: old_name +# new: new_name