commit 1637cbdd9642069102218731a43ae5de771302f7 Author: Alexander Zhirov Date: Wed Apr 23 22:41:05 2025 +0300 init diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..efd3789 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,14 @@ +FROM alpine:3.21.3 + +LABEL maintainer="Alexander Zhirov " + +COPY deploy /usr/bin/deploy + +RUN < /etc/apk/repositories + echo "http://mirror.yandex.ru/mirrors/alpine/edge/community" >> /etc/apk/repositories + apk update + apk upgrade --no-cache + apk add --no-cache hugo rsync wget nodejs npm git openssh-client + wget -O - https://github.com/CloudCannon/pagefind/releases/download/v1.3.0/pagefind-v1.3.0-x86_64-unknown-linux-musl.tar.gz | tar -xz -C /usr/bin +EOF diff --git a/README.md b/README.md new file mode 100644 index 0000000..e52a14c --- /dev/null +++ b/README.md @@ -0,0 +1,3 @@ +# Hugo Builder + +Сборка Hugo блога diff --git a/build.sh b/build.sh new file mode 100644 index 0000000..395a1b3 --- /dev/null +++ b/build.sh @@ -0,0 +1,137 @@ +#!/bin/sh + +usage() { + echo "✏️ Использование: $0 -n <имя> -v <версия> [-a <адрес>] [-p <порт>] [-r]" + echo "🔧 Опции:" + echo " -n, --name Имя образа (обязательно)" + echo " -v, --version Версия образа в формате X.Y.Z (обязательно)" + echo " -a, --address Адрес registry (требуется с -r)" + echo " -p, --port Порт registry (опционально)" + echo " -r, --push-to-registry Создать теги и отправить образы в registry" + echo "" + echo "📌 Примеры:" + echo " Только сборка: $0 -n myapp -v 2.5.7" + echo " Сборка и отправка: $0 -n myapp -v 2.5.7 -a registry.example.com -p 5000 -r" + exit 1 +} + +validate_version() { + echo "$1" | grep -Eq '^[0-9]+\.[0-9]+\.[0-9]+$' || { + echo "❌ Ошибка: Версия должна быть в формате X.Y.Z (например, 2.5.7)" + exit 1 + } +} + +validate_address() { + if [ -z "$1" ]; then + echo "❌ Ошибка: Адрес не может быть пустым" + exit 1 + fi +} + +validate_port() { + if [ -n "$1" ]; then + echo "$1" | grep -Eq '^[0-9]+$' || { + echo "❌ Ошибка: Порт должен быть числом" + exit 1 + } + fi +} + +push_to_registry=false +name="" +version="" +address="" +port="" + +while getopts ":n:v:a:p:r" opt; do + case $opt in + n) name="$OPTARG" ;; + v) version="$OPTARG" ;; + a) address="$OPTARG" ;; + p) port="$OPTARG" ;; + r) push_to_registry=true ;; + \?) echo "❌ Неверный аргумент -$OPTARG" >&2; usage ;; + :) echo "❌ Опция -$OPTARG требует аргумент" >&2; usage ;; + esac +done + +if [ -z "$name" ] || [ -z "$version" ]; then + echo "❌ Ошибка: Не указаны обязательные аргументы (-n и -v)" + usage +fi + +validate_version "$version" + +if [ "$push_to_registry" = true ]; then + if [ -z "$address" ]; then + echo "❌ Ошибка: Для отправки в registry необходимо указать адрес (-a)" + usage + fi + + validate_address "$address" + validate_port "$port" +fi + +echo "🐳 Сборка образа $name:$version..." +docker build . -t "${name}:${version}" || { + echo "❌ Ошибка при сборке образа" + exit 1 +} + +if [ "$push_to_registry" = true ]; then + if [ -z "$port" ]; then + registry="$address" + else + registry="$address:$port" + fi + + echo "🏷 Создание тегов для registry..." + + docker tag "${name}:${version}" "${registry}/${name}:latest" || { + echo "❌ Ошибка при создании тега latest" + exit 1 + } + + major=$(echo "$version" | cut -d. -f1) + minor=$(echo "$version" | cut -d. -f1-2) + full="$version" + + docker tag "${name}:${version}" "${registry}/${name}:$full" || { + echo "❌ Ошибка при создании тега $full" + exit 1 + } + docker tag "${name}:${version}" "${registry}/${name}:$minor" || { + echo "❌ Ошибка при создании тега $minor" + exit 1 + } + docker tag "${name}:${version}" "${registry}/${name}:$major" || { + echo "❌ Ошибка при создании тега $major" + exit 1 + } + + echo " ✅ Созданы теги: latest, $full, $minor, $major" + + echo "🚀 Отправка образов в registry..." + docker push "${registry}/${name}:latest" || { + echo "❌ Ошибка при отправке тега latest" + exit 1 + } + docker push "${registry}/${name}:$full" || { + echo "❌ Ошибка при отправке тега $full" + exit 1 + } + docker push "${registry}/${name}:$minor" || { + echo "❌ Ошибка при отправке тега $minor" + exit 1 + } + docker push "${registry}/${name}:$major" || { + echo "❌ Ошибка при отправке тега $major" + exit 1 + } +fi + +echo "🎉 Готово! Образ ${name}:${version} успешно:" +echo " ✅ Собран" +[ "$push_to_registry" = true ] && echo " ✅ Размечен" +[ "$push_to_registry" = true ] && echo " ✅ Отправлен в registry" diff --git a/deploy b/deploy new file mode 100755 index 0000000..cb9d476 --- /dev/null +++ b/deploy @@ -0,0 +1,77 @@ +#!/bin/sh + +# Парсинг аргументов командной строки +while [ $# -gt 0 ]; do + case $1 in + --ssh-host) SSH_HOST="$2"; shift 2 ;; + --ssh-port) SSH_PORT="$2"; shift 2 ;; + --ssh-user) SSH_USER="$2"; shift 2 ;; + --deploy-path) DEPLOY_PATH="$2"; shift 2 ;; + --private-key) USER_PRIVATE_KEY="$2"; shift 2 ;; + *) echo "❌ Ошибка: Неизвестный параметр: $1"; exit 1 ;; + esac +done + +# Функция для проверки наличия аргумента +check_arg() { + arg_name="$1" + arg_value="$2" + if [ -z "$arg_value" ]; then + echo "❌ Ошибка: Не указан обязательный параметр --$arg_name" + exit 1 + fi +} + +# Проверка каждого аргумента отдельно +check_arg "ssh-host" "$SSH_HOST" +check_arg "ssh-user" "$SSH_USER" +check_arg "deploy-path" "$DEPLOY_PATH" +check_arg "private-key" "$USER_PRIVATE_KEY" + +# Проверка формата SSH-порта (если указан) +if [ -n "$SSH_PORT" ]; then + if ! echo "$SSH_PORT" | grep -Eq '^[0-9]+$' || [ "$SSH_PORT" -lt 1 ] || [ "$SSH_PORT" -gt 65535 ]; then + echo "❌ Ошибка: Порт должен быть числом от 1 до 65535" + exit 1 + fi +else + SSH_PORT=22 # Значение по умолчанию +fi + +# Проверка формата приватного ключа +if ! echo "$USER_PRIVATE_KEY" | grep -q "PRIVATE KEY"; then + echo "❌ Ошибка: Указанный приватный ключ не содержит 'PRIVATE KEY' (возможно, некорректный формат)" + exit 1 +fi + +# Создаем папку .ssh, если её нет +mkdir -p ~/.ssh +chmod 700 ~/.ssh + +# Сохраняем приватный ключ +echo "$USER_PRIVATE_KEY" > ~/.ssh/id_rsa +chmod 600 ~/.ssh/id_rsa + +# Добавляем хост в known_hosts +echo "🔑 Добавляем $SSH_HOST в known_hosts..." +ssh-keyscan -p "$SSH_PORT" -H "$SSH_HOST" > ~/.ssh/known_hosts 2>/dev/null || { + echo "❌ Ошибка: Не удалось добавить хост $SSH_HOST в known_hosts" + exit 1 +} + +# Запускаем ssh-agent и добавляем ключ +echo "🔐 Запускаем ssh-agent..." +eval "$(ssh-agent -s)" >/dev/null +ssh-add ~/.ssh/id_rsa 2>/dev/null || { + echo "❌ Ошибка: Не удалось добавить SSH-ключ в агент (проверьте ключ и пароль)" + exit 1 +} + +# Деплой через rsync +echo "🚀 Начинаем деплой в $SSH_USER@$SSH_HOST:$DEPLOY_PATH..." +rsync -avz --progress -e "ssh -p $SSH_PORT -i ~/.ssh/id_rsa" public/ "$SSH_USER@$SSH_HOST:$DEPLOY_PATH" || { + echo "❌ Ошибка: Деплой не удался (проверьте путь, права или подключение)" + exit 1 +} + +echo "✅ Деплой успешно завершен!"