Solution Administration Console · Part 1 of 4

One solution per work item, and then the merge

Dataverse has no feature branches. What it has is unmanaged solutions, and if you create one per work item, you have forty of them after three months. The first version of the console was a tool to merge them back together.

On my client engagements, development has followed the same pattern for years. Every work item in Azure DevOps gets its own unmanaged solution, unique name feature_4711 or bug_4712. Everything that belongs to the topic goes in there. When the topic is done, its content moves into the release solution, and that goes through the environment chain as a managed package. It is the closest thing to feature branches that Dataverse offers, and it works.

What doesn't work is everything around it.

Graphic: The DevOps cycle as a figure eight on its side, with the eight stages Plan, Code, Build, Test, Release, Deploy, Operate and Monitor.
The cycle the console lives in. This part takes place between Code and Build: creating Working Solutions and merging them into a release.

Forty solutions and an Excel list

After three months the maker portal shows forty solutions with names like feature_4711, and without DevOps nobody knows anymore what 4711 was, whether it is already in the release, or who owns it. Two colleagues change the same form in two solutions, and whoever deploys last overwrites the other. You only notice when a field is missing in UAT.

And then the merge itself. In the maker portal, open the release solution, click “Add existing”, then go type by type, component by component, and for every table decide whether all subcomponents should come along. With thirty components that is half an hour, with three hundred an afternoon. Afterwards nobody can say exactly what was added, and you write the release notes from memory.

For years I handled this with an Excel list that mapped solutions to work items, and with XrmToolBox. Its Solution Components Mover moves components between solutions, and it does that reasonably well. But it knows nothing about work items, states, or what has already been merged. And the spreadsheet did not maintain itself. After two releases the list was out of date, and from then on it was worse than none, because people still believed it.

After two releases the list was out of date, and from then on it was worse than none, because people still believed it.

A Working Solution is two things

I made the first commit on June 10, 2026. Back then the app was called Solution Forge, and the name lasted one day. The core idea has not changed since: a Working Solution consists of a record with title, type, DevOps ID, owner and deployment status, and of the actual unmanaged solution that holds the components. Creating one creates both in a single step, and the unique name still follows the convention. Solutions that someone created by going around the tool stay visible and are sorted in by their name.

That was the end of the Excel list. The Workbench shows the list with filters for feature, bug and release, and with search across title, unique name and DevOps ID. A toggle also searches the components of all open solutions, which answers the question I was asked most often on the project: which solution is this table in? The collision radar came on the second day. It loads the components of all open solutions and flags every one that sits in more than one. That is exactly where someone later overwrites someone else.

Screenshot: Workbench with an expanded row, components by type and the match against the DevOps work item.
The Workbench with an expanded row. What used to be in the Excel list is now attached to the record. Sample data, no customer data.

The merge picks a release solution as the target, then the feature and bug solutions, shows the component plan with conflicts and duplicates, and merges. Every run writes a history row with the components it added. Since June 22 the release notes are generated from this history, incrementally from the second time on. That was not a planned feature. The data was simply there.

Screenshot: Merge in three steps, choosing the source solutions, choosing the target release, reviewing the component plan.
Merge in three steps. The plan is there before the run, the history after it.

On top of that came a cloud flow that writes the status of the work items back into the Working Solutions. If a work item is Done but its solution is still open, the list flags it. I had planned more DevOps integration, and a panel was already built. It failed on the tenant: the OAuth token came from my account's home tenant, the DevOps organization belonged to a different one, error TF400813, and a guest membership does not help there. The panel has been switched off since June 11 and is waiting for a service principal.

What it changed

The merge takes minutes instead of an afternoon, and afterwards it is clear what was added. The release notes come for free. You see collisions before anyone deploys. For two weeks now the console has been in daily use at a customer in automation engineering, with three environments and a team that used to keep the Excel list.

What the Workbench does not answer: whether the import goes through in the target. That is what the second part is about. All Workbench features are listed on the product page.

Addendum, August 2: the bug you don't see

The merge had been in daily use for two months, and it had a bug you don't see. The component list came from the same table the maker portal uses for its object list. That table collapses subcomponents under their table. So for a table, a merge based on it copied only the shell and left behind the columns, forms and views that were explicitly included in the source. No error message. After all, the component was in the target.

The duplicate check was even worse. If the target already held the table as a shell and the source held it with all subcomponents, the merge skipped it as a duplicate. On August 1 I saw this live on a table whose columns were missing from the release. Since August 2 a pure function with tests decides what happens to each component: add, widen, skip, or excluded. Widening means the existing row is upgraded in place to “all subcomponents”. Dataverse never downgrades in the process, so repeating the call carries no risk.

A side effect that made me doubt myself for a moment: after widening, the row count of the target solution goes down. Three rows, the shell plus two explicit columns, become one row with everything. Fewer rows, more content. If you use component counts as a measure of success, you will read that as a loss.

Addendum, September 16: zero percent

On large releases the merge sat at zero percent for minutes, because before the first step it fully resolved the release solution, with names for every column, every form, every view. None of that was displayed. The decision only needs the ID and the behavior of the row. Now it reads the target raw, takes the sources from the Workbench plan, and progress moves from the first second. The calls themselves still run one after another. Running them in parallel would probably work, but not without first checking how Dataverse locks the target solution.

Solution Administration Console, all parts
  1. 01One solution per work item, and then the merge
  2. 02Why imports fail, and how to see it coming
  3. 03Who can do what, and what the system is doing right now
  4. 04Moving configuration data, and turning the tool into a product
Contact

Running the same pattern?

One solution per work item, one release solution per environment chain, and a lot of manual work in between. If you want to know what the console looks like in your environment, send me a short message.