fix(skills): ibcmd non-interactive — fast-fail вместо зависания на запросе учётки (#28)

ibcmd при отсутствии/неверных учётных данных уходил в интерактивный запрос и
зависал. Эмпирически (реальный ibcmd, macOS+Windows, базы с пользователями):
вис возникает только когда не задан -UserName; stdin=DEVNULL НЕ лечит (наоборот
виснет). Лечит закрытый stdin-пайп (EOF) → ibcmd падает за ~4-7с с внятным
«Идентификация пользователя не выполнена».

- python (12 файлов + stub): run_ibcmd(cmd, has_username) c input="" вместо
  прямого subprocess.run; без таймаута. Остаточный случай python+Windows+нет
  -UserName (ibcmd читает консоль) помечается hint'ом в stderr (English, model-facing).
- PowerShell (12 файлов): Invoke-IbcmdProcess через [System.Diagnostics.Process] +
  RedirectStandardInput + StandardInput.Close() → fast-fail; StandardOutputEncoding
  cp866 (кириллица ibcmd не мойибейлится). Ветка 1cv8/DESIGNER не тронута.
- Жёсткий таймаут не вводим: у вызывающей стороны свой бэкстоп, авто-kill рвал бы
  длинные легитимные операции.
- Синхронный бамп версий ps1+py всех затронутых навыков.

Fixes #28

Co-Authored-By: Korolev Pavel <korolev.vrn@gmail.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Nick Shirokov
2026-06-30 17:23:59 +03:00
parent 696af58cf7
commit 4b6bdac484
24 changed files with 656 additions and 66 deletions
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
# db-load-xml v1.11 — Load 1C configuration from XML files
# db-load-xml v1.12 — Load 1C configuration from XML files
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
import argparse
@@ -78,6 +78,27 @@ def resolve_v8path(v8path):
return v8path
IBCMD_NOUSER_HINT = (
"[ibcmd] No -UserName/-Password given; the infobase may require authentication. "
"On Windows ibcmd reads credentials from the console (stdin is ignored), so this "
"call may block instead of failing. If it does not return promptly, abort and "
"re-run with -UserName and -Password.\n"
)
def run_ibcmd(cmd, has_username=False, warn_no_user=True):
"""Run an ibcmd command non-interactively.
input="" closes stdin (EOF) so ibcmd's auth prompt fast-fails instead of hanging.
On Windows without -UserName ibcmd reads the console directly and may still block —
that residual case is flagged via IBCMD_NOUSER_HINT (model-facing).
"""
if warn_no_user and os.name == "nt" and not has_username:
sys.stderr.write(IBCMD_NOUSER_HINT)
sys.stderr.flush()
return subprocess.run(cmd, input="", capture_output=True, encoding="utf-8", errors="replace")
def main():
sys.stdout.reconfigure(encoding="utf-8")
sys.stderr.reconfigure(encoding="utf-8")
@@ -179,7 +200,7 @@ def main():
arguments.append(f"--password={args.Password}")
arguments.append(f"--data={ib_data}")
print(f"Running: ibcmd {' '.join(arguments)}")
result = subprocess.run([v8path] + arguments, capture_output=True, encoding="utf-8", errors="replace")
result = run_ibcmd([v8path] + arguments, bool(args.UserName))
if result.returncode != 0:
print(f"Error loading configuration from files (code: {result.returncode})", file=sys.stderr)
if result.stdout:
@@ -199,7 +220,7 @@ def main():
apply_args.append(f"--password={args.Password}")
apply_args.append(f"--data={ib_data}")
print(f"Running: ibcmd {' '.join(apply_args)}")
ar = subprocess.run([v8path] + apply_args, capture_output=True, encoding="utf-8", errors="replace")
ar = run_ibcmd([v8path] + apply_args, bool(args.UserName))
exit_code = ar.returncode
if exit_code == 0:
print("Database configuration updated successfully")