Введение
В условиях современного развития программного обеспечения и необходимости ускорения выпуска обновлений, автоматизация процессов разработки и доставки (DevOps) становится критически важной. Для экосистемы 1С, характеризующейся сложностью конфигураций, наличием множества расширений и необходимостью строгого контроля качества, ручные операции по сборке, тестированию и развертыванию становятся узким местом.
Меня зовут Владимир, я эксперт по развитию финансовых и учетных систем в Группе MOEX. В этой статье предлагаю рассмотреть архитектуру, используемые инструменты, этапы конвейера, а также стратегии оптимизации и мониторинга, которые позволяют обеспечить стабильность и скорость доставки программного обеспечения.
Цель
Автоматизировать рутинные ручные операции, связанные со сборкой, тестированием, проверками и доставкой на различные стенды проектов 1С.
Не будем вдаваться в теорию процесса DevOps и для чего это нужно, это и так все знают. Сконцентрируемся на практике использования инфраструктуры и инструментов для достижения цели.
Инфраструктура
Это конкретные сервера (физические или виртуальные), на которых развернуты те или иные сервисы. Все они предоставляются другими подразделениями компании. А мы по сути используем их по модели SaaS (ПО как услуга).

С другой стороны никто не мешает развернуть все эти сервисы самостоятельно.
-
Linux + PostgreSQL
В рамках процессов импортозамещения в компании все наши сервера 1С переведены на Linux, а сервера баз данных на PostgreSQL. С точки зрения платформы 1С обычное дело, поддержка здесь полная.
-
GitLab (CI/CD)
Весь исходный код хранится в GitLab. Попадает он туда разными путями (исторически для разных проектов):
На проектах, работающих с хранилищами конфигураций 1С, через GitConverter.
На проектах, работающих по технологии Native Git (выгрузка/загрузка в XML из конфигуратора) или на проектах EDT напрямую через коммиты или merge request.
Раз у нас есть GitLab и у него есть свой движок CI/CD, то используем его для целей DevOps без привлечения отдельных инструментов.
-
Nexus (Docker Registry + File Storage)
Можно считать это большим складом различных репозиториев. Для наших целей интересны 2 из них:
Docker Registry - храним собранные нами docker-образы с необходимыми инструментами (ниже)
File Storage - храним различные утилиты, дистрибутивы, модельные базы и артефакты выпущенных релизов
-
TestOps
Место, куда складываются результаты прогонов автотестов (дымовых, сценарных, юнит, API).
-
SonarQube + BSL Comminuty Plugin
Сервис статического анализа исходного кода и сбора информации о его покрытии. С учетом установленного плагина, позволяет проверять модули конфигураций и расширений по установленным правилам.
-
Express
Наш корпоративный мессенджер, Используем созданные в нем каналы для отправки уведомлений о ходе выполнения конвейера.
-
API-портал
Все публикуемые API в компании проходят через единый портал, на котором то или иное API нужно зарегистрировать. 1С не является исключением. Мы активно взаимодействуем с внешними системами по API как в качестве потребителя, так и в качестве поставщика.
Инструменты
-
Docker
Позволяет поместить в контейнер необходимые для выполнения задачи конвейера инструменты. Мы собираем 2 docker-образа:
client1c - основан на RedOS (один из согласованных дистрибутивов в компании) включает в себя платформу 1С, EDT, oscript+библиотеки, allurectl, Java JDK, Coverage41C. Используется для основной работы, в которой участвует платформа 1С (сборка, запуск тестов). Размер образа большой, порядка 10 Gb.
oscript - так же основан на RedOS, включает в себя oscript+библиотеки. Используется там, где платформа 1С не нужна. Достаточно легковесный, порядка 600 Mb.
С выходом новой версии платформы или необходимости добавления библиотеки oscript собирается новый образ, новой версии. Версионность позволяет точечно менять используемые в проектах docker-образы.
Dockerfile прилагаю:
FROM registry.red-soft.ru/ubi7/ubi-minimal LABEL maintainer="Vladimir Bronnikov <vladimir.bronnikov@moex.com>" WORKDIR /tmp # Пакеты iputils (ping), procps (ps) необходимы для запуска Ванессы без ошибок # Пакеты mesa-dri-drivers, vulkan-loader убирают ошибки GUI при запуске Ванессы RUN set -xe \ && yum -y update \ && yum -y install \ alsa-lib \ bash \ ca-certificates \ cabextract \ curl \ fontconfig \ git \ iputils \ libXtst \ mesa-dri-drivers \ mono-core \ mono-locale-extras \ msttcore-fonts-installer \ net-tools \ openldap-clients \ procps \ tar \ unzip \ unixODBC \ vulkan-loader \ which \ x11vnc \ xorg-x11-font-utils \ xorg-x11-server-Xvfb \ && yum -y clean all \ && rm -rf /var/cache ARG USR1CV8_UID="1000" ARG GRP1CV8_GID="1000" RUN groupadd -r grp1cv8 --gid=${GRP1CV8_GID} \ && useradd -r -g grp1cv8 --uid=${USR1CV8_UID} --home-dir=/home/usr1cv8 --shell=/bin/bash usr1cv8 \ && mkdir -p /var/log/1C /home/usr1cv8/.1cv8/1C/1cv8/conf \ && chown -R usr1cv8:grp1cv8 /var/log/1C /home/usr1cv8 # Устанавливаем язык консоли для вывода русских символов вместо знаков ??? ENV LANG=ru_RU.UTF-8 ENV LANGUAGE=ru_RU:ru ENV LC_ALL=ru_RU.UTF-8 # Необходимые дистрибутивы и библиотеки грузим из хранилища Nexus ARG NEXUS_REPO RUN set -xe; \ curl -o /usr/local/bin/gosu ${NEXUS_REPO}/tools/gosu-amd64; \ chmod +x /usr/local/bin/gosu; \ curl -o /usr/local/bin/allurectl ${NEXUS_REPO}/tools/allurectl_linux_amd64; \ chmod +x /usr/local/bin/allurectl RUN set -xe; \ curl -o /tmp/zulu.rpm ${NEXUS_REPO}/distr/java/zulu17.54.21-ca-fx-jdk17.0.13-linux.x86_64.rpm; \ rpm -i ./zulu.rpm; \ rm -rf /tmp/* RUN set -xe; \ curl -o /tmp/edt.tar.gz ${NEXUS_REPO}/distr/edt/1c_edt_distr_offline_2025.1.4_15_linux_x86_64.tar.gz; \ mkdir edt; \ tar -C edt -xvf ./edt.tar.gz; \ ./edt/1ce-installer-cli install --ignore-signature-warnings; \ rm -rf /tmp/* ENV PATH="/opt/1C/1CE/components/1c-edt-2025.1.4+15-x86_64:$PATH" RUN set -xe; \ curl -o /tmp/v8.zip ${NEXUS_REPO}/distr/v8/server64_8_3_27_1786.zip; \ unzip -o -d v8 v8.zip; \ ./v8/setup-full-8.3.27.1786-x86_64.run --mode unattended --enable-components v8_install_deps,ru,client_full,server; \ rm -rf /tmp/* ENV PATH="/opt/1cv8/x86_64/8.3.27.1786:$PATH" # Удаляаем символическую ссылку libstdc++ для запуска клиентов 1С (началось с версии платформы 8.3.24) RUN set -xe; \ rm /opt/1cv8/x86_64/8.3.27.1786/libstdc++.so.6; \ mv $(dirname $(find /opt/1C/1CE -name ring)) /opt/1C/1CE/components/1c-enterprise-ring ENV PATH="/opt/1C/1CE/components/1c-enterprise-ring:$PATH" RUN set -xe; \ curl -o /tmp/oscript.rpm ${NEXUS_REPO}/distr/oscript/onescript-engine-1.9.1-1.fc26.noarch.rpm; \ rpm -i ./oscript.rpm; \ for i in cmdline-1.0.0 csv-1.0.2 json-1.1.1 xml-parser-0.1.1 v8metadata-reader-0.3.6 swagger-0.5.0 messenger-2.0.8-mb irac-1.4.0 InternetMail-1.0.6; \ do \ curl -o /tmp/$i.ospx ${NEXUS_REPO}/distr/oscript/lib/$i.ospx; \ opm install -f ./$i.ospx; \ done; \ rm -rf /tmp/* RUN set -xe; \ curl -o /tmp/coverage41c.zip ${NEXUS_REPO}/distr/coverage41c/Coverage41C-2.7.2.zip; \ unzip -o -d /opt coverage41c.zip; \ cp $(find /opt/1C/1CE -name com._1c.g5.v8.dt.debug.core*) /opt/Coverage41C-2.7.2/lib; \ cp $(find /opt/1C/1CE -name com._1c.g5.v8.dt.debug.model*) /opt/Coverage41C-2.7.2/lib; \ rm -rf /tmp/* ENV PATH="/opt/Coverage41C-2.7.2/bin:$PATH" ENV EDT_LOCATION="/opt/Coverage41C-2.7.2/lib" COPY config/nethasp.ini /opt/1cv8/conf COPY config/conf.cfg /opt/1cv8/conf COPY ./v8ci /usr/local/bin/ COPY ./docker-entrypoint.sh /usr/local/bin/ # Публикую порт для подключения к экрану с использованием протокола VNC EXPOSE 5900 ENTRYPOINT ["docker-entrypoint.sh"]
-
Платформа 1С
Является необходимой частью docker-образов и использует практически все свои компоненты: клиент (тонкий и толстый), конфигуратор, сервер отладки, автономный сервер и сервер удаленного администрирования.
-
EDT
Т.к. во многих проектах исходники хранятся в формате EDT, то используем утилиту 1сedtcli (ранее ring) для преобразования конифгурации из формата EDT в формат XML и дальнейшего формирования cf/cfe уже средствами платформы 1С.
-
Oscript
Основной инструмент для написания скриптов автоматизации. Он имеет 1С-подобный язык программирования, все необходимые процедуры и функции для автоматизации и богатый набор библиотек для работы с 1С. Используемые на практике библиотеки (не реклама):
1connector - удобная обертка над HTTP-запросами
autumn - с интересом смотрю на эту библиотеку, добавляющую Dependency Injection в код oscript
cli - работа с командной строкой (парсинг опций, аргументов)
irac - работа с сервером администрирования RAS
InternetMail - отправка электронной почты
json - работа с JSON
logos - подсистема логирования
messenger - интеграция с различными мессенджерами, тут пришлось допилить код для интеграции с Express
swagger - создание описания API в формате swagger на основе комментариев к методам HTTP-сервисов
v8metadata-reader - чтение метаданных конфигурации/расширения, используется для получения версии проекта
v8runner - запуск всего, что связано с 1С (конфигуратор, клиенты, тестирование)
xml-parser - работа с XML
-
Vanessa Automation
Дымовое и сценарное тестирование реализовано на данном фреймворке. Тесты пишут автотестировщики и помещают в GitLab.
Обработку собираем самостоятельно из исходников, т.к. иногда оперативно исправляем найденные ошибки или под запросы автотестировщиков (незначительные доработки).
-
YaxUnit
Юнит тестирование и тестирование API реализовано на данном фреймворке. Тесты пишут разработчики в отдельных расширениях, которые так же помещаются в GitLab, собираются в процессе работы конвейера и подключаются к базам тестирования.
-
Coverage41C
Инструмент сбора покрытия кода с использованием подключения к серверу отладки 1С.
-
allurectl
Единственная цель отправить собранные в процессе тестирования данные (в формате allure) в TestOps.
Этапы конвейера

-
build
Сборка артефактов из исходных кодов. На выходе получаем необходимые cf/cfe.
-
pre-test
Подготовка информационных баз для тестирования. Здесь есть несколько вариантов:
Если есть заранее подготовленная модельная база (выгрузка dt), то разворачивается файловая база, к ней применяются собранные на предыдущем этапе cf/cfe, производится запуск и обновление и выгрузка обратно в dt с сохранением в артефакты. Применяется при небольших модельных базах.
Есть заранее подготовленная обезличенная копия информационной базы на сервере 1С, то к ней сразу применяются собранные на предыдущем этапе cf/cfe, производится запуски и обновление.
-
test
Все задачи тестирования выполняются на данном этапе. По большей части задачи независимые и выполняются параллельно. Выделяем следующие виды тестирования:
Сценарное тестирование - feature-файлы со сценариями на языке Gherkin. Выполняются с помощью инструмента Vanessa Automation.
Дымовое тестирование - автоматически генерируемые feature-файлы с помощью Vanessa Automation. В качестве необходимых настроек ведутся файлы исключений определенных действий с определенными метаданными.
Юнит тестирование - тесты, написанные с помощью инструмента yaxUnit, реализованное в виде отдельного расширения, собираемого и подключаемого на предыдущих этапах.
Тестирование API - отдельный набор тестов, написанных также на yaxUnit, но предназначенные для тестирования API.
-
check
На этом этапе идет отправка исходного кода на проверку в SonarQube. Именно после тестирования, т.к. на этапе тестирования собирается информация о покрытии кода.
-
pre-deploy-api
Подготовка спецификации в формате openapi 3.0 для HTTP-сервисов проекта.
-
deploy-api
Публикация API на портале.
-
release
Формирование релиза. Запускается при указании тега на определенный коммит. Подготовленные на предыдущем этапе артефакты (cf/cfe) отправляем в хранилище Nexus, готовим changelog коммитов относительно предыдущего релиза (предыдущего коммита с тегом) и создаем релиз в GitLab с текстом изменений и ссылками на артефакты из Nexus.
Задачи конвейера
-
Управление переменными и секретами
В конвейере используется определенный набор переменных, разбитый на несколько групп:
Секретные - настраиваются на уровне группы проектов 1С, единые для всех проектов. Это обычно логины, пароли, токены к различным внешним сервисам.
GIT-переменные - влияют на процесс клонирования проекта и его подмодулей при запуске GitLab-раннера
Доступ к внешним сервисам - хосты, порты, URL и прочее к внешним сервисам: TestOps, Nexus, SonarQube, Express, API-портал
Доступ к базам тестирования - хосты и порты сервера 1С, имена баз, адреса публикации баз 1С для работы через web
-
Структура задачи, модульность и наследование
Основные критерии при описании задач в конвейере были компактность, понятность и единообразие. Абсолютно не хотелось писать большие портянки скриптов на различных языках программирования. В этом нам помог oscript. Условно вся обертка над логикой работы с переменными среды, файлами, запуском 1С реализованы внутри скрипта oscript. А задача выглядит как последовательный вызов нескольких команд.
Например:
cf: extends: - .client1c-base - .build-all-rules stage: build script: # Преобразуем проект из формата EDT в формат XML - 1cedtcli -data ${CI_PROJECT_DIR}/build/workspace -command export --project ${CI_PROJECT_DIR}/${MB_PROJECT} --configuration-files ${CI_PROJECT_DIR}/build/xml # Создаем пустую файловую базу - v8ci createib # Загружаем конфигурацию из файлов (xml) - v8ci loadconfigfiles # Сохраняем конфигурацию в файл (cf) - v8ci dumpcfg artifacts: paths: - results/build/*.cfгде v8ci - это cli приложение на oscript вызывающее одну конкретную команду. Каждая команда реализуется в отдельном классе, принимает определенный набор опций и аргументов (большинство из них по умолчанию из переменных среды) и выполняет всю работу.
Второй важный момент - использование наследования (extends). У нас есть базовые шаблоны gitlab-ci, которые можно наследовать в разных задачах. И тут есть 2 набора шаблонов:
Шаблоны действий - содержат используемый образ (image), переменные (variables) и исполняемые скрипты (script). Можно относиться к таким шаблонам как к функциям, которые принимают набор переменных и выполняют определенную работу. Шаблон .cfe-base собирает указанное расширение. В самой задаче достаточно наследоваться от него и указать в переменной имя расширения, которое необходимо собрать.
Например:
cfe 1/2: extends: .cfe-base stage: build variables: MB_EXTENSION: Расширение1 cfe 2/2: extends: .cfe-base stage: build variables: MB_EXTENSION: Расширение2Шаблоны правил - содержат правила (rules) для запуска той ли иной задачи. Комбинация двух типов шаблонов дает возможность гибко настраивать задачи без дублирования кода.
-
Использование inputs
Достаточно новая возможность GitLab, позиционируется как замена переменных. Можно относится к inputs, как к типизированным переменным. В нашем случае используем их для разделения конвейера на части и возможности выполнения каждой части отдельно.
spec: inputs: pipeline-action: description: "Действие для запуска конвейера (или его части)" options: ["-- Выберите действие --", "Полный запуск", "Полная сборка", "Сборка", "Юнит-тесты", "Дымовые тесты", "Сценарные тесты", "Тесты API", "Публикация API", "Релиз"] default: "-- Выберите действие --"Значение pipeline-action прописано в правилах (rules) запуска той или иной задачи.
А ручной запуск конвейера выглядит так:
Ручной запуск конвейера -
Скрипты
Как уже писал ранее каждая команда - это отдельный класс библиотеки cli. У каждого скрипта есть процедура с описанием команды, включающая опции и аргументы и процедура исполнения команды, реализующая всю логику скрипта.
Скрипты добавляются по мере необходимости. Общий подход к написанию - делать их максимально переиспользуемыми в разных проектах 1С.

Скрипты Все скрипты вынесены в отдельный проект GitLab (обзовем его cicd) и подключаются к основному проекту 1С как подмодуль (submodule) средствами Git. Это дает следующие преимущества:
За проект отвечает и вносит изменения отдельная роль DevOps.
Нет дублирования скриптов в разных проектах (во всех проектах подключается submodule).
Есть возможность внести изменения в проект cicd, а в основном проекте перезапустить задачу уже запущенного конвейера без коммитов в основной проект (удобно для отладки и оперативных изменений в конвейере).
-
Тестирование
Настройками тестирования так же вынесены в отдельные проекты. Причины похожи:
За тестирование отвечает отдельная роль AQA (Automated Quality Assurance).
В отличие от проекта cicd для каждой конфигурации свой отдельный проект для дымовых и сценарных тестов.

Тестирование
Оптимизация, мониторинг
-
Стратегия GIT
Не во всех задачах конвейера требуется получения проекта из Git-репозитория, например:
применение изменений к информационной базе - работаем только с артефактами, полученных из предыдущих задач
запуск дымовых и сценарных тестов - нужны только настройки тестирования и тексты сценариев
На крупных проектах, основанных на типовых конфигурациях 1С, объем и время клонирования могут отнимать большое количество ресурсов (времени и места на диске). Для оптимизации используем следующий прием:
отключаем клонирование проекта с помощью переменных среды GIT_STRATEGY = none
проекты со скриптами oscript и дымовыми и сценарными тестами клонируем в задаче before_script
before_script: # Клонируем проекты, необходимые для запуска дымовых тестов. - git clone ${CI_SERVER_URL}/1c/devops/cicd.git ./build - git clone ${CI_SERVER_URL}/1c/qa/${MB_SMOKE_PROJECT}.git ./test/smokeгде:
MB_SMOKE_PROJECT - имя проекта с настройками запуска дымовых тестов
-
Параллельность выполнения задач
Если есть множество однотипных задач и возможность запустить их параллельно, то не упустим возможность это сделать. Например запуск дымовых тестов. В данном случае используем следующий подход:
добавляем задачу для динамического создания задач дымовых тестов
в зависимости от установленных переменных среды с помощью oscript формируем yml-файл для запуска подчиненного конвейера (downstream pipeline)
добавляем задачу trigger, которая запускает подчиненный пайплайн (нml-файл берем из артефактов предыдущей задачи)
в итоге будет запущено 31 задача дымовых тестов, которые будут выполняться параллельно и результаты прогона тестов выгружены в ТестОпс.
Пример задач:
gen-smoke: stage: pre-test script: # Генерим задачи дымовых тестов для downstrem pipeline - v8ci gensmoke results/${CI_JOB_STAGE} artifacts: paths: - results/pre-test/smoke.yml smoke: stage: test trigger: include: - artifact: results/pre-test/smoke.yml job: gen-smoke strategy: mirror variables: GIT_STRATEGY: none MB_SMOKE_PROJECT: zup3one-smoke PARENT_PIPELINE_ID: ${CI_PIPELINE_ID}Результат запуска дымовых тестов (2500+ тестов стабильно выполняются около 1 часа):

Запуск дымовых тестов -
Интеграция с мессенджерами
У многих мессенджеров есть API для интеграции. С помощью oscript (и библиотеки messenger, поддерживает по умолчанию несколько популярных мессенджеров) мы реализовали отправку сообщений о ходе выполнения конвейера в корпоративный мессенджер Express. В сообщении есть ссылки на проект, конвейер и задачу и сам текст сообщения. Отправляем сообщения в специально выделенный канал.

Мессенджеры -
Вопросы лицензирования
Для запуска клиентов 1С используются клиентские лицензии, а в случае использования серверных баз, ещё и серверная лицензия. На случай больших баз у нас есть данные лицензии для DEV-контура.
Но для небольших (модельных) информационных баз, для тестирования используем следующий подход:
готовим модельную базу к запуску тестов
выгружаем базу в *.dt
на каждом шаге тестирования создаем файловую базу из *.dt
запускаем созданную файловую базу на автономном сервере (не требует лицензий)
на автономном сервере так же запущен веб-сервер
smoke-standalone: variables: # Стандартный URL публикации базы на автономном сервере MB_IB_CONN: /WS"http://localhost:8314/" script: # Создаем и загружаем информационную базу (из *.dt) - ibcmd infobase create --restore=results/pre-test/1cv8-before.dt # Запускаем автономный сервер на созданной базе (только http, без отладчика, без регламентных заданий) - ibsrv --daemon --disable-direct --schedule-jobs=false # Запуск дымовых тестов - v8ci runsmoke
Идеи
-
Использование тонких клонов для тестирования
С помощью инструмента DBLab стром у себя систему создания тонких клонов. Инструмент позволит создавать клоны больших по объему информационных баз за секунды, а тесты запускать изолированно всегда с одного и того же состояния информационной базы (независимо от предыдущих запусков тестов). Идея в следующем:
инструмент DBLab держит у себя актуальную реплику (PostgreSQL) основной информационной базы
ежедневно с данной реплики делается снимок (snapshot). В данном процессе база обезличивается и обогащается данными и настройками для запуска тестов
конвейер перед запуском тестов обращается в DBLab по API с запросом на создание клона со свежего снимка, создает информационную базу на сервере 1С и использует эту базу для запуска тестов
после завершения прогона тестов конвейер так же по API удаляет созданный ранее клон и базу на сервере 1С
можно создать сразу несколько клонов и запустить тесты параллельно, при этом состояние базы каждого запуска будет одинаковым, а на уровне БД будут храниться только изменения (оценочно 1…5% от размера исходной базы)
-
Использование ИИ
Куда же без ИИ. Идея пока полностью не сформировалась. Но общий подход использовать вызовы по API по анализу логов выполнения конвейера, мониторинга и обобщения результатов.
Выводы и результаты
Внедрение описанной выше системы CI/CD позволило достичь значительных результатов в автоматизации процессов разработки и тестирования для экосистемы 1С.
Ключевые особенности:
Сокращение времени доставки: Автоматизация сборки, тестирования и развертывания исключила ручной труд на этих этапах
Повышение стабильности: Использование модульных скриптов на oscript, наследования шаблонов и единой инфраструктуры (GitLab, Nexus, SonarQube) обеспечило единообразие процессов во всех проектах
-
Эффективное использование ресурсов:
Параллельный запуск задач (особенно дымовых тестов) позволил выполнить более 2500 тестов за ~1 час
Использование автономных серверов для тестирования модельных баз позволило сэкономить на лицензиях
Прозрачность и контроль: Интеграция с TestOps, SonarQube и мессенджерами обеспечивает полную видимость результатов тестирования, покрытия кода и статуса конвейера в реальном времени
Гибкость: Возможность ручного запуска отдельных частей конвейера и использование подмодулей позволяет быстро вносить изменения и отлаживать процессы без коммитов в основные проекты