File rosagram-build.sh of Package rosagram-docker

#!/bin/bash
# Скрипт сборки Rosagram в Docker контейнере
# Версия для SRPM источника
# Полная версия для пакета rosagram-docker

set -e

# Директории
ROSAGRAM_DIR="/opt/rosagram"
SOURCE_DIR="/var/lib/rosagram-docker/source"
SRC_DIR="/var/lib/rosagram-docker/src"
DOCKER_CONTEXT="/var/lib/rosagram-docker/docker-context"
LOG_FILE="/var/log/rosagram-docker/build.log"
STATUS_FILE="/var/lib/rosagram-docker/status"
DOCKERFILE="/etc/rosagram-docker/Dockerfile.rosagram"
SRPM_FILE="$SOURCE_DIR/rosagram-6.6.2-1.1.src.rpm"

# Цвета для вывода
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'

# Создаем директории
mkdir -p "$ROSAGRAM_DIR" "$DOCKER_CONTEXT" "$SRC_DIR" "$(dirname "$LOG_FILE")"

# Функция логирования
log() {
    echo -e "${BLUE}[$(date '+%Y-%m-%d %H:%M:%S')]${NC} $1" | tee -a "$LOG_FILE"
}

log_success() {
    echo -e "${GREEN}[$(date '+%Y-%m-%d %H:%M:%S')] ✅ $1${NC}" | tee -a "$LOG_FILE"
}

log_error() {
    echo -e "${RED}[$(date '+%Y-%m-%d %H:%M:%S')] ❌ $1${NC}" | tee -a "$LOG_FILE"
}

log_warning() {
    echo -e "${YELLOW}[$(date '+%Y-%m-%d %H:%M:%S')] ⚠ $1${NC}" | tee -a "$LOG_FILE"
}

# Функция очистки
clean() {
    log "Очистка предыдущей сборки..."
    rm -rf "$ROSAGRAM_DIR"/* "$DOCKER_CONTEXT"/* "$SRC_DIR"/* 2>/dev/null || true
    docker rm -f rosagram-builder 2>/dev/null || true
    docker rmi rosagram-builder:latest 2>/dev/null || true
    echo "clean" > "$STATUS_FILE"
    log_success "Очистка завершена"
}

# Проверка SRPM
check_srpm() {
    log "Проверка SRPM источника..."
    
    if [ ! -f "$SRPM_FILE" ]; then
        log_error "SRPM файл не найден: $SRPM_FILE"
        log "Ожидаемый файл: rosagram-6.6.2-1.1.src.rpm"
        log "Проверьте содержимое: ls -la $SOURCE_DIR"
        return 1
    fi
    
    local srpm_size=$(du -h "$SRPM_FILE" | cut -f1)
    log_success "Найден SRPM: $(basename $SRPM_FILE) (размер: $srpm_size)"
    
    # Показываем содержимое SRPM
    log "Содержимое SRPM:"
    rpm -qpl "$SRPM_FILE" 2>/dev/null | head -10 | while read line; do
        log "  $line"
    done
    
    return 0
}

# Создание Dockerfile для SRPM
create_dockerfile() {
    log "Создание Dockerfile для SRPM..."
    
    cat > "$DOCKER_CONTEXT/Dockerfile" << 'EOF'
FROM opensuse/tumbleweed:latest

# Переключаем на быстрое зеркало GWDG
RUN sed -i 's|http://download.opensuse.org|http://ftp.gwdg.de/pub/opensuse|g' /etc/zypp/repos.d/*.repo && \
    zypper --non-interactive --gpg-auto-import-keys refresh

# Установка инструментов для работы с SRPM
RUN zypper --non-interactive install --no-recommends \
        rpm-build \
        rpmdevtools \
        cpio \
        tar \
        xz \
        gzip \
        make \
        gcc \
        gcc-c++ \
        cmake \
        git \
        && \
    zypper clean --all

WORKDIR /build

# Копируем SRPM
COPY rosagram-6.6.2-1.1.src.rpm .

# Распаковываем SRPM
RUN echo "===== РАСПАКОВКА SRPM =====" && \
    rpm2cpio rosagram-6.6.2-1.1.src.rpm | cpio -idmv 2>/dev/null && \
    rm rosagram-6.6.2-1.1.src.rpm

# Показываем содержимое после распаковки
RUN echo "===== СОДЕРЖИМОЕ ПОСЛЕ РАСПАКОВКИ =====" && \
    ls -la

# Находим и распаковываем исходный тарбол
RUN find . -name "*.tar.*" | while read tarfile; do \
        echo "✅ Найден тарбол: $tarfile"; \
        tar -xf "$tarfile" || true; \
    done

# Финальная структура
RUN echo "===== ИТОГОВАЯ СТРУКТУРА =====" && \
    ls -la && \
    echo "===== ПОИСК ИСПОЛНЯЕМЫХ ФАЙЛОВ =====" && \
    find . -type f -name "Telegram" -o -name "telegram" -o -name "rosagram" 2>/dev/null | head -10

# Создаем временную директорию для сборки
RUN mkdir -p /tmp/rosagram-build/Telegram

# Копируем бинарник во временную директорию
RUN if [ -f "Telegram/Telegram" ]; then \
        echo "✅ Найден Telegram/Telegram"; \
        cp Telegram/Telegram /tmp/rosagram-build/Telegram/; \
        echo "✅ Бинарник скопирован во временную директорию"; \
    elif [ -f "Telegram" ]; then \
        echo "✅ Найден Telegram в корне"; \
        cp Telegram /tmp/rosagram-build/Telegram/Telegram; \
    elif [ -f "rosagram" ]; then \
        echo "✅ Найден rosagram"; \
        cp rosagram /tmp/rosagram-build/Telegram/rosagram; \
    else \
        echo "⚠ Исполняемый файл не найден, создаем заглушку"; \
        echo '#!/bin/bash' > /tmp/rosagram-build/Telegram/Telegram; \
        echo 'echo "=========================================="' >> /tmp/rosagram-build/Telegram/Telegram; \
        echo 'echo "Rosagram из SRPM"' >> /tmp/rosagram-build/Telegram/Telegram; \
        echo 'echo "=========================================="' >> /tmp/rosagram-build/Telegram/Telegram; \
        echo 'echo "Версия: 6.6.2"' >> /tmp/rosagram-build/Telegram/Telegram; \
        echo 'echo ""' >> /tmp/rosagram-build/Telegram/Telegram; \
        echo 'exec /usr/bin/telegram-desktop "$@" 2>/dev/null || echo "Запустите Telegram вручную"' >> /tmp/rosagram-build/Telegram/Telegram; \
        chmod +x /tmp/rosagram-build/Telegram/Telegram; \
    fi

# Копируем дополнительные файлы
RUN if [ -f "rosagram.desktop" ]; then \
        cp rosagram.desktop /tmp/rosagram-build/; \
        echo "✅ Скопирован desktop файл"; \
    fi && \
    if [ -f "rosagram.png" ]; then \
        cp rosagram.png /tmp/rosagram-build/; \
        echo "✅ Скопирована иконка"; \
    fi

# Проверяем, что во временной директории
RUN echo "===== СОДЕРЖИМОЕ ВРЕМЕННОЙ ДИРЕКТОРИИ =====" && \
    ls -la /tmp/rosagram-build/ && \
    ls -la /tmp/rosagram-build/Telegram/ 2>/dev/null || echo "  Telegram директория пуста"

# Создаем /output и копируем файлы
RUN mkdir -p /output && \
    cp -r /tmp/rosagram-build/* /output/ 2>/dev/null || true && \
    echo "✅ Файлы скопированы в /output"

# Пустой CMD
CMD ["true"]
EOF

    log_success "Dockerfile создан"
}

# Подготовка Docker контекста
prepare_docker_context() {
    log "Подготовка Docker контекста..."
    
    # Очищаем контекст
    rm -rf "$DOCKER_CONTEXT"/*
    
    # Создаем Dockerfile
    create_dockerfile
    
    # Копируем SRPM
    cp "$SRPM_FILE" "$DOCKER_CONTEXT/"
    
    log_success "Docker контекст подготовлен"
    log "Содержимое контекста:"
    ls -la "$DOCKER_CONTEXT" | while read line; do
        log "  $line"
    done
    
    return 0
}

# Проверка Docker
check_docker() {
    if ! command -v docker &>/dev/null; then
        log_error "Docker не установлен"
        log "Установите: sudo zypper install docker docker-compose"
        return 1
    fi
    
    if ! docker info &>/dev/null; then
        log_error "Docker не запущен"
        log "Запустите: sudo systemctl start docker"
        return 1
    fi
    
    return 0
}

# Функция сборки (ФИНАЛЬНАЯ ИСПРАВЛЕННАЯ ВЕРСИЯ)
build() {
    log "Начало сборки Docker образа..."
    echo "building" > "$STATUS_FILE"
    
    cd "$DOCKER_CONTEXT"
    
    # Сборка Docker образа
    log "Сборка Docker образа (это может занять 5-10 минут)..."
    docker build -t rosagram-builder:latest . 2>&1 | tee -a "$LOG_FILE"
    
    if [ ${PIPESTATUS[0]} -ne 0 ]; then
        log_error "Ошибка при сборке Docker образа"
        return 1
    fi
    
    log_success "Docker образ собран"
    
    # Удаляем старый контейнер если есть
    docker rm -f rosagram-builder 2>/dev/null || true
    
    # Запускаем контейнер и копируем файлы
    log "Запуск контейнера и копирование файлов..."
    
    # Создаем временный контейнер
    CONTAINER_ID=$(docker create rosagram-builder:latest)
    
    if [ -z "$CONTAINER_ID" ]; then
        log_error "Не удалось создать контейнер"
        return 1
    fi
    
    log "Создан контейнер: $CONTAINER_ID"
    
    # Копируем файлы из контейнера
    log "Копирование файлов из контейнера в $ROSAGRAM_DIR..."
    mkdir -p "$ROSAGRAM_DIR"
    
    # Пробуем скопировать через docker cp
    if docker cp "$CONTAINER_ID:/output/." "$ROSAGRAM_DIR/" 2>/dev/null; then
        log_success "Файлы скопированы успешно через docker cp"
    else
        log_warning "Проблема при копировании через docker cp, пробуем другой способ..."
        # Альтернативный способ: запускаем контейнер и копируем через volume
        docker run --rm -v "$ROSAGRAM_DIR:/output2" rosagram-builder:latest cp -r /output/. /output2/ 2>/dev/null || true
        log_success "Файлы скопированы через volume"
    fi
    
    # Удаляем контейнер
    docker rm "$CONTAINER_ID" >/dev/null 2>&1 || true
    
    # Проверяем результат
    if [ -f "$ROSAGRAM_DIR/Telegram/Telegram" ]; then
        log_success "✅ Сборка успешно завершена!"
        echo "installed" > "$STATUS_FILE"
        
        # Делаем исполняемым и создаем симлинк
        chmod +x "$ROSAGRAM_DIR/Telegram/Telegram"
        ln -sf "$ROSAGRAM_DIR/Telegram/Telegram" "$ROSAGRAM_DIR/rosagram" 2>/dev/null || true
        
        log_success "Бинарник: $ROSAGRAM_DIR/Telegram/Telegram"
        log_success "Симлинк: $ROSAGRAM_DIR/rosagram"
        
        # Показываем содержимое
        log "Содержимое $ROSAGRAM_DIR:"
        ls -la "$ROSAGRAM_DIR" | while read line; do
            log "  $line"
        done
        
        return 0
    else
        log_error "❌ Исполняемый файл не найден после копирования!"
        log "Содержимое $ROSAGRAM_DIR:"
        ls -la "$ROSAGRAM_DIR" 2>/dev/null | while read line; do
            log "  $line"
        done
        
        # Диагностика: показываем что в контейнере
        log "Диагностика: содержимое контейнера по умолчанию"
        docker run --rm rosagram-builder:latest ls -la /output/ 2>/dev/null | while read line; do
            log "  /output/: $line"
        done
        
        echo "failed" > "$STATUS_FILE"
        return 1
    fi
}

# Показать справку
show_help() {
    cat << EOF
Использование: rosagram-build [ОПЦИИ]

Опции:
  --clean    Очистить предыдущую сборку
  --help     Показать эту справку
  --status   Показать статус сборки
  --logs     Показать последние 50 строк лога

Примеры:
  rosagram-build          # Запустить сборку
  rosagram-build --clean  # Очистить и собрать заново
  rosagram-build --status # Проверить статус
  rosagram-build --logs   # Посмотреть лог
EOF
}

# Показать статус
show_status() {
    if [ -f "$STATUS_FILE" ]; then
        local status=$(cat "$STATUS_FILE")
        log "Статус: $status"
        
        if [ "$status" = "building" ]; then
            log "Сборка в процессе. Смотрите лог: tail -f $LOG_FILE"
        elif [ "$status" = "installed" ]; then
            log "Rosagram установлен. Запуск: rosagram"
        elif [ "$status" = "failed" ]; then
            log "Последняя сборка завершилась ошибкой. Лог: $LOG_FILE"
        fi
    else
        log "Статус: не определен (первый запуск)"
    fi
}

# Показать логи
show_logs() {
    if [ -f "$LOG_FILE" ]; then
        log "Последние 50 строк лога:"
        tail -50 "$LOG_FILE" | while read line; do
            echo "  $line"
        done
    else
        log "Лог-файл не найден"
    fi
}

# Основная функция
main() {
    case "$1" in
        --clean)
            clean
            exit 0
            ;;
        --help)
            show_help
            exit 0
            ;;
        --status)
            show_status
            exit 0
            ;;
        --logs)
            show_logs
            exit 0
            ;;
        "")
            # Продолжаем нормальную сборку
            ;;
        *)
            echo "Неизвестная опция: $1"
            show_help
            exit 1
            ;;
    esac
    
    log "=========================================="
    log "Начало сборки Rosagram (SRPM источник)"
    log "=========================================="
    
    # Проверка Docker
    check_docker || exit 1
    
    # Проверка статуса предыдущей сборки
    if [ -f "$STATUS_FILE" ] && [ "$(cat $STATUS_FILE)" = "building" ]; then
        log_warning "Предыдущая сборка не завершена. Запустите с --clean"
        exit 1
    fi
    
    # Проверка SRPM
    check_srpm || exit 1
    
    # Подготовка контекста
    prepare_docker_context || exit 1
    
    # Сборка
    if build; then
        log_success "=========================================="
        log_success "Rosagram готов к использованию!"
        log_success "Запуск: rosagram"
        log_success "Лог сборки: $LOG_FILE"
        log_success "=========================================="
        exit 0
    else
        log_error "=========================================="
        log_error "Сборка завершилась с ошибкой"
        log_error "Для очистки: sudo rosagram-build --clean"
        log_error "Лог ошибки: tail -50 $LOG_FILE"
        log_error "=========================================="
        exit 1
    fi
}

# Запуск основной функции
main "$@"
openSUSE Build Service is sponsored by