Skip to content

PowerShell wrapper: documented positional paths bind to -Root and silently scan "." #315

Description

@PhysShell

Дефект

Документированный способ вызова PowerShell-обёртки принимает путь, но связывает его с -Root, после чего сканирует ..

Собственные примеры скрипта:

scripts\own-check.ps1 -Format msbuild -- src\MyApp
scripts\own-check.ps1 -Format github -Severity warning -FailOnFinding -- .

Первый из них сканирует не src\MyApp. Он принимает src\MyApp за корень чекаута Own.NET и проверяет текущий каталог.

Почему так

В PowerShell -- завершает разбор параметров: всё, что после него, связывается позиционно. В блоке параметров $Root объявлен первым и занимает нулевую позицию, а $Paths задуман как ValueFromRemainingArguments. Скрипт сам себе противоречит: он даже содержит строку, отбрасывающую литерал -- из $Paths, — то есть автор ожидал, что путь туда дойдёт.

Проверено на сокращённом блоке параметров (PowerShell 7.4.6):

Вызов Куда попал путь
-Format github -- /tmp/tree $Root
-Format github /tmp/tree $Root
-Format github -Paths /tmp/tree $Paths

Почему это P1, а не опечатка в документации

Отказ тихий. Пользователь просит проверить каталог A, обёртка проверяет каталог B и не сообщает об ошибке. Если в текущем каталоге чисто, он получает зелёный результат и уверенность, что в A нет находок.

Это тот же класс лжи, который арки A1 и A4 методично выжигали: «не посмотрел» не имеет права выглядеть как «посмотрел и ничего не нашёл». Здесь хуже — инструмент посмотрел, но не туда, куда его просили.

На Windows с настоящим чекаутом это чаще всего проявится как жёсткая ошибка (экстрактор ищется внутри src\MyApp и не находится → exit 2), что как раз и вскрыло дефект в CI. Но при неудачном стечении — если по указанному пути окажется что-то похожее на чекаут, или при вызове из корня репозитория — тишина вероятна.

Критерии приёмки

documented `-- <path>` form    → <path> binds to Paths
bare positional <path>         → <path> binds to Paths, if kept supported
explicit -Paths <path>         → unchanged
explicit -Root <checkout>      → unchanged
no path                        → defaults to "."
requested target has finding,
cwd is clean                   → finding must still appear

Последняя строка — главная: она ловит именно тихую подмену цели, а не только жёсткий отказ.

Заметки к исправлению

  • Причина — порядок позиционных параметров, поэтому чинить нужно связывание (позиция у $Paths, снятие позиции у $Root), а не примеры в документации. Переписать примеры под текущее поведение значило бы узаконить дефект.
  • Закрепить проверкой в джобе own-check-ps1-surface, добавленной в test(ci): pin own-check.ps1's exit-code tiers on Windows (#313) #314: там уже есть Windows-раннер и фикстуры чистого и «протекающего» деревьев.
  • Эквивалент на own-check.sh не затронут: там разбор аргументов свой и -- обрабатывается явно.

Контекст

Найдено при работе над #313 — не чтением, а исполнением обёртки. Правка намеренно не включена в #314: тест, обнаруживший дефект, не должен чинить объект испытания в том же пакете.

Refs #313, #314.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions