1
0
mirror of https://github.com/nixel2007/gitlab-ci-for-1c.git synced 2025-12-03 22:39:14 +02:00
Files
gitlab-ci-for-1c/scripts/ci_deploy.os

430 lines
24 KiB
Plaintext

#Использовать "../vendor/oscript-library/src/v8runner"
#Использовать "../vendor/oscript-library/src/tempfiles"
// logos объявлен в одном из модулей. Ждем фикса от разработчиков библиотеки
// #Использовать "../vendor/oscript-library/src/logos"
Перем Лог;
Перем Соединение;
Перем КодВозврата;
Перем СписокОбработокДляОбновления;
Процедура Инициализация()
Лог = Логирование.ПолучитьЛог("oscript.app.gitlab-deploy");
Лог.УстановитьРаскладку(ЭтотОбъект);
КодВозврата = 0;
СписокОбработокДляОбновления = Новый Массив;
КонецПроцедуры
Функция Форматировать(Знач Уровень, Знач Сообщение) Экспорт
Возврат СтрШаблон("%1: %2 - %3", ТекущаяДата(), УровниЛога.НаименованиеУровня(Уровень), Сообщение);
КонецФункции
Процедура ВывестиГоризонтальнуюЧерту()
Лог.Информация("------------------------------------------");
КонецПроцедуры
Процедура ВыполнитьОбновлениеБазы()
Если КодВозврата > 0 Тогда
Возврат;
КонецЕсли;
ВывестиГоризонтальнуюЧерту();
Лог.Информация("Выполняем обновление базы...");
ВывестиГоризонтальнуюЧерту();
СтрокаИзмененныхФайлов = ПолучитьСтрокуИзмененныхФайлов("src/cf/");
Если НЕ ЗначениеЗаполнено(СтрокаИзмененныхФайлов) Тогда
Лог.Информация("Обновление базы не требуется.");
Возврат;
КонецЕсли;
Лог.Информация("Строка измененных файлов: " + СтрокаИзмененныхФайлов);
Конфигуратор = Новый УправлениеКонфигуратором();
УстановитьКонтекстКонфигуратора(Конфигуратор);
ПараметрыЗапуска = Конфигуратор.ПолучитьПараметрыЗапуска();
// Временно отключаем инкрементальную загрузку. см #109
//КомандаЗапуска = "/LoadConfigFromFiles ""%1"" -Files ""%2""";
//КомандаЗапуска = СтрШаблон(КомандаЗапуска, ОбъединитьПути(ТекущийКаталог(), "source", "cf"), СтрокаИзмененныхФайлов);
КомандаЗапуска = "/LoadConfigFromFiles ""%1""";
КомандаЗапуска = СтрШаблон(КомандаЗапуска, ОбъединитьПути(ТекущийКаталог(), "source", "cf"));
Лог.Информация("Команда обновления конфигурации: " + КомандаЗапуска);
ПараметрыЗапуска.Добавить(КомандаЗапуска);
Попытка
Конфигуратор.ВыполнитьКоманду(ПараметрыЗапуска);
ВыводКоманды = Конфигуратор.ВыводКоманды();
Если ЗначениеЗаполнено(ВыводКоманды) Тогда
Лог.Информация(ВыводКоманды);
КонецЕсли;
Исключение
Лог.Ошибка(Конфигуратор.ВыводКоманды());
КодВозврата = 1;
Возврат;
КонецПопытки;
ВывестиГоризонтальнуюЧерту();
Лог.Информация("Конфигурация обновлена.");
ВывестиГоризонтальнуюЧерту();
Лог.Информация("Выполняем обновление конфигурации БД");
Попытка
Конфигуратор.ОбновитьКонфигурациюБазыДанных();
ВыводКоманды = Конфигуратор.ВыводКоманды();
Если ЗначениеЗаполнено(ВыводКоманды) Тогда
Лог.Информация(ВыводКоманды);
КонецЕсли;
Исключение
Лог.Ошибка(Конфигуратор.ВыводКоманды());
КодВозврата = 2;
Возврат;
КонецПопытки;
ВывестиГоризонтальнуюЧерту();
Лог.Информация("Обновление конфигурации завершено.");
КонецПроцедуры
Процедура ЗагрузитьВнешниеОтчетыИОбработки()
Если КодВозврата > 0 Тогда
Возврат;
КонецЕсли;
ПутьКИсходникам = "src/processings";
ВывестиГоризонтальнуюЧерту();
Лог.Информация("Выполняем обновление обрабток...");
ВывестиГоризонтальнуюЧерту();
СтрокаИзмененныхФайлов = ПолучитьСтрокуИзмененныхФайлов(ПутьКИсходникам);
Если НЕ ЗначениеЗаполнено(СтрокаИзмененныхФайлов) Тогда
Лог.Информация("Обновление обработок не требуется.");
Возврат;
КонецЕсли;
Лог.Информация("Строка измененных файлов: " + СтрокаИзмененныхФайлов);
ВывестиГоризонтальнуюЧерту();
Лог.Информация("Собираем дополнительные отчеты и обработки");
ВывестиГоризонтальнуюЧерту();
СобратьКаталог(ПутьКИсходникам, "processings", СтрокаИзмененныхФайлов);
ВывестиГоризонтальнуюЧерту();
Лог.Информация("Обновляем обработки в базе");
ВывестиГоризонтальнуюЧерту();
СтрокаСоединения = ПолучитьСтрокуСоединенияКБазе();
V83COMConnector = Новый COMОбъект("V83.COMConnector");
Попытка
Соединение = V83COMConnector.Connect(СтрокаСоединения);
Исключение
Лог.Ошибка("Не удалось подключиться к базе-приемнику для обновления обработок");
Лог.Ошибка(ОписаниеОшибки());
КодВозврата = 4;
Возврат;
КонецПопытки;
Соединение.НачатьТранзакцию();
КаталогОбработок = ОбъединитьПути(ТекущийКаталог(), "processings");
ЗагрузитьКаталогОбработокВБазу(КаталогОбработок);
Соединение.ЗафиксироватьТранзакцию();
ВывестиГоризонтальнуюЧерту();
Лог.Информация("Обновление обработок в базе завершено.");
КонецПроцедуры
Процедура СобратьКаталог(Знач ПутьКИсходникам, Знач КаталогВыгрузки, Знач СтрокаИзмененныхФайлов)
ТекущийКаталог = ТекущийКаталог();
ПолныйПутьКИсходникам = ОбъединитьПути(ТекущийКаталог, ПутьКИсходникам);
СписокФайловВКаталоге = НайтиФайлы(ПолныйПутьКИсходникам);
ПолныйПутьКаталогВыгрузки = ОбъединитьПути(ТекущийКаталог, КаталогВыгрузки);
Если НЕ Новый Файл(ПолныйПутьКаталогВыгрузки).Существует() Тогда
СоздатьКаталог(ПолныйПутьКаталогВыгрузки);
КонецЕсли;
Для Каждого Файл Из СписокФайловВКаталоге Цикл
Если НЕ Файл.ЭтоКаталог() Тогда
Продолжить;
КонецЕсли;
Если ЭтоПутьКИсходнымКодамОбработок(Файл.ПолноеИмя) И СтрНайти(СтрокаИзмененныхФайлов, Файл.ПолноеИмя) Тогда
КомандаЗапуска = "oscript -encoding=utf-8 vendor/precommit1c/v8files-extractor.os --compile ""%1"" ""%2""";
КомандаЗапуска = СтрШаблон(КомандаЗапуска, ОбъединитьПути(ПутьКИсходникам, Файл.Имя), КаталогВыгрузки);
Процесс = СоздатьПроцесс(КомандаЗапуска, ТекущийКаталог, Истина, , КодировкаТекста.UTF8);
Процесс.Запустить();
Пока НЕ Процесс.Завершен Цикл
Пока Процесс.ПотокВывода.ЕстьДанные Цикл
СтрокаВывода = Процесс.ПотокВывода.ПрочитатьСтроку();
Сообщить(СтрокаВывода);
КонецЦикла;
КонецЦикла;
Если Процесс.КодВозврата <> 0 Тогда
ВызватьИсключение "Ошибка сбора обработки из исходников";
КонецЕсли;
ИмяСобранногоФайла = ОбъединитьПути(ТекущийКаталог, КаталогВыгрузки, Файл.Имя);
СписокОбработокДляОбновления.Добавить(ИмяСобранногоФайла + ".erf");
СписокОбработокДляОбновления.Добавить(ИмяСобранногоФайла + ".epf");
Иначе
НовыйПутьКИсходникам = ОбъединитьПути(ПутьКИсходникам, Файл.Имя);
НовыйПутьВыгрузки = ОбъединитьПути(КаталогВыгрузки, Файл.Имя);
СобратьКаталог(НовыйПутьКИсходникам, НовыйПутьВыгрузки, СтрокаИзмененныхФайлов);
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Процедура ЗагрузитьКаталогОбработокВБазу(Знач КаталогОбработок)
Файлы = НайтиФайлы(КаталогОбработок, ПолучитьМаскуВсеФайлы());
Для Каждого Файл Из Файлы Цикл
Если Файл.ЭтоКаталог() Тогда
ЗагрузитьКаталогОбработокВБазу(Файл.ПолноеИмя);
ИначеЕсли ЭтоФайлОтчетаИлиОбработки(Файл) И СписокОбработокДляОбновления.Найти(Файл.ПолноеИмя) <> Неопределено Тогда
Попытка
ЗагрузитьОбработкуВБазу(Файл.ПолноеИмя);
Исключение
ВывестиГоризонтальнуюЧерту();
Лог.Ошибка("Ошибка загрузки обработок, откат изменений");
ВызватьИсключение ОписаниеОшибки();
КонецПопытки;
КонецЕсли;
КонецЦикла
КонецПроцедуры
Процедура ЗагрузитьОбработкуВБазу(ИмяФайла)
Лог.Информация("Загрузка обработки <" + ИмяФайла + ">");
ПараметрыРегистрации = Соединение.NewObject("Структура");
ПараметрыРегистрации.Вставить("ИмяФайла", "");
ПараметрыРегистрации.Вставить("ЭтоОтчет", Неопределено);
ПараметрыРегистрации.Вставить("ОтключатьКонфликтующие", Ложь);
ПараметрыРегистрации.Вставить("Конфликтующие", Соединение.NewObject("СписокЗначений"));
ПараметрыРегистрации.Вставить("АдресДанныхОбработки", "");
ДД = Соединение.NewObject("ДвоичныеДанные", ИмяФайла);
АдресДанныхОбработки = Соединение.ПоместитьВоВременноеХранилище(ДД, Соединение.NewObject("УникальныйИдентификатор"));
ПараметрыРегистрации.АдресДанныхОбработки = АдресДанныхОбработки;
ФайлОбработки = Новый Файл(ИмяФайла);
ПараметрыРегистрации.ИмяФайла = ФайлОбработки.Имя;
РасширениеФайла = ВРег(ФайлОбработки.Расширение);
Если РасширениеФайла = ".ERF" Тогда
ПараметрыРегистрации.ЭтоОтчет = Истина;
ИначеЕсли РасширениеФайла = ".EPF" Тогда
ПараметрыРегистрации.ЭтоОтчет = Ложь;
Иначе
ВызватьИсключение("Расширение файла не соответствует расширению внешнего отчета (ERF) или обработки (EPF): " + РасширениеФайла);
Возврат;
КонецЕсли;
// Вызов сервера
РезультатРегистрации = ЗарегистрироватьОбработку(ПараметрыРегистрации);
// Обработка результата работы сервера
Если РезультатРегистрации.Успешно = Истина Тогда
РезультатРегистрации.ОбъектСправочника.ХранилищеОбработки = Соединение.NewObject("ХранилищеЗначения" , ДД, Соединение.NewObject("СжатиеДанных", 9));
РезультатРегистрации.ОбъектСправочника.Записать();
Лог.Информация("Обработка <" + ПараметрыРегистрации.ИмяФайла + "> успешно загружена");
Возврат;
КонецЕсли;
// Разбор причины отказа загрузки обработки и отображение информации пользователю
Если РезультатРегистрации.ИмяОбъектаЗанято = Ложь Тогда
// Причина отказа в КраткоеПредставлениеОшибки
ВызватьИсключение(РезультатРегистрации.КраткоеПредставлениеОшибки);
Иначе
// Представление занявших объектов
КоличествоКонфликтующих = РезультатРегистрации.Конфликтующие.Количество();
ПредставлениеЗанявших = "";
Для Каждого ЭлементСписка Из РезультатРегистрации.Конфликтующие Цикл
ПредставлениеЗанявших = ПредставлениеЗанявших
+ ?(ПредставлениеЗанявших = "", "", ", ")
+ СокрЛП(ЭлементСписка.Представление);
Если СтрДлина(ПредставлениеЗанявших) > 80 Тогда
ПредставлениеЗанявших = Лев(ПредставлениеЗанявших, 70)
+ "... ("
+ Формат(КоличествоКонфликтующих, "ЧН=0; ЧГ=")
+ " "
+ Соединение.НСтр("ru = 'шт'")
+ ")";
Прервать;
КонецЕсли;
КонецЦикла;
ТекстВопроса = СтрШаблон(
Соединение.НСтр("ru = 'Имя ""%1"" уже занято другими дополнительными отчетами (обработками):
|%2.'"),
РезультатРегистрации.ИмяОбъекта,
ПредставлениеЗанявших
);
КонецЕсли;
// Отменить загрузку
ВызватьИсключение("Не удалось записать обработку <" + ИмяФайла + ">");
КонецПроцедуры
Функция ЗарегистрироватьОбработку(ПараметрыРегистрации)
СсылкаСправочника = Соединение.Справочники.ДополнительныеОтчетыИОбработки.НайтиПоРеквизиту("ИмяФайла", ПараметрыРегистрации.ИмяФайла);
Если СсылкаСправочника.Пустая() Тогда
Лог.Информация("Обработка <" + ПараметрыРегистрации.ИмяФайла + "> не найдена, создаем элемент");
ОбъектСправочника = Соединение.Справочники.ДополнительныеОтчетыИОбработки.СоздатьЭлемент();
ОбъектСправочника.Заполнить(Неопределено);
ОбъектСправочника.ИспользоватьДляФормыОбъекта = Истина;
ОбъектСправочника.ИспользоватьДляФормыСписка = Истина;
Иначе
Лог.Информация("Обработка <" + ПараметрыРегистрации.ИмяФайла + "> найдена в базе. Используем существующий элемент");
ОбъектСправочника = СсылкаСправочника.ПолучитьОбъект();
КонецЕсли;
Результат = Соединение.ДополнительныеОтчетыИОбработки.ЗарегистрироватьОбработку(ОбъектСправочника, ПараметрыРегистрации);
АдресРазрешений = Соединение.ПоместитьВоВременноеХранилище(ОбъектСправочника.Разрешения.Выгрузить());
Результат.Вставить("ОбъектСправочника", ОбъектСправочника);
Возврат Результат;
КонецФункции
Функция ЭтоФайлОтчетаИлиОбработки(Знач Файл)
РасширениеФайла = ВРег(Файл.Расширение);
Возврат РасширениеФайла = ".EPF" ИЛИ РасширениеФайла = ".ERF";
КонецФункции
Функция ЭтоПутьКИсходнымКодамОбработок(ПутьКПапке)
ФайлПереименования = Новый Файл(ОбъединитьПути(ПутьКПапке, "renames.txt"));
Возврат ФайлПереименования.Существует();
КонецФункции
Функция ПолучитьСтрокуИзмененныхФайлов(Знач ОтборПоНачалуСтроки = "")
ТекущийКаталог = ТекущийКаталог();
КоманднаяСтрока = "git diff --name-only HEAD^ HEAD";
Процесс = СоздатьПроцесс(КоманднаяСтрока, ТекущийКаталог, Истина, , КодировкаТекста.UTF8);
Процесс.Запустить();
Процесс.ОжидатьЗавершения();
СтрокаИзмененныхФайлов = "";
Пока Процесс.ПотокВывода.ЕстьДанные Цикл
СтрокаВывода = Процесс.ПотокВывода.ПрочитатьСтроку();
Если НЕ ЗначениеЗаполнено(ОтборПоНачалуСтроки) ИЛИ СтрНачинаетсяС(СтрокаВывода, ОтборПоНачалуСтроки) Тогда
ТекущаяСтрока = ОбъединитьПути(ТекущийКаталог, СтрокаВывода);
ТекущаяСтрока = СтрЗаменить(ТекущаяСтрока, "/", ПолучитьРазделительПути());
СтрокаИзмененныхФайлов = СтрокаИзмененныхФайлов + ТекущаяСтрока + ",";
КонецЕсли;
КонецЦикла;
Если ЗначениеЗаполнено(СтрокаИзмененныхФайлов) Тогда
СтрокаИзмененныхФайлов = Лев(СтрокаИзмененныхФайлов, СтрДлина(СтрокаИзмененныхФайлов) - 1);
КонецЕсли;
Возврат СтрокаИзмененныхФайлов;
КонецФункции
Функция ПолучитьПараметрыПодключенияКБазе()
СтруктураПодключения = Новый Структура;
СистемнаяИнформация = Новый СистемнаяИнформация;
Сервер = СистемнаяИнформация.ПолучитьПеременнуюСреды("SERVER_1C");
База = СистемнаяИнформация.ПолучитьПеременнуюСреды("SERVER_REF");
Пользователь = СистемнаяИнформация.ПолучитьПеременнуюСреды("1C_USERNAME");
Пароль = СистемнаяИнформация.ПолучитьПеременнуюСреды("1C_PASSWORD");
СтруктураПодключения.Вставить("Сервер", Сервер);
СтруктураПодключения.Вставить("База", База);
СтруктураПодключения.Вставить("Пользователь", Пользователь);
СтруктураПодключения.Вставить("Пароль", Пароль);
Возврат СтруктураПодключения;
КонецФункции
Процедура УстановитьКонтекстКонфигуратора(УправлениеКонфигуратором)
Параметры = ПолучитьПараметрыПодключенияКБазе();
СтрокаСоединения = "/IBConnectionString""Srvr=%1;Ref=%2;""";
СтрокаСоединения = СтрШаблон(СтрокаСоединения, Параметры.Сервер, Параметры.База);
УправлениеКонфигуратором.УстановитьКонтекст(СтрокаСоединения, Параметры.Пользователь, Параметры.Пароль);
КонецПроцедуры
Функция ПолучитьСтрокуСоединенияКБазе()
Параметры = ПолучитьПараметрыПодключенияКБазе();
СтрокаСоединения = "Srvr=%1;Ref=%2;Usr=%3;Pwd=%4;";
СтрокаСоединения = СтрШаблон(СтрокаСоединения, Параметры.Сервер, Параметры.База, Параметры.Пользователь, Параметры.Пароль);
Возврат СтрокаСоединения;
КонецФункции
Инициализация();
ВыполнитьОбновлениеБазы();
ЗагрузитьВнешниеОтчетыИОбработки();
ВременныеФайлы.Удалить();
ЗавершитьРаботу(КодВозврата);