From eb1796ef9452ea92e86aa111bdb2c9827f3002f0 Mon Sep 17 00:00:00 2001 From: Nick Shirokov Date: Sat, 26 Sep 2026 13:53:51 +0300 Subject: [PATCH] =?UTF-8?q?fix(db-*,=20epf-*):=20=D0=BE=D1=88=D0=B8=D0=B1?= =?UTF-8?q?=D0=BA=D0=B0=20=D0=B4=D0=BE=20=D0=B7=D0=B0=D0=BF=D1=83=D1=81?= =?UTF-8?q?=D0=BA=D0=B0=20=D0=BF=D0=BB=D0=B0=D1=82=D1=84=D0=BE=D1=80=D0=BC?= =?UTF-8?q?=D1=8B=20=D0=BD=D0=B5=20=D0=B2=D1=8B=D0=B4=D0=B0=D1=91=D1=82?= =?UTF-8?q?=D1=81=D1=8F=20=D0=B7=D0=B0=20=D1=83=D1=81=D0=BF=D0=B5=D1=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Временный каталог брался из $env:TEMP, которой вне Windows нет. Join-Path падал на привязке параметра внутри try/finally без catch: try прерывался, finally отрабатывал, и скрипт выходил с кодом 0 — платформа не запускалась, постусловие не проверялось (#106). - временный каталог — [IO.Path]::GetTempPath() (на Windows тот же путь); - верхнеуровневый trap { … exit 1 } в 15 скриптах db-*/epf-*, запускающих платформу: любая необработанная ошибка даёт код 1 и печатает место; - уборка временного каталога в finally не падает на пустом пути; - гард check-ps-portability.mjs держит оба правила. Co-Authored-By: Claude Opus 5.5 (1M context) --- .../db-cfe-admin/scripts/db-cfe-admin.ps1 | 11 ++- .../db-cfe-admin/scripts/db-cfe-admin.py | 2 +- .../skills/db-create/scripts/db-create.ps1 | 11 ++- .claude/skills/db-create/scripts/db-create.py | 2 +- .../skills/db-dump-cf/scripts/db-dump-cf.ps1 | 11 ++- .../skills/db-dump-cf/scripts/db-dump-cf.py | 2 +- .../skills/db-dump-dt/scripts/db-dump-dt.ps1 | 11 ++- .../skills/db-dump-dt/scripts/db-dump-dt.py | 2 +- .../db-dump-xml/scripts/db-dump-xml.ps1 | 11 ++- .../skills/db-dump-xml/scripts/db-dump-xml.py | 2 +- .../skills/db-load-cf/scripts/db-load-cf.ps1 | 15 +++-- .../skills/db-load-cf/scripts/db-load-cf.py | 2 +- .../skills/db-load-dt/scripts/db-load-dt.ps1 | 11 ++- .../skills/db-load-dt/scripts/db-load-dt.py | 2 +- .../db-load-git/scripts/db-load-git.ps1 | 15 +++-- .../skills/db-load-git/scripts/db-load-git.py | 2 +- .../db-load-xml/scripts/db-load-xml.ps1 | 15 +++-- .../skills/db-load-xml/scripts/db-load-xml.py | 2 +- .claude/skills/db-repo/scripts/db-repo.ps1 | 17 +++-- .claude/skills/db-repo/scripts/db-repo.py | 2 +- .claude/skills/db-run/scripts/db-run.ps1 | 7 +- .claude/skills/db-run/scripts/db-run.py | 2 +- .../skills/db-update/scripts/db-update.ps1 | 15 +++-- .claude/skills/db-update/scripts/db-update.py | 2 +- .../skills/epf-build/scripts/epf-build.ps1 | 19 ++++-- .claude/skills/epf-build/scripts/epf-build.py | 2 +- .../epf-build/scripts/stub-db-create.ps1 | 15 +++-- .../epf-build/scripts/stub-db-create.py | 2 +- .claude/skills/epf-dump/scripts/epf-dump.ps1 | 11 ++- .claude/skills/epf-dump/scripts/epf-dump.py | 2 +- .../web-publish/scripts/web-publish.ps1 | 6 +- .../skills/web-publish/scripts/web-publish.py | 2 +- tests/skills/README.md | 11 +++ tests/skills/check-all.mjs | 1 + tests/skills/check-ps-portability.mjs | 67 +++++++++++++++++++ 35 files changed, 233 insertions(+), 79 deletions(-) create mode 100644 tests/skills/check-ps-portability.mjs diff --git a/.claude/skills/db-cfe-admin/scripts/db-cfe-admin.ps1 b/.claude/skills/db-cfe-admin/scripts/db-cfe-admin.ps1 index ee97a96ea..5dcc09b70 100644 --- a/.claude/skills/db-cfe-admin/scripts/db-cfe-admin.ps1 +++ b/.claude/skills/db-cfe-admin/scripts/db-cfe-admin.ps1 @@ -1,4 +1,4 @@ -# db-cfe-admin v1.1 — Configuration extensions in a 1C infobase: list, check, properties, delete +# db-cfe-admin v1.2 — Configuration extensions in a 1C infobase: list, check, properties, delete # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills # NB: *nix-раскладку платформы (/opt/1cv8//1cv8, без .exe) знает только .py-порт — PS на *nix не исполняется. <# @@ -103,6 +103,11 @@ param( [string[]]$AdditionalIbcmdArguments = @() ) +# Необработанная ошибка (напр. привязка параметра) внутри try/finally без catch завершала +# скрипт с кодом 0 — ложный успех без запуска платформы. Любая такая ошибка — код 1. +# py-порт: необработанное исключение и так даёт код 1. +trap { Write-Host "Error: $($_.Exception.Message) ($($_.InvocationInfo.ScriptName):$($_.InvocationInfo.ScriptLineNumber))" -ForegroundColor Red; exit 1 } + $OutputEncoding = [System.Text.Encoding]::UTF8 [Console]::OutputEncoding = [System.Text.Encoding]::UTF8 @@ -663,7 +668,7 @@ function Invoke-Designer { Write-Host "Error: 1C executable not found at $v8Exe" -ForegroundColor Red exit 1 } - $tempDir = Join-Path $env:TEMP "db_cfe_admin_$(Get-Random)" + $tempDir = Join-Path ([IO.Path]::GetTempPath()) "db_cfe_admin_$(Get-Random)" New-Item -ItemType Directory -Path $tempDir -Force | Out-Null try { $arguments = @("DESIGNER") @@ -694,7 +699,7 @@ function Invoke-Designer { Output = $res.Output } } finally { - if (Test-Path $tempDir) { Remove-Item -Path $tempDir -Recurse -Force -ErrorAction SilentlyContinue } + if ($tempDir -and (Test-Path $tempDir)) { Remove-Item -Path $tempDir -Recurse -Force -ErrorAction SilentlyContinue } } } diff --git a/.claude/skills/db-cfe-admin/scripts/db-cfe-admin.py b/.claude/skills/db-cfe-admin/scripts/db-cfe-admin.py index b95008e9a..6761aa2d9 100644 --- a/.claude/skills/db-cfe-admin/scripts/db-cfe-admin.py +++ b/.claude/skills/db-cfe-admin/scripts/db-cfe-admin.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# db-cfe-admin v1.1 — Configuration extensions in a 1C infobase: list, check, properties, delete +# db-cfe-admin v1.2 — Configuration extensions in a 1C infobase: list, check, properties, delete # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse diff --git a/.claude/skills/db-create/scripts/db-create.ps1 b/.claude/skills/db-create/scripts/db-create.ps1 index d827ab385..43d4b9d69 100644 --- a/.claude/skills/db-create/scripts/db-create.ps1 +++ b/.claude/skills/db-create/scripts/db-create.ps1 @@ -1,4 +1,4 @@ -# db-create v1.15 — Create 1C information base +# db-create v1.16 — Create 1C information base # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills # NB: *nix-раскладку платформы (/opt/1cv8//1cv8, без .exe) знает только .py-порт — PS на *nix не исполняется. <# @@ -76,6 +76,11 @@ param( [string[]]$AdditionalIbcmdArguments = @() ) +# Необработанная ошибка (напр. привязка параметра) внутри try/finally без catch завершала +# скрипт с кодом 0 — ложный успех без запуска платформы. Любая такая ошибка — код 1. +# py-порт: необработанное исключение и так даёт код 1. +trap { Write-Host "Error: $($_.Exception.Message) ($($_.InvocationInfo.ScriptName):$($_.InvocationInfo.ScriptLineNumber))" -ForegroundColor Red; exit 1 } + $OutputEncoding = [System.Text.Encoding]::UTF8 [Console]::OutputEncoding = [System.Text.Encoding]::UTF8 @@ -433,7 +438,7 @@ if ($UseTemplate -and -not (Test-Path $UseTemplate)) { } # --- Temp dir --- -$tempDir = Join-Path $env:TEMP "db_create_$(Get-Random)" +$tempDir = Join-Path ([IO.Path]::GetTempPath()) "db_create_$(Get-Random)" New-Item -ItemType Directory -Path $tempDir -Force | Out-Null try { @@ -533,7 +538,7 @@ try { exit $exitCode } finally { - if (Test-Path $tempDir) { + if ($tempDir -and (Test-Path $tempDir)) { Remove-Item -Path $tempDir -Recurse -Force -ErrorAction SilentlyContinue } } diff --git a/.claude/skills/db-create/scripts/db-create.py b/.claude/skills/db-create/scripts/db-create.py index c51821715..8c31c17af 100644 --- a/.claude/skills/db-create/scripts/db-create.py +++ b/.claude/skills/db-create/scripts/db-create.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# db-create v1.15 — Create 1C information base +# db-create v1.16 — Create 1C information base # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse diff --git a/.claude/skills/db-dump-cf/scripts/db-dump-cf.ps1 b/.claude/skills/db-dump-cf/scripts/db-dump-cf.ps1 index 2028f8efb..3cb05d197 100644 --- a/.claude/skills/db-dump-cf/scripts/db-dump-cf.ps1 +++ b/.claude/skills/db-dump-cf/scripts/db-dump-cf.ps1 @@ -1,4 +1,4 @@ -# db-dump-cf v1.17 — Dump 1C configuration to CF file +# db-dump-cf v1.18 — Dump 1C configuration to CF file # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills # NB: *nix-раскладку платформы (/opt/1cv8//1cv8, без .exe) знает только .py-порт — PS на *nix не исполняется. <# @@ -85,6 +85,11 @@ param( [string[]]$AdditionalIbcmdArguments = @() ) +# Необработанная ошибка (напр. привязка параметра) внутри try/finally без catch завершала +# скрипт с кодом 0 — ложный успех без запуска платформы. Любая такая ошибка — код 1. +# py-порт: необработанное исключение и так даёт код 1. +trap { Write-Host "Error: $($_.Exception.Message) ($($_.InvocationInfo.ScriptName):$($_.InvocationInfo.ScriptLineNumber))" -ForegroundColor Red; exit 1 } + $OutputEncoding = [System.Text.Encoding]::UTF8 [Console]::OutputEncoding = [System.Text.Encoding]::UTF8 @@ -461,7 +466,7 @@ if ($outDir -and -not (Test-Path $outDir)) { } # --- Temp dir --- -$tempDir = Join-Path $env:TEMP "db_dump_cf_$(Get-Random)" +$tempDir = Join-Path ([IO.Path]::GetTempPath()) "db_dump_cf_$(Get-Random)" New-Item -ItemType Directory -Path $tempDir -Force | Out-Null try { @@ -553,7 +558,7 @@ try { exit $exitCode } finally { - if (Test-Path $tempDir) { + if ($tempDir -and (Test-Path $tempDir)) { Remove-Item -Path $tempDir -Recurse -Force -ErrorAction SilentlyContinue } } diff --git a/.claude/skills/db-dump-cf/scripts/db-dump-cf.py b/.claude/skills/db-dump-cf/scripts/db-dump-cf.py index 2b74e872e..692814cf9 100644 --- a/.claude/skills/db-dump-cf/scripts/db-dump-cf.py +++ b/.claude/skills/db-dump-cf/scripts/db-dump-cf.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# db-dump-cf v1.17 — Dump 1C configuration to CF file +# db-dump-cf v1.18 — Dump 1C configuration to CF file # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse diff --git a/.claude/skills/db-dump-dt/scripts/db-dump-dt.ps1 b/.claude/skills/db-dump-dt/scripts/db-dump-dt.ps1 index c2d720920..a64973332 100644 --- a/.claude/skills/db-dump-dt/scripts/db-dump-dt.ps1 +++ b/.claude/skills/db-dump-dt/scripts/db-dump-dt.ps1 @@ -1,4 +1,4 @@ -# db-dump-dt v1.16 — Dump 1C information base to DT file +# db-dump-dt v1.17 — Dump 1C information base to DT file # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills # NB: *nix-раскладку платформы (/opt/1cv8//1cv8, без .exe) знает только .py-порт — PS на *nix не исполняется. <# @@ -69,6 +69,11 @@ param( [string[]]$AdditionalIbcmdArguments = @() ) +# Необработанная ошибка (напр. привязка параметра) внутри try/finally без catch завершала +# скрипт с кодом 0 — ложный успех без запуска платформы. Любая такая ошибка — код 1. +# py-порт: необработанное исключение и так даёт код 1. +trap { Write-Host "Error: $($_.Exception.Message) ($($_.InvocationInfo.ScriptName):$($_.InvocationInfo.ScriptLineNumber))" -ForegroundColor Red; exit 1 } + $OutputEncoding = [System.Text.Encoding]::UTF8 [Console]::OutputEncoding = [System.Text.Encoding]::UTF8 @@ -445,7 +450,7 @@ if ($outDir -and -not (Test-Path $outDir)) { } # --- Temp dir --- -$tempDir = Join-Path $env:TEMP "db_dump_dt_$(Get-Random)" +$tempDir = Join-Path ([IO.Path]::GetTempPath()) "db_dump_dt_$(Get-Random)" New-Item -ItemType Directory -Path $tempDir -Force | Out-Null try { @@ -527,7 +532,7 @@ try { exit $exitCode } finally { - if (Test-Path $tempDir) { + if ($tempDir -and (Test-Path $tempDir)) { Remove-Item -Path $tempDir -Recurse -Force -ErrorAction SilentlyContinue } } diff --git a/.claude/skills/db-dump-dt/scripts/db-dump-dt.py b/.claude/skills/db-dump-dt/scripts/db-dump-dt.py index 72aa08260..1a3fbcc29 100644 --- a/.claude/skills/db-dump-dt/scripts/db-dump-dt.py +++ b/.claude/skills/db-dump-dt/scripts/db-dump-dt.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# db-dump-dt v1.16 — Dump 1C information base to DT file +# db-dump-dt v1.17 — Dump 1C information base to DT file # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse diff --git a/.claude/skills/db-dump-xml/scripts/db-dump-xml.ps1 b/.claude/skills/db-dump-xml/scripts/db-dump-xml.ps1 index df03f5e8a..ed0181976 100644 --- a/.claude/skills/db-dump-xml/scripts/db-dump-xml.ps1 +++ b/.claude/skills/db-dump-xml/scripts/db-dump-xml.ps1 @@ -1,4 +1,4 @@ -# db-dump-xml v1.23 — Dump 1C configuration to XML files +# db-dump-xml v1.24 — Dump 1C configuration to XML files # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills # NB: *nix-раскладку платформы (/opt/1cv8//1cv8, без .exe) знает только .py-порт — PS на *nix не исполняется. <# @@ -122,6 +122,11 @@ param( [string[]]$AdditionalIbcmdArguments = @() ) +# Необработанная ошибка (напр. привязка параметра) внутри try/finally без catch завершала +# скрипт с кодом 0 — ложный успех без запуска платформы. Любая такая ошибка — код 1. +# py-порт: необработанное исключение и так даёт код 1. +trap { Write-Host "Error: $($_.Exception.Message) ($($_.InvocationInfo.ScriptName):$($_.InvocationInfo.ScriptLineNumber))" -ForegroundColor Red; exit 1 } + $OutputEncoding = [System.Text.Encoding]::UTF8 [Console]::OutputEncoding = [System.Text.Encoding]::UTF8 @@ -620,7 +625,7 @@ if (-not (Test-Path $ConfigDir)) { } # --- Temp dir --- -$tempDir = Join-Path $env:TEMP "db_dump_xml_$(Get-Random)" +$tempDir = Join-Path ([IO.Path]::GetTempPath()) "db_dump_xml_$(Get-Random)" New-Item -ItemType Directory -Path $tempDir -Force | Out-Null try { @@ -782,7 +787,7 @@ try { exit $exitCode } finally { - if (Test-Path $tempDir) { + if ($tempDir -and (Test-Path $tempDir)) { Remove-Item -Path $tempDir -Recurse -Force -ErrorAction SilentlyContinue } } diff --git a/.claude/skills/db-dump-xml/scripts/db-dump-xml.py b/.claude/skills/db-dump-xml/scripts/db-dump-xml.py index 729fb80e7..ebb5917c0 100644 --- a/.claude/skills/db-dump-xml/scripts/db-dump-xml.py +++ b/.claude/skills/db-dump-xml/scripts/db-dump-xml.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# db-dump-xml v1.23 — Dump 1C configuration to XML files +# db-dump-xml v1.24 — Dump 1C configuration to XML files # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse diff --git a/.claude/skills/db-load-cf/scripts/db-load-cf.ps1 b/.claude/skills/db-load-cf/scripts/db-load-cf.ps1 index 946f146ee..af57cf3dc 100644 --- a/.claude/skills/db-load-cf/scripts/db-load-cf.ps1 +++ b/.claude/skills/db-load-cf/scripts/db-load-cf.ps1 @@ -1,4 +1,4 @@ -# db-load-cf v1.19 — Load 1C configuration from CF file +# db-load-cf v1.20 — Load 1C configuration from CF file # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills # NB: *nix-раскладку платформы (/opt/1cv8//1cv8, без .exe) знает только .py-порт — PS на *nix не исполняется. <# @@ -95,6 +95,11 @@ param( [string[]]$AdditionalIbcmdArguments = @() ) +# Необработанная ошибка (напр. привязка параметра) внутри try/finally без catch завершала +# скрипт с кодом 0 — ложный успех без запуска платформы. Любая такая ошибка — код 1. +# py-порт: необработанное исключение и так даёт код 1. +trap { Write-Host "Error: $($_.Exception.Message) ($($_.InvocationInfo.ScriptName):$($_.InvocationInfo.ScriptLineNumber))" -ForegroundColor Red; exit 1 } + $OutputEncoding = [System.Text.Encoding]::UTF8 [Console]::OutputEncoding = [System.Text.Encoding]::UTF8 @@ -472,7 +477,7 @@ function Invoke-ApplyCheck { $exeLeaf = Split-Path $Exe -Leaf $v8 = if ($exeLeaf -match '^ibcmd') { Join-Path $exeDir ("1cv8" + [System.IO.Path]::GetExtension($Exe)) } else { $Exe } if (-not (Test-Path $v8)) { return @{ Skipped = $true; Reason = "1cv8 not found at $v8"; ExitCode = 0; Lines = @() } } - $dir = Join-Path $env:TEMP "apply_check_$(Get-Random)" + $dir = Join-Path ([IO.Path]::GetTempPath()) "apply_check_$(Get-Random)" New-Item -ItemType Directory -Path $dir -Force | Out-Null try { $a = @("DESIGNER") + $ConnArgs + @("/CheckCanApplyConfigurationExtensions") @@ -488,7 +493,7 @@ function Invoke-ApplyCheck { } return @{ Skipped = $false; Reason = ''; ExitCode = $res.ExitCode; Lines = $lines } } finally { - if (Test-Path $dir) { Remove-Item -Path $dir -Recurse -Force -ErrorAction SilentlyContinue } + if ($dir -and (Test-Path $dir)) { Remove-Item -Path $dir -Recurse -Force -ErrorAction SilentlyContinue } } } @@ -548,7 +553,7 @@ if (-not (Test-Path $InputFile)) { } # --- Temp dir --- -$tempDir = Join-Path $env:TEMP "db_load_cf_$(Get-Random)" +$tempDir = Join-Path ([IO.Path]::GetTempPath()) "db_load_cf_$(Get-Random)" New-Item -ItemType Directory -Path $tempDir -Force | Out-Null try { @@ -646,7 +651,7 @@ try { exit $exitCode } finally { - if (Test-Path $tempDir) { + if ($tempDir -and (Test-Path $tempDir)) { Remove-Item -Path $tempDir -Recurse -Force -ErrorAction SilentlyContinue } } diff --git a/.claude/skills/db-load-cf/scripts/db-load-cf.py b/.claude/skills/db-load-cf/scripts/db-load-cf.py index c3f14d579..b83a5a2d5 100644 --- a/.claude/skills/db-load-cf/scripts/db-load-cf.py +++ b/.claude/skills/db-load-cf/scripts/db-load-cf.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# db-load-cf v1.19 — Load 1C configuration from CF file +# db-load-cf v1.20 — Load 1C configuration from CF file # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse diff --git a/.claude/skills/db-load-dt/scripts/db-load-dt.ps1 b/.claude/skills/db-load-dt/scripts/db-load-dt.ps1 index 50a91df6a..68c2da3a4 100644 --- a/.claude/skills/db-load-dt/scripts/db-load-dt.ps1 +++ b/.claude/skills/db-load-dt/scripts/db-load-dt.ps1 @@ -1,4 +1,4 @@ -# db-load-dt v1.17 — Load 1C information base from DT file +# db-load-dt v1.18 — Load 1C information base from DT file # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills # NB: *nix-раскладку платформы (/opt/1cv8//1cv8, без .exe) знает только .py-порт — PS на *nix не исполняется. <# @@ -82,6 +82,11 @@ param( [string[]]$AdditionalIbcmdArguments = @() ) +# Необработанная ошибка (напр. привязка параметра) внутри try/finally без catch завершала +# скрипт с кодом 0 — ложный успех без запуска платформы. Любая такая ошибка — код 1. +# py-порт: необработанное исключение и так даёт код 1. +trap { Write-Host "Error: $($_.Exception.Message) ($($_.InvocationInfo.ScriptName):$($_.InvocationInfo.ScriptLineNumber))" -ForegroundColor Red; exit 1 } + $OutputEncoding = [System.Text.Encoding]::UTF8 [Console]::OutputEncoding = [System.Text.Encoding]::UTF8 @@ -468,7 +473,7 @@ if (-not (Test-Path $InputFile)) { } # --- Temp dir --- -$tempDir = Join-Path $env:TEMP "db_load_dt_$(Get-Random)" +$tempDir = Join-Path ([IO.Path]::GetTempPath()) "db_load_dt_$(Get-Random)" New-Item -ItemType Directory -Path $tempDir -Force | Out-Null try { @@ -544,7 +549,7 @@ try { exit $exitCode } finally { - if (Test-Path $tempDir) { + if ($tempDir -and (Test-Path $tempDir)) { Remove-Item -Path $tempDir -Recurse -Force -ErrorAction SilentlyContinue } } diff --git a/.claude/skills/db-load-dt/scripts/db-load-dt.py b/.claude/skills/db-load-dt/scripts/db-load-dt.py index c97447bfd..80a84cab7 100644 --- a/.claude/skills/db-load-dt/scripts/db-load-dt.py +++ b/.claude/skills/db-load-dt/scripts/db-load-dt.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# db-load-dt v1.17 — Load 1C information base from DT file +# db-load-dt v1.18 — Load 1C information base from DT file # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse diff --git a/.claude/skills/db-load-git/scripts/db-load-git.ps1 b/.claude/skills/db-load-git/scripts/db-load-git.ps1 index 2dc527a61..1573a1650 100644 --- a/.claude/skills/db-load-git/scripts/db-load-git.ps1 +++ b/.claude/skills/db-load-git/scripts/db-load-git.ps1 @@ -1,4 +1,4 @@ -# db-load-git v1.29 — Load Git changes into 1C database +# db-load-git v1.30 — Load Git changes into 1C database # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills # NB: *nix-раскладку платформы (/opt/1cv8//1cv8, без .exe) знает только .py-порт — PS на *nix не исполняется. <# @@ -136,6 +136,11 @@ param( [string[]]$AdditionalIbcmdArguments = @() ) +# Необработанная ошибка (напр. привязка параметра) внутри try/finally без catch завершала +# скрипт с кодом 0 — ложный успех без запуска платформы. Любая такая ошибка — код 1. +# py-порт: необработанное исключение и так даёт код 1. +trap { Write-Host "Error: $($_.Exception.Message) ($($_.InvocationInfo.ScriptName):$($_.InvocationInfo.ScriptLineNumber))" -ForegroundColor Red; exit 1 } + $OutputEncoding = [System.Text.Encoding]::UTF8 [Console]::OutputEncoding = [System.Text.Encoding]::UTF8 @@ -664,7 +669,7 @@ function Invoke-ApplyCheck { $exeLeaf = Split-Path $Exe -Leaf $v8 = if ($exeLeaf -match '^ibcmd') { Join-Path $exeDir ("1cv8" + [System.IO.Path]::GetExtension($Exe)) } else { $Exe } if (-not (Test-Path $v8)) { return @{ Skipped = $true; Reason = "1cv8 not found at $v8"; ExitCode = 0; Lines = @() } } - $dir = Join-Path $env:TEMP "apply_check_$(Get-Random)" + $dir = Join-Path ([IO.Path]::GetTempPath()) "apply_check_$(Get-Random)" New-Item -ItemType Directory -Path $dir -Force | Out-Null try { $a = @("DESIGNER") + $ConnArgs + @("/CheckCanApplyConfigurationExtensions") @@ -680,7 +685,7 @@ function Invoke-ApplyCheck { } return @{ Skipped = $false; Reason = ''; ExitCode = $res.ExitCode; Lines = $lines } } finally { - if (Test-Path $dir) { Remove-Item -Path $dir -Recurse -Force -ErrorAction SilentlyContinue } + if ($dir -and (Test-Path $dir)) { Remove-Item -Path $dir -Recurse -Force -ErrorAction SilentlyContinue } } } @@ -911,7 +916,7 @@ if ($DryRun) { } # --- Temp dir --- -$tempDir = Join-Path $env:TEMP "db_load_git_$(Get-Random)" +$tempDir = Join-Path ([IO.Path]::GetTempPath()) "db_load_git_$(Get-Random)" New-Item -ItemType Directory -Path $tempDir -Force | Out-Null try { @@ -1060,7 +1065,7 @@ try { exit $exitCode } finally { - if (Test-Path $tempDir) { + if ($tempDir -and (Test-Path $tempDir)) { Remove-Item -Path $tempDir -Recurse -Force -ErrorAction SilentlyContinue } } diff --git a/.claude/skills/db-load-git/scripts/db-load-git.py b/.claude/skills/db-load-git/scripts/db-load-git.py index 337ab1ba4..74296bbbb 100644 --- a/.claude/skills/db-load-git/scripts/db-load-git.py +++ b/.claude/skills/db-load-git/scripts/db-load-git.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# db-load-git v1.29 — Load Git changes into 1C database +# db-load-git v1.30 — Load Git changes into 1C database # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse diff --git a/.claude/skills/db-load-xml/scripts/db-load-xml.ps1 b/.claude/skills/db-load-xml/scripts/db-load-xml.ps1 index 96ae8c4d8..e1e7e9090 100644 --- a/.claude/skills/db-load-xml/scripts/db-load-xml.ps1 +++ b/.claude/skills/db-load-xml/scripts/db-load-xml.ps1 @@ -1,4 +1,4 @@ -# db-load-xml v1.31 — Load 1C configuration from XML files +# db-load-xml v1.32 — Load 1C configuration from XML files # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills # NB: *nix-раскладку платформы (/opt/1cv8//1cv8, без .exe) знает только .py-порт — PS на *nix не исполняется. <# @@ -132,6 +132,11 @@ param( [string[]]$AdditionalIbcmdArguments = @() ) +# Необработанная ошибка (напр. привязка параметра) внутри try/finally без catch завершала +# скрипт с кодом 0 — ложный успех без запуска платформы. Любая такая ошибка — код 1. +# py-порт: необработанное исключение и так даёт код 1. +trap { Write-Host "Error: $($_.Exception.Message) ($($_.InvocationInfo.ScriptName):$($_.InvocationInfo.ScriptLineNumber))" -ForegroundColor Red; exit 1 } + $OutputEncoding = [System.Text.Encoding]::UTF8 [Console]::OutputEncoding = [System.Text.Encoding]::UTF8 @@ -627,7 +632,7 @@ function Invoke-ApplyCheck { $exeLeaf = Split-Path $Exe -Leaf $v8 = if ($exeLeaf -match '^ibcmd') { Join-Path $exeDir ("1cv8" + [System.IO.Path]::GetExtension($Exe)) } else { $Exe } if (-not (Test-Path $v8)) { return @{ Skipped = $true; Reason = "1cv8 not found at $v8"; ExitCode = 0; Lines = @() } } - $dir = Join-Path $env:TEMP "apply_check_$(Get-Random)" + $dir = Join-Path ([IO.Path]::GetTempPath()) "apply_check_$(Get-Random)" New-Item -ItemType Directory -Path $dir -Force | Out-Null try { $a = @("DESIGNER") + $ConnArgs + @("/CheckCanApplyConfigurationExtensions") @@ -643,7 +648,7 @@ function Invoke-ApplyCheck { } return @{ Skipped = $false; Reason = ''; ExitCode = $res.ExitCode; Lines = $lines } } finally { - if (Test-Path $dir) { Remove-Item -Path $dir -Recurse -Force -ErrorAction SilentlyContinue } + if ($dir -and (Test-Path $dir)) { Remove-Item -Path $dir -Recurse -Force -ErrorAction SilentlyContinue } } } @@ -726,7 +731,7 @@ if ($Mode -eq "Partial" -and $AllExtensions) { } # --- Temp dir --- -$tempDir = Join-Path $env:TEMP "db_load_xml_$(Get-Random)" +$tempDir = Join-Path ([IO.Path]::GetTempPath()) "db_load_xml_$(Get-Random)" New-Item -ItemType Directory -Path $tempDir -Force | Out-Null try { @@ -940,7 +945,7 @@ try { exit $exitCode } finally { - if (Test-Path $tempDir) { + if ($tempDir -and (Test-Path $tempDir)) { Remove-Item -Path $tempDir -Recurse -Force -ErrorAction SilentlyContinue } } diff --git a/.claude/skills/db-load-xml/scripts/db-load-xml.py b/.claude/skills/db-load-xml/scripts/db-load-xml.py index 5924a5ca9..af16c5863 100644 --- a/.claude/skills/db-load-xml/scripts/db-load-xml.py +++ b/.claude/skills/db-load-xml/scripts/db-load-xml.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# db-load-xml v1.31 — Load 1C configuration from XML files +# db-load-xml v1.32 — Load 1C configuration from XML files # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse diff --git a/.claude/skills/db-repo/scripts/db-repo.ps1 b/.claude/skills/db-repo/scripts/db-repo.ps1 index 99166c5b7..fb49331f1 100644 --- a/.claude/skills/db-repo/scripts/db-repo.ps1 +++ b/.claude/skills/db-repo/scripts/db-repo.ps1 @@ -1,4 +1,4 @@ -# db-repo v1.16 — 1C configuration repository operations +# db-repo v1.17 — 1C configuration repository operations # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills # NB: движок только 1cv8 — ibcmd работу с хранилищем не поддерживает (нет такого режима). <# @@ -176,6 +176,11 @@ param( [string[]]$AdditionalV8Arguments = @() ) +# Необработанная ошибка (напр. привязка параметра) внутри try/finally без catch завершала +# скрипт с кодом 0 — ложный успех без запуска платформы. Любая такая ошибка — код 1. +# py-порт: необработанное исключение и так даёт код 1. +trap { Write-Host "Error: $($_.Exception.Message) ($($_.InvocationInfo.ScriptName):$($_.InvocationInfo.ScriptLineNumber))" -ForegroundColor Red; exit 1 } + $OutputEncoding = [System.Text.Encoding]::UTF8 [Console]::OutputEncoding = [System.Text.Encoding]::UTF8 function Protect-Secrets { @@ -749,7 +754,7 @@ function Write-ReceivedWarning { $owners = Get-OwnerObjects $Received $hasRoot = @($Received | Where-Object { ($_ -split '\.').Count -eq 1 }).Count -gt 0 if ($owners.Count -gt 0) { - $listPath = Join-Path $env:TEMP "db-repo-received.txt" + $listPath = Join-Path ([IO.Path]::GetTempPath()) "db-repo-received.txt" $utf8Bom = New-Object System.Text.UTF8Encoding($true) [System.IO.File]::WriteAllLines($listPath, $owners, $utf8Bom) Write-Host "Исходники в проекте устарели по этим объектам. Перевыгрузите их ПЕРЕД правкой," -ForegroundColor Yellow @@ -838,7 +843,7 @@ $script:ListLimit = 20 function Save-ObjectList { param([string[]]$Names, [string]$Key) if (-not $Key) { $Key = 'objects' } - $path = Join-Path $env:TEMP "db-repo-$Key.txt" + $path = Join-Path ([IO.Path]::GetTempPath()) "db-repo-$Key.txt" $utf8Bom = New-Object System.Text.UTF8Encoding($true) [System.IO.File]::WriteAllLines($path, $Names, $utf8Bom) return $path @@ -1097,7 +1102,7 @@ if ($WithChildren) { switch ($cmd) { 'report' { # Отчёт печатается в вывод, поэтому путь нужен только если его хотят сохранить. - if (-not $OutputFile) { $OutputFile = Join-Path $env:TEMP "db-repo-report.$ReportFormat" } + if (-not $OutputFile) { $OutputFile = Join-Path ([IO.Path]::GetTempPath()) "db-repo-report.$ReportFormat" } } 'dump-cfg' { if (-not $OutputFile) { Write-Host "Error: -OutputFile (path to the .cf file) is required for dump-cfg" -ForegroundColor Red; exit 1 } } 'add-user' { if (-not $NewUser -or -not $Rights) { Write-Host "Error: -NewUser and -Rights are required for add-user" -ForegroundColor Red; exit 1 } } @@ -1107,7 +1112,7 @@ switch ($cmd) { $extraArgs = @(Resolve-ExtraArgs $AdditionalV8Arguments @{}) -$tempDir = Join-Path $env:TEMP "db_repo_$(Get-Random)" +$tempDir = Join-Path ([IO.Path]::GetTempPath()) "db_repo_$(Get-Random)" New-Item -ItemType Directory -Path $tempDir -Force | Out-Null try { @@ -1275,7 +1280,7 @@ try { exit $verdict } finally { - if (Test-Path $tempDir) { + if ($tempDir -and (Test-Path $tempDir)) { Remove-Item -Path $tempDir -Recurse -Force -ErrorAction SilentlyContinue } } diff --git a/.claude/skills/db-repo/scripts/db-repo.py b/.claude/skills/db-repo/scripts/db-repo.py index 91ed4b196..0a42f0c4e 100644 --- a/.claude/skills/db-repo/scripts/db-repo.py +++ b/.claude/skills/db-repo/scripts/db-repo.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# db-repo v1.16 — 1C configuration repository operations +# db-repo v1.17 — 1C configuration repository operations # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills # NB: движок только 1cv8 — ibcmd работу с хранилищем не поддерживает (нет такого режима). """Работа с хранилищем конфигурации 1С. diff --git a/.claude/skills/db-run/scripts/db-run.ps1 b/.claude/skills/db-run/scripts/db-run.ps1 index 659675360..864e17f70 100644 --- a/.claude/skills/db-run/scripts/db-run.ps1 +++ b/.claude/skills/db-run/scripts/db-run.ps1 @@ -1,4 +1,4 @@ -# db-run v1.11 — Launch 1C:Enterprise +# db-run v1.12 — Launch 1C:Enterprise # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills # NB: *nix-раскладку платформы (/opt/1cv8//1cv8, без .exe) знает только .py-порт — PS на *nix не исполняется. <# @@ -88,6 +88,11 @@ param( [string[]]$AdditionalIbcmdArguments = @() ) +# Необработанная ошибка (напр. привязка параметра) внутри try/finally без catch завершала +# скрипт с кодом 0 — ложный успех без запуска платформы. Любая такая ошибка — код 1. +# py-порт: необработанное исключение и так даёт код 1. +trap { Write-Host "Error: $($_.Exception.Message) ($($_.InvocationInfo.ScriptName):$($_.InvocationInfo.ScriptLineNumber))" -ForegroundColor Red; exit 1 } + $OutputEncoding = [System.Text.Encoding]::UTF8 [Console]::OutputEncoding = [System.Text.Encoding]::UTF8 diff --git a/.claude/skills/db-run/scripts/db-run.py b/.claude/skills/db-run/scripts/db-run.py index d1c9c794b..73d3dc5f9 100644 --- a/.claude/skills/db-run/scripts/db-run.py +++ b/.claude/skills/db-run/scripts/db-run.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# db-run v1.11 — Launch 1C:Enterprise +# db-run v1.12 — Launch 1C:Enterprise # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse diff --git a/.claude/skills/db-update/scripts/db-update.ps1 b/.claude/skills/db-update/scripts/db-update.ps1 index c39f3ee8f..613cb60ed 100644 --- a/.claude/skills/db-update/scripts/db-update.ps1 +++ b/.claude/skills/db-update/scripts/db-update.ps1 @@ -1,4 +1,4 @@ -# db-update v1.21 — Update 1C database configuration +# db-update v1.22 — Update 1C database configuration # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills # NB: *nix-раскладку платформы (/opt/1cv8//1cv8, без .exe) знает только .py-порт — PS на *nix не исполняется. <# @@ -119,6 +119,11 @@ param( [string[]]$AdditionalIbcmdArguments = @() ) +# Необработанная ошибка (напр. привязка параметра) внутри try/finally без catch завершала +# скрипт с кодом 0 — ложный успех без запуска платформы. Любая такая ошибка — код 1. +# py-порт: необработанное исключение и так даёт код 1. +trap { Write-Host "Error: $($_.Exception.Message) ($($_.InvocationInfo.ScriptName):$($_.InvocationInfo.ScriptLineNumber))" -ForegroundColor Red; exit 1 } + if ($Dynamic) { $Dynamic = if (@('on', 'yes', '+') -contains $Dynamic.ToLower()) { '+' } else { '-' } } $OutputEncoding = [System.Text.Encoding]::UTF8 @@ -577,7 +582,7 @@ function Invoke-ApplyCheck { $exeLeaf = Split-Path $Exe -Leaf $v8 = if ($exeLeaf -match '^ibcmd') { Join-Path $exeDir ("1cv8" + [System.IO.Path]::GetExtension($Exe)) } else { $Exe } if (-not (Test-Path $v8)) { return @{ Skipped = $true; Reason = "1cv8 not found at $v8"; ExitCode = 0; Lines = @() } } - $dir = Join-Path $env:TEMP "apply_check_$(Get-Random)" + $dir = Join-Path ([IO.Path]::GetTempPath()) "apply_check_$(Get-Random)" New-Item -ItemType Directory -Path $dir -Force | Out-Null try { $a = @("DESIGNER") + $ConnArgs + @("/CheckCanApplyConfigurationExtensions") @@ -593,7 +598,7 @@ function Invoke-ApplyCheck { } return @{ Skipped = $false; Reason = ''; ExitCode = $res.ExitCode; Lines = $lines } } finally { - if (Test-Path $dir) { Remove-Item -Path $dir -Recurse -Force -ErrorAction SilentlyContinue } + if ($dir -and (Test-Path $dir)) { Remove-Item -Path $dir -Recurse -Force -ErrorAction SilentlyContinue } } } @@ -647,7 +652,7 @@ if ($engine -eq "ibcmd") { } # --- Temp dir --- -$tempDir = Join-Path $env:TEMP "db_update_$(Get-Random)" +$tempDir = Join-Path ([IO.Path]::GetTempPath()) "db_update_$(Get-Random)" New-Item -ItemType Directory -Path $tempDir -Force | Out-Null try { @@ -773,7 +778,7 @@ try { exit $exitCode } finally { - if (Test-Path $tempDir) { + if ($tempDir -and (Test-Path $tempDir)) { Remove-Item -Path $tempDir -Recurse -Force -ErrorAction SilentlyContinue } } diff --git a/.claude/skills/db-update/scripts/db-update.py b/.claude/skills/db-update/scripts/db-update.py index 1cb73b2ed..4b4751ac8 100644 --- a/.claude/skills/db-update/scripts/db-update.py +++ b/.claude/skills/db-update/scripts/db-update.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# db-update v1.21 — Update 1C database configuration +# db-update v1.22 — Update 1C database configuration # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse diff --git a/.claude/skills/epf-build/scripts/epf-build.ps1 b/.claude/skills/epf-build/scripts/epf-build.ps1 index d951d0058..a0bdd3dfe 100644 --- a/.claude/skills/epf-build/scripts/epf-build.ps1 +++ b/.claude/skills/epf-build/scripts/epf-build.ps1 @@ -1,4 +1,4 @@ -# epf-build v1.20 — Build external data processor or report (EPF/ERF) from XML sources +# epf-build v1.21 — Build external data processor or report (EPF/ERF) from XML sources # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills # NB: *nix-раскладку платформы (/opt/1cv8//1cv8, без .exe) знает только .py-порт — PS на *nix не исполняется. <# @@ -95,6 +95,11 @@ param( [string[]]$AdditionalIbcmdArguments = @() ) +# Необработанная ошибка (напр. привязка параметра) внутри try/finally без catch завершала +# скрипт с кодом 0 — ложный успех без запуска платформы. Любая такая ошибка — код 1. +# py-порт: необработанное исключение и так даёт код 1. +trap { Write-Host "Error: $($_.Exception.Message) ($($_.InvocationInfo.ScriptName):$($_.InvocationInfo.ScriptLineNumber))" -ForegroundColor Red; exit 1 } + $OutputEncoding = [System.Text.Encoding]::UTF8 [Console]::OutputEncoding = [System.Text.Encoding]::UTF8 @@ -517,7 +522,7 @@ function Invoke-SourceCheck { Write-Host "[note] source check skipped: 1cv8 not found at $v8" -ForegroundColor Yellow return $false } - $dir = Join-Path $env:TEMP "epf_check_$(Get-Random)" + $dir = Join-Path ([IO.Path]::GetTempPath()) "epf_check_$(Get-Random)" New-Item -ItemType Directory -Path $dir -Force | Out-Null try { $outFile = Join-Path $dir "check_log.txt" @@ -550,7 +555,7 @@ function Invoke-SourceCheck { } return $true } finally { - if (Test-Path $dir) { Remove-Item -Path $dir -Recurse -Force -ErrorAction SilentlyContinue } + if ($dir -and (Test-Path $dir)) { Remove-Item -Path $dir -Recurse -Force -ErrorAction SilentlyContinue } } } @@ -652,7 +657,7 @@ $autoCreatedBase = $null $checkBase = $null $checkBasePath = $null if (-not $InfoBasePath -and (-not $InfoBaseServer -or -not $InfoBaseRef)) { - $autoBasePath = Join-Path $env:TEMP "epf_stub_db_$(Get-Random)" + $autoBasePath = Join-Path ([IO.Path]::GetTempPath()) "epf_stub_db_$(Get-Random)" Write-Host "No database specified. Creating temporary stub database..." if ((New-StubBase $autoBasePath -Embed:($checkList.Count -gt 0)) -ne 0) { # С внедрённой обработкой база падает прежде всего из-за самих исходников @@ -671,7 +676,7 @@ if (-not $InfoBasePath -and (-not $InfoBaseServer -or -not $InfoBaseRef)) { } elseif ($checkList.Count -gt 0) { # Базу указали снаружи: класть проверяемую обработку в чужую конфигурацию нельзя, поэтому под # проверку поднимается своя временная база, а сборка идёт на указанной. - $checkBase = Join-Path $env:TEMP "epf_check_db_$(Get-Random)" + $checkBase = Join-Path ([IO.Path]::GetTempPath()) "epf_check_db_$(Get-Random)" Write-Host "Creating temporary database for the source check..." if ((New-StubBase $checkBase -Embed) -ne 0) { Write-Host "Error: платформа не приняла исходники при подготовке проверки — сборка отменена" -ForegroundColor Red @@ -706,7 +711,7 @@ if ($outDir -and -not (Test-Path $outDir)) { } # --- Temp dir --- -$tempDir = Join-Path $env:TEMP "epf_build_$(Get-Random)" +$tempDir = Join-Path ([IO.Path]::GetTempPath()) "epf_build_$(Get-Random)" New-Item -ItemType Directory -Path $tempDir -Force | Out-Null try { @@ -786,7 +791,7 @@ try { exit $exitCode } finally { - if (Test-Path $tempDir) { + if ($tempDir -and (Test-Path $tempDir)) { Remove-Item -Path $tempDir -Recurse -Force -ErrorAction SilentlyContinue } if ($autoCreatedBase -and (Test-Path $autoCreatedBase)) { diff --git a/.claude/skills/epf-build/scripts/epf-build.py b/.claude/skills/epf-build/scripts/epf-build.py index 58052cfff..38da747dc 100644 --- a/.claude/skills/epf-build/scripts/epf-build.py +++ b/.claude/skills/epf-build/scripts/epf-build.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# epf-build v1.20 — Build external data processor or report (EPF/ERF) from XML sources +# epf-build v1.21 — Build external data processor or report (EPF/ERF) from XML sources # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse diff --git a/.claude/skills/epf-build/scripts/stub-db-create.ps1 b/.claude/skills/epf-build/scripts/stub-db-create.ps1 index dbc05a8b1..1665df240 100644 --- a/.claude/skills/epf-build/scripts/stub-db-create.ps1 +++ b/.claude/skills/epf-build/scripts/stub-db-create.ps1 @@ -1,4 +1,4 @@ -# stub-db-create v1.12 — Create temp 1C infobase with metadata stubs for EPF/ERF build +# stub-db-create v1.13 — Create temp 1C infobase with metadata stubs for EPF/ERF build # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [Parameter(Mandatory)] @@ -22,6 +22,11 @@ param( [string[]]$AdditionalIbcmdArguments = @() ) +# Необработанная ошибка (напр. привязка параметра) внутри try/finally без catch завершала +# скрипт с кодом 0 — ложный успех без запуска платформы. Любая такая ошибка — код 1. +# py-порт: необработанное исключение и так даёт код 1. +trap { Write-Host "Error: $($_.Exception.Message) ($($_.InvocationInfo.ScriptName):$($_.InvocationInfo.ScriptLineNumber))" -ForegroundColor Red; exit 1 } + $ErrorActionPreference = "Stop" [Console]::OutputEncoding = [System.Text.Encoding]::UTF8 @@ -422,7 +427,7 @@ $needCfg = $hasRefTypes -or $embedRequested -or $commonModules.Count -gt 0 # --- 2. Determine TempBasePath --- if (-not $TempBasePath) { - $TempBasePath = Join-Path $env:TEMP "epf_stub_db_$(Get-Random)" + $TempBasePath = Join-Path ([IO.Path]::GetTempPath()) "epf_stub_db_$(Get-Random)" } # --- 3. If registers need a registrator, add stub document --- @@ -1751,7 +1756,7 @@ function Format-ArgToken { $extraArgString = -join ($extraArgs | ForEach-Object { Format-ArgToken $_ }) if ($stubEngine -eq "ibcmd") { Write-Host "Creating infobase (ibcmd): $TempBasePath" - $ibData = Join-Path $env:TEMP "stub_data_$(Get-Random)" + $ibData = Join-Path ([IO.Path]::GetTempPath()) "stub_data_$(Get-Random)" New-Item -ItemType Directory -Path $ibData -Force | Out-Null $ibArgs = @("infobase", "create", "--db-path=$TempBasePath", "--create-database") if ($needCfg) { $ibArgs += "--import=$(Join-Path $TempBasePath 'cfg')", "--apply", "--force" } @@ -1787,7 +1792,7 @@ if ($needCfg) { $cfgDir = Join-Path $TempBasePath "cfg" # LoadConfigFromFiles Write-Host "Loading configuration from files..." - $loadLog = Join-Path $env:TEMP "stub_load_log.txt" + $loadLog = Join-Path ([IO.Path]::GetTempPath()) "stub_load_log.txt" $loadArgs = "DESIGNER /F`"$TempBasePath`" /LoadConfigFromFiles `"$cfgDir`" /Out `"$loadLog`" /DisableStartupDialogs" + $extraArgString $proc = Invoke-PlatformProcess $V8Path @($loadArgs) -PreQuoted if ($proc.ExitCode -ne 0) { @@ -1799,7 +1804,7 @@ if ($needCfg) { # UpdateDBCfg Write-Host "Updating database configuration..." - $updateLog = Join-Path $env:TEMP "stub_update_log.txt" + $updateLog = Join-Path ([IO.Path]::GetTempPath()) "stub_update_log.txt" $updateArgs = "DESIGNER /F`"$TempBasePath`" /UpdateDBCfg /Out `"$updateLog`" /DisableStartupDialogs" + $extraArgString $proc = Invoke-PlatformProcess $V8Path @($updateArgs) -PreQuoted if ($proc.ExitCode -ne 0) { diff --git a/.claude/skills/epf-build/scripts/stub-db-create.py b/.claude/skills/epf-build/scripts/stub-db-create.py index 00472e758..34c441602 100644 --- a/.claude/skills/epf-build/scripts/stub-db-create.py +++ b/.claude/skills/epf-build/scripts/stub-db-create.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# stub-db-create v1.12 — Create temp 1C infobase with metadata stubs for EPF/ERF build +# stub-db-create v1.13 — Create temp 1C infobase with metadata stubs for EPF/ERF build # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse diff --git a/.claude/skills/epf-dump/scripts/epf-dump.ps1 b/.claude/skills/epf-dump/scripts/epf-dump.ps1 index ababe0ffe..9de516613 100644 --- a/.claude/skills/epf-dump/scripts/epf-dump.ps1 +++ b/.claude/skills/epf-dump/scripts/epf-dump.ps1 @@ -1,4 +1,4 @@ -# epf-dump v1.16 — Dump external data processor or report (EPF/ERF) to XML sources +# epf-dump v1.17 — Dump external data processor or report (EPF/ERF) to XML sources # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills # NB: *nix-раскладку платформы (/opt/1cv8//1cv8, без .exe) знает только .py-порт — PS на *nix не исполняется. <# @@ -86,6 +86,11 @@ param( [string[]]$AdditionalIbcmdArguments = @() ) +# Необработанная ошибка (напр. привязка параметра) внутри try/finally без catch завершала +# скрипт с кодом 0 — ложный успех без запуска платформы. Любая такая ошибка — код 1. +# py-порт: необработанное исключение и так даёт код 1. +trap { Write-Host "Error: $($_.Exception.Message) ($($_.InvocationInfo.ScriptName):$($_.InvocationInfo.ScriptLineNumber))" -ForegroundColor Red; exit 1 } + $OutputEncoding = [System.Text.Encoding]::UTF8 [Console]::OutputEncoding = [System.Text.Encoding]::UTF8 @@ -474,7 +479,7 @@ if (-not (Test-Path $OutputDir)) { } # --- Temp dir --- -$tempDir = Join-Path $env:TEMP "epf_dump_$(Get-Random)" +$tempDir = Join-Path ([IO.Path]::GetTempPath()) "epf_dump_$(Get-Random)" New-Item -ItemType Directory -Path $tempDir -Force | Out-Null try { @@ -554,7 +559,7 @@ try { exit $exitCode } finally { - if (Test-Path $tempDir) { + if ($tempDir -and (Test-Path $tempDir)) { Remove-Item -Path $tempDir -Recurse -Force -ErrorAction SilentlyContinue } } diff --git a/.claude/skills/epf-dump/scripts/epf-dump.py b/.claude/skills/epf-dump/scripts/epf-dump.py index 45ecb00cc..792b99c37 100644 --- a/.claude/skills/epf-dump/scripts/epf-dump.py +++ b/.claude/skills/epf-dump/scripts/epf-dump.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# epf-dump v1.16 — Dump external data processor or report (EPF/ERF) to XML sources +# epf-dump v1.17 — Dump external data processor or report (EPF/ERF) to XML sources # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse diff --git a/.claude/skills/web-publish/scripts/web-publish.ps1 b/.claude/skills/web-publish/scripts/web-publish.ps1 index ff6f5ef83..fb2a26c75 100644 --- a/.claude/skills/web-publish/scripts/web-publish.ps1 +++ b/.claude/skills/web-publish/scripts/web-publish.ps1 @@ -1,4 +1,4 @@ -# web-publish v1.10 — Publish 1C infobase via Apache (+_version_dir/_version_key: общий эталон db-семейства) +# web-publish v1.11 — Publish 1C infobase via Apache (+_version_dir/_version_key: общий эталон db-семейства) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills <# .SYNOPSIS @@ -205,8 +205,8 @@ if (-not (Test-Path $httpdExe)) { } Write-Host "Apache не найден. Скачиваю..." -ForegroundColor Cyan - $tmpZip = Join-Path $env:TEMP "apache24.zip" - $tmpDir = Join-Path $env:TEMP "apache24_extract" + $tmpZip = Join-Path ([IO.Path]::GetTempPath()) "apache24.zip" + $tmpDir = Join-Path ([IO.Path]::GetTempPath()) "apache24_extract" try { [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 diff --git a/.claude/skills/web-publish/scripts/web-publish.py b/.claude/skills/web-publish/scripts/web-publish.py index b53901865..e93418346 100644 --- a/.claude/skills/web-publish/scripts/web-publish.py +++ b/.claude/skills/web-publish/scripts/web-publish.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# web-publish v1.10 — Publish 1C infobase via Apache (+_version_dir/_version_key: общий эталон db-семейства) +# web-publish v1.11 — Publish 1C infobase via Apache (+_version_dir/_version_key: общий эталон db-семейства) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills """ diff --git a/tests/skills/README.md b/tests/skills/README.md index 4738eaf09..147b9c380 100644 --- a/tests/skills/README.md +++ b/tests/skills/README.md @@ -115,6 +115,7 @@ node tests/skills/check-inline-drift.mjs --list # реестр: семья → | `check-agent-portability.mjs` | исходники навыков не привязаны к конкретному AI-агенту: единственная разрешённая форма — плейсхолдер `${CLAUDE_SKILL_DIR}/`, который разворачивает `scripts/switch.py` | | `check-error-streams.mjs` | сообщения об ошибках идут в один и тот же поток в обоих портах навыка (соответствие из `docs/python-porting-guide.md`) | | `check-nonascii-fs.mjs` | `fsutil`: удаление и копирование держат не-ASCII пути (кириллический `%TEMP%`, кириллические имена объектов 1С), обе копии модуля не разошлись | +| `check-ps-portability.mjs` | `.ps1` навыков не читают `$env:TEMP`/`$env:TMP`; скрипты `db-*`/`epf-*`, запускающие платформу, держат верхнеуровневый `trap { … exit 1 }` | `check-inline-drift.mjs` держит реестр семей внутри себя: у каждой семьи перечислены варианты, у варианта — навык-эталон и список копий. Отклоняющийся вариант обязан иметь обоснование (`why`), @@ -159,6 +160,16 @@ node tests/skills/check-inline-drift.mjs --list # реестр: семья → [nafs]: https://github.com/nodejs/node/issues/61067 +`check-ps-portability.mjs` держит два следствия issue #106. Вне Windows `$env:TEMP` равна `$null`, +и `Join-Path $env:TEMP …` падает на привязке параметра. Внутри `try { } finally { }` без `catch` +такая ошибка прерывает `try`, отрабатывает `finally` — и скрипт выходит с **кодом 0**: платформа +не запускалась, постусловие не проверялось, навык «успешен». Поэтому временный каталог берётся +через `[IO.Path]::GetTempPath()`, а скрипты `db-*`/`epf-*`, запускающие платформу, ставят после +`param(...)` верхнеуровневый `trap { … exit 1 }` — он ловит и ошибки вне `try`, внутренние `catch` +сохраняют приоритет, `finally` отрабатывает. Кейсом это не проверить: libuv на Windows возвращает +`TEMP` в окружение дочернего процесса, даже если раннер его убрал, а пустое значение ломает +`GetTempPath()` иначе, чем отсутствие переменной. + `check-format-versions.mjs` держит границы проверенного диапазона версий формата выгрузки. Раньше допустимый список версий был независимым литералом в каждом валидаторе, и сверять его было не с чем: волна 2.21 прошла по четырём валидаторам и молча обошла пятый — `form-validate` остался на diff --git a/tests/skills/check-all.mjs b/tests/skills/check-all.mjs index 7daeb6957..29389cadb 100644 --- a/tests/skills/check-all.mjs +++ b/tests/skills/check-all.mjs @@ -23,6 +23,7 @@ const GUARDS = [ ['check-agent-portability.mjs', 'исходники навыков: без привязки к конкретному AI-агенту'], ['check-error-streams.mjs', 'сообщения об ошибках: один и тот же поток в обоих портах'], ['check-nonascii-fs.mjs', 'fsutil: удаление и копирование держат не-ASCII пути, копии не разошлись'], + ['check-ps-portability.mjs', '.ps1: без $env:TEMP, необработанная ошибка у db-*/epf-* даёт код 1'], ]; let failed = 0; diff --git a/tests/skills/check-ps-portability.mjs b/tests/skills/check-ps-portability.mjs new file mode 100644 index 000000000..c02867e14 --- /dev/null +++ b/tests/skills/check-ps-portability.mjs @@ -0,0 +1,67 @@ +#!/usr/bin/env node +// Инвариант: PS-скрипты навыков не опираются на окружение, которое есть только в Windows, а +// скрипты, запускающие платформу, не могут завершиться с кодом 0 из-за необработанной ошибки. +// +// Issue #106: вне Windows `$env:TEMP` равна $null. `Join-Path $env:TEMP …` внутри +// `try { } finally { }` без catch — ошибка привязки параметра прерывает try, отрабатывает +// finally, и скрипт выходит с кодом 0: платформа не запускалась, постусловие не проверялось. +// db-create/db-dump-*/db-load-xml рапортовали «успех», ничего не сделав. +// +// Два правила: +// 1. `$env:TEMP` / `$env:TMP` в .ps1 навыков запрещены — временный каталог берётся через +// [IO.Path]::GetTempPath() (на Windows тот же путь, вне Windows — TMPDIR или /tmp). +// 2. .ps1 в db-*/epf-*, запускающий платформу (Invoke-PlatformProcess / Start-Process), +// держит верхнеуровневый `trap { … exit 1 }`: любая необработанная ошибка — код 1. +// Рантайм-кейсом это не поймать: после правила 1 штатного способа уронить скрипт нет. +// +// Почему гард, а не кейс с урезанным окружением: libuv на Windows возвращает TEMP в окружение +// дочернего процесса, даже если его убрали (обязательная переменная), — «TEMP нет» из Node на +// Windows не выразить. +// +// Запуск: node tests/skills/check-ps-portability.mjs +import { readFileSync, readdirSync, existsSync } from 'node:fs'; +import { fileURLToPath } from 'node:url'; +import { dirname, join } from 'node:path'; + +const ROOT = join(dirname(fileURLToPath(import.meta.url)), '..', '..'); +const SKILLS = join(ROOT, '.claude', 'skills'); + +const errors = []; +let checked = 0; +let trapped = 0; + +for (const skill of readdirSync(SKILLS)) { + const dir = join(SKILLS, skill, 'scripts'); + if (!existsSync(dir)) continue; + for (const file of readdirSync(dir)) { + if (!file.endsWith('.ps1')) continue; + checked++; + const lines = readFileSync(join(dir, file), 'utf8').replace(/^/, '').split(/\r?\n/); + const code = lines.map((l, i) => ({ l, n: i + 1 })).filter(({ l }) => !l.trimStart().startsWith('#')); + + for (const { l, n } of code) { + if (/\$env:(TEMP|TMP)\b/i.test(l)) { + errors.push(`${skill}/${file}:${n}: $env:TEMP/$env:TMP есть только в Windows — ` + + `используйте [IO.Path]::GetTempPath()`); + } + } + + if (!/^(db|epf)-/.test(skill)) continue; + const runsPlatform = code.some(({ l }) => /Invoke-PlatformProcess|Start-Process/.test(l)); + if (!runsPlatform) continue; + trapped++; + if (!code.some(({ l }) => /^trap \{.*\bexit 1\b/.test(l))) { + errors.push(`${skill}/${file}: запускает платформу, но нет верхнеуровневого ` + + '`trap { … exit 1 }` — необработанная ошибка внутри try/finally даст код 0'); + } + } +} + +console.log(`Проверено .ps1: ${checked}; из них запускают платформу (db-*/epf-*): ${trapped}`); +if (errors.length === 0) { + console.log('OK — без Windows-only окружения, необработанная ошибка даёт код 1.'); + process.exit(0); +} +console.log(`\n${errors.length} НАРУШЕНИЙ:`); +for (const e of errors) console.log(` [ERROR] ${e}`); +process.exit(1);