Настройка 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 при этом выступает связующим слоем между локальной разработкой, автоматическими проверками и доставкой приложений на разные платформы.