diff --git a/scripts/easy-docker/lib/app/wizard/common/compose.sh b/scripts/easy-docker/lib/app/wizard/common/compose.sh index b6691146..ec5def28 100755 --- a/scripts/easy-docker/lib/app/wizard/common/compose.sh +++ b/scripts/easy-docker/lib/app/wizard/common/compose.sh @@ -1,5 +1,7 @@ #!/usr/bin/env bash +EASY_DOCKER_BUILD_ERROR_DETAIL="" + render_stack_compose_from_metadata() { local stack_dir="${1}" local metadata_path="" @@ -74,3 +76,122 @@ EOF 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 < ${EASY_DOCKER_BUILD_ERROR_DETAIL}" 6 + ;; + *) + show_warning_and_wait "Custom image build failed (${build_image_status})." 4 + ;; + esac + continue + fi + + show_warning_and_wait "Custom image build finished successfully for stack: ${stack_name}" 3 + ;; "Generate docker compose from env") generated_compose_path="$(get_stack_generated_compose_path "${stack_dir}")" if render_stack_compose_from_metadata "${stack_dir}"; then diff --git a/scripts/easy-docker/lib/checks/docker.sh b/scripts/easy-docker/lib/checks/docker.sh index 1b703f7f..33ebb826 100755 --- a/scripts/easy-docker/lib/checks/docker.sh +++ b/scripts/easy-docker/lib/checks/docker.sh @@ -16,7 +16,7 @@ get_missing_docker_commands() { local missing=() local subcommand="" - for subcommand in ps exec inspect cp; do + for subcommand in ps exec inspect cp build; do if ! docker_supports_command "${subcommand}"; then missing+=("docker ${subcommand}") fi diff --git a/scripts/easy-docker/lib/ui/screens/production.sh b/scripts/easy-docker/lib/ui/screens/production.sh index a28df88d..4c1d3ade 100755 --- a/scripts/easy-docker/lib/ui/screens/production.sh +++ b/scripts/easy-docker/lib/ui/screens/production.sh @@ -382,7 +382,7 @@ show_manage_stack_apps_menu() { --header "Stack apps actions" \ --cursor.foreground 63 \ --selected.foreground 45 \ - "Generate apps.json" \ + "Regenerate apps.json from metadata" \ "Select apps and branches" \ "Back" \ "Exit and close easy-docker" @@ -400,10 +400,11 @@ show_manage_stack_docker_menu() { render_box_message "${status_text}" "0 2" >&2 gum choose \ - --height 7 \ + --height 8 \ --header "Stack docker actions" \ --cursor.foreground 63 \ --selected.foreground 45 \ + "Build custom image" \ "Generate docker compose from env" \ "Back" \ "Exit and close easy-docker" diff --git a/scripts/easy-docker/lib/ui/screens/tools.sh b/scripts/easy-docker/lib/ui/screens/tools.sh index d6d94711..4a22a7f2 100755 --- a/scripts/easy-docker/lib/ui/screens/tools.sh +++ b/scripts/easy-docker/lib/ui/screens/tools.sh @@ -9,7 +9,7 @@ show_tools_menu() { render_box_message "${status_text}" "0 2" >&2 gum choose \ - --height 8 \ + --height 9 \ --header "Tools - App Catalog Utilities" \ --cursor.foreground 63 \ --selected.foreground 45 \