Signed-copy drift guard (check 2 of 2)#34
Open
crutkas wants to merge 7 commits into
Open
Conversation
Introduces src/tools/check-signed-drift.ps1 (shared comparator) and .github/workflows/signed-copy-guard.yml. The workflow runs on PRs that touch the top-level signed-copy roots and fails if any PR-touched file no longer matches its src/ counterpart (modulo the Authenticode signature block on .ps1 files). A follow-up PR will layer a non-blocking "Drift status" visibility check on the same comparator (check 1 of 2). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add comment for intentional file touch to flag behavior
Member
Author
Member
Author
Member
|
Are there already checks to ensure that the signable things in the signed location are in fact signed in PRs? |
JohnMcPMS
approved these changes
May 29, 2026
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.


What this PR adds
src/tools/check-signed-drift.ps1— a shared PowerShell comparator that walks every file undersrc/{Workloads,windows-dev-config,wsl-comfort}/and the matching three top-level signed-copy roots, pairs each one with its counterpart, and emits a JSON drift report..ps1files are compared after stripping the UTF-8 BOM, normalizing CRLF→LF, and dropping everything from the first# SIG # Begin signature blockline to EOF on the signed side; every other file (.winget/.sh/.md/ images / any extension) is compared strict byte-equal, because the sign pipeline only modifies.ps1bodies. The script is a pure reporter — it always exits 0 and lets callers decide pass/fail..github/workflows/signed-copy-guard.yml— Check 2 of 2. Triggered bypull_requestwith apaths:filter on the three top-level signed-copy roots, so PRs that touch onlysrc/skip the check entirely. The job intersects the comparator's drift list with the PR's changed paths (under those roots) and fails with an actionableGITHUB_STEP_SUMMARYmessage when any intersected entry hasstatus != "ok". Drift report is uploaded as a build artifact for debugging.src/docs/development.md— new### Signed-copy drift guardsubsection under "Repo layout: signed vs source" explaining what the guard does, where the shared comparator lives, and that the guard does not replace the sign pipeline.What this PR does NOT add
src/tools/check-signed-drift.ps1comparator on a push/schedule trigger and report drift across the whole tree without failing any build. The comparator's contract (always exit 0, full JSON, deterministic ordering) is designed for that reuse.After merge: maintainer action
Please add
Signed copy guardto the required status checks onmainin branch protection. Otherwise PRs can bypass the guard by not requesting that check.How I verified
Locally on a clean checkout of this branch:
pwsh -NoProfile -Command "[void][System.Management.Automation.Language.Parser]::ParseFile('./src/tools/check-signed-drift.ps1', ...)"— passes.powershell-yamlConvertFrom-Yaml— theon/permissions/concurrency/jobs.guard.stepsshape is correct.main: running the comparator against the current branch reports{ ok: 30, drifted: 0, missing_in_root: 0, missing_in_src: 0 }, which matches the dev guide's expectation that the two trees only differ on the.ps1sig block today.windows-dev-config/dev-config.wingetand re-ran. Comparator reportedstatus: drifted, reason: "bytes differ at offset 10 (src len=39522, root len=39522)". Reverted..ps1sig-strip failure path: prepended a junkXbyte towindows-dev-config/install.ps1(the signed copy) and re-ran. Comparator reportedstatus: drifted, reason: "normalized .ps1 bytes differ at offset 0 (src len=923, root len=924)"— proving the sig block is being stripped (without it the diff would be tens of KB, not 1 byte) and the unsigned body is then compared byte-for-byte. Reverted.windows-dev-config/install.ps1) and a drifted path (windows-dev-config/dev-config.wingetwith one byte flipped). Exit 0 on the clean case, exit 1 with the actionable bullet list on the drifted case.Reference
Drift definition follows the dev guide's "Repo layout: signed vs source" section: https://github.com/microsoft/WindowsDeveloperConfig/blob/main/src/docs/development.md#repo-layout-signed-vs-source