fix(preflight): normalize deployment paths on Windows#9743
fix(preflight): normalize deployment paths on Windows#9743tianmind-studio wants to merge 1 commit into
Conversation
Current bindings used pathlib's native separators while Git base paths always used forward slashes, so the ratchet treated every binding as new on Windows. Emit POSIX repository-relative paths and cover the invariant with PureWindowsPath. Closes BasedHardware#9738.
|
Fresh Windows reproduction while preparing #9753 from current main: the shared PR preflight fed backslash paths into the deployment binding guard, so checked-in bindings were misclassified against the slash-normalized policy and the check failed across unrelated workflow entries. Re-running the focused validators directly passed. This confirms the normalization here fixes a current contributor workflow, not only a synthetic unit case. |
Git-on-my-level
left a comment
There was a problem hiding this comment.
Thanks for tracking this down — the actual path-normalization fix looks directionally right to me. I verified the focused regression on Linux with the PR head checked out:
python3 .github/scripts/test_check_deployment_secret_boundary.pypasses (8 tests)python3 .github/scripts/check_deployment_secret_boundary.py --base HEADpassesuvx ruff check --target-version py39 ...passes
Requesting changes only because the touched Python files do not currently satisfy the repo's Black formatting command from the PR description:
uvx black --check --line-length 120 --skip-string-normalization \
.github/scripts/check_deployment_secret_boundary.py \
.github/scripts/test_check_deployment_secret_boundary.py
would reformat .github/scripts/test_check_deployment_secret_boundary.py
would reformat .github/scripts/check_deployment_secret_boundary.py
Black's diff is just removing the extra blank line after the from pathlib import ... import in both files, so this should be a tiny cleanup. After that, this is a good targeted fix for the Windows separator mismatch in the deployment secret-boundary preflight. Because this touches workflow/security preflight code, I’m leaving it for maintainer review rather than formal auto-approval.
by AI on behalf of David — if you need David’s attention urgently, please @Git-on-my-level and escalate with need human response.
What changed and why
Normalize current-tree deployment paths to POSIX repository-relative form before comparing them with Git's base-tree paths. This prevents the deployment secret-boundary ratchet from treating every existing binding as new on native Windows. Add a host-independent
PureWindowsPathregression test so Linux CI also enforces the separator contract. Closes #9738.Product invariants affected
none
How it was verified
test_rejects_new_unclassified_binding_but_allows_legacy_baseline, and the production checker failed even with--base HEADwhile reporting hundreds of unchanged bindings.python3 .github/scripts/test_check_deployment_secret_boundary.py(8 tests passed after the fix)python3 .github/scripts/check_deployment_secret_boundary.py --base HEADblack --check --line-length 120 --skip-string-normalization .github/scripts/check_deployment_secret_boundary.py .github/scripts/test_check_deployment_secret_boundary.pyruff check --target-version py39 .github/scripts/check_deployment_secret_boundary.py .github/scripts/test_check_deployment_secret_boundary.pypython3 .github/scripts/pr_preflight.py --lane local --base origin/main --head HEAD(10 selected checks passed)bash scripts/pre-push fork(all fast pre-push checks passed on native Windows)Tests
The new
PureWindowsPathfixture verifies that production path normalization emits.github/workflows/deploy.yml, matching Git tree output. The existing temporary-repository fixture then exercises the complete current-vs-base binding comparison and now passes on Windows.Root cause and durable guard (bug fixes)
_deployment_paths()convertedPath.relative_to()withstr(), producing backslashes on Windows, while_base_paths()consumes Git output with forward slashes. Since eachBindingincludes its path, identical bindings never compared equal and the diff ratchet collapsed into a full-repository scan. The shared path conversion now usesPurePath.as_posix()for every discovered current-tree file, and the Windows-path unit fixture keeps that cross-platform contract enforced in all CI environments.