Repository navigation
ci(p3a): establish reproducible Windows portable build identity #448
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
10 commits
Select commit
Hold shift + click to select a range
54a470b
build(p3a): request reproducible ArdIrec bridge linking
masarray af457c0
build(p3a): emit deterministic portable build identity
masarray 947481d
ci(p3a): publish canonical portable build identity evidence
masarray a77f206
ci(p3a): publish Field Capture build identity evidence
masarray 5667a34
test(p3a): lock reproducible portable packaging contract
masarray a0158d3
evidence(p3a): record reproducible packaging acceptance gate
masarray 0861e29
docs(p3a): define reproducible build acceptance boundary
masarray dfee2c5
fix(p3a): repair portable identity PowerShell block
masarray a5f02b8
ci(p3a): fail early on packaging PowerShell syntax errors
masarray 7b2a0a9
fix(p3a): delimit packaging parser diagnostic variable
masarray File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
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
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,48 @@ | ||
| # CI-P3A — Reproducible Windows portable build identity | ||
|
|
||
| Issue #447. | ||
|
|
||
| ## Purpose | ||
|
|
||
| P2F proved that matching ARSAS and ARIEC61850 revisions could still produce | ||
| different portable single-file executables in independent workflows. Therefore | ||
| binary artifact reuse remains prohibited until reproducibility is proven. | ||
|
|
||
| ## Root-cause hypothesis and controlled change | ||
|
|
||
| The Windows package embeds a pinned ArdIrec native bridge. That bridge is built | ||
| independently with MSVC/CMake in each workflow. A PE linker timestamp or other | ||
| non-reproducible native metadata can change the embedded bridge and, because the | ||
| single-file payload is compressed, propagate into a large executable diff. | ||
|
|
||
| P3A does not treat that hypothesis as accepted evidence. It makes the native | ||
| shared-library linker request reproducible output with /Brepro and makes the | ||
| .NET publish determinism intent explicit with Deterministic=true and | ||
| ContinuousIntegrationBuild=true. Existing ArdIrec native regression tests remain. | ||
|
|
||
| ## Build identity | ||
|
|
||
| Each single-file publish writes a JSON identity next to the executable containing: | ||
|
|
||
| - ARSAS source commit when the source is a Git checkout; | ||
| - ARIEC61850 engine commit when the project is a Git checkout; | ||
| - pinned ArdIrec lock commit; | ||
| - ArdIrec bridge SHA-256 and byte size; | ||
| - portable executable SHA-256 and byte size; | ||
| - version/runtime and deterministic-build flags. | ||
|
|
||
| Both Build ARSAS and Smart Discovery Field Capture upload that identity. | ||
|
|
||
| ## Acceptance boundary | ||
|
|
||
| P3A itself does not authorize installer/release artifact reuse. After CI, the two | ||
| independent builders must report identical source, engine and ArdIrec inputs and | ||
| identical bridge plus portable SHA-256. Only that measured result can unlock P3B. | ||
|
|
||
| Installer/release/physical authority and runtime behavior are unchanged. | ||
|
|
||
| ## Efficiency | ||
|
|
||
| No new heavy workflow is introduced. Existing canonical and Field Capture lanes | ||
| serve as the independent builders, so reproducibility evidence is obtained from | ||
| work already required by the repository. |
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
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
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
75 changes: 75 additions & 0 deletions
75
tests/ARSAS.Tests/WindowsPackagingReproducibilityContractTests.cs
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,75 @@ | ||
| namespace ARSAS.Tests; | ||
|
|
||
| public sealed class WindowsPackagingReproducibilityContractTests | ||
| { | ||
| [Fact] | ||
| public void NativeBridge_RequestsReproducibleMsvcLinkOutput() | ||
| { | ||
| var bridge = File.ReadAllText( | ||
| FindRepositoryFile("scripts/build-ardirec-bridge.ps1")); | ||
|
|
||
| Assert.Contains( | ||
| "-DCMAKE_SHARED_LINKER_FLAGS_RELEASE=/Brepro", | ||
| bridge, | ||
| StringComparison.Ordinal); | ||
| Assert.Contains( | ||
| "-DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreaded", | ||
| bridge, | ||
| StringComparison.Ordinal); | ||
| Assert.Contains( | ||
| "ctest --test-dir", | ||
| bridge, | ||
| StringComparison.Ordinal); | ||
| } | ||
|
|
||
| [Fact] | ||
| public void PortablePublish_IsDeterministicAndEmitsHashBoundBuildIdentity() | ||
| { | ||
| var publish = File.ReadAllText( | ||
| FindRepositoryFile("scripts/publish-windows-portable.ps1")); | ||
|
|
||
| Assert.Contains("-p:Deterministic=true", publish, StringComparison.Ordinal); | ||
| Assert.Contains("-p:ContinuousIntegrationBuild=true", publish, StringComparison.Ordinal); | ||
| Assert.Contains("arsas-portable-build-identity", publish, StringComparison.Ordinal); | ||
| Assert.Contains("ardIrecBridgeSha256", publish, StringComparison.Ordinal); | ||
| Assert.Contains("portableSha256", publish, StringComparison.Ordinal); | ||
| Assert.Contains("sourceCommit", publish, StringComparison.Ordinal); | ||
| Assert.Contains("engineCommit", publish, StringComparison.Ordinal); | ||
| Assert.Contains("ardIrecLockCommit", publish, StringComparison.Ordinal); | ||
| Assert.Contains("reproducibleNativeLinkRequested = $true", publish, StringComparison.Ordinal); | ||
| } | ||
|
|
||
| [Fact] | ||
| public void CanonicalAndFieldCaptureArtifacts_BothCarryBuildIdentity() | ||
| { | ||
| var canonical = File.ReadAllText( | ||
| FindRepositoryFile(".github/workflows/build.yml")); | ||
| var capture = File.ReadAllText( | ||
| FindRepositoryFile(".github/workflows/smart-discovery-capture-build.yml")); | ||
|
|
||
| const string identity = | ||
| "ArIED61850Tester\\dist\\ARSAS-*-win-x64-portable-build-identity.json"; | ||
|
|
||
| Assert.Contains(identity, canonical, StringComparison.Ordinal); | ||
| Assert.Contains(identity, capture, StringComparison.Ordinal); | ||
| Assert.Contains( | ||
| "Packaging authority: independent Field Capture publish/smoke", | ||
| capture, | ||
| StringComparison.Ordinal); | ||
| } | ||
|
|
||
| private static string FindRepositoryFile(string relativePath) | ||
| { | ||
| DirectoryInfo? directory = new(AppContext.BaseDirectory); | ||
| while (directory != null) | ||
| { | ||
| var candidate = Path.Combine(directory.FullName, relativePath); | ||
| if (File.Exists(candidate)) | ||
| return candidate; | ||
| directory = directory.Parent; | ||
| } | ||
|
|
||
| throw new FileNotFoundException( | ||
| $"Repository file not found: {relativePath}"); | ||
| } | ||
| } |
Oops, something went wrong.
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When callers supply
-ArdIrecBridgePath, or whenbuild-ardirec-bridge.ps1reuses its existing destination DLL, this publish invocation never links the bridge with/Brepro; nevertheless, the emitted identity unconditionally attests that reproducible native linking was requested. This can make an arbitrary or stale bridge appear to carry reproducible-build provenance in evidence later used for cross-run acceptance. Derive this field from the actual bridge-build path, or verify/rebuild the bridge before setting it to true.AGENTS.md reference: AGENTS.md:L11-L17
Useful? React with 👍 / 👎.