feat(epf-build): исходники проверяются платформой до сборки

Сборка .epf/.erf не компилирует модули, поэтому сломанный BSL уезжал
пользователю и падал при открытии обработки. Прямой команды «проверь
внешнюю обработку» у платформы нет, но объект конфигурации она проверяет:
обработка кладётся в конфигурацию временной базы (stub-db-create
-EmbedSourceFile) и спрашивается /CheckConfig. При находках сборка
отменяется, в выводе — сообщение платформы и путь к файлу исходника.

Ключи -Checks и -Context; выключение -Checks off или externalCheck: false
в .v8-project.json. С выключенной проверкой поведение прежнее.

У копии объекта перевыпускаются все GUID: с идентификаторами исходника
платформа путает копию в базе с загружаемой внешней обработкой и через раз
отвечает «Исключение XDTO при чтении файла» на исправном исходнике.

Ручная матрица (база есть/нет × ps1/py × исправный/битый × с модулями/без)
вскрыла ещё три вещи: отказ платформы принять исходники при подготовке
проверки выдавался за сбой базы; py-порт стаба терял причину отказа
LoadConfigFromFiles (не было /Out, в PS он есть); копии общих утилит в
stub-db-create.py разошлись с эталоном db-create — у run_v8 не было
POSIX-ветки, из-за чего на darwin/Linux временная база с пробелом в пути
молча не находилась бы.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013MQkqXxErBepYmoUycfkbn
This commit is contained in:
Nick Shirokov
2026-09-05 17:46:30 +03:00
co-authored by Claude Opus 5
parent a3ea0b7be6
commit 448f05ed11
23 changed files with 1081 additions and 67 deletions
@@ -0,0 +1,39 @@
{
"name": "Перед сборкой запускается /CheckConfig (fake platform)",
"osOnly": "win32",
"fakePlatform": {
"exit": 0,
"log": "Загрузка завершена.\n",
"check": {
"exit": 0,
"log": ""
}
},
"preRun": [
{
"script": "epf-init/scripts/init",
"args": {
"-Name": "Тест",
"-SrcDir": "{workDir}/src"
}
}
],
"args_extra": [
"-V8Path",
"{workDir}\\fake.cmd",
"-InfoBasePath",
"{workDir}\\ib",
"-SourceFile",
"{workDir}\\src\\Тест.xml",
"-OutputFile",
"{workDir}\\build\\Тест.epf"
],
"expect": {
"stdoutContains": [
"/CheckConfig -ThinClient -Server -HandlersExistence",
"/LoadExternalDataProcessorOrReportFromFiles"
]
},
"expectError": true,
"noSnapshot": "платформа фейковая, EPF не собирается — проверяется командная строка проверки"
}
@@ -0,0 +1,43 @@
{
"name": "Находки проверки отменяют сборку (fake platform)",
"osOnly": "win32",
"fakePlatform": {
"exit": 0,
"log": "",
"check": {
"exit": 101,
"log": "{Обработка.Тест.МодульОбъекта(5,1)}: Ожидается ключевое слово 'КонецФункции'\r\n"
}
},
"preRun": [
{
"script": "epf-init/scripts/init",
"args": {
"-Name": "Тест",
"-SrcDir": "{workDir}/src"
}
}
],
"args_extra": [
"-V8Path",
"{workDir}\\fake.cmd",
"-InfoBasePath",
"{workDir}\\ib",
"-SourceFile",
"{workDir}\\src\\Тест.xml",
"-OutputFile",
"{workDir}\\build\\Тест.epf"
],
"expect": {
"stdoutContains": [
"платформа нашла проблемы в исходниках",
"МодульОбъекта(5,1)",
"src\\Тест\\Ext\\ObjectModule.bsl"
],
"stdoutNotContains": [
"/LoadExternalDataProcessorOrReportFromFiles"
]
},
"expectError": true,
"noSnapshot": "сборка отменена — артефакта нет по замыслу"
}
@@ -0,0 +1,56 @@
{
"name": "ibcmd-аргументы не утекают в проверку (fake platform)",
"osOnly": "win32",
"preRun": [
{
"script": "epf-init/scripts/init",
"args": {
"-Name": "Тест",
"-SrcDir": "{workDir}/src"
}
},
{
"writeFile": {
"path": "ibcmd.cmd",
"content": "@echo off\r\necho ARGS: %*\r\nexit /b 0\r\n",
"executable": true
}
},
{
"writeFile": {
"path": "1cv8.cmd",
"content": "@echo off\r\necho ARGS: %*\r\nexit /b 0\r\n",
"executable": true
}
},
{
"writeFile": {
"path": "ib/1Cv8.1CD",
"content": "stub\n"
}
}
],
"args_extra": [
"-V8Path",
"{workDir}\\ibcmd.cmd",
"-InfoBasePath",
"{workDir}\\ib",
"-SourceFile",
"{workDir}\\src\\Тест.xml",
"-OutputFile",
"{workDir}\\build\\Тест.epf",
"-AdditionalIbcmdArguments",
"--nonesuch=1"
],
"expect": {
"stdoutContains": [
"/CheckConfig -ThinClient -Server -HandlersExistence",
"Running: ibcmd infobase config import"
],
"stdoutNotContains": [
"/DisableStartupDialogs --nonesuch=1"
]
},
"expectError": true,
"noSnapshot": "платформа фейковая, EPF не собирается — проверяется состав командных строк"
}
@@ -0,0 +1,43 @@
{
"name": "-Checks off отключает проверку (fake platform)",
"osOnly": "win32",
"fakePlatform": {
"exit": 0,
"log": "",
"check": {
"exit": 101,
"log": "Не должно быть вызвано\n"
}
},
"preRun": [
{
"script": "epf-init/scripts/init",
"args": {
"-Name": "Тест",
"-SrcDir": "{workDir}/src"
}
}
],
"args_extra": [
"-V8Path",
"{workDir}\\fake.cmd",
"-InfoBasePath",
"{workDir}\\ib",
"-SourceFile",
"{workDir}\\src\\Тест.xml",
"-OutputFile",
"{workDir}\\build\\Тест.epf",
"-Checks",
"off"
],
"expect": {
"stdoutContains": [
"/LoadExternalDataProcessorOrReportFromFiles"
],
"stdoutNotContains": [
"/CheckConfig"
]
},
"expectError": true,
"noSnapshot": "платформа фейковая, EPF не собирается — проверяется командная строка"
}
@@ -0,0 +1,42 @@
{
"name": "Путь не печатается, если файла нет (fake platform)",
"osOnly": "win32",
"fakePlatform": {
"exit": 0,
"log": "",
"check": {
"exit": 101,
"log": "{Обработка.Тест.МодульМенеджера(3,1)}: Ошибка\r\n"
}
},
"preRun": [
{
"script": "epf-init/scripts/init",
"args": {
"-Name": "Тест",
"-SrcDir": "{workDir}/src"
}
}
],
"args_extra": [
"-V8Path",
"{workDir}\\fake.cmd",
"-InfoBasePath",
"{workDir}\\ib",
"-SourceFile",
"{workDir}\\src\\Тест.xml",
"-OutputFile",
"{workDir}\\build\\Тест.epf"
],
"expect": {
"stdoutContains": [
"платформа нашла проблемы в исходниках",
"МодульМенеджера(3,1)"
],
"stdoutNotContains": [
"ManagerModule.bsl"
]
},
"expectError": true,
"noSnapshot": "сборка отменена — артефакта нет по замыслу"
}
@@ -0,0 +1,47 @@
{
"name": "ibcmd без соседнего 1cv8: проверка пропускается, сборка идёт (fake platform)",
"osOnly": "win32",
"preRun": [
{
"script": "epf-init/scripts/init",
"args": {
"-Name": "Тест",
"-SrcDir": "{workDir}/src"
}
},
{
"writeFile": {
"path": "ibcmd.cmd",
"content": "@echo off\r\necho ARGS: %*\r\nexit /b 0\r\n",
"executable": true
}
},
{
"writeFile": {
"path": "ib/1Cv8.1CD",
"content": "stub\n"
}
}
],
"args_extra": [
"-V8Path",
"{workDir}\\ibcmd.cmd",
"-InfoBasePath",
"{workDir}\\ib",
"-SourceFile",
"{workDir}\\src\\Тест.xml",
"-OutputFile",
"{workDir}\\build\\Тест.epf"
],
"expect": {
"stdoutContains": [
"[note] source check skipped",
"Running: ibcmd infobase config import"
],
"stdoutNotContains": [
"/CheckConfig"
]
},
"expectError": true,
"noSnapshot": "платформа фейковая, EPF не собирается — проверяется поведение без 1cv8 рядом"
}
@@ -0,0 +1,42 @@
{
"name": "-Context без modules отбивается",
"osOnly": "win32",
"fakePlatform": {
"exit": 0,
"log": ""
},
"preRun": [
{
"script": "epf-init/scripts/init",
"args": {
"-Name": "Тест",
"-SrcDir": "{workDir}/src"
}
}
],
"args_extra": [
"-V8Path",
"{workDir}\\fake.cmd",
"-InfoBasePath",
"{workDir}\\ib",
"-SourceFile",
"{workDir}\\src\\Тест.xml",
"-OutputFile",
"{workDir}\\build\\Тест.epf",
"-Checks",
"handlers",
"-Context",
"Server"
],
"expect": {
"stdoutContains": [
"-Context задан, но в -Checks нет modules"
],
"stdoutNotContains": [
"/CheckConfig",
"/LoadExternalDataProcessorOrReportFromFiles"
]
},
"expectError": true,
"noSnapshot": "отказ до запуска платформы"
}
@@ -0,0 +1,36 @@
{
"name": "Отказ платформы при подготовке проверки не выдаётся за сбой базы (fake platform)",
"osOnly": "win32",
"fakePlatform": {
"exit": 1,
"log": ""
},
"preRun": [
{
"script": "epf-init/scripts/init",
"args": {
"-Name": "Тест",
"-SrcDir": "{workDir}/src"
}
}
],
"args_extra": [
"-V8Path",
"{workDir}\\fake.cmd",
"-SourceFile",
"{workDir}\\src\\Тест.xml",
"-OutputFile",
"{workDir}\\build\\Тест.epf"
],
"expect": {
"stdoutContains": [
"платформа не приняла исходники"
],
"stdoutNotContains": [
"failed to create stub database",
"/LoadExternalDataProcessorOrReportFromFiles"
]
},
"expectError": true,
"noSnapshot": "платформа фейковая и падает на первом запуске — проверяется вердикт"
}
@@ -0,0 +1,40 @@
{
"name": "Неизвестная проверка отбивается",
"osOnly": "win32",
"fakePlatform": {
"exit": 0,
"log": ""
},
"preRun": [
{
"script": "epf-init/scripts/init",
"args": {
"-Name": "Тест",
"-SrcDir": "{workDir}/src"
}
}
],
"args_extra": [
"-V8Path",
"{workDir}\\fake.cmd",
"-InfoBasePath",
"{workDir}\\ib",
"-SourceFile",
"{workDir}\\src\\Тест.xml",
"-OutputFile",
"{workDir}\\build\\Тест.epf",
"-Checks",
"syntax"
],
"expect": {
"stdoutContains": [
"unknown check 'syntax'"
],
"stdoutNotContains": [
"/CheckConfig",
"/LoadExternalDataProcessorOrReportFromFiles"
]
},
"expectError": true,
"noSnapshot": "отказ до запуска платформы"
}
@@ -2,6 +2,13 @@
"name": "Доп. аргументы доходят до самой сборки EPF (fake platform)",
"osOnly": "win32",
"preRun": [
{
"script": "epf-init/scripts/init",
"args": {
"-Name": "Тест",
"-SrcDir": "{workDir}/src"
}
},
{
"writeFile": {
"path": "fake.cmd",
@@ -13,12 +20,6 @@
"path": "ib/1Cv8.1CD",
"content": "fake infobase\n"
}
},
{
"writeFile": {
"path": "src/Обработка.xml",
"content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<MetaDataObject xmlns=\"http://v8.1c.ru/8.3/MDClasses\"/>\n"
}
}
],
"args_extra": [
@@ -27,9 +28,9 @@
"-InfoBasePath",
"{workDir}\\ib",
"-SourceFile",
"{workDir}\\src\\Обработка.xml",
"{workDir}\\src\\Тест.xml",
"-OutputFile",
"{workDir}\\build\\Обработка.epf",
"{workDir}\\build\\Тест.epf",
"-AdditionalV8Arguments",
"/UseHwLicenses+"
],
@@ -3,15 +3,16 @@
"osOnly": "win32",
"preRun": [
{
"writeFile": {
"path": "fake.cmd",
"content": "@echo off\r\necho ARGS: %*\r\nexit /b 1\r\n"
"script": "epf-init/scripts/init",
"args": {
"-Name": "Тест",
"-SrcDir": "{workDir}/src"
}
},
{
"writeFile": {
"path": "src/Обработка.xml",
"content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<MetaDataObject xmlns=\"http://v8.1c.ru/8.3/MDClasses\"/>\n"
"path": "fake.cmd",
"content": "@echo off\r\necho ARGS: %*\r\nexit /b 1\r\n"
}
}
],
@@ -19,9 +20,9 @@
"-V8Path",
"{workDir}\\fake.cmd",
"-SourceFile",
"{workDir}\\src\\Обработка.xml",
"{workDir}\\src\\Тест.xml",
"-OutputFile",
"{workDir}\\build\\Обработка.epf",
"{workDir}\\build\\Тест.epf",
"-AdditionalV8Arguments",
"/UseHwLicenses+"
],