Skip to content

fix: install.ps1 не мог прочитать версию любого релизного PowerShell 7 - #13

Merged
bivlked merged 1 commit into
mainfrom
fix/install-pwsh-version
Jul 23, 2026
Merged

fix: install.ps1 не мог прочитать версию любого релизного PowerShell 7#13
bivlked merged 1 commit into
mainfrom
fix/install-pwsh-version

Conversation

@bivlked

@bivlked bivlked commented Jul 23, 2026

Copy link
Copy Markdown
Owner

Симптом

Пользователь на машине с PowerShell 7.6.4 запустил one-liner установки и получил отказ:

PowerShell 7 was found at C:\Program Files\PowerShell\7\pwsh.exe, but its version
could not be read - WinClean requires 7.1+ and will not assume it.

Причина

pwsh.exe отдаёт ProductVersion как 7.6.4 SHA: 929d27f4...+929d27f4... - хеш коммита отделён пробелом. Код отрезал суффикс по дефису (это покрывает только preview-сборки вида 7.7.0-preview.2), хеш оставался, приведение к [version] бросало, версия становилась $null.

Воспроизведено локально на 7.6.4: Cannot convert value "7.6.4 SHA: ..." to type "System.Version".

Что это значит на самом деле

Разбор был сломан всегда. До v2.22 условие if ($pwshVersion -and $pwshVersion -lt '7.1') при $null просто пропускало сравнение, и установщик три релиза работал вообще без проверки версии. Fail-closed из v2.22 ничего не сломал - он обнажил дыру, которую fail-open прикрывал.

Исправление

Читаются числовые поля ProductMajorPart / ProductMinorPart / ProductBuildPart - там нет строки, которую можно разобрать неверно. major = 0 по-прежнему трактуется как нечитаемая версия и остаётся fail-closed.

Почему не поймали 702 теста

Единственным стражем был греп-тест: он проверял ФОРМУ кода (if (-not $pwshVersion) есть, старой fail-open формы нет) и ни разу не выполнял выражение.

Добавлен поведенческий тест: он достаёт присваивание $pwshVersion из install.ps1 через AST и выполняет его против реального pwsh.exe на машине тестов, затем проверяет, что результат проходит планку 7.1.

Проверено мутацией: со старым выражением поведенческий тест краснеет, а греп-тест рядом остаётся зелёным. Ровно та разница, из-за которой дефект прожил три релиза.

702 -> 704 теста.

Область

  • get.ps1 не затронут: он работает уже внутри PowerShell и читает $PSVersionTable.
  • WinClean.ps1 не менялся, релиз и PSGallery не требуются.
  • Фикс становится живым сразу после мержа: one-liner берёт install.ps1 из main, а не из ассета релиза.

ProductVersion у pwsh.exe выглядит как '7.6.4 SHA: <hash>+<hash>' - хеш
отделён ПРОБЕЛОМ, а код отрезал суффикс по дефису, поэтому приведение к
[version] бросало и версия становилась null. Теперь читаются числовые поля
ProductMajorPart/MinorPart/BuildPart - разбирать нечего.

Разбор был сломан с самого начала: до 2.22 форма if ($pwshVersion -and ...)
пропускала сравнение вместо того, чтобы о нём сообщить, и установщик три
релиза работал вообще без проверки версии. Fail-closed из 2.22 не сломал
ничего - он это обнажил.

Единственным стражем был греп-тест: он проверял ФОРМУ кода и ни разу его не
выполнял, поэтому 702 зелёных теста ничего не заметили. Добавлен поведенческий
тест, выполняющий выражение самого install.ps1 против реального pwsh.exe.
Проверено мутацией: со старым выражением он краснеет, а греп-тест рядом
остаётся зелёным.

Фикс живой сразу после попадания в main: one-liner берёт install.ps1 из ветки,
а не из ассета релиза. get.ps1 не затронут - он читает $PSVersionTable.
@bivlked
bivlked merged commit dd5ca39 into main Jul 23, 2026
5 checks passed
@bivlked
bivlked deleted the fix/install-pwsh-version branch July 23, 2026 16:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant