Skip to content

Instantly share code, notes, and snippets.

@ponfertato
Created September 24, 2025 11:06
Show Gist options
  • Select an option

  • Save ponfertato/08b968a59a0ca97ca21a8199b55e3964 to your computer and use it in GitHub Desktop.

Select an option

Save ponfertato/08b968a59a0ca97ca21a8199b55e3964 to your computer and use it in GitHub Desktop.
#!/bin/bash
set -e
# Функция для выполнения docker compose команды в указанном каталоге,
# если найден файл compose.yaml или docker-compose.yaml
run_docker() {
local dir="$1"
local docker_cmd="$2"
if [ -f "${dir}/compose.yaml" ]; then
echo "Выполнение: docker compose -f ${dir}/compose.yaml ${docker_cmd}"
docker compose -f "${dir}/compose.yaml" ${docker_cmd}
elif [ -f "${dir}/docker-compose.yaml" ]; then
echo "Выполнение: docker compose -f ${dir}/docker-compose.yaml ${docker_cmd}"
docker compose -f "${dir}/docker-compose.yaml" ${docker_cmd}
else
echo "Файл compose.yaml или docker-compose.yaml не найден в ${dir} — пропуск..."
fi
}
# Функция для проверки, настроен ли upstream для git текущей ветки
upstream_exists() {
if git rev-parse --abbrev-ref --symbolic-full-name @{u} >/dev/null 2>&1; then
return 0
else
return 1
fi
}
# Функция выполнения git pull для каталога (подпапок второго уровня)
# Если upstream настроен, то делается git pull и обновляются подмодули,
# если в каталоге присутствует файл .gitmodules.
run_git() {
local dir="$1"
if [ -d "${dir}/.git" ]; then
echo "Обнаружен git репозиторий в ${dir}"
(
cd "$dir" || exit
if upstream_exists; then
echo "Выполнение: git pull в ${dir}"
git pull
if [ -f ".gitmodules" ]; then
echo "Обновление git submodules в ${dir}"
git submodule update --init --recursive
fi
else
echo "Upstream не настроен для текущей ветки в ${dir} — пропуск git pull"
fi
)
else
echo "Каталог ${dir} не является git репозиторием — пропуск git pull..."
fi
}
# Обход директорий до 2-х уровней вложенности.
# base_dir - базовый каталог (например, "./" с завершающим слешем)
# level - глубина обхода (1 или 2)
# docker_cmd- команда для docker compose
# need_git - "true", если для подпапок второго уровня необходимо выполнить git pull
traverse_dirs() {
local base_dir="$1"
local level="$2"
local docker_cmd="$3"
local need_git="$4"
# Обходим каталоги первого уровня
for dir in ${base_dir}*/; do
[ -d "$dir" ] || continue
dir="${dir%/}" # удаляем завершающий слеш
# Выполнение docker compose для первого уровня
run_docker "$dir" "${docker_cmd}"
if [ "$level" -ge 2 ]; then
# Подкаталоги (второй уровень)
for sub_dir in "${dir}/"*/; do
[ -d "$sub_dir" ] || continue
sub_dir="${sub_dir%/}"
# Если требуется git — выполняем git pull для подпапок
if [ "$need_git" == "true" ]; then
run_git "$sub_dir"
fi
run_docker "$sub_dir" "${docker_cmd}"
done
fi
done
}
# Функция отображения меню с упрощёнными названиями операций
show_menu() {
clear
echo "Доступные операции:"
echo "1. Down (docker compose down)"
echo "2. Up (docker compose up -d)"
echo "3. Pull (docker compose pull + git pull для подпапок)"
echo "4. Refresh (docker compose pull + docker compose up -d)"
echo "5. Full update (docker compose pull + git pull (для подпапок) + docker compose up -d)"
echo "6. Exit"
read -p "Введите номер операции: " option
}
while true; do
show_menu
case "$option" in
1)
# Down: docker compose down
read -p "Выполнить для (a) конкретного каталога или (b) для всех проектов? [a/b]: " choice
if [ "$choice" == "a" ]; then
read -p "Введите путь к проекту (без завершающего /): " proj_path
run_docker "$proj_path" "down"
else
traverse_dirs "./" 2 "down" "false"
fi
;;
2)
# Up: docker compose up -d
read -p "Выполнить для (a) конкретного каталога или (b) для всех проектов? [a/b]: " choice
if [ "$choice" == "a" ]; then
read -p "Введите путь к проекту (без завершающего /): " proj_path
run_docker "$proj_path" "up -d"
else
traverse_dirs "./" 2 "up -d" "false"
fi
;;
3)
# Pull: docker compose pull + git pull (для подпапок 2-го уровня)
read -p "Выполнить для (a) конкретного каталога или (b) для всех проектов? [a/b]: " choice
if [ "$choice" == "a" ]; then
read -p "Введите путь к проекту (без завершающего /): " proj_path
run_docker "$proj_path" "pull"
# Для подпапок второго уровня выполняем git pull
for sub_dir in "${proj_path}/"*/; do
[ -d "$sub_dir" ] || continue
sub_dir="${sub_dir%/}"
run_git "$sub_dir"
done
else
traverse_dirs "./" 2 "pull" "true"
fi
;;
4)
# Refresh: docker compose pull + docker compose up -d (без git)
read -p "Выполнить для (a) конкретного каталога или (b) для всех проектов? [a/b]: " choice
if [ "$choice" == "a" ]; then
read -p "Введите путь к проекту (без завершающего /): " proj_path
run_docker "$proj_path" "pull"
run_docker "$proj_path" "up -d"
else
traverse_dirs "./" 2 "pull" "false"
traverse_dirs "./" 2 "up -d" "false"
fi
;;
5)
# Full update: docker compose pull + git pull (подпапки 2-го уровня) + docker compose up -d
read -p "Выполнить для (a) конкретного каталога или (b) для всех проектов? [a/b]: " choice
if [ "$choice" == "a" ]; then
read -p "Введите путь к проекту (без завершающего /): " proj_path
run_docker "$proj_path" "pull"
for sub_dir in "${proj_path}/"*/; do
[ -d "$sub_dir" ] || continue
sub_dir="${sub_dir%/}"
run_git "$sub_dir"
done
run_docker "$proj_path" "up -d"
else
traverse_dirs "./" 2 "pull" "true"
traverse_dirs "./" 2 "up -d" "false"
fi
;;
6)
echo "Выход..."
exit 0
;;
*)
echo "Неверный выбор. Попробуйте снова."
;;
esac
echo "Нажмите Enter для продолжения..."
read
done
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment