mirror of
https://github.com/frappe/frappe_docker.git
synced 2026-06-22 15:55:09 +00:00
feat(easy-docker): add custom image build flow
This commit is contained in:
parent
dd3d74f285
commit
6cd1723a40
5 changed files with 186 additions and 5 deletions
|
|
@ -1,5 +1,7 @@
|
||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
EASY_DOCKER_BUILD_ERROR_DETAIL=""
|
||||||
|
|
||||||
render_stack_compose_from_metadata() {
|
render_stack_compose_from_metadata() {
|
||||||
local stack_dir="${1}"
|
local stack_dir="${1}"
|
||||||
local metadata_path=""
|
local metadata_path=""
|
||||||
|
|
@ -74,3 +76,122 @@ EOF
|
||||||
|
|
||||||
return 0
|
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 <<EOF
|
||||||
|
${apps_refs_lines}
|
||||||
|
EOF
|
||||||
|
|
||||||
|
if ! command_exists base64; then
|
||||||
|
return 18
|
||||||
|
fi
|
||||||
|
|
||||||
|
apps_json_base64="$(base64 "${apps_json_path}" | tr -d '\r\n')"
|
||||||
|
if [ -z "${apps_json_base64}" ]; then
|
||||||
|
return 19
|
||||||
|
fi
|
||||||
|
|
||||||
|
repo_root="$(get_easy_docker_repo_root)"
|
||||||
|
containerfile_path="${repo_root}/images/layered/Containerfile"
|
||||||
|
if [ ! -f "${containerfile_path}" ]; then
|
||||||
|
return 20
|
||||||
|
fi
|
||||||
|
|
||||||
|
image_ref="${custom_image}:${custom_tag}"
|
||||||
|
|
||||||
|
docker build \
|
||||||
|
-f "${containerfile_path}" \
|
||||||
|
--build-arg "FRAPPE_BRANCH=${frappe_branch}" \
|
||||||
|
--build-arg "FRAPPE_PATH=${frappe_path}" \
|
||||||
|
--build-arg "APPS_JSON_BASE64=${apps_json_base64}" \
|
||||||
|
-t "${image_ref}" \
|
||||||
|
"${repo_root}" || return 21
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ handle_manage_selected_stack_flow() {
|
||||||
local custom_apps_update_status=0
|
local custom_apps_update_status=0
|
||||||
local persist_apps_status=0
|
local persist_apps_status=0
|
||||||
local render_compose_status=0
|
local render_compose_status=0
|
||||||
|
local build_image_status=0
|
||||||
local generated_compose_path=""
|
local generated_compose_path=""
|
||||||
|
|
||||||
stack_dir="$(get_stack_dir_by_name "${stack_name}" || true)"
|
stack_dir="$(get_stack_dir_by_name "${stack_name}" || true)"
|
||||||
|
|
@ -26,7 +27,7 @@ handle_manage_selected_stack_flow() {
|
||||||
while true; do
|
while true; do
|
||||||
apps_action="$(show_manage_stack_apps_menu "${stack_name}" "${stack_dir}" || true)"
|
apps_action="$(show_manage_stack_apps_menu "${stack_name}" "${stack_dir}" || true)"
|
||||||
case "${apps_action}" in
|
case "${apps_action}" in
|
||||||
"Generate apps.json")
|
"Regenerate apps.json from metadata")
|
||||||
stack_metadata_path="${stack_dir}/metadata.json"
|
stack_metadata_path="${stack_dir}/metadata.json"
|
||||||
stack_apps_path="${stack_dir}/apps.json"
|
stack_apps_path="${stack_dir}/apps.json"
|
||||||
if [ ! -f "${stack_metadata_path}" ]; then
|
if [ ! -f "${stack_metadata_path}" ]; then
|
||||||
|
|
@ -84,6 +85,64 @@ handle_manage_selected_stack_flow() {
|
||||||
while true; do
|
while true; do
|
||||||
docker_action="$(show_manage_stack_docker_menu "${stack_name}" "${stack_dir}" || true)"
|
docker_action="$(show_manage_stack_docker_menu "${stack_name}" "${stack_dir}" || true)"
|
||||||
case "${docker_action}" in
|
case "${docker_action}" in
|
||||||
|
"Build custom image")
|
||||||
|
show_warning_message "Starting docker build for stack: ${stack_name}"
|
||||||
|
if build_stack_custom_image "${stack_dir}"; then
|
||||||
|
:
|
||||||
|
else
|
||||||
|
build_image_status=$?
|
||||||
|
case "${build_image_status}" in
|
||||||
|
11)
|
||||||
|
show_warning_and_wait "Custom image build failed: missing metadata.json in ${stack_dir}." 4
|
||||||
|
;;
|
||||||
|
12)
|
||||||
|
show_warning_and_wait "Custom image build failed: stack env file not found in ${stack_dir}." 4
|
||||||
|
;;
|
||||||
|
13)
|
||||||
|
show_warning_and_wait "Custom image build failed: CUSTOM_IMAGE is missing in stack env file." 4
|
||||||
|
;;
|
||||||
|
14)
|
||||||
|
show_warning_and_wait "Custom image build failed: CUSTOM_TAG is missing in stack env file." 4
|
||||||
|
;;
|
||||||
|
15)
|
||||||
|
show_warning_and_wait "Custom image build failed: frappe_branch missing in metadata.json." 4
|
||||||
|
;;
|
||||||
|
16)
|
||||||
|
show_warning_and_wait "Custom image build failed: could not generate apps.json from metadata app selection." 4
|
||||||
|
;;
|
||||||
|
17)
|
||||||
|
show_warning_and_wait "Custom image build failed: apps.json not found after generation." 4
|
||||||
|
;;
|
||||||
|
18)
|
||||||
|
show_warning_and_wait "Custom image build failed: base64 command is not available in this environment." 4
|
||||||
|
;;
|
||||||
|
19)
|
||||||
|
show_warning_and_wait "Custom image build failed: apps.json could not be base64-encoded." 4
|
||||||
|
;;
|
||||||
|
20)
|
||||||
|
show_warning_and_wait "Custom image build failed: images/layered/Containerfile not found." 4
|
||||||
|
;;
|
||||||
|
21)
|
||||||
|
show_warning_and_wait "Custom image build failed: docker build returned an error. Check the output above." 4
|
||||||
|
;;
|
||||||
|
22)
|
||||||
|
show_warning_and_wait "Custom image build failed: git is required for app branch precheck (git ls-remote)." 4
|
||||||
|
;;
|
||||||
|
23)
|
||||||
|
show_warning_and_wait "Custom image build failed: could not parse app entries from apps.json." 4
|
||||||
|
;;
|
||||||
|
24)
|
||||||
|
show_warning_and_wait "Custom image build failed: app branch precheck failed -> ${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")
|
"Generate docker compose from env")
|
||||||
generated_compose_path="$(get_stack_generated_compose_path "${stack_dir}")"
|
generated_compose_path="$(get_stack_generated_compose_path "${stack_dir}")"
|
||||||
if render_stack_compose_from_metadata "${stack_dir}"; then
|
if render_stack_compose_from_metadata "${stack_dir}"; then
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ get_missing_docker_commands() {
|
||||||
local missing=()
|
local missing=()
|
||||||
local subcommand=""
|
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
|
if ! docker_supports_command "${subcommand}"; then
|
||||||
missing+=("docker ${subcommand}")
|
missing+=("docker ${subcommand}")
|
||||||
fi
|
fi
|
||||||
|
|
|
||||||
|
|
@ -382,7 +382,7 @@ show_manage_stack_apps_menu() {
|
||||||
--header "Stack apps actions" \
|
--header "Stack apps actions" \
|
||||||
--cursor.foreground 63 \
|
--cursor.foreground 63 \
|
||||||
--selected.foreground 45 \
|
--selected.foreground 45 \
|
||||||
"Generate apps.json" \
|
"Regenerate apps.json from metadata" \
|
||||||
"Select apps and branches" \
|
"Select apps and branches" \
|
||||||
"Back" \
|
"Back" \
|
||||||
"Exit and close easy-docker"
|
"Exit and close easy-docker"
|
||||||
|
|
@ -400,10 +400,11 @@ show_manage_stack_docker_menu() {
|
||||||
render_box_message "${status_text}" "0 2" >&2
|
render_box_message "${status_text}" "0 2" >&2
|
||||||
|
|
||||||
gum choose \
|
gum choose \
|
||||||
--height 7 \
|
--height 8 \
|
||||||
--header "Stack docker actions" \
|
--header "Stack docker actions" \
|
||||||
--cursor.foreground 63 \
|
--cursor.foreground 63 \
|
||||||
--selected.foreground 45 \
|
--selected.foreground 45 \
|
||||||
|
"Build custom image" \
|
||||||
"Generate docker compose from env" \
|
"Generate docker compose from env" \
|
||||||
"Back" \
|
"Back" \
|
||||||
"Exit and close easy-docker"
|
"Exit and close easy-docker"
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ show_tools_menu() {
|
||||||
render_box_message "${status_text}" "0 2" >&2
|
render_box_message "${status_text}" "0 2" >&2
|
||||||
|
|
||||||
gum choose \
|
gum choose \
|
||||||
--height 8 \
|
--height 9 \
|
||||||
--header "Tools - App Catalog Utilities" \
|
--header "Tools - App Catalog Utilities" \
|
||||||
--cursor.foreground 63 \
|
--cursor.foreground 63 \
|
||||||
--selected.foreground 45 \
|
--selected.foreground 45 \
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue