Skip to content

Commit 375b2a2

Browse files
VortexUKclaude
andcommitted
v0.1.7: merge Core into UI DLL via ILRepack to fix load error
The v0.1.6 release split Core out into its own assembly but the release workflow still uploads only EQ2Lexicon.ACTPlugin.dll. Users who placed the single DLL into Plugins\ got: Could not load file or assembly 'EQ2Lexicon.ACTPlugin.Core, Version=0.1.6.0, Culture=neutral, PublicKeyToken=null' The plugin's runtime distribution should be one self-contained file — that's the install muscle memory we built up through v0.1.5, and it's what release.yml's "Download EQ2Lexicon.ACTPlugin.dll" instructions imply. The Core/UI split is purely a build/test convenience; it shouldn't leak into how the DLL is shipped. - Add ILRepack.Lib.MSBuild.Task 2.0.37 to the UI csproj - Merge Core.dll into the UI DLL on Release builds via an AfterBuild target; delete the standalone Core.dll/.pdb from the UI bin folder afterwards so what we ship matches what's in bin/Release/net48/ - Bump UI + Core to 0.1.7 (lockstep per CLAUDE.md) Verified: the merged DLL's referenced-assemblies list contains no 'EQ2Lexicon.ACTPlugin.Core' entry — just BCL + ACT. PayloadBuilder, UploadClient, PluginConfig, EncounterSnapshot are all present inside the merged assembly. 72/72 tests pass. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 602f83a commit 375b2a2

3 files changed

Lines changed: 52 additions & 4 deletions

File tree

CLAUDE.md

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ The UI assembly `<ProjectReference>`s Core and excludes `Core/**/*.cs` from its
1717

1818
The split also unlocks GitHub Actions CI: the workflow at `.github/workflows/ci.yml` builds Core + tests + runs coverage on `windows-latest`, never touching the UI assembly.
1919

20+
**Single-file distribution via ILRepack** (added in v0.1.7): the split is a build/test convenience; users still get one DLL. On Release builds the `ILRepackMergeCore` target in `src/EQ2Lexicon.ACTPlugin.csproj` merges `EQ2Lexicon.ACTPlugin.Core.dll` into the UI DLL (via `ILRepack.Lib.MSBuild.Task`) and deletes the standalone Core DLL/PDB from the UI bin folder. The Core project still produces its own DLL in `src/Core/bin/Release/net48/` for the test project to reference. Debug builds skip the merge so the VS debugger isn't slowed. v0.1.6 shipped without this and users got `Could not load file or assembly 'EQ2Lexicon.ACTPlugin.Core'` because the release workflow only uploads the UI DLL — see commit `3d4051b`.
21+
2022
## Key files
2123

2224
| File | Purpose |
@@ -33,9 +35,9 @@ The split also unlocks GitHub Actions CI: the workflow at `.github/workflows/ci.
3335

3436
## Versioning + releases
3537

36-
- Version lives in `src/EQ2Lexicon.ACTPlugin.csproj` `<Version>`. Bump it when shipping.
38+
- Version lives in `src/EQ2Lexicon.ACTPlugin.csproj` `<Version>`. Bump **both** csproj files (UI + Core) in lockstep when shipping — the Core version is referenced in error-message text and stays meaningful for diagnostics even after ILRepack folds it in.
3739
- Releases are tags `v0.1.x` pushed to GitHub, with the DLL attached as a release asset.
38-
- DLL output path after `dotnet build -c Release`: `src/bin/Release/net48/EQ2Lexicon.ACTPlugin.dll`.
40+
- DLL output path after `dotnet build -c Release`: `src/bin/Release/net48/EQ2Lexicon.ACTPlugin.dll` — a single self-contained DLL (Core is ILRepacked in; see Architecture above).
3941

4042
Release recipe — fully automated end-to-end:
4143

@@ -122,6 +124,7 @@ See the audit findings + fixes in commits `9eb39e0` (v0.1.4) and `5f9e11a` (v0.1
122124

123125
- GitHub Releases is the only distribution channel. Direct download URL pattern:
124126
`https://github.com/VortexUK/EQ2LexiconACTPlugin/releases/download/vX.Y.Z/EQ2Lexicon.ACTPlugin.dll`
127+
- **Single self-contained DLL** — even though the source is split across UI + Core assemblies, the release is one file. ILRepack merges Core into the UI DLL on Release builds; the release workflow uploads only that merged DLL. Do not switch to a two-file release without updating `release.yml`'s upload list **and** the install-instructions block in its release-notes generator (line ~85) together — v0.1.6 forgot the upload step and broke every fresh install.
125128
- The DLL is unsigned. Windows SmartScreen may warn on first run; users click through. A code-signing certificate would fix this but costs ~$200/yr — not currently worth it.
126129

127130
## CI/CD gaps
@@ -137,6 +140,7 @@ Comprehensive pipeline status as of v0.1.5 + the B2.16 sprint:
137140
| Vulnerability scanning |`dotnet list package --vulnerable` in pre-push + CI |
138141
| Dependabot |`.github/dependabot.yml` |
139142
| Core/UI assembly split (so CI can build without ACT) |`src/Core/` |
143+
| Single-DLL distribution despite the split | ✅ ILRepack merges Core into the UI DLL on Release builds (`ILRepackMergeCore` target) |
140144
| Auto-release on `v*` tag push |`.github/workflows/release.yml` — builds UI DLL on the runner via extracted ACT, drafts release with notes + DLL attached, maintainer just publishes |
141145
| Authenticode-signed DLL | ❌ Skipped — ~$200/yr cert not worth it; users click through SmartScreen |
142146
| Changelog automation | ❌ Skipped — release notes hand-written per release |

src/Core/EQ2Lexicon.ACTPlugin.Core.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
Build metadata is mirrored from the UI csproj so this assembly's
1919
version tracks the user-facing plugin version.
2020
-->
21-
<Version>0.1.6</Version>
21+
<Version>0.1.7</Version>
2222
<Company>EQ2 Lexicon</Company>
2323
<Product>EQ2 Lexicon Uploader (Core)</Product>
2424
<Description>Pure payload / config / HTTP layer shared by EQ2Lexicon.ACTPlugin.</Description>

src/EQ2Lexicon.ACTPlugin.csproj

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,56 @@
2222
<ActInstallDir Condition="'$(ActInstallDir)' == ''">C:\Program Files (x86)\Advanced Combat Tracker</ActInstallDir>
2323

2424
<!-- Build metadata shown in ACT's plugin list -->
25-
<Version>0.1.6</Version>
25+
<Version>0.1.7</Version>
2626
<Company>EQ2 Lexicon</Company>
2727
<Product>EQ2 Lexicon Uploader</Product>
2828
<Description>Uploads ACT-parsed encounters to the EQ2 Lexicon site.</Description>
2929
</PropertyGroup>
3030

31+
<!--
32+
ILRepack merges the sibling Core.dll back into the UI assembly so the
33+
release ships as a single self-contained DLL — the same UX users had
34+
before the v0.1.6 assembly split. Without this, ACT would load the UI
35+
DLL, fail to bind 'EQ2Lexicon.ACTPlugin.Core' from the Plugins folder,
36+
and throw a "Could not load file or assembly" error (the v0.1.6 bug).
37+
38+
Internalize=true: Core's public types become internal to the merged
39+
DLL, so nothing outside the plugin can take a dependency on them.
40+
Tests still reference the standalone Core.dll in its own bin folder,
41+
so InternalsVisibleTo on Core continues to work for the test project.
42+
43+
Release-only so VS Debug builds aren't slowed by the merge step.
44+
-->
45+
<ItemGroup>
46+
<PackageReference Include="ILRepack.Lib.MSBuild.Task" Version="2.0.37" PrivateAssets="all" />
47+
</ItemGroup>
48+
49+
<!--
50+
AfterTargets="AfterBuild" (the legacy extensibility point) fires once
51+
per build invocation, unlike AfterTargets="Build" which fires twice
52+
in SDK-style projects (once after inner Build, once after outer Build)
53+
and would re-merge the already-merged DLL with itself.
54+
-->
55+
<Target Name="ILRepackMergeCore" AfterTargets="AfterBuild"
56+
Condition="'$(Configuration)' == 'Release' AND Exists('$(OutputPath)EQ2Lexicon.ACTPlugin.Core.dll')">
57+
<ItemGroup>
58+
<_MergeInputs Include="$(OutputPath)$(AssemblyName).dll" />
59+
<_MergeInputs Include="$(OutputPath)EQ2Lexicon.ACTPlugin.Core.dll" />
60+
</ItemGroup>
61+
<ILRepack
62+
Parallel="true"
63+
Internalize="true"
64+
DebugInfo="true"
65+
InputAssemblies="@(_MergeInputs)"
66+
OutputFile="$(OutputPath)$(AssemblyName).dll"
67+
TargetKind="Dll" />
68+
<!-- After the merge the standalone Core.dll/.pdb in the UI bin folder
69+
are dead weight; delete them so the bin folder matches what we
70+
actually ship. Core's own project bin (src/Core/bin/) keeps its
71+
copy for the test project to reference. -->
72+
<Delete Files="$(OutputPath)EQ2Lexicon.ACTPlugin.Core.dll;$(OutputPath)EQ2Lexicon.ACTPlugin.Core.pdb" />
73+
</Target>
74+
3175
<!--
3276
ACT itself is the reference assembly (the EXE is a .NET assembly that
3377
exposes the plugin interfaces). Private=False stops MSBuild copying the

0 commit comments

Comments
 (0)