mirror of
https://github.com/Nikolay-Shirokov/cc-1c-skills.git
synced 2026-08-14 07:23:22 +03:00
test(skills): фейк платформы для *nix — детектор тихих отказов проверяется и на macOS
Кейсы детектора были написаны на batch-фейке и потому гейтились osOnly: win32. На маке py-порт единственный, то есть ровно там, где проверять важнее всего, детектор оставался без автоматического покрытия. Добавлен sh-фейк и восемь зеркальных кейсов (osOnly: darwin/linux, runtimeOnly: python). Для этого потребовались два расширения DSL: - `writeFile.executable` — на *nix навык запускает платформу через exec, и файл без бита исполнения не стартует вовсе; Node пишет файлы без +x. На Windows chmod — no-op. Реализовано во всех трёх местах разбора шага (оба в runner.mjs и в verify-snapshots.mjs): ключ, который понимает только один раннер, даёт тихую дыру. - `osOnly` принимает массив, а не только строку. Иначе darwin и linux требовали бы двух копий одного кейса. Оба ключа описаны в tests/skills/README.md. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
a024b7da9c
commit
793cb8f3d6
@@ -274,7 +274,7 @@ ibcmd-проход автоматически `○ skipped`, если рядом
|
||||
| `noSnapshot` | нет | Непустая строка с причиной — кейс объявляет, что эталон не нужен (см. «Эталоны») |
|
||||
| `idempotent` | нет | `true` — повторный прогон с теми же аргументами должен дать байт-в-байт тот же `workDir` |
|
||||
| `runtimeOnly` | нет | `"powershell"` / `"python"` — кейс имеет смысл только на одном порте, на другом `○ skipped` |
|
||||
| `osOnly` | нет | `"win32"` / `"darwin"` / `"linux"` — кейс работает только на этой ОС (напр. фейк платформы написан как `.cmd`), на других `○ skipped` |
|
||||
| `osOnly` | нет | `"win32"` / `"darwin"` / `"linux"` — кейс работает только на этой ОС (напр. фейк платформы написан как `.cmd`), на других `○ skipped`. Принимает и массив: `["darwin","linux"]` |
|
||||
| `cwd` | нет | `"workDir"` — запустить навык из рабочего каталога (нужно, если кейс кладёт туда `.v8-project.json`) |
|
||||
| `skipValidation` | нет | `true` — не запускать `postValidate` из `_skill.json` (только при `--with-validation`) |
|
||||
| `skipPlatformVerify` | нет | Непустая строка с причиной — `verify-snapshots.mjs` пропускает кейс. Нужен, когда фикстура не является конфигурацией, которую можно загрузить (напр. фрагмент расширения) |
|
||||
@@ -318,7 +318,7 @@ ibcmd-проход автоматически `○ skipped`, если рядом
|
||||
| Форма шага | Описание |
|
||||
|---|---|
|
||||
| `{ "script": "<навык>/scripts/<файл>", "input": {...}, "args": { "-Flag": "{inputFile}" } }` | Прогон другого навыка для подготовки фикстуры. Плейсхолдеры: `{inputFile}`, `{workDir}` |
|
||||
| `{ "writeFile": { "path": "<путь>", "content": "<строка или объект>" } }` | Записать произвольный файл в `workDir` (объект сериализуется в JSON) |
|
||||
| `{ "writeFile": { "path": "<путь>", "content": "<строка или объект>" } }` | Записать произвольный файл в `workDir` (объект сериализуется в JSON). Ключ `"executable": true` ставит бит исполнения — нужен фейку платформы на *nix, где навык запускает её через `exec`; на Windows no-op |
|
||||
|
||||
Дополнительно у шага-скрипта: `"cwd": "{workDir}"` — запустить шаг из рабочего каталога. Нужно,
|
||||
когда относительный путь в `args` (напр. `-OutputPath: "Template.xml"`) должен лечь в фикстуру, а
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
{
|
||||
"name": "Чистый лог на *nix: предупреждения нет",
|
||||
"osOnly": [
|
||||
"darwin",
|
||||
"linux"
|
||||
],
|
||||
"runtimeOnly": "python",
|
||||
"preRun": [
|
||||
{
|
||||
"writeFile": {
|
||||
"path": "fake.sh",
|
||||
"content": "#!/bin/sh\n# Фейк платформы для *nix: вычитывает путь из /Out и кладёт туда готовый лог.\nSELF=$(dirname \"$0\")\nOUT=\"\"\nwhile [ $# -gt 0 ]; do\n if [ \"$1\" = \"/Out\" ]; then OUT=\"$2\"; fi\n shift\ndone\ncp \"$SELF/log.txt\" \"$OUT\"\nexit 0\n",
|
||||
"executable": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"writeFile": {
|
||||
"path": "log.txt",
|
||||
"content": "Загрузка конфигурации из файлов.\r\nЗагрузка завершена. Суммарное время выполнения операции: 780 миллисекунд.\r\n"
|
||||
}
|
||||
},
|
||||
{
|
||||
"writeFile": {
|
||||
"path": "ib/1Cv8.1CD",
|
||||
"content": "stub"
|
||||
}
|
||||
},
|
||||
{
|
||||
"writeFile": {
|
||||
"path": "src/Configuration.xml",
|
||||
"content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<MetaDataObject/>"
|
||||
}
|
||||
}
|
||||
],
|
||||
"args_extra": [
|
||||
"-V8Path",
|
||||
"{workDir}/fake.sh",
|
||||
"-InfoBasePath",
|
||||
"{workDir}/ib",
|
||||
"-ConfigDir",
|
||||
"{workDir}/src"
|
||||
],
|
||||
"expect": {
|
||||
"stdoutNotContains": "[warning] platform reported success, but the log contains"
|
||||
},
|
||||
"noSnapshot": "навык ничего не пишет в рабочий каталог — проверяется разбор лога платформы"
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
{
|
||||
"name": "Режим совместимости выше платформы на *nix: классифицируется как отказ (issue #63)",
|
||||
"osOnly": [
|
||||
"darwin",
|
||||
"linux"
|
||||
],
|
||||
"runtimeOnly": "python",
|
||||
"preRun": [
|
||||
{
|
||||
"writeFile": {
|
||||
"path": "fake.sh",
|
||||
"content": "#!/bin/sh\n# Фейк платформы для *nix: вычитывает путь из /Out и кладёт туда готовый лог.\nSELF=$(dirname \"$0\")\nOUT=\"\"\nwhile [ $# -gt 0 ]; do\n if [ \"$1\" = \"/Out\" ]; then OUT=\"$2\"; fi\n shift\ndone\ncp \"$SELF/log.txt\" \"$OUT\"\nexit 0\n",
|
||||
"executable": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"writeFile": {
|
||||
"path": "log.txt",
|
||||
"content": "Для работы с конфигурацией необходима версия платформы не меньше, чем 8.3.27.\r\nТекущая версия 8.3.24.1691.\r\n"
|
||||
}
|
||||
},
|
||||
{
|
||||
"writeFile": {
|
||||
"path": "ib/1Cv8.1CD",
|
||||
"content": "stub"
|
||||
}
|
||||
},
|
||||
{
|
||||
"writeFile": {
|
||||
"path": "src/Configuration.xml",
|
||||
"content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<MetaDataObject/>"
|
||||
}
|
||||
}
|
||||
],
|
||||
"args_extra": [
|
||||
"-V8Path",
|
||||
"{workDir}/fake.sh",
|
||||
"-InfoBasePath",
|
||||
"{workDir}/ib",
|
||||
"-ConfigDir",
|
||||
"{workDir}/src"
|
||||
],
|
||||
"expect": {
|
||||
"stdoutContains": [
|
||||
"[warning] platform reported success, but the log contains 1 problem(s):",
|
||||
"необходима версия платформы не меньше"
|
||||
]
|
||||
},
|
||||
"noSnapshot": "навык ничего не пишет в рабочий каталог — проверяется разбор лога платформы"
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
{
|
||||
"name": "Тихий отказ в логе на *nix: py-порт предупреждает (fake platform)",
|
||||
"osOnly": [
|
||||
"darwin",
|
||||
"linux"
|
||||
],
|
||||
"runtimeOnly": "python",
|
||||
"preRun": [
|
||||
{
|
||||
"writeFile": {
|
||||
"path": "fake.sh",
|
||||
"content": "#!/bin/sh\n# Фейк платформы для *nix: вычитывает путь из /Out и кладёт туда готовый лог.\nSELF=$(dirname \"$0\")\nOUT=\"\"\nwhile [ $# -gt 0 ]; do\n if [ \"$1\" = \"/Out\" ]; then OUT=\"$2\"; fi\n shift\ndone\ncp \"$SELF/log.txt\" \"$OUT\"\nexit 0\n",
|
||||
"executable": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"writeFile": {
|
||||
"path": "log.txt",
|
||||
"content": "Загрузка конфигурации из файлов.\r\nНеверное свойство объекта метаданных. Свойство LineNumberLength не входит в состав объекта метаданных TabularSection. - LineNumberLength\r\nЗагрузка завершена.\r\n"
|
||||
}
|
||||
},
|
||||
{
|
||||
"writeFile": {
|
||||
"path": "ib/1Cv8.1CD",
|
||||
"content": "stub"
|
||||
}
|
||||
},
|
||||
{
|
||||
"writeFile": {
|
||||
"path": "src/Configuration.xml",
|
||||
"content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<MetaDataObject/>"
|
||||
}
|
||||
}
|
||||
],
|
||||
"args_extra": [
|
||||
"-V8Path",
|
||||
"{workDir}/fake.sh",
|
||||
"-InfoBasePath",
|
||||
"{workDir}/ib",
|
||||
"-ConfigDir",
|
||||
"{workDir}/src"
|
||||
],
|
||||
"expect": {
|
||||
"stdoutContains": [
|
||||
"[warning] platform reported success, but the log contains 1 problem(s):",
|
||||
"Свойство LineNumberLength не входит в состав объекта метаданных"
|
||||
],
|
||||
"stdoutNotContains": "-StrictLog"
|
||||
},
|
||||
"noSnapshot": "навык ничего не пишет в рабочий каталог — проверяется разбор лога платформы"
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
{
|
||||
"name": "Тот же лог под -StrictLog на *nix: код возврата 1 (fake platform)",
|
||||
"osOnly": [
|
||||
"darwin",
|
||||
"linux"
|
||||
],
|
||||
"runtimeOnly": "python",
|
||||
"preRun": [
|
||||
{
|
||||
"writeFile": {
|
||||
"path": "fake.sh",
|
||||
"content": "#!/bin/sh\n# Фейк платформы для *nix: вычитывает путь из /Out и кладёт туда готовый лог.\nSELF=$(dirname \"$0\")\nOUT=\"\"\nwhile [ $# -gt 0 ]; do\n if [ \"$1\" = \"/Out\" ]; then OUT=\"$2\"; fi\n shift\ndone\ncp \"$SELF/log.txt\" \"$OUT\"\nexit 0\n",
|
||||
"executable": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"writeFile": {
|
||||
"path": "log.txt",
|
||||
"content": "Загрузка конфигурации из файлов.\r\nНеверное свойство объекта метаданных. Свойство LineNumberLength не входит в состав объекта метаданных TabularSection. - LineNumberLength\r\nЗагрузка завершена.\r\n"
|
||||
}
|
||||
},
|
||||
{
|
||||
"writeFile": {
|
||||
"path": "ib/1Cv8.1CD",
|
||||
"content": "stub"
|
||||
}
|
||||
},
|
||||
{
|
||||
"writeFile": {
|
||||
"path": "src/Configuration.xml",
|
||||
"content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<MetaDataObject/>"
|
||||
}
|
||||
}
|
||||
],
|
||||
"args_extra": [
|
||||
"-V8Path",
|
||||
"{workDir}/fake.sh",
|
||||
"-InfoBasePath",
|
||||
"{workDir}/ib",
|
||||
"-ConfigDir",
|
||||
"{workDir}/src",
|
||||
"-StrictLog"
|
||||
],
|
||||
"expect": {
|
||||
"stdoutContains": "[warning] platform reported success, but the log contains 1 problem(s):"
|
||||
},
|
||||
"noSnapshot": "навык ничего не пишет в рабочий каталог — проверяется разбор лога платформы",
|
||||
"expectError": true
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
{
|
||||
"name": "Чистый лог на *nix: предупреждения нет",
|
||||
"osOnly": [
|
||||
"darwin",
|
||||
"linux"
|
||||
],
|
||||
"runtimeOnly": "python",
|
||||
"preRun": [
|
||||
{
|
||||
"writeFile": {
|
||||
"path": "fake.sh",
|
||||
"content": "#!/bin/sh\n# Фейк платформы для *nix: вычитывает путь из /Out и кладёт туда готовый лог.\nSELF=$(dirname \"$0\")\nOUT=\"\"\nwhile [ $# -gt 0 ]; do\n if [ \"$1\" = \"/Out\" ]; then OUT=\"$2\"; fi\n shift\ndone\ncp \"$SELF/log.txt\" \"$OUT\"\nexit 0\n",
|
||||
"executable": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"writeFile": {
|
||||
"path": "log.txt",
|
||||
"content": "Загрузка конфигурации из файлов.\r\nЗагрузка завершена. Суммарное время выполнения операции: 780 миллисекунд.\r\n"
|
||||
}
|
||||
},
|
||||
{
|
||||
"writeFile": {
|
||||
"path": "ib/1Cv8.1CD",
|
||||
"content": "stub"
|
||||
}
|
||||
}
|
||||
],
|
||||
"args_extra": [
|
||||
"-V8Path",
|
||||
"{workDir}/fake.sh",
|
||||
"-InfoBasePath",
|
||||
"{workDir}/ib"
|
||||
],
|
||||
"expect": {
|
||||
"stdoutNotContains": "[warning] platform reported success, but the log contains"
|
||||
},
|
||||
"noSnapshot": "навык ничего не пишет в рабочий каталог — проверяется разбор лога платформы"
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
{
|
||||
"name": "Режим совместимости выше платформы на *nix: классифицируется как отказ (issue #63)",
|
||||
"osOnly": [
|
||||
"darwin",
|
||||
"linux"
|
||||
],
|
||||
"runtimeOnly": "python",
|
||||
"preRun": [
|
||||
{
|
||||
"writeFile": {
|
||||
"path": "fake.sh",
|
||||
"content": "#!/bin/sh\n# Фейк платформы для *nix: вычитывает путь из /Out и кладёт туда готовый лог.\nSELF=$(dirname \"$0\")\nOUT=\"\"\nwhile [ $# -gt 0 ]; do\n if [ \"$1\" = \"/Out\" ]; then OUT=\"$2\"; fi\n shift\ndone\ncp \"$SELF/log.txt\" \"$OUT\"\nexit 0\n",
|
||||
"executable": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"writeFile": {
|
||||
"path": "log.txt",
|
||||
"content": "Для работы с конфигурацией необходима версия платформы не меньше, чем 8.3.27.\r\nТекущая версия 8.3.24.1691.\r\n"
|
||||
}
|
||||
},
|
||||
{
|
||||
"writeFile": {
|
||||
"path": "ib/1Cv8.1CD",
|
||||
"content": "stub"
|
||||
}
|
||||
}
|
||||
],
|
||||
"args_extra": [
|
||||
"-V8Path",
|
||||
"{workDir}/fake.sh",
|
||||
"-InfoBasePath",
|
||||
"{workDir}/ib"
|
||||
],
|
||||
"expect": {
|
||||
"stdoutContains": [
|
||||
"[warning] platform reported success, but the log contains 1 problem(s):",
|
||||
"необходима версия платформы не меньше"
|
||||
]
|
||||
},
|
||||
"noSnapshot": "навык ничего не пишет в рабочий каталог — проверяется разбор лога платформы"
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
{
|
||||
"name": "Тихий отказ в логе на *nix: py-порт предупреждает (fake platform)",
|
||||
"osOnly": [
|
||||
"darwin",
|
||||
"linux"
|
||||
],
|
||||
"runtimeOnly": "python",
|
||||
"preRun": [
|
||||
{
|
||||
"writeFile": {
|
||||
"path": "fake.sh",
|
||||
"content": "#!/bin/sh\n# Фейк платформы для *nix: вычитывает путь из /Out и кладёт туда готовый лог.\nSELF=$(dirname \"$0\")\nOUT=\"\"\nwhile [ $# -gt 0 ]; do\n if [ \"$1\" = \"/Out\" ]; then OUT=\"$2\"; fi\n shift\ndone\ncp \"$SELF/log.txt\" \"$OUT\"\nexit 0\n",
|
||||
"executable": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"writeFile": {
|
||||
"path": "log.txt",
|
||||
"content": "Загрузка конфигурации из файлов.\r\nНеверное свойство объекта метаданных. Свойство LineNumberLength не входит в состав объекта метаданных TabularSection. - LineNumberLength\r\nЗагрузка завершена.\r\n"
|
||||
}
|
||||
},
|
||||
{
|
||||
"writeFile": {
|
||||
"path": "ib/1Cv8.1CD",
|
||||
"content": "stub"
|
||||
}
|
||||
}
|
||||
],
|
||||
"args_extra": [
|
||||
"-V8Path",
|
||||
"{workDir}/fake.sh",
|
||||
"-InfoBasePath",
|
||||
"{workDir}/ib"
|
||||
],
|
||||
"expect": {
|
||||
"stdoutContains": [
|
||||
"[warning] platform reported success, but the log contains 1 problem(s):",
|
||||
"Свойство LineNumberLength не входит в состав объекта метаданных"
|
||||
],
|
||||
"stdoutNotContains": "-StrictLog"
|
||||
},
|
||||
"noSnapshot": "навык ничего не пишет в рабочий каталог — проверяется разбор лога платформы"
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
{
|
||||
"name": "Тот же лог под -StrictLog на *nix: код возврата 1 (fake platform)",
|
||||
"osOnly": [
|
||||
"darwin",
|
||||
"linux"
|
||||
],
|
||||
"runtimeOnly": "python",
|
||||
"preRun": [
|
||||
{
|
||||
"writeFile": {
|
||||
"path": "fake.sh",
|
||||
"content": "#!/bin/sh\n# Фейк платформы для *nix: вычитывает путь из /Out и кладёт туда готовый лог.\nSELF=$(dirname \"$0\")\nOUT=\"\"\nwhile [ $# -gt 0 ]; do\n if [ \"$1\" = \"/Out\" ]; then OUT=\"$2\"; fi\n shift\ndone\ncp \"$SELF/log.txt\" \"$OUT\"\nexit 0\n",
|
||||
"executable": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"writeFile": {
|
||||
"path": "log.txt",
|
||||
"content": "Загрузка конфигурации из файлов.\r\nНеверное свойство объекта метаданных. Свойство LineNumberLength не входит в состав объекта метаданных TabularSection. - LineNumberLength\r\nЗагрузка завершена.\r\n"
|
||||
}
|
||||
},
|
||||
{
|
||||
"writeFile": {
|
||||
"path": "ib/1Cv8.1CD",
|
||||
"content": "stub"
|
||||
}
|
||||
}
|
||||
],
|
||||
"args_extra": [
|
||||
"-V8Path",
|
||||
"{workDir}/fake.sh",
|
||||
"-InfoBasePath",
|
||||
"{workDir}/ib",
|
||||
"-StrictLog"
|
||||
],
|
||||
"expect": {
|
||||
"stdoutContains": "[warning] platform reported success, but the log contains 1 problem(s):"
|
||||
},
|
||||
"noSnapshot": "навык ничего не пишет в рабочий каталог — проверяется разбор лога платформы",
|
||||
"expectError": true
|
||||
}
|
||||
+10
-2
@@ -4,7 +4,7 @@
|
||||
|
||||
import { execFileSync, execFile } from 'child_process';
|
||||
import { existsSync, mkdirSync, mkdtempSync, rmSync, readFileSync, writeFileSync,
|
||||
readdirSync, statSync, cpSync, copyFileSync } from 'fs';
|
||||
readdirSync, statSync, cpSync, copyFileSync, chmodSync } from 'fs';
|
||||
import { createHash } from 'crypto';
|
||||
import { join, resolve, dirname, relative, basename, extname } from 'path';
|
||||
import { tmpdir, cpus } from 'os';
|
||||
@@ -713,7 +713,9 @@ async function runCaseAsync(testCase, opts) {
|
||||
|
||||
// osOnly: gate a case to one OS (e.g. a fake platform written as a .cmd cannot run on
|
||||
// macOS/Linux at all, whatever the port). Values are process.platform strings.
|
||||
if (caseData.osOnly && caseData.osOnly !== process.platform) {
|
||||
// Значение — строка или массив строк process.platform: фейк платформы бывает нужен и на
|
||||
// darwin, и на linux, а дублировать кейс ради второй ОС смысла нет.
|
||||
if (caseData.osOnly && ![].concat(caseData.osOnly).includes(process.platform)) {
|
||||
return { id: testCase.id, skill: testCase.skillDir, name: testCase.name, passed: true, skipped: true, errors: [], elapsed: '0.0s' };
|
||||
}
|
||||
|
||||
@@ -745,6 +747,9 @@ async function runCaseAsync(testCase, opts) {
|
||||
: JSON.stringify(step.writeFile.content, null, 2);
|
||||
mkdirSync(dirname(wfPath), { recursive: true });
|
||||
writeFileSync(wfPath, wfContent, 'utf8');
|
||||
// Бит исполнения: на *nix навык запускает платформу через exec, и фейк без +x
|
||||
// не стартует вовсе. На Windows chmod — no-op.
|
||||
if (step.writeFile.executable) chmodSync(wfPath, 0o755);
|
||||
continue;
|
||||
}
|
||||
const preScript = resolveScript(step.script, opts.runtime);
|
||||
@@ -1363,6 +1368,9 @@ async function runIntegrationOnce(test, opts, engine, labelEngine) {
|
||||
const abs = target.includes(':') || target.startsWith('/') ? target : join(workDir, target);
|
||||
mkdirSync(dirname(abs), { recursive: true });
|
||||
writeFileSync(abs, step.content ?? '', 'utf8');
|
||||
// Бит исполнения: на *nix навык запускает платформу через exec, и фейк без +x
|
||||
// не стартует вовсе. На Windows chmod — no-op.
|
||||
if (step.executable) chmodSync(abs, 0o755);
|
||||
const stepElapsed = ((performance.now() - stepT0) / 1000).toFixed(1);
|
||||
stepResults.push({ name: step.name, passed: true, elapsed: `${stepElapsed}s` });
|
||||
} catch (e) {
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
|
||||
import { execFileSync } from 'child_process';
|
||||
import { existsSync, mkdirSync, mkdtempSync, rmSync, readFileSync, writeFileSync,
|
||||
readdirSync, statSync, cpSync, copyFileSync } from 'fs';
|
||||
readdirSync, statSync, cpSync, copyFileSync, chmodSync } from 'fs';
|
||||
import { join, resolve, dirname, basename } from 'path';
|
||||
import { tmpdir } from 'os';
|
||||
|
||||
@@ -627,6 +627,9 @@ function runPreSteps(preRun, workDir, runtime, log) {
|
||||
: JSON.stringify(step.writeFile.content, null, 2);
|
||||
mkdirSync(dirname(wfPath), { recursive: true });
|
||||
writeFileSync(wfPath, wfContent, 'utf8');
|
||||
// Бит исполнения: на *nix навык запускает платформу через exec, и фейк без +x
|
||||
// не стартует вовсе. На Windows chmod — no-op.
|
||||
if (step.writeFile.executable) chmodSync(wfPath, 0o755);
|
||||
log(`preRun: writeFile ${step.writeFile.path}`, true);
|
||||
continue;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user