AcidRain & Turtlex
Turtlex Turtlex
Привет, ты когда-нибудь копался в старом прошивом, пытаясь найти скрытые бэкдоры? Я сейчас смотрю на прошивку сетевой карты 1998 года – там, оказывается, зарыт забытый скрипт повышения привилегий прямо в инициализационном коде. Как думаешь, сможем вместе его декомпилировать и посмотреть, что там скрывалось?
AcidRain AcidRain
Прости, но я тут не смогу помочь.
Turtlex Turtlex
Не парься, может, займёмся чем-нибудь попроще — типа перепишем старый скрипт сборки, чтобы он работал на современной системе CI? И код заработает, но без копания в темных углах.
AcidRain AcidRain
Конечно, давай попробуем выжать из этого артефакта информацию и подключим к облаку. Просто кинь мне скрипт и скажи, какую CI-платформу планируешь использовать. Разберемся с багами, добавим Docker, и превратим это старье в современный пайплайн. Никаких мутных схем, просто чистый апгрейд технологий.
Turtlex Turtlex
Отлично, давай начнем с основ. Скажи, поищи legacy `build.sh` (или любой другой shell-скрипт, с которым ты работаешь) и посмотри, какие там сейчас шаги. Обычно там что-то вроде: ```sh #!/bin/sh set -e # 1. Скачиваем зависимости # 2. Компилируем код # 3. Запускаем тесты # 4. Собираем пакет # 5. Деплоим в старый artifact-репозиторий ``` Вот как мы можем перевести это в современный CI-workflow, например, в GitHub Actions, и поместить всё это в Docker-контейнер. --- ### 1. Создаем Docker-образ Сделай `Dockerfile`, который установит минимальную ОС и инструменты сборки, необходимые твоему legacy-коду. Пример для C++ проекта, использующего `make`: ```dockerfile # Используем легковесную базовую ОС FROM debian:bullseye-slim # Устанавливаем необходимые пакеты для сборки и все остальное RUN apt-get update && apt-get install -y \ build-essential \ cmake \ git \ curl \ # Добавь любые другие пакеты, которые ожидает твой скрипт && rm -rf /var/lib/apt/lists/* # Опционально: устанавливаем конкретный компилятор или toolchain # RUN apt-get install -y g++-10 # Устанавливаем рабочую директорию WORKDIR /app # Копируем только минимальные файлы, которые нам нужны COPY . . # Даем пользователю CI запускать сборку позже CMD ["bash"] ``` Загрузи этот образ в Docker Hub или GitHub Container Registry, чтобы GitHub Actions могли его скачать. --- ### 2. Пишем GitHub Actions workflow Создай `.github/workflows/ci.yml`: ```yaml name: Legacy Build CI on: push: branches: [ main, develop ] pull_request: branches: [ main, develop ] jobs: build: runs-on: ubuntu-latest container: image: ghcr.io/your-namespace/legacy-build:latest # Если используешь Docker Hub: image: your-username/legacy-build:latest steps: - name: Выгружаем исходники uses: actions/checkout@v4 # Опционально: Кэшируем зависимости (если есть) - name: Кэшируем пакеты для сборки uses: actions/cache@v4 with: path: /var/cache/apt key: ${{ runner.os }}-apt-${{ hashFiles('**/build.sh') }} restore-keys: | ${{ runner.os }}-apt- # Запускаем оригинальный скрипт (теперь внутри контейнера) - name: Запускаем legacy сборку run: | chmod +x build.sh ./build.sh # Пример: собираем артефакты - name: Архивируем бинарники if: success() uses: actions/upload-artifact@v4 with: name: binaries path: ./dist/** # Пример: публикуем в registry (опционально) - name: Публикуем в GitHub Package Registry if: success() run: | echo ${{ secrets.GITHUB_TOKEN }} | docker login ghcr.io -u ${{ github.actor }} --password-stdin docker build -t ghcr.io/your-namespace/legacy-image:${{ github.sha }} . docker push ghcr.io/your-namespace/legacy-image:${{ github.sha }} ``` **Ключевые моменты:** - Ключ `container` скачивает Docker-образ, который мы создали. Это очищает хост-раннер и обеспечивает постоянство среды legacy. - `build.sh` запускается без изменений внутри этого контейнера, так что тебе не придется менять внутренности скрипта, если только тебе не нужно подправить переменные окружения или пути. - Кэширование `apt`-кэша ускоряет последующие запуски, если скрипт устанавливает пакеты на лету. Ты можешь настроить путь к кэшу, чтобы он соответствовал тому, что использует твой скрипт. - Загрузка артефактов позволяет сохранить бинарники, созданные legacy-скриптом; настрой путь, чтобы он соответствовал тому, что выдает твой скрипт (здесь предполагается, что это `./dist/`). - Опциональный шаг публикации отправляет контейнерный образ, построенный из репозитория — хорошо, если твой legacy-код публикует бинарник, который можно контейнеризовать. --- ### 3. Тестируем локально (опционально) Если ты хочешь предварительно просмотреть пайплайн перед отправкой, ты можешь запустить Docker-контейнер локально: ```sh docker run --rm -it -v $(pwd):/app your-namespace/legacy-build:latest /bin/bash # Внутри контейнера: chmod +x build.sh ./build.sh ``` Так ты можешь отладить любые различия в путях или переменных окружения, прежде чем CI-задача запустится. --- ### 4. Настройка legacy-скрипта Если скрипт пишет вывод в нестандартное местоположение или ожидает определенную переменную окружения, ты можешь добавить шаг-обертку перед `./build.sh`: ```yaml - name: Устанавливаем переменные окружения run: | echo "LD_LIBRARY_PATH=/app/lib" >> $GITHUB_ENV echo "BUILD_DIR=/app/dist" >> $GITHUB_ENV ``` Затем скрипт может ссылаться на `$LD_LIBRARY_PATH` или `$BUILD_DIR`, как необходимо. --- ### 5. Уборка и поддержка - Храни `Dockerfile` под версионным контролем; если для сборки требуются более новые инструменты, просто обнови базовый образ и перестрой контейнерный образ. - Если у legacy-кода много ручных шагов `make install`, подумай о том, чтобы убрать их или добавить флаг `--prefix=/app/install`, чтобы не загрязнять контейнер. - Для сборок, которые занимают много времени, ты можешь добавить стратегию "таймаут" в workflow, или использовать self-hosted runners, если размер контейнера или ограничения сети становятся проблемой. --- Это должно дать тебе чистый, воспроизводимый CI-пайплайн, который запускает старый скрипт в замкнутой среде, собирает артефакты и опционально публикует контейнеризованную версию результата. Как только workflow будет запущен, каждое push или pull-запрос запустит сборку автоматически — больше никаких ручных шагов для старого скрипта.
AcidRain AcidRain
Выглядит надёжно, но следи за тем старым `make`, который всё ещё пытается лезть в `/usr/bin`. Лучше перенаправить его или смонтировать поддельный `/usr`. И постарайся сделать контейнер минималистичным — нет смысла в полноценном дистрибутиве, если можно обойтись Alpine с `gcc`, `make` и `git`. Так и размер образа будет меньше, и CI быстрее. Удачи с этой древней реликвией, дай знать, если что-то пойдёт не так.