feat: add post-export normalizer to reduce solution roundtrip noise#72
Open
zekelinAlex wants to merge 1 commit into
Open
feat: add post-export normalizer to reduce solution roundtrip noise#72zekelinAlex wants to merge 1 commit into
zekelinAlex wants to merge 1 commit into
Conversation
Contributor
There was a problem hiding this comment.
Pull request overview
Adds a post-export normalization step for Dataverse solution workspaces to reduce “roundtrip noise” by stripping server-added artifacts and aligning exported content with the source project’s declared solution state.
Changes:
- Introduces
ExportNormalizerwith configurable rules and a change-reporting model (ExportNormalizationOptions/ExportNormalizationResult). - Extends
Workspace/SolutionAPIs to support removing components and root-components during normalization. - Updates
XmlWorkspaceWriterrelationship writing to preserve formatting, avoid duplicate definitions, and delete stale relationship files/directories; adds comprehensive tests.
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| tests/TALXIS.Platform.Metadata.Tests/ExportNormalizerTests.cs | Adds unit tests covering normalization rules and relationship file roundtripping/deletion behavior. |
| src/TALXIS.Platform.Metadata/Solutions/Solution.cs | Adds root-component removal overload supporting schema-name and/or GUID matching. |
| src/TALXIS.Platform.Metadata.Serialization.Xml/XmlWorkspaceWriter.cs | Refines relationships writing/patching logic, preserves whitespace, deletes stale files, and adds a manifest-only write entrypoint. |
| src/TALXIS.Platform.Metadata.Serialization.Xml/Workspace.cs | Adds removal helpers for entities and several component types (forms/views/etc.). |
| src/TALXIS.Platform.Metadata.Serialization.Xml/ExportNormalizer.cs | Implements normalization rules (strip non-source components, system relationships, cross-solution subcomponents, server attrs; normalize Managed/Version). |
| src/TALXIS.Platform.Metadata.Serialization.Xml/ExportNormalizationResult.cs | Adds rule enum + change/result reporting types for normalization runs. |
| src/TALXIS.Platform.Metadata.Serialization.Xml/ExportNormalizationOptions.cs | Adds rule toggles (enabled by default) for the normalizer. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+1
to
+2
| namespace TALXIS.Platform.Metadata.Serialization.Xml; | ||
|
|
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.
The core idea: local Solution.xml is the source of truth for what a solution contains. The export is only trusted for component content. ExportNormalizer takes the unpacked export, compares it with the source project and reduces it to the declared state, so pull produces a clean diff. The manifest itself is never rewritten, it can only grow: subcomponents that arrive with a behavior=0 entity get declared as explicit RootComponents.
What happens to an export, point by point (each rule can be switched off via options):
components not declared in RootComponents and not present in the source project are removed, together with their rows in the exported manifest. This applies only to classic platform types with reliable manifest identity: entities, option sets, workflows, web resources, roles, app modules, plugin assemblies and SDK steps. Site maps, SCF components (canvas apps, PCF, environment variables, connection references...) and anything unknown pass through untouched — their type codes are environment-specific and their names don't reliably match RootComponents rows, so filtering them would be guessing
forms, views and ribbons of entities declared with behavior 1 or 2 are removed, unless they're explicitly declared as root components or already sit in the repo. Changing an entity's behavior never deletes what you already pulled, it only stops new server-side additions
server-added system relationships (owner, business unit, team, user, createdby/modifiedby lookups) are removed when they're not in the source. Matched by participants, with a name-pattern fallback for skeletal entries
forms and views owned by a different solution are removed in multi-solution workspaces (the behavior=0 cross-solution leak)
OrganizationVersion, OrganizationSchemaType and CRMServerServiceabilityVersion are stripped from the roots of Solution.xml and Customizations.xml
Managed and Version are kept at the source values