rzaripov.kz

Настройка CI/CD для Delphi-проекта с GitLab CI

Автоматизация сборки и проверок помогает обнаруживать ошибки до ручной проверки кода и ускоряет выпуск приложений. Для Delphi-проектов это особенно актуально, когда одна кодовая база поддерживает Windows, macOS, Linux, Android и iOS. GitLab CI позволяет объединить компиляцию, тестирование, формирование установщиков и публикацию релизов в едином воспроизводимом процессе.

Я Равиль Зарипов, разработчик из Алматы. В своих проектах работаю с Delphi и FireMonkey, дополняю мобильные части Kotlin и Swift, а серверные компоненты связываю с PHP и базами данных. Для межплатформенных команд основой служит автоматизация: одинаковые правила сборки, проверок и поставки артефактов уменьшают зависимость результата от конкретного компьютера разработчика.

Подготовка репозитория и сборки

Рабочий конвейер начинается с подготовки репозитория. Файлы проекта .dproj и .dpr, параметры подключения ресурсов, каталоги модулей и сценарии сборки должны находиться под контролем версий. Локальные пути, персональные настройки IDE и результаты компиляции лучше исключить из индекса. Это предотвращает ситуации, когда проект собирается у одного разработчика, но сразу ломается у другого.

Отдельно стоит организовать тесты. Для модульной логики подходит DUnitX или другой совместимый фреймворк: тесты получают отдельный проект без графического интерфейса и запускаются в консольном режиме. Проверки должны завершаться ненулевым кодом при ошибке, а результаты сохраняться в формате JUnit. Такой отчёт GitLab показывает прямо в интерфейсе задания и позволяет сравнивать результаты разных запусков.

Стратегию сборки необходимо определить до создания YAML-файла. Консольные тесты можно выполнять через dcc64 на Linux, тогда как полноценные настольные приложения и мобильные компоненты требуют MSBuild, RAD Studio, Android SDK или Xcode. Конфигурации Debug и Release имеют разные параметры оптимизации и подписи. Сборку релизных артефактов следует отделять от повседневных проверок и запускать только для защищённых веток и тегов.

Раннеры, секреты и воспроизводимость

GitLab Runner выполняет задания на выделенных машинах или в контейнерах. Для Linux обычно применяют shell- или Docker-executor, фиксируя версию образа с компилятором и системными библиотеками. Windows-проекты требуют раннера с установленным MSBuild, а сборка под Apple выполняется на macOS с Xcode. Общие раннеры удобны для проверок, но производственные задания лучше закрепить за защищёнными узлами.

Секреты нельзя хранить в .gitlab-ci.yml или коммитить вместе с проектом. Сертификаты, пароли баз данных и ключи подписи передаются через защищённые и замаскированные переменные GitLab либо через файловые переменные с ограниченным доступом. Для каждого окружения нужны отдельные учётные данные. Доступ к выпуску ограничивают правилами веток и тегов, а срок действия сертификатов контролируют заранее, чтобы истекающий ключ не остановил релиз.

При интеграции с существующим серверным кодом полезно заранее разделять ответственность между Delphi-клиентом и PHP-сервисами. Подходы к последовательному обновлению legacy-кода описаны в моём материале практический опыт рефакторинга. Контракт между клиентом и сервером фиксируют версией API, а изменение формата данных проверяют совместимыми примерами. Это снижает риск регрессий при автоматическом обновлении одной из частей системы.

Проверки, артефакты и публикация

Каждое задание GitLab CI описывается в .gitlab-ci.yml. Стадии отражают последовательность работ: сначала проверка, затем сборка и только после успешного результата подготовка релизных файлов. Пример базовой конфигурации выглядит так:

stages:
  - verify
  - build

variables:
  GIT_DEPTH: "20"

verify:
  stage: verify
  tags:
    - linux
  script:
    - dcc64 -B -Q -U"units" Tests/UnitTests.dpr
    - ./scripts/publish-coverage.sh reports/coverage.xml
  artifacts:
    when: always
    paths:
      - reports/
    reports:
      junit: reports/junit.xml

build:
  stage: build
  tags:
    - windows
  script:
    - msbuild Client.dproj /t:Build /p:Configuration=Release /p:Platform=Win64
    - powershell -File scripts/package.ps1
  artifacts:
    paths:
      - dist/
    expire_in: 7 days

В примере тестовый проект компилируется консольным компилятором, а скрипт формирует отчёты покрытия и JUnit. Пути и названия параметров необходимо привести к структуре конкретного репозитория. Сборщик создаёт дистрибутив и помещает его в артефакты задания, откуда его можно скачать без доступа к рабочей машине.

Один универсальный раннер редко покрывает все требования проекта, поэтому среды разделяют по целям:

Задача Среда выполнения Полученный результат
Юнит-тесты ядра Linux с shell или Docker Отчёт JUnit и покрытие
Сборка Windows Windows с MSBuild EXE, DLL и установщик
Сборка Android Linux с Android SDK APK или AAB
Сборка iOS и macOS macOS с Xcode IPA, DMG и подписанное приложение

Базы данных, релизы и откат

После успешной сборки готовые файлы публикуют в реестре пакетов GitLab или привязывают к релизу. Каждому тегу версии соответствует неизменяемый набор артефактов, созданный из определённого коммита. В описание включают краткие изменения, условия обновления и контрольные суммы. Хранение нескольких версий позволяет восстановить предыдущий выпуск без повторной компиляции на нестабильном окружении.

Миграции баз данных помещают в репозиторий и выполняют отдельным заданием. Для PostgreSQL или MySQL используют нумерованные SQL-файлы и служебную таблицу с уже применёнными версиями. Обновление схемы желательно строить по схеме расширения: сначала добавляются новые элементы, затем приложение переводится на них, и только на следующем этапе удаляются устаревшие. Удаляющие миграции требуют отдельного подтверждения, резервной копии и проверки совместимости.

Развёртывание на тестовый и production-контур разделяют переменными окружения и ручными подтверждениями. Механизм resource_group не допускает параллельного обновления одного сервиса, а environment связывает задание с конкретным контуром и показывает его состояние. Если проверка после публикации не проходит, приложение возвращают на прежнюю версию. Откат базы данных не выполняют автоматически вместе с кодом: для этого требуется отдельная проверенная миграция.

Масштабирование и сопровождение пайплайна

Повторяющиеся загрузки замедляют конвейер, поэтому кэшируют зависимости и промежуточные данные компиляции. Ключ кэша должен учитывать версию компилятора, целевую платформу и хеш файлов блокировки зависимостей. Устаревшие или неиспользуемые записи удаляют автоматически. Кэш нежелательно делать общим для заданий с разными уровнями доверия, особенно если сборка выполняется из недоверенных веток.

Нестабильные тесты способны постоянно останавливать выпуск. Их изолируют, измеряют длительность и связывают с отдельной задачей. Полезно отслеживать частоту развёртываний, время от коммита до production, долю неудачных изменений и скорость восстановления. Эти показатели показывают реальную надёжность автоматизации, а не только число зелёных заданий. Побочные материалы о разработке и инструментах доступны по ссылке истории из практики.

В Delphi-проектах устойчивый процесс достигается сочетанием фиксированных версий инструментов, изолированных раннеров, проверяемых артефактов и дисциплинированных миграций. GitLab CI при этом выступает связующим слоем между локальной разработкой, автоматическими проверками и доставкой приложений на разные платформы.