test(ci): pin own-check.ps1's exit-code tiers on Windows (#313) - #314
Merged
Conversation
Closes the evidence gap recorded in the #312 merge commit. The stage-1 normalisation — a broken extractor must land in the >=2 tier instead of borrowing exit 1 from "analysed, findings present" — was mirrored into the PowerShell wrapper and proven nowhere. No other job touches that file: the composite action drives the .sh, and the .ps1 builds its paths with backslashes, so it cannot run on Linux at all. A new windows-latest job exercises the tiers the wrapper actually has: broken stage 1 -> >=2, clean -> 0, findings -> 1 with -FailOnFinding and 0 without. The findings pair also asserts the two runs produce IDENTICAL output, so the flag can never quietly become a second, differently-behaving analysis. The "broken config -> 2" tier from the issue is deliberately absent: the PowerShell wrapper has no -Config parameter, so that tier does not exist on this surface. Asserting it would have meant inventing the surface to fit the test. One platform detail is load-bearing enough to be a comment rather than folk knowledge: the assertions read $LASTEXITCODE, never the wrapper process's exit code. Inside a PowerShell session — which is what `shell: pwsh` is — a script's `exit N` sets $LASTEXITCODE to N, but `pwsh -Command "& ./x.ps1"` collapses it to 1 at the process boundary. Measured the wrong way, every tier here reads as pass/fail and the contract looks broken when it is not; that is exactly what happened once while writing this. Verified locally with PowerShell 7.4.6: the stage-1 tier runs on Linux (the failure is the point) and reports $LASTEXITCODE = 2; every step body was parse-checked with the PowerShell parser. The remaining tiers need a working extractor and therefore first run on the Windows runner. Refs #313. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015de4MezSeUnZBoWq1fFU5M
…ilure does not fail the step The job's first run printed exactly what it was written to prove — "OK: stage-1 failure landed in the hard-error tier (2)" — and then reported the step as failed. The assertion was right; the step's status was not. GitHub's `shell: pwsh` wrapper finishes with `exit $LASTEXITCODE`. These steps deliberately run commands that FAIL, so the code left behind by the last one decides the step's fate no matter what the assertion concluded. Each step now ends with an explicit `exit 0`, and the reason sits in a comment above the job rather than in anyone's memory. Worth noting what this was NOT: the tier contract held on Windows on the first attempt — a broken stage 1 really did land on 2. The harness around it was wrong, not the thing it measures. Refs #313. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015de4MezSeUnZBoWq1fFU5M
…oot, not -Paths
The Windows run failed with the extractor being looked for under the tree
being scanned:
The provided file path does not exist:
D:\a\_temp\ps1-clean\frontend\roslyn\OwnSharp.Extractor
The path had bound to -Root. In PowerShell `--` ends parameter parsing and
everything after it binds POSITIONALLY, and own-check.ps1 declares $Root
first, so it takes position 0. Verified against a reduced param block: both
`-Format github -- <path>` and `-Format github <path>` land in $Root, and
only `-Paths <path>` reaches $Paths.
This job now binds -Paths explicitly. It does NOT change the wrapper: that
the script's own .EXAMPLE lines (`own-check.ps1 -Format msbuild -- src\MyApp`)
therefore scan "." instead of src\MyApp is a real user-facing defect, but it
is a different one from the exit-code tiers this job exists to pin, and it is
being reported rather than folded in here.
Also worth recording honestly: the tier>=2 assertion passed in the previous
run while malformed — -Root and -Format were bound by name, so the stray
positional argument went to some other parameter entirely and the tier was
proven for the right verdict by an accident of binding. Re-verified locally
with the corrected invocation: LASTEXITCODE = 2.
Refs #313.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015de4MezSeUnZBoWq1fFU5M
📝 WalkthroughWalkthroughAdds a Windows CI job that validates ChangesPowerShell CI validation
Estimated code review effort: 3 (Moderate) | ~20 minutes Suggested reviewers: 🚥 Pre-merge checks | ✅ 4✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
13 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Что и зачем
Закрывает доказательный разрыв, записанный в merge-коммите PR #312: правка кодов возврата первой стадии была закреплена ассерцией CI только для
scripts/own-check.sh, а зеркальная ветка вscripts/own-check.ps1существовала «в коде и нигде больше». Ни одна другая джоба этот файл не трогает — композитный Action гоняет.sh. PowerShell-обёртка исполняется на Linux достаточно далеко, чтобы доказать ярус отказа первой стадии, но её успешный extraction path строит Windows-style пути и требует Windows.Новая джоба на
windows-latestпроверяет ярусы, которые у обёртки действительно есть:Последняя строка — не украшение: флаг
-FailOnFindingне имеет права стать вторым, иначе ведущим себя анализом, поэтому оба прогона сравниваются посимвольно.Ярус «битый конфиг → 2» из issue намеренно отсутствует: у
.ps1нет параметра-Config, и эта поверхность на нём не существует. Утверждать её значило бы дописать скрипт под тест.Область — один файл,
.github/workflows/ci.yml. Ни рефакторинга обёрток, ни улучшений документации.Три коммита, и почему их стоит читать по отдельности
Предмет проверки оказался исправен с самого начала — дважды ломался измерительный стенд:
f370acd.ps1впервые исполняется хоть где-то.2ea190dOK: stage-1 failure landed in the hard-error tier (2)и всё равно упал. Обёрткаshell: pwshзавершаетсяexit $LASTEXITCODE, а шаги намеренно запускают падающие команды — оставленный код решал судьбу шага независимо от вывода ассерции. Лечится явнымexit 0в конце каждого шага.dd1f05f-Root, а не с-Paths. В PowerShell--завершает разбор параметров, дальше аргументы идут позиционно, а$Rootобъявлен первым.Только после этого стало видно, что контракт ярусов держится.
Найденное попутно (в этот PR не входит)
Из третьего пункта следует пользовательский дефект самой обёртки: её собственные
.EXAMPLE—own-check.ps1 -Format msbuild -- src\MyApp— связывают путь с-Rootи сканируют.. Скрипт здесь не менялся: тест, обнаруживший дефект, не должен чинить объект испытания в том же пакете. Заведено отдельно — #315.Тип изменения
Как проверено
Локально с PowerShell 7.4.6: ярус
>= 2исполнен по-настоящему (на Linux провал первой стадии гарантирован Windows-style путями в extraction path) —LASTEXITCODE = 2при корректном связывании через-PathsСвязывание аргументов проверено на сокращённом блоке параметров:
-Format github -- /tmp/tree$Root-Format github /tmp/tree$Root-Format github -Paths /tmp/tree$Paths✔Семантика завершения шага воспроизведена локально на форме обёртки GitHub: без явного
exit 0шаг получает код упавшей команды, с ним — 0Тело каждого шага проверено парсером PowerShell до пуша
CI зелёный на
dd1f05f: 19 джоб, ни одной не-успешной; новая джоба прошла всеми четырьмя шагамиpython tests/run_tests.py/ruff— не применимо: Python и продуктовый код не менялисьСвязанные issue
Closes #313. Refs #312 (где разрыв был записан), #315 (найденный попутно дефект связывания аргументов).
Чеклист
feat:,fix:,docs:…)Generated by Claude Code