Автоматизация создания файлов поставки и обновления в 1С

Введение

DevOps постепенно охватывает все большее и большее пространство и завоевывает себе все больше последователей. И причины для этого вполне себе очевидны. В настоящей статье я бы хотел рассказать о своем опыте внедрения некоторых практик в процесс разработки продукта на платформе 1С.

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

Немного о цикле разработки

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

Подробнее о создании файлов поставки

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

  1. Обновляемся из хранилища — получаем все последние изменения.
  2. Захватываем корень конфигурации в хранилище. Если корень захвачен кем-то другим сборка не состоится.
  3. Изменяем номер версии конфигурации.
  4. Помещаем измененный объект в хранилище.
  5. Создаем файлы поставки и обновления — cf и cfu.

Обновление конфигурации ИБ можно сделать как после третьего, так и после четвертого пункта. Вроде бы для создания файлов обновления можно и не делать вовсе, но я всегда делаю. 

На первый взгляд ничего сложного и алгоритм понятен. Давайте автоматизировать. Платформа у нас 8.3.10, поэтому выбираем пакетный режим конфигуратора.

И тут нас ждет первая не то чтобы проблема, но неожиданность. Я и раньше знал об этой особенности, но здесь она мне показалась выраженной еще более ярко, чем когда-либо раньше. Речь о том, что “пакетный” режим конфигуратора, на мой взгляд некорректно называть “пакетным”. Там обычно можно выполнять по одной команде, максимум некоторые могут комбинироваться с обновлением конфигурации ИБ. Для тех, кто ни разу не имел дела с пакетным режимом конфигуратора, дальше я объясню это более подробно.

Начинаю автоматизировать этот рутинный процесс — пытаюсь кодом сделать то, что до этого делал руками. 

Обновление из хранилища

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

Здесь уместно напомнить о той особенности пакетного режима, о которой я говорил ранее. Когда я делаю все действия по подготовке файлов поставки вручную, я один раз запускаю конфигуратор на базе, подключенной к хранилищу, делаю все необходимые действия, и закрываю конфигуратор. В случае, когда я хочу этот процесс автоматизировать, каждый шаг из списка выше мне необходимо заново запускать конфигуратор и закрывать его. Так образуются дополнительные накладные расходы на запуск и остановку процесса. Да, есть особенный вариант работы пакетного режима конфигуратора — режим агента — когда к запущенному конфигуратору можно подключиться ssh-клиентом и отправлять ему команды, но там нет возможностей работы с хранилищем конфигурации.

Захват корня в хранилище конфигурации

Снова запускаем конфигуратор, на этот раз с ключом ConfigurationRepositoryLock. Дополнительным параметром Objects здесь нужно указать путь к файлу со списком объектов, которые должны быть захвачены. Нам нужно захватить только корень конфигурации, необходимо это прописать в файле.

<Objects xmlns="http://v8.1c.ru/8.3/config/objects" version="1.0">
   <Configuration includeChildObjects = "false"/>
</Objects>

Изменение номера версии

На мой взгляд, это главный раздел в этой статье. Собственно, здесь встретились некоторые трудности в автоматизации процесса создания файлов поставки.

Проблема первая — нельзя просто так взять и поменять версию конфигурации. Но есть обходной путь. Можно выгрузить конфигурацию в файлы, в xml-файле корня конфигурации поменять номер версии на нужную, загрузить конфигурацию из файлов. Это вновь увеличивает количество запусков-остановов конфигуратора, что опять же не ускоряет процесс. Но механизм реализуемый, и это главное.

Решено — выгружаем конфигурации в файлы. Для этого используется ключ DumpConfigToFiles.

Следующим шагом здесь нужно в файле Configuration.xml найти версию конфигурации и изменить ее. Одновременно с этим нужно в файле ConfigDumpInfo.xml отметить, что элемент конфигурации изменился. Для этого в соответствующем элементе (у которого в поле name значится Configuration.ИмяКонфигурации) нужно изменить аттрибут configVersion. Изменение версии у нас делится на два возможных варианта. В случае исправительного обновления без реструктуризации выпускается новая версия — меняется последнее число из четырех. В случае выхода нового релиза увеличивается третье число, а четвертое меняется на единицу — 1. 

После изменения версии в файле, нужно информацию из файла загрузить обратно в конфигурацию. Вновь запускаем конфигуратор для загрузки из файлов — ключ для запуска LoadConfigFromFiles. Этот параметр можно комбинировать с параметром обновления конфигурации ИБ — UpdateDBCfg. И вся эта задача была бы “легкой прогулкой”, если бы на этом этапе прошло все гладко. Оказалось, что наша конфигурация где-то сломана и обратно из файлов она не загружается, даже без каких-либо изменений. 

Загрузка конфигурации в интерактивном режиме не дает результатов, помогающих в локализации ошибки — загрузка проходит успешно. В пакетном режиме можно добавить параметр Out с указанием имени файла, в который будет писаться некий лог работы. С помощью этого лога удалось найти ошибку. Оказывается, в подписках на событие нельзя указывать общий тип СправочникОбъект и ДокументОбъект. Точнее в обычной работе мы никаких сложностей не обнаружили, а вот при загрузке конфигурации из файлов в пакетном режиме операция завершалась с ошибкой. Заменил подобное указание типа в подписке на событие на определяемые типы. Очевидный минус этого решения — при добавлении нового справочника или документа нужно не забыть добавить его в определяемый тип. С другой стороны это добавляет осмысленности действий — при добавлении объекта мы будем самостоятельно решать, нужна на него подписка на событие или нет. У нас подписка не критичная и позволяет эту вариативность.

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

Помещение корня в хранилище

Здесь уже нет никаких особенностей. Запускаем конфигуратор с ключом ConfigurationRepositoryCommit, дополнительным параметром, как и при захвате, является параметр Objects — путь к файлу со списком помещаемых объектов. Используется тот же файл, что и при захвате объектов в хранилище. Ещё один параметр — comment — текст комментария для истории хранилища. Здесь я использую новый номер версии конфигурации.

Создание файлов поставки и обновления

На этом этапе нужно определить предыдущие версии, с которых будет возможно обновление конфигурации. Для простоты я решил брать определенное количество (N) предыдущих версий, это количество вынесено в настройки скрипта. Определение предыдущих версии тоже упрощено — подкаталоги в каталоге поставок отсортированы по времени изменения, берутся последние N подкаталогов и внутри них берутся cf-файлы. Непосредственно создание файлов поставки и обновления выполняется с помощью ключа CreateDistributionFiles. Дополнительными параметрами там выступает путь к создаваемым cf и cfu файлам и пути к cf-файлам, с которых будет доступно обновление.

Дальнейшие действия

Кроме описанных выше трудностей были различные мелкие проблемы с запуском 1Ски, с кодировками файлов и разные другие сложности, которые хоть и решались быстро, но все же занимали некоторое количество времени. И вот у меня есть рабочий скрипт, который умеет в автоматическом режиме создавать файлы поставки для нашей конфигурации. Следующим шагом нужно реализовать автоматическое обновление тестовых баз. Да, для этого есть уже готовые инструменты (deployka, например), но поскольку у меня уже есть методы для запуска конфигуратора, а для обновления нужен всего-то один запуск в режиме Конфигуратора и один в режиме Предприятия, то я решил сделать всю работу в одной среде. В конфигурационном файле были описаны строки подключения к базам и они запускались для обновления в разных потоках. В каждом потоке моего скрипта был запуск сначала Конфигуратора, затем Предприятия.

Велосипед?

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

Об инструменте автоматизации

В качестве инструмента для написания скрипта я выбрал Python. Тут дело вкуса, конечно. С этой задачей можно справиться и с помощью других скриптовых языков, но я выбрал этот, потому что было интересно.

Результаты

Свой скрипт я проверял только на разрабатываемой нашей командой конфигурации, для чего он, собственно, и предназначался. При благоприятных внешних условиях (никто не захватил корень в хранилище, места везде хватает, в тестовых базах народ не мешает) работает стабильно. А вот работать с нештатными ситуациями еще предстоит научиться, но я пока не спешу это делать. Среднее время выполнения — 25 минут — это сборка и обновление 2 тестовых конфигураций без сильной реструктуризации. Пока запуск производится вручную, в дальнейшем планируется посадить это дело на расписание в Windows и у нас будут ночные сборки. Кстати, при помещении в хранилище в комментарии я так и написал — night build.