#!/usr/bin/env bash set -euo pipefail ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" APPS_DIR="${ROOT_DIR}/docker_compose_applications" INVENTORY_FILE="${ROOT_DIR}/inventories/hetzner/host_vars/cit-docker-host.yaml" log() { printf '[add-service] %s\n' "$*" } die() { printf '[add-service] ERROR: %s\n' "$*" >&2 exit 1 } usage() { cat < [service-name] Examples: $(basename "$0") git@github.com:example/repo.git $(basename "$0") git@github.com:example/repo.git custom-name $(basename "$0") my-new-service When a GitHub SSH URI is provided, the repo is cloned into docker_compose_applications/ and the inventory is updated. When plain text is provided, a scaffold folder with a compose.yaml template is created and the inventory is updated. EOF exit 1 } require_cmd() { command -v "$1" >/dev/null 2>&1 || die "Missing required command: $1" } ensure_paths() { [ -d "$APPS_DIR" ] || mkdir -p "$APPS_DIR" [ -f "$INVENTORY_FILE" ] || die "services list $INVENTORY_FILE not found" } is_github_ssh_uri() { [[ "$1" =~ ^git@github\.com:.+\.git$ ]] } sanitize_name() { local raw="$1" local clean clean="$(printf '%s' "$raw" | tr '[:upper:]' '[:lower:]' | sed -E 's/[^a-z0-9]+/-/g; s/^-+//; s/-+$//; s/-+/-/g')" [ -n "$clean" ] || die "Service name resolved to empty after sanitizing" printf '%s' "$clean" } service_in_inventory() { local name="$1" grep -Eq "^[[:space:]]+- name: ${name}$" "$INVENTORY_FILE" } append_inventory_entry() { local name="$1" local dir_name="$2" if service_in_inventory "$name"; then die "Service '${name}' already present in inventory" fi { printf '\n - name: %s\n' "$name" printf ' files_directory: ../docker_compose_applications/%s\n' "$dir_name" } >>"$INVENTORY_FILE" log "Added '${name}' to inventory" } derive_name_from_uri() { local uri="$1" local repo="${uri##*/}" repo="${repo%.git}" sanitize_name "$repo" } clone_repo() { local uri="$1" local target_dir="$2" [ -e "$target_dir" ] && die "Target directory already exists: $target_dir" require_cmd git log "Cloning ${uri} into ${target_dir}" git clone --depth=1 "$uri" "$target_dir" } create_compose_template() { local dir="$1" local service_name="$2" local compose_path="${dir}/compose.yaml" [ -e "$compose_path" ] && die "compose.yaml already exists at ${compose_path}" cat >"$compose_path" <