Add ClickOnce publish-layout resolution - #1051
Merged
Merged
Conversation
4 of 10 tasks
dtivel
force-pushed
the
dtivel/clickonce-file-graph
branch
from
August 11, 2026 04:31
30bdd3a to
0eebbb8
Compare
There was a problem hiding this comment.
Pull request overview
Adds dormant ClickOnce file-graph resolution for the version 2 signing pipeline.
Changes:
- Adds graph models and application/deployment manifest resolvers.
- Implements payload mapping, fallback resolution, diagnostics, and adjacent executable discovery.
- Adds comprehensive tests and localized resources.
Show a summary per file
| File | Description |
|---|---|
test/Sign.Core.Test/Tools/ClickOnce/ClickOnceFileGraphResolverTests.cs |
Tests resolution behavior and edge cases. |
test/Sign.Core.Test/Tools/ClickOnce/ClickOnceFileGraphModelTests.cs |
Tests graph models and validation. |
src/Sign.Core/Tools/ClickOnce/ClickOncePayloadFileResolver.cs |
Resolves referenced payload files. |
src/Sign.Core/Tools/ClickOnce/ClickOnceManifestDiagnostic.cs |
Models manifest diagnostics. |
src/Sign.Core/Tools/ClickOnce/ClickOnceFileGraphResolutionException.cs |
Defines resolution failures. |
src/Sign.Core/Tools/ClickOnce/ClickOnceFileGraphEntryKind.cs |
Defines graph entry categories. |
src/Sign.Core/Tools/ClickOnce/ClickOnceFileGraphEntry.cs |
Models individual graph entries. |
src/Sign.Core/Tools/ClickOnce/ClickOnceFileGraph.cs |
Models resolved ClickOnce graphs. |
src/Sign.Core/Tools/ClickOnce/ClickOnceDeployManifestFileGraphResolver.cs |
Resolves deployment-manifest graphs. |
src/Sign.Core/Tools/ClickOnce/ClickOnceApplicationManifestFileGraphResolver.cs |
Resolves application-manifest graphs. |
src/Sign.Core/Resources.resx |
Adds resolution messages. |
src/Sign.Core/Resources.Designer.cs |
Exposes generated resource properties. |
src/Sign.Core/xlf/Resources.zh-Hant.xlf |
Adds Traditional Chinese localization entries. |
src/Sign.Core/xlf/Resources.zh-Hans.xlf |
Adds Simplified Chinese localization entries. |
src/Sign.Core/xlf/Resources.tr.xlf |
Adds Turkish localization entries. |
src/Sign.Core/xlf/Resources.ru.xlf |
Adds Russian localization entries. |
src/Sign.Core/xlf/Resources.pt-BR.xlf |
Adds Brazilian Portuguese localization entries. |
src/Sign.Core/xlf/Resources.pl.xlf |
Adds Polish localization entries. |
src/Sign.Core/xlf/Resources.ko.xlf |
Adds Korean localization entries. |
src/Sign.Core/xlf/Resources.ja.xlf |
Adds Japanese localization entries. |
src/Sign.Core/xlf/Resources.it.xlf |
Adds Italian localization entries. |
src/Sign.Core/xlf/Resources.fr.xlf |
Adds French localization entries. |
src/Sign.Core/xlf/Resources.es.xlf |
Adds Spanish localization entries. |
src/Sign.Core/xlf/Resources.de.xlf |
Adds German localization entries. |
src/Sign.Core/xlf/Resources.cs.xlf |
Adds Czech localization entries. |
Review details
Tip
Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Files not reviewed (1)
- src/Sign.Core/Resources.Designer.cs: Generated file
- Files reviewed: 24/25 changed files
- Comments generated: 0
- Review effort level: Balanced
dtivel
force-pushed
the
dtivel/clickonce-file-graph
branch
from
August 12, 2026 19:14
0eebbb8 to
24496c7
Compare
dtivel
force-pushed
the
dtivel/clickonce-file-graph
branch
from
August 12, 2026 22:43
24496c7 to
d99a714
Compare
dtivel
force-pushed
the
dtivel/clickonce-file-graph
branch
3 times, most recently
from
August 15, 2026 19:20
8e4dc41 to
57f5560
Compare
kartheekp-ms
previously approved these changes
Aug 18, 2026
dtivel
force-pushed
the
dtivel/clickonce-file-graph
branch
from
September 6, 2026 04:11
57f5560 to
588e39d
Compare
dtivel
requested review from
kartheekp-ms
and
a balanced review from Copilot
September 7, 2026 17:49
There was a problem hiding this comment.
Copilot review overview
🔵 Needs a closer look
Its broad manifest-resolution and path-safety behavior warrants final human review despite no unresolved comments.
Review tier: Balanced
Findings: None
Files not reviewed (1)
- src/Sign.Core/Resources.Designer.cs: Generated file
There was a problem hiding this comment.
Copilot review overview
🔵 Needs a closer look
The broad manifest parsing and filesystem path-resolution surface warrants final human validation despite extensive tests and no identified blocking defect.
Review tier: Balanced
Findings: None
Files not reviewed (1)
- src/Sign.Core/Resources.Designer.cs: Generated file
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: be91288d-5106-4c59-a1fa-c5353dccb828
Add typed resolved models and enforce deployment, payload, mapping, diagnostic, and target-path invariants. Preserve manifest input, validate unsupported deployment shapes, and expand resolver regression coverage. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: de6a34fe-6989-49f6-a128-ee13323c7c9e
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: de6a34fe-6989-49f6-a128-ee13323c7c9e
Remove preliminary application manifest resolution attempts whose diagnostics can be superseded by supported publish-layout fallback. Reserve ManifestUtilities resolution for authoritative validation of the staged layout. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: de6a34fe-6989-49f6-a128-ee13323c7c9e
dtivel
force-pushed
the
dtivel/clickonce-file-graph
branch
from
September 20, 2026 20:24
af8ec58 to
ccd1584
Compare
kartheekp-ms
approved these changes
Sep 21, 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.
Part of #1049.
Summary
ClickOnceApplicationPublishLayoutResolverClickOnceDeploymentPublishLayoutResolverClickOncePayloadResolverResolvedClickOncePublishLayoutResolvedClickOnceDeploymentResolvedClickOnceApplicationResolvedClickOncePayloadResolvedClickOnceAdjacentExecutableClickOncePublishLayoutResolutionExceptionwhile preserving ordered manifest diagnostics.ManifestUtilitiesneither models nor preserves. Reject unsupported shapes before file resolution soManifestUtilitiesormage.execannot reorder or rewrite them before signing.ResolvedClickOncePayloadvalidates that the source filename matches the target filename, with or without exactly one additional.deploysuffix, and derivesIsFileExtensionMappedfrom that relationship.ResolvedClickOnceAdjacentExecutablederives its target path from its source filename and validates the filename against its kind.setup.exeand unreferenced root-levelLauncher.exefiles; referenced launchers remain application payloads.Intentional scope boundary
This PR resolves and models the publish layout only. It does not register the resolvers with dependency injection and does not change production signing behavior or the CLI surface. Diagnostic text may reference the planned
--clickonce-signing-version 2 --no-update-clickonce-manifestoption, but the resolvers remain dormant until signer integration adds that option.Staging, relative-path containment validation, copying, temporary
.deploysuffix removal and restoration, manifest metadata updates, signing-operation coordination, and signing remain deferred to the signer-integration work. Resolution rejects rooted target paths but does not rewrite or remap accepted relative paths. Staging must ensure those relative paths remain within the staging directory and fail when a referenced layout cannot be represented safely.The deployment resolver establishes that
Application.Sourceis the file initially identified byDeployment.ApplicationManifestReference.ResolvedPath. This is a resolution-time postcondition rather than a durable model invariant because staging must redirect that mutableResolvedPath. The staging implementation must stageApplication.Source, redirect the deployment entry point to that exact staged copy, verify that it is contained within the staging directory, and only then update deployment-manifest metadata. At the start of staging, it must capture the deployment entry point's target path. Immediately before deployment-manifest metadata update and serialization, it must fail unless the live entry point is still the resolvedApplicationManifestReference, remains the sole assembly reference with no file references, and its target path still ordinally equals the captured value. It must not reconcile or serialize mutated deployment structure.For payloads,
ResolvedClickOncePayload.TargetPathis an immutable resolution-time snapshot ofReference.TargetPath, not a live projection. Staging must use that snapshot to determine the intended layout, preserve the manifest-relative meaning rather than remapping it, and bind each mutable reference'sResolvedPathto the corresponding contained staged file before updating metadata. Before computing staging destinations or collision claims, and again immediately before updating application-manifest metadata and serializing the manifest, staging must verify with ordinal comparison that each mutableReference.TargetPathstill equals its resolved snapshot. A mismatch must fail staging rather than reconcile or emit an inconsistent manifest.The deployment-directory payload fallback is a source-discovery mechanism. Signer integration must retain an explicit mapping from every staged file to the original
ResolvedClickOncePayload.Sourceit was staged from and copy signed bytes back to that exact source path. It must not derive copy-back destinations from staging-relative paths or reuse a directory-mirroring copy-back seam that would create a new application-directory file for a deployment-directory fallback source. Integration coverage must verify that a fallback payload is returned to its original source and that no unintended target-relative file is created.Discovery can also produce two resolved references to one physical file: a root-level
setup.exereferenced by the application manifest is classified as both aResolvedClickOncePayloadand aResolvedClickOnceAdjacentExecutable, with bothSourcevalues identifying the same file and potentially the same target path. Signer integration must apply the same source-keyed coordinated signing operation to both references so the file is staged, signed, and copied back exactly once rather than processed as two independent operations.