#!/usr/bin/env bash EASY_DOCKER_BUILD_ERROR_DETAIL="" render_stack_compose_from_metadata() { local stack_dir="${1}" local metadata_path="" local env_path="" local generated_compose_path="" local generated_compose_tmp_path="" local compose_files_lines="" local compose_file="" local source_compose_path="" local env_erpnext_version="" local fallback_erpnext_version="" local repo_root="" local -a compose_args=() metadata_path="${stack_dir}/metadata.json" env_path="$(get_stack_env_path "${stack_dir}")" generated_compose_path="$(get_stack_generated_compose_path "${stack_dir}")" generated_compose_tmp_path="${generated_compose_path}.tmp" if [ ! -f "${metadata_path}" ]; then return 1 fi if [ ! -f "${env_path}" ]; then return 1 fi env_erpnext_version="$(get_env_file_key_value "${env_path}" "ERPNEXT_VERSION" || true)" if [ -z "${env_erpnext_version}" ]; then fallback_erpnext_version="$(get_default_erpnext_version || true)" fi compose_files_lines="$(get_metadata_compose_files_lines "${metadata_path}" || true)" if [ -z "${compose_files_lines}" ]; then return 1 fi repo_root="$(get_easy_docker_repo_root)" while IFS= read -r compose_file; do if [ -z "${compose_file}" ]; then continue fi source_compose_path="${repo_root}/${compose_file}" if [ ! -f "${source_compose_path}" ]; then return 1 fi compose_args+=(-f "${source_compose_path}") done <"${generated_compose_tmp_path}"; then rm -f -- "${generated_compose_tmp_path}" >/dev/null 2>&1 || true return 1 fi elif ! docker compose --env-file "${env_path}" "${compose_args[@]}" config >"${generated_compose_tmp_path}"; then rm -f -- "${generated_compose_tmp_path}" >/dev/null 2>&1 || true return 1 fi if ! mv -- "${generated_compose_tmp_path}" "${generated_compose_path}"; then rm -f -- "${generated_compose_tmp_path}" >/dev/null 2>&1 || true return 1 fi return 0 } build_stack_custom_image() { local stack_dir="${1}" local metadata_path="" local env_path="" local apps_json_path="" local custom_image="" local custom_tag="" local frappe_branch="" local frappe_path="https://github.com/frappe/frappe" local repo_root="" local containerfile_path="" local apps_json_base64="" local apps_refs_lines="" local app_ref_line="" local app_url="" local app_branch="" local git_error="" local image_ref="" EASY_DOCKER_BUILD_ERROR_DETAIL="" metadata_path="${stack_dir}/metadata.json" env_path="$(get_stack_env_path "${stack_dir}")" apps_json_path="${stack_dir}/apps.json" if [ ! -f "${metadata_path}" ]; then return 11 fi if [ ! -f "${env_path}" ]; then return 12 fi custom_image="$(get_env_file_key_value "${env_path}" "CUSTOM_IMAGE" || true)" custom_tag="$(get_env_file_key_value "${env_path}" "CUSTOM_TAG" || true)" frappe_branch="$(get_stack_frappe_branch "${stack_dir}" || true)" if [ -z "${custom_image}" ]; then return 13 fi if [ -z "${custom_tag}" ]; then return 14 fi if [ -z "${frappe_branch}" ]; then return 15 fi # Keep apps.json aligned with current metadata app selection before build. if ! persist_stack_apps_json_from_metadata_apps "${stack_dir}"; then return 16 fi if [ ! -f "${apps_json_path}" ]; then return 17 fi if ! command_exists git; then return 22 fi apps_refs_lines="$( awk ' match($0, /"url"[[:space:]]*:[[:space:]]*"([^"]+)"/, url_parts) && match($0, /"branch"[[:space:]]*:[[:space:]]*"([^"]+)"/, branch_parts) { print url_parts[1] "|" branch_parts[1] } ' "${apps_json_path}" )" if [ -z "${apps_refs_lines}" ]; then return 23 fi while IFS= read -r app_ref_line; do if [ -z "${app_ref_line}" ]; then continue fi app_url="${app_ref_line%%|*}" app_branch="${app_ref_line#*|}" if [ -z "${app_url}" ] || [ -z "${app_branch}" ]; then continue fi if git_error="$(git ls-remote --exit-code --heads "${app_url}" "${app_branch}" 2>&1)"; then : else # shellcheck disable=SC2034 # Read by manage flow after build_stack_custom_image returns 24. EASY_DOCKER_BUILD_ERROR_DETAIL="$(printf '%s@%s :: %s' "${app_url}" "${app_branch}" "${git_error}")" return 24 fi done <