Skip to content

fix: publish/ ships the unmerged Plugin assembly; missing entirely for WorkflowActivity - #107

Merged
TomProkop merged 2 commits into
masterfrom
fix/plugin-publish-on-build
Aug 11, 2026
Merged

TomProkop merged 2 commits into
masterfrom
fix/plugin-publish-on-build

Conversation

@TomProkop

@TomProkop TomProkop commented Aug 10, 2026 •

Copy link
Copy Markdown
Member

Verified behavior

Tested by packing this branch and building a real Solution project (2 Plugin projects, BuildInParallel="true", default net472, no TargetFramework/SDK version pinned anywhere — matching normal consumer usage) against the actual BuildPluginLibraries path, and comparing against the pre-fix code.

Plugin: Microsoft.PowerApps.MSBuild.Plugin (pinned 1.48.2 in Directory.Build.props) already defaults PublishOnBuild=true on its own, so the dormant _PublishPluginAfterBuild target already ran today, before this PR. The actual, currently-shipping bug is that it's anchored on plain AfterTargets="Build" — the same anchor as _AssemblyMergePluginDependenciesAfterBuild (the ILRepack merge) — and is declared earlier in the file, so it deterministically runs before the merge, not after. Confirmed by hash: on the current master, a Plugin project with a real merged dependency produces a 14,336-byte merged bin/<Name>.dll next to a 4,096-byte unmerged publish/<Name>.dll — every build, silently missing all merged dependencies. This is not a hypothetical: it's what ships today whenever AssemblyMergeSkip isn't set.

WorkflowActivity: no equivalent Microsoft package sets a PublishOnBuild default here, so publish/ is genuinely never created at all — the original FileNotFoundException: Build not found symptom is real and reproducible for this project type.

Fix

  • Anchor the publish target on _AssemblyMerge*DependenciesAfterBuild instead of Build, so it always runs after the merge, not racing it (AfterTargets is OR, not AND — listing both anchors doesn't fix the ordering).
  • Re-copy the merged bin/ assembly over publish/'s copy: the SDK's publish pipeline stages the primary assembly from obj/ (the pre-merge output) regardless of ordering, so without this the merged bytes still wouldn't reach publish/.
  • Default PublishOnBuild=true for ProjectType=WorkflowActivity, where nothing else provides that default. Kept the same default for Plugin too, for symmetry and as a safeguard if the Microsoft package's own default ever changes — it's a no-op today since Microsoft.PowerApps.MSBuild.Plugin already sets it.

Not verified

  • Not tested on PdPackage projects.
  • No end-to-end test through the real NuGet packages / a scaffolded project template with a signed assembly (EnsurePluginAssemblyDataXml requires a strong-name-signed assembly beyond this fix's scope; verified up to that point).

Companion fix

A related fix is needed in talxis/tools-devkit-templates (GenerateAssembly.cs net462 hardcoding) for a fully working Dataverse plugin + solution build.

…ublish/ folder exists

BuildPluginLibraries invokes referenced Plugin projects with Targets="Build", but
EnsurePluginAssemblyDataXml looks for the assembly under bin/<Config>/<TFM>/publish/,
which a plain Build never creates - only Publish does. The dormant _PublishPluginAfterBuild
hook that produces this folder only fired when PublishOnBuild=true, which nothing ever set.

Default PublishOnBuild=true for ProjectType=Plugin (and, analogously, WorkflowActivity,
which has the identical assumption feeding EnsureWorkflowActivityAssemblyDataXml but no
publish hook at all) unless the consumer already set it explicitly.

Fixing the missing publish/ folder alone isn't sufficient: _AssemblyMergePluginDependenciesAfterBuild
(ILRepack merge) also hooks AfterTargets="Build", and AfterTargets lists are OR not AND, so
anchoring the new publish hook on "_AssemblyMergePluginDependenciesAfterBuild;Build" would let it
attach right after Build and run before the merge. Anchoring on the merge target alone (itself
anchored on Build) fixes the ordering. Separately, the SDK's Publish pipeline copies the primary
assembly from the intermediate obj/ output rather than the merged bin/ output, so the merged
assembly is explicitly re-copied into the publish/ folder afterwards.

Both fixes were verified experimentally against a minimal net8.0 project importing the real
target files with a genuine ILRepack merge (see PR description).
Rewrites the AfterTargets-ordering and obj/-vs-bin/-copy comments as
plain documentation instead of a narrated verification log, and drops
the ProjectType==Plugin/WorkflowActivity condition on the PublishOnBuild
default - both files are only ever imported for that project type, and
every other property default in them (IsPackable, ILRepackTargetsFile,
etc.) is already unconditioned on ProjectType for the same reason.

No target ordering, AfterTargets, or task logic changes.
@TomProkop TomProkop changed the title fix: default PublishOnBuild=true for Plugin projects so the publish/ folder exists fix: default PublishOnBuild=true for Plugin/WorkflowActivity so publish/ exists Aug 10, 2026
@TomProkop
TomProkop requested a lite review from Copilot August 10, 2026 23:24

This comment was marked as outdated.

@TomProkop TomProkop changed the title fix: default PublishOnBuild=true for Plugin/WorkflowActivity so publish/ exists fix: publish/ ships the unmerged Plugin assembly; missing entirely for WorkflowActivity Aug 11, 2026
@TomProkop
TomProkop merged commit 21d3720 into master Aug 11, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants