Skip to content

feat: retarget ConfuserEx from .NET Framework 4.6.1 to .NET 10 - #71

Merged
mcpolo99 merged 30 commits into
pre-releasefrom
feat/issue-53-net10-retarget
Jun 11, 2026
Merged

feat: retarget ConfuserEx from .NET Framework 4.6.1 to .NET 10#71
mcpolo99 merged 30 commits into
pre-releasefrom
feat/issue-53-net10-retarget

Conversation

@mcpolo99

@mcpolo99 mcpolo99 commented Jun 10, 2026

Copy link
Copy Markdown
Owner

Summary

Retargets ConfuserEx from .NET Framework 4.6.1 (EOL April 2022) to .NET 10 LTS (supported until Nov 2028).

Fixes #53

TFM Changes

Project Before After
Core, Protections, Renamer, DynCipher, MSBuild.Tasks net461;netstandard2.0 net48;netstandard2.0
GUI (ConfuserEx) net461 net10.0-windows
CLI (Confuser.CLI) net461 net10.0
Runtime net20 net20 (unchanged)
Test harness (UnitTest) net461 net462;net10.0
Integration test projects net461 net462
Confuser.Core.Test, Renamer.Test net461 net10.0

Breaking Changes

  • MvvmLightLibs → CommunityToolkit.Mvvm 8.x (7 files, sealed RelayCommand<T>)
  • AppDomain → AssemblyLoadContext in ComponentDiscovery (plugin isolation)
  • Ookii.Dialogs.Wpf 4.0.0 → 5.x
  • Microsoft.Build.Tasks.Core 15.9 → 17.x

What Changed (5 commits)

  1. Config cleanup — LangVersion latest, remove redundant NuGet packages, delete appveyor.yml
  2. Library TFMs — net461 → net48 (all library projects)
  3. GUI retarget — net10.0-windows, MvvmLight → CommunityToolkit, AppDomain → ALC, Process.Start fix
  4. CLI retarget — net10.0, cross-platform Console.Title guard
  5. CI + tests — dotnet CLI build, .NET 10 SDK, NuGet bumps, global.json

Build Result

  • 70 projects build successfully
  • 0 new errors, 0 new warnings
  • 2 pre-existing test subject failures (C++ project, sn.exe) — not regressions

Test plan

  • Build succeeds in CI with .NET 10 SDK
  • GUI launches and loads a .crproj file
  • CLI obfuscates a sample assembly
  • Plugin loading works via new AssemblyLoadContext
  • Integration tests pass on net462
  • Pre-release binary runs on a clean machine

RandomCrocodile added 12 commits June 10, 2026 16:44
- LangVersion 7.3 → latest
- Conditionalize AutoGenerateBindingRedirects to net48 only
- Remove redundant NuGet packages (System.Threading, System.ValueTuple, System.Runtime.Extensions)
- Delete obsolete appveyor.yml (replaced by GitHub Actions)
- Update RepositoryUrl to mcpolo99/ConfuserExx
- Core, Protections, Renamer, DynCipher, MSBuild.Tasks: net461 → net48
- Update conditional references (Runtime, System.Web) to check net48
- Update MSBuild.Tasks NuGet packaging paths to net48
- Build verified: all library projects compile for both net48 and netstandard2.0
- ConfuserEx.csproj: net461 → net10.0-windows, SDK → Microsoft.NET.Sdk
- MvvmLightLibs 5.4.1.1 → CommunityToolkit.Mvvm 8.x
  - 7 files: GalaSoft.MvvmLight.CommandWpf → CommunityToolkit.Mvvm.Input
  - RaiseCanExecuteChanged → NotifyCanExecuteChanged
  - DragDropCommand subclass removed (RelayCommand<T> is sealed in CommunityToolkit)
- Ookii.Dialogs.Wpf 4.0.0 → 5.x
- ComponentDiscovery: AppDomain → collectible AssemblyLoadContext
  - PluginLoadContext defers Confuser.Core/dnlib to default context for type identity
  - CrossDomainContext (MarshalByRefObject) deleted
- AboutTabVM: Process.Start(url) → ProcessStartInfo with UseShellExecute=true
- Build verified: 0 errors, 0 warnings
- Confuser.CLI.csproj: net461 → net10.0
- Guard Console.Title get/set with OperatingSystem.IsWindows() for cross-platform support
- Build verified: 0 errors, 0 warnings
- CI: switch from VS MSBuild to dotnet CLI (MSBuild 18+ required by .NET 10 SDK)
- CI: add actions/setup-dotnet for .NET 10 SDK, remove MSBuild setup step
- CI: update packaging paths from net461 to net10.0/net10.0-windows
- CI: add dotnet test step
- global.json: pin .NET 10 SDK with latestMinor rollForward
- Confuser.UnitTest: multi-target net462;net10.0 (integration tests need Framework)
- Integration test projects: net461 → net462 (xunit.runner.visualstudio 2.8+ minimum)
- Confuser.Core.Test, Confuser.Renamer.Test: net461 → net10.0, Moq 4.17 → 4.20
- Confuser.UnitTest: xunit 2.4.1 → 2.9, Microsoft.NET.Test.Sdk 17.0 → 17.12
- Microsoft.Build.Tasks.Core: 15.9 → 17.x
- Build verified: 70 projects succeed, 2 pre-existing failures (C++ project, sn.exe)
…pport (#53)

- Switch all jobs from windows-2022 to windows-2025 (VS2026 / MSBuild 18)
- MSBuild 18 supports .NET 10 SDK natively — no hybrid build needed
- Single msbuild call builds all projects: .NET 10, Framework, C++/CLI
- Fix 118_EnhancedStrongName: resolve sn.exe via registry fallback
  when SDK40ToolsPath is not set (dotnet CLI environments)
- 244_ClrProtection.vcxproj: TargetFrameworkVersion v4.6.1 → v4.8
- windows-2025 runner does not include 4.6.1 targeting pack
- Consistent with library TFM migration (all Framework targets → net48)
…ility (#53)

- dotnet test on the full solution fails because vcxproj can't be loaded
- Instead, enumerate *.Test.csproj files and test each individually
- Gives proper per-project test reporting and exit code
- Obfuscate_SampleApp_ProducesRunnableOutput: builds a net461 sample app,
  runs Confuser.CLI with rename protection, verifies output exists, differs
  from original, and the obfuscated exe runs correctly (START/Hello/END, exit 42)
- Cli_NoArgs_ReturnsNonZeroAndShowsUsage: verifies CLI shows usage on no args
- SampleApp fixture pre-built via MSBuild target (avoids SDK version conflicts)
- Confuser.Runtime.dll copied to test output for protection pipeline
- .NET 10 SDK, .NET Framework 4.8 Developer Pack, VS 2025+ with C++ workload
- Build commands for full solution (MSBuild 18) and .NET-only (dotnet CLI)
- TFM table showing net48, netstandard2.0, net10.0, net10.0-windows, net20
- SampleApp.csproj: net461 → net48 (windows-2025 lacks 4.6.1 targeting pack)
- 244_ClrProtection.Test: net462 → net48 (match C++/CLI project TFM, eliminates MSB3274 warning)
#53)

- Tests/Directory.Build.props: auto-inject coverlet.collector into all *.Test projects
- CI test step: collect XPlat Code Coverage (Cobertura XML) per test project
- CI report step: generate HTML + text summary via ReportGenerator
- Upload coverage-report artifact (downloadable HTML with per-file drill-down)
- Coverage summary printed to CI log for quick visibility
@mcpolo99
mcpolo99 marked this pull request as draft June 10, 2026 17:07
RandomCrocodile added 2 commits June 10, 2026 20:23
)

GUI smoke tests (FlaUI.UIA3):
- Gui_Launches_ShowsMainWindow: verifies GUI starts, title shows project name
- Gui_LoadProject_ShowsModules: opens .crproj, verifies modules appear in list
- Gui_ProtectSampleApp_ShowsSuccess: full protect cycle through UI, verifies
  obfuscated exe exists, runs correctly with expected output

Runtime deployment fix:
- ConfuserEx.csproj + Confuser.CLI.csproj: add CopyConfuserRuntime target
  to copy Confuser.Runtime.dll (net20) to output after build
- Protection pipeline requires Runtime.dll at the same path as Confuser.Core.dll
- Previously worked on net461 via transitive project reference, but net10.0
  doesn't copy net20 assemblies automatically
- Add MarkdownSummaryGithub report type to ReportGenerator
- Post coverage table to GitHub Actions job summary (visible in run's Summary tab)
- Post sticky coverage comment on PRs via marocchino/sticky-pull-request-comment
- Add pull-requests: write permission to build job for PR comment access
- Coverage table shows per-assembly line/branch % directly in the PR
@github-actions

github-actions Bot commented Jun 10, 2026

Copy link
Copy Markdown

Summary

Summary
Generated on: 6/10/2026 - 10:04:47 PM
Coverage date: 6/10/2026 - 10:03:32 PM - 6/10/2026 - 10:04:34 PM
Parser: MultiReport (3x Cobertura)
Assemblies: 6
Classes: 326
Files: 243
Line coverage: 25.1% (4160 of 16539)
Covered lines: 4160
Uncovered lines: 12379
Coverable lines: 16539
Total lines: 32233
Branch coverage: 21% (1573 of 7483)
Covered branches: 1573
Total branches: 7483
Method coverage: Feature is only available for sponsors

Coverage

Confuser.CLI - 53.3%
Name Line Branch
Confuser.CLI 53.3% 23.4%
Confuser.CLI.Program 53.3% 23.4%
Confuser.Core - 25.7%
Name Line Branch
Confuser.Core 25.7% 21.9%
Confuser.Core.AfterProtectionAttribute 100%
Confuser.Core.Annotations 72.4% 54.6%
Confuser.Core.API.APIStore 25% 0%
Confuser.Core.BeforeProtectionAttribute 100%
Confuser.Core.CircularDependencyException 0%
Confuser.Core.ConfuserAssemblyResolver 65.2% 69.4%
Confuser.Core.ConfuserContext 45.4% 16.6%
Confuser.Core.ConfuserEngine 63.8% 53.8%
Confuser.Core.ConfuserException 0%
Confuser.Core.ConfuserParameters 100% 83.3%
Confuser.Core.CoreComponent 75%
Confuser.Core.DependencyResolver 97.8% 94.4%
Confuser.Core.DnlibUtils 30% 27.2%
Confuser.Core.DotNetCorePathResolver 60.4% 50%
Confuser.Core.Helpers.ControlFlowBlock 0%
Confuser.Core.Helpers.ControlFlowGraph 0% 0%
Confuser.Core.Helpers.InjectHelper 0% 0%
Confuser.Core.Helpers.KeySequence 0% 0%
Confuser.Core.Helpers.MutationHelper 0% 0%
Confuser.Core.Marker 18.6% 11.6%
Confuser.Core.MarkerResult 100%
Confuser.Core.ModuleSorter 58.9% 55.5%
Confuser.Core.NativeEraser 0% 0%
Confuser.Core.NullLogger 0%
Confuser.Core.ObfAttrMarker 49.8% 41.7%
Confuser.Core.ObfAttrParser 30.5% 29.7%
Confuser.Core.Packer 0% 0%
Confuser.Core.PackerDiscovery 0%
Confuser.Core.PackerLogger 0% 0%
Confuser.Core.PackerMarker 0% 0%
Confuser.Core.PluginDiscovery 59% 94.4%
Confuser.Core.Project.ConfuserProject 53.4% 39.5%
Confuser.Core.Project.InvalidPatternException 0%
Confuser.Core.Project.PatternParser 43.3% 26.9%
Confuser.Core.Project.Patterns.AndOperator 0% 0%
Confuser.Core.Project.Patterns.DeclTypeFunction 0% 0%
Confuser.Core.Project.Patterns.FullNameFunction 0%
Confuser.Core.Project.Patterns.HasAttrFunction 0%
Confuser.Core.Project.Patterns.InheritsFunction 0% 0%
Confuser.Core.Project.Patterns.IsPublicFunction 0% 0%
Confuser.Core.Project.Patterns.IsTypeFunction 0% 0%
Confuser.Core.Project.Patterns.LiteralExpression 50% 0%
Confuser.Core.Project.Patterns.MatchFunction 0%
Confuser.Core.Project.Patterns.MatchNameFunction 0%
Confuser.Core.Project.Patterns.MatchTypeNameFunction 0% 0%
Confuser.Core.Project.Patterns.MemberTypeFunction 0% 0%
Confuser.Core.Project.Patterns.ModuleFunction 0% 0%
Confuser.Core.Project.Patterns.NameFunction 0%
Confuser.Core.Project.Patterns.NamespaceFunction 0% 0%
Confuser.Core.Project.Patterns.NotOperator 0%
Confuser.Core.Project.Patterns.OrOperator 0% 0%
Confuser.Core.Project.Patterns.PatternFunction 0% 0%
Confuser.Core.Project.Patterns.PatternOperator 0% 0%
Confuser.Core.Project.PatternToken 17.3% 0%
Confuser.Core.Project.PatternTokenizer 55.5% 51.2%
Confuser.Core.Project.ProjectModule 47.1% 26%
Confuser.Core.Project.ProjectValidationException 0%
Confuser.Core.Project.Rule 39.5% 25%
Confuser.Core.Project.SettingItem`1 33.3% 16.6%
Confuser.Core.ProtectionParameters 64.2% 43.7%
Confuser.Core.ProtectionPhase 100%
Confuser.Core.ProtectionPipeline 92.8% 87.5%
Confuser.Core.ProtectionSettings 62.5% 50%
Confuser.Core.ServiceRegistry 63.6% 33.3%
Confuser.Core.Services.CompressionService 3.6% 0%
Confuser.Core.Services.MarkerService 68.4% 50%
Confuser.Core.Services.MethodTrace 0% 0%
Confuser.Core.Services.RandomGenerator 62.8% 53.1%
Confuser.Core.Services.RandomService 91.6% 66.6%
Confuser.Core.Services.RuntimeService 83.3% 80%
Confuser.Core.Services.TraceService 50% 0%
Confuser.Core.UnreachableException 0%
Confuser.Core.Utils 80.5% 64%
Confuser.Core.WatermarkingProtection 92.3% 75%
SevenZip.Buffer.InBuffer 0% 0%
SevenZip.Buffer.OutBuffer 0% 0%
SevenZip.Compression.LZ.BinTree 0% 0%
SevenZip.Compression.LZ.InWindow 0% 0%
SevenZip.Compression.LZ.OutWindow 0% 0%
SevenZip.Compression.LZMA.Base 0% 0%
SevenZip.Compression.LZMA.Decoder 0% 0%
SevenZip.Compression.LZMA.Encoder 0% 0%
SevenZip.Compression.RangeCoder.BitDecoder 0% 0%
SevenZip.Compression.RangeCoder.BitEncoder 0% 0%
SevenZip.Compression.RangeCoder.BitTreeDecoder 0% 0%
SevenZip.Compression.RangeCoder.BitTreeEncoder 0% 0%
SevenZip.Compression.RangeCoder.Decoder 0% 0%
SevenZip.Compression.RangeCoder.Encoder 0% 0%
SevenZip.CRC 0% 0%
SevenZip.DataErrorException 0%
SevenZip.InvalidParamException 0%
Confuser.DynCipher - 0.2%
Name Line Branch
Confuser.DynCipher 0.2% 0%
Confuser.DynCipher.AST.ArrayIndexExpression 0%
Confuser.DynCipher.AST.AssignmentStatement 0%
Confuser.DynCipher.AST.BinOpExpression 0% 0%
Confuser.DynCipher.AST.Expression 0%
Confuser.DynCipher.AST.LiteralExpression 0%
Confuser.DynCipher.AST.LoopStatement 0%
Confuser.DynCipher.AST.Statement 0%
Confuser.DynCipher.AST.StatementBlock 0% 0%
Confuser.DynCipher.AST.UnaryOpExpression 0% 0%
Confuser.DynCipher.AST.Variable 0%
Confuser.DynCipher.AST.VariableExpression 0%
Confuser.DynCipher.CodeGenUtils 0% 0%
Confuser.DynCipher.DynCipherComponent 42.8%
Confuser.DynCipher.DynCipherService 0%
Confuser.DynCipher.Elements.AddKey 0%
Confuser.DynCipher.Elements.BinOp 0% 0%
Confuser.DynCipher.Elements.CryptoElement 0%
Confuser.DynCipher.Elements.Matrix 0% 0%
Confuser.DynCipher.Elements.NumOp 0% 0%
Confuser.DynCipher.Elements.RotateBit 0% 0%
Confuser.DynCipher.Elements.Swap 0% 0%
Confuser.DynCipher.Generation.CILCodeGen 0% 0%
Confuser.DynCipher.Generation.CipherGenContext 0% 0%
Confuser.DynCipher.Generation.CipherGenerator 0% 0%
Confuser.DynCipher.Generation.DMCodeGen 0% 0%
Confuser.DynCipher.Generation.ExpressionGenerator 0% 0%
Confuser.DynCipher.Generation.x86CodeGen 0% 0%
Confuser.DynCipher.Generation.x86ImmediateOperand 0%
Confuser.DynCipher.Generation.x86Instruction 0% 0%
Confuser.DynCipher.Generation.x86RegisterOperand 0%
Confuser.DynCipher.MathsUtils 0% 0%
Confuser.DynCipher.Transforms.ConvertVariables 0% 0%
Confuser.DynCipher.Transforms.ExpansionTransform 0% 0%
Confuser.DynCipher.Transforms.MulToShiftTransform 0% 0%
Confuser.DynCipher.Transforms.NormalizeBinOpTransform 0% 0%
Confuser.DynCipher.Transforms.ShuffleTransform 0% 0%
Confuser.Protections - 4.9%
Name Line Branch
Confuser.Protections 4.9% 1.9%
Confuser.Protections.AntiDebugProtection 22% 3.8%
Confuser.Protections.AntiDumpProtection 59% 25%
Confuser.Protections.AntiILDasmProtection 58.8% 50%
Confuser.Protections.AntiTamper.AntiMode 0% 0%
Confuser.Protections.AntiTamper.AntiTamperExtensions 0% 0%
Confuser.Protections.AntiTamper.DynamicDeriver 0% 0%
Confuser.Protections.AntiTamper.JITBodyIndex 0% 0%
Confuser.Protections.AntiTamper.JITMethodBody 0% 0%
Confuser.Protections.AntiTamper.JITMethodBodyWriter 0% 0%
Confuser.Protections.AntiTamper.JITMode 0% 0%
Confuser.Protections.AntiTamper.NormalDeriver 0% 0%
Confuser.Protections.AntiTamper.NormalMode 0% 0%
Confuser.Protections.AntiTamperProtection 48.8% 25%
Confuser.Protections.Compress.CompressorContext 0% 0%
Confuser.Protections.Compress.DynamicDeriver 0% 0%
Confuser.Protections.Compress.ExtractPhase 12.8% 5.5%
Confuser.Protections.Compress.NormalDeriver 0% 0%
Confuser.Protections.Compress.StubProtection 0% 0%
Confuser.Protections.Compressor 1.7% 0%
Confuser.Protections.ConstantProtection 61.5%
Confuser.Protections.Constants.DynamicMode 0% 0%
Confuser.Protections.Constants.EncodePhase 2.7% 1.1%
Confuser.Protections.Constants.InjectPhase 4.3% 1.7%
Confuser.Protections.Constants.NormalMode 0% 0%
Confuser.Protections.Constants.ReferenceReplacer 0% 0%
Confuser.Protections.Constants.x86Mode 0% 0%
Confuser.Protections.ControlFlow.BlockBase 0%
Confuser.Protections.ControlFlow.BlockParser 0% 0%
Confuser.Protections.ControlFlow.CFContext 0% 0%
Confuser.Protections.ControlFlow.ControlFlowPhase 23% 20.5%
Confuser.Protections.ControlFlow.ExpressionPredicate 0% 0%
Confuser.Protections.ControlFlow.InstrBlock 0% 0%
Confuser.Protections.ControlFlow.JumpMangler 0% 0%
Confuser.Protections.ControlFlow.ManglerBase 0% 0%
Confuser.Protections.ControlFlow.NormalPredicate 0% 0%
Confuser.Protections.ControlFlow.ScopeBlock 0% 0%
Confuser.Protections.ControlFlow.SwitchMangler 0% 0%
Confuser.Protections.ControlFlow.x86Predicate 0% 0%
Confuser.Protections.ControlFlowProtection 54.5%
Confuser.Protections.HardeningPhase 25% 3.5%
Confuser.Protections.HardeningProtection 57.1%
Confuser.Protections.InvalidMetadataProtection 21.7% 10%
Confuser.Protections.ReferenceProxy.ExpressionEncoding 0% 0%
Confuser.Protections.ReferenceProxy.MildMode 0% 0%
Confuser.Protections.ReferenceProxy.NormalEncoding 0% 0%
Confuser.Protections.ReferenceProxy.ReferenceProxyPhase 24.1% 6.7%
Confuser.Protections.ReferenceProxy.RPMode 0% 0%
Confuser.Protections.ReferenceProxy.StrongMode 0% 0%
Confuser.Protections.ReferenceProxy.x86Encoding 0% 0%
Confuser.Protections.ReferenceProxyProtection 37.5%
Confuser.Protections.ResourceProtection 62.5%
Confuser.Protections.Resources.DynamicMode 0% 0%
Confuser.Protections.Resources.InjectPhase 5.4% 3.3%
Confuser.Protections.Resources.MDPhase 0% 0%
Confuser.Protections.Resources.NormalMode 0% 0%
Confuser.Protections.TypeScrambler.AnalyzePhase 61.5% 30%
Confuser.Protections.TypeScrambler.ScramblePhase 36.8% 16.6%
Confuser.Protections.TypeScrambler.Scrambler.Analyzers.ContextAnalyzer`1 0%
Confuser.Protections.TypeScrambler.Scrambler.Analyzers.ContextAnalyzerFacto
ry
0% 0%
Confuser.Protections.TypeScrambler.Scrambler.Analyzers.MemberRefAnalyzer 0% 0%
Confuser.Protections.TypeScrambler.Scrambler.Analyzers.MethodDefAnalyzer 0% 0%
Confuser.Protections.TypeScrambler.Scrambler.Analyzers.MethodSpecAnalyzer 0% 0%
Confuser.Protections.TypeScrambler.Scrambler.Analyzers.TypeRefAnalyzer 0%
Confuser.Protections.TypeScrambler.Scrambler.Rewriter.Instructions.FieldDef
InstructionRewriter
0% 0%
Confuser.Protections.TypeScrambler.Scrambler.Rewriter.Instructions.Instruct
ionRewriter`1
0%
Confuser.Protections.TypeScrambler.Scrambler.Rewriter.Instructions.Instruct
ionRewriterFactory
0% 0%
Confuser.Protections.TypeScrambler.Scrambler.Rewriter.Instructions.MemberRe
fInstructionRewriter
0% 0%
Confuser.Protections.TypeScrambler.Scrambler.Rewriter.Instructions.MethodDe
fInstructionRewriter
0% 0%
Confuser.Protections.TypeScrambler.Scrambler.Rewriter.Instructions.MethodSp
ecInstructionRewriter
0% 0%
Confuser.Protections.TypeScrambler.Scrambler.Rewriter.Instructions.TypeDefI
nstructionRewriter
0% 0%
Confuser.Protections.TypeScrambler.Scrambler.Rewriter.Instructions.TypeRefI
nstructionRewriter
0% 0%
Confuser.Protections.TypeScrambler.Scrambler.ScannedItem 0% 0%
Confuser.Protections.TypeScrambler.Scrambler.ScannedMethod 0% 0%
Confuser.Protections.TypeScrambler.Scrambler.ScannedType 0% 0%
Confuser.Protections.TypeScrambler.Scrambler.SignatureUtils 0% 0%
Confuser.Protections.TypeScrambler.Scrambler.TypeRewriter 0% 0%
Confuser.Protections.TypeScrambler.TypeScrambleProtection 75% 50%
Confuser.Protections.TypeScrambler.TypeService 13.3% 0%
Confuser.Protections.Utils 0% 0%
Confuser.Renamer - 42%
Name Line Branch
Confuser.Renamer 42% 37.7%
Confuser.Renamer.AnalyzePhase 66.2% 61.5%
Confuser.Renamer.Analyzers.CaliburnAnalyzer 0% 0%
Confuser.Renamer.Analyzers.CallSiteAnalyzer 22.2% 25.8%
Confuser.Renamer.Analyzers.InterReferenceAnalyzer 87.5% 90%
Confuser.Renamer.Analyzers.JsonAnalyzer 0% 0%
Confuser.Renamer.Analyzers.LdtokenEnumAnalyzer 12.6% 18.5%
Confuser.Renamer.Analyzers.ManifestResourceAnalyzer 35.7% 65.7%
Confuser.Renamer.Analyzers.ReflectionAnalyzer 19.6% 21.2%
Confuser.Renamer.Analyzers.ResourceAnalyzer 27.2% 30%
Confuser.Renamer.Analyzers.TypeBlobAnalyzer 59.5% 53.4%
Confuser.Renamer.Analyzers.VisualBasicRuntimeAnalyzer 0% 0%
Confuser.Renamer.Analyzers.VsCompositionAnalyzer 0% 0%
Confuser.Renamer.Analyzers.VTableAnalyzer 59.1% 55%
Confuser.Renamer.Analyzers.WinFormsAnalyzer 28% 31.7%
Confuser.Renamer.Analyzers.WPFAnalyzer 58.3% 53%
Confuser.Renamer.BAML.AssemblyInfoRecord 100%
Confuser.Renamer.BAML.AttributeInfoRecord 100%
Confuser.Renamer.BAML.BAMLAnalyzer 41.7% 42.7%
Confuser.Renamer.BAML.BamlBinaryReader 100%
Confuser.Renamer.BAML.BamlBinaryWriter 100%
Confuser.Renamer.BAML.BamlDocument 100%
Confuser.Renamer.BAML.BamlElement 77% 71.2%
Confuser.Renamer.BAML.BAMLPropertyReference 0% 0%
Confuser.Renamer.BAML.BamlReader 37.2% 28.7%
Confuser.Renamer.BAML.BamlRecord 100%
Confuser.Renamer.BAML.BAMLStringReference 100% 75%
Confuser.Renamer.BAML.BamlWriter 95.4% 66.6%
Confuser.Renamer.BAML.ConnectionIdRecord 100%
Confuser.Renamer.BAML.ConstructorParametersEndRecord 0%
Confuser.Renamer.BAML.ConstructorParametersStartRecord 0%
Confuser.Renamer.BAML.ConstructorParameterTypeRecord 0%
Confuser.Renamer.BAML.ContentPropertyRecord 100%
Confuser.Renamer.BAML.DefAttributeKeyStringRecord 0% 0%
Confuser.Renamer.BAML.DefAttributeKeyTypeRecord 0% 0%
Confuser.Renamer.BAML.DefAttributeRecord 0%
Confuser.Renamer.BAML.DeferableContentStartRecord 0%
Confuser.Renamer.BAML.DocumentEndRecord 100%
Confuser.Renamer.BAML.DocumentStartRecord 100%
Confuser.Renamer.BAML.ElementEndRecord 100%
Confuser.Renamer.BAML.ElementStartRecord 100%
Confuser.Renamer.BAML.IndexerParamInfo 0%
Confuser.Renamer.BAML.KeyElementEndRecord 0%
Confuser.Renamer.BAML.KeyElementStartRecord 0%
Confuser.Renamer.BAML.KnownThingsv3 0% 0%
Confuser.Renamer.BAML.KnownThingsv4 99.9% 100%
Confuser.Renamer.BAML.LineNumberAndPositionRecord 0%
Confuser.Renamer.BAML.LinePositionRecord 0%
Confuser.Renamer.BAML.LiteralContentRecord 0%
Confuser.Renamer.BAML.NamedElementStartRecord 0% 0%
Confuser.Renamer.BAML.OptimizedStaticResourceRecord 0%
Confuser.Renamer.BAML.PIMappingRecord 0%
Confuser.Renamer.BAML.PresentationOptionsAttributeRecord 0%
Confuser.Renamer.BAML.PropertyArrayEndRecord 0%
Confuser.Renamer.BAML.PropertyArrayStartRecord 0%
Confuser.Renamer.BAML.PropertyComplexEndRecord 0%
Confuser.Renamer.BAML.PropertyComplexStartRecord 0%
Confuser.Renamer.BAML.PropertyCustomRecord 0%
Confuser.Renamer.BAML.PropertyDictionaryEndRecord 0%
Confuser.Renamer.BAML.PropertyDictionaryStartRecord 0%
Confuser.Renamer.BAML.PropertyListEndRecord 0%
Confuser.Renamer.BAML.PropertyListStartRecord 0%
Confuser.Renamer.BAML.PropertyPathIndexUpdater 0% 0%
Confuser.Renamer.BAML.PropertyPathParser 0.7% 0%
Confuser.Renamer.BAML.PropertyPathPartUpdater 0% 0%
Confuser.Renamer.BAML.PropertyPathUpdater 0% 0%
Confuser.Renamer.BAML.PropertyRecord 88.8%
Confuser.Renamer.BAML.PropertyStringReferenceRecord 0%
Confuser.Renamer.BAML.PropertyTypeReferenceRecord 0%
Confuser.Renamer.BAML.PropertyWithConverterRecord 100%
Confuser.Renamer.BAML.PropertyWithExtensionRecord 0%
Confuser.Renamer.BAML.PropertyWithStaticResourceIdRecord 0%
Confuser.Renamer.BAML.RoutedEventRecord 0%
Confuser.Renamer.BAML.SizedBamlRecord 66.6% 12.5%
Confuser.Renamer.BAML.SourceValueInfo 0%
Confuser.Renamer.BAML.StaticResourceEndRecord 0%
Confuser.Renamer.BAML.StaticResourceIdRecord 0%
Confuser.Renamer.BAML.StaticResourceStartRecord 0%
Confuser.Renamer.BAML.StringInfoRecord 0%
Confuser.Renamer.BAML.TextRecord 0%
Confuser.Renamer.BAML.TextWithConverterRecord 0%
Confuser.Renamer.BAML.TextWithIdRecord 0%
Confuser.Renamer.BAML.TypeInfoRecord 100%
Confuser.Renamer.BAML.TypeSerializerInfoRecord 0%
Confuser.Renamer.BAML.XmlnsPropertyRecord 100% 100%
Confuser.Renamer.DisplayNormalizedName 100%
Confuser.Renamer.GenericArgumentResolver 37.8% 40%
Confuser.Renamer.GenericArguments 50% 46.4%
Confuser.Renamer.MessageDeobfuscator 0% 0%
Confuser.Renamer.NameProtection 60.7% 16.6%
Confuser.Renamer.NameService 60.5% 41%
Confuser.Renamer.PostRenamePhase 100% 100%
Confuser.Renamer.Properties.Resources 0% 0%
Confuser.Renamer.RecursionCounter 75% 50%
Confuser.Renamer.References.BAMLAttributeReference 0% 0%
Confuser.Renamer.References.BAMLConverterMemberReference 0% 0%
Confuser.Renamer.References.BAMLConverterTypeReference 0% 0%
Confuser.Renamer.References.BAMLEnumReference 0% 0%
Confuser.Renamer.References.BAMLPathTypeReference 0% 0%
Confuser.Renamer.References.BAMLTypeReference 52.9% 100%
Confuser.Renamer.References.CAMemberReference 0% 0%
Confuser.Renamer.References.MemberOldestSiblingReference 0% 0%
Confuser.Renamer.References.MemberOverrideReference 0% 0%
Confuser.Renamer.References.MemberRefReference 23.5% 0%
Confuser.Renamer.References.MemberSiblingReference 0% 0%
Confuser.Renamer.References.OverrideDirectiveReference 53.8% 50%
Confuser.Renamer.References.RequiredPrefixReference`1 0% 0%
Confuser.Renamer.References.ResourceReference 0% 0%
Confuser.Renamer.References.StringMemberNameReference 0% 0%
Confuser.Renamer.References.StringTypeReference 0% 0%
Confuser.Renamer.References.TypeRefReference 21% 0%
Confuser.Renamer.ReferenceUtilities 0% 0%
Confuser.Renamer.RenamePhase 53.5% 51%
Confuser.Renamer.ReversibleRenamer 0% 0%
Confuser.Renamer.RickRoller 0% 0%
Confuser.Renamer.VTable 90.9% 84.2%
Confuser.Renamer.VTableSignature 80.7% 66.6%
Confuser.Renamer.VTableSlot 87.5%
Confuser.Renamer.VTableStorage 78% 62.5%
Confuser.UnitTest - 0%
Name Line Branch
Confuser.UnitTest 0% ****
AutoGeneratedProgram 0%

RandomCrocodile added 2 commits June 10, 2026 21:12
#53)

- ci.yml: build + package + release only (lean, ~3 min)
- test.yml: tests + coverage + PR comment + HTML report (separate pipeline)
- Both triggered on same events, run in parallel
- CONTRIBUTING.md: testing policy, coverage targets, ratchet strategy,
  test types, how to write integration/unit tests, commit conventions
- Run dotnet format on all 280 source files for consistent style
- Fix import ordering (System.* first, then project namespaces)
- Fix missing final newlines
- Fix merge-conflict markers left by dotnet format in multi-TFM projects
- Add .github/workflows/format.yml: checks formatting on PRs, reports
  which files need fixing if violations found
- All formatting rules enforced via existing .editorconfig
@jeremy-visionaid

Copy link
Copy Markdown

Nice one! I've got a bunch of other fixes locally, but they're going to conflict pretty heavily with the formatting changes here. Currently the line endings are pretty inconsitent too. I'd propose adding something like the following in .gitattributes:

# Set default behavior, in case users don't have core.autocrlf set.
* text=auto

# Explicitly declare text files we want to always be normalized and converted
# to native line endings on checkout.
*.config text
*.cs text
*.manifest text
*.md text
*.resx text
*.txt text
*.xml text

# Declare files that will always have CRLF line endings on checkout.
*.csproj text eol=crlf
*.dbproj text eol=crlf
*.fsproj text eol=crlf
*.inf text eol=crlf
*.lsproj text eol=crlf
*.modelproj text eol=crlf
*.sln text eol=crlf
*.sqlproj text eol=crlf
*.vbproj text eol=crlf
*.vcproj text eol=crlf
*.vcxproj text eol=crlf
*.wixproj text eol=crlf
*.wmaproj text eol=crlf

# Denote all files that are truly binary and should not be modified.
*.apk binary
*.dll binary
*.exe binary
*.ico binary
*.jpeg binary
*.jpg binary
*.pdf binary
*.png binary

Then:
git add --renormalize .

- Normalize text files to native line endings on checkout
- Force CRLF for project files (.sln, .csproj, .vcxproj, etc.)
- Mark binary files (dll, exe, ico, snk, otf) as binary
- Run git add --renormalize to fix existing inconsistencies
- Addresses review feedback on PR #71
@mcpolo99

Copy link
Copy Markdown
Owner Author

Good suggestion — added .gitattributes with the proposed configuration in commit 068f704.

Also added *.xaml, *.yml, *.json, *.props, *.targets as text files, and *.otf, *.snk as binary.

Ran git add --renormalize . to fix existing inconsistencies (9 files had mixed line endings).

Regarding your local fixes conflicting with the formatting — the formatting commit (3fe4389) was a one-time dotnet format pass. Going forward, the format CI check enforces consistent style on PRs. If you rebase your branch on top of this one, dotnet format should auto-resolve most conflicts. Happy to help coordinate if needed.

RandomCrocodile and others added 6 commits June 10, 2026 23:55
17 new tests covering obfuscation across all supported .NET frameworks:

Console (7 tests):
- net20, net35, net40, net48: obfuscate + run + verify output
- net6.0, net8.0, net10.0: obfuscate .dll (apphost .exe is not managed)

WinForms (4 tests):
- net35, net40, net48: obfuscate + run with --verify + verify output
- net10.0-windows: obfuscate .dll

WPF (4 tests):
- net35, net40: code-only WPF (no XAML codegen for old TFMs)
- net48: XAML + code-behind (tests BAML renaming)
- net10.0-windows: obfuscate .dll

Class Library (2 tests):
- netstandard2.0, net8.0: obfuscate DLL with public API surface

Infrastructure:
- TestBase.Run() now accepts processArguments parameter
- Each test uses unique outputDirSuffix to prevent parallel conflicts
- Confuser.Runtime.dll copied to test output
- All old TFMs use Microsoft.NETFramework.ReferenceAssemblies for CI compat
#73)

- WinForms: net6.0-windows, net8.0-windows (obfuscate .dll)
- Library: net48, net6.0 (obfuscate DLL with public API surface)
- Total: 21 cross-framework tests (was 17)
Root cause: Coverlet instruments all assemblies in the test output with
RecordHit() calls. ConfuserEx then obfuscates the subjects (renaming
RecordHit), and the obfuscated exe crashes at runtime with:
  MissingMethodException: Method not found 'Void ???.RecordHit(Int32)'

Fix: add shared coverlet.runsettings that limits coverage collection to
Confuser.* assemblies only, excluding test subjects (CrossFramework.*,
*.Test, xunit, Moq). Applied globally via Directory.Build.props.
windows-2025 runner only has .NET 8/9/10 pre-installed.
.NET 6.0 is EOL but we test it for backward compatibility.
The WinForms_Net6 test failed with TypeResolveException because
System.Runtime 6.0.0 wasn't available for assembly resolution.
…rix (#73)

Full coverage now: 24 tests across all supported frameworks and app types.

Added:
- WPF: net6.0-windows, net8.0-windows (obfuscate .dll)
- Library: net10.0 (obfuscate DLL)

Complete matrix:
| App Type | net20 | net35 | net40 | net48 | net6 | net8 | net10 | netstd2.0 |
|----------|-------|-------|-------|-------|------|------|-------|-----------|
| Console  |   x   |   x   |   x   |   x   |  x   |  x   |   x   |           |
| WinForms |       |   x   |   x   |   x   |  x   |  x   |   x   |           |
| WPF      |       |   x   |   x   |   x   |  x   |  x   |   x   |           |
| Library  |       |       |       |   x   |  x   |  x   |   x   |     x     |
test: cross-framework integration tests (Console, WinForms, WPF, Library)
@mcpolo99

Copy link
Copy Markdown
Owner Author

Nice one! I've got a bunch of other fixes locally, but they're going to conflict pretty heavily with the formatting changes here. Currently the line endings are pretty inconsitent too. I'd propose adding something like the following in .gitattributes:

# Set default behavior, in case users don't have core.autocrlf set.
* text=auto

# Explicitly declare text files we want to always be normalized and converted
# to native line endings on checkout.
*.config text
*.cs text
*.manifest text
*.md text
*.resx text
*.txt text
*.xml text

# Declare files that will always have CRLF line endings on checkout.
*.csproj text eol=crlf
*.dbproj text eol=crlf
*.fsproj text eol=crlf
*.inf text eol=crlf
*.lsproj text eol=crlf
*.modelproj text eol=crlf
*.sln text eol=crlf
*.sqlproj text eol=crlf
*.vbproj text eol=crlf
*.vcproj text eol=crlf
*.vcxproj text eol=crlf
*.wixproj text eol=crlf
*.wmaproj text eol=crlf

# Denote all files that are truly binary and should not be modified.
*.apk binary
*.dll binary
*.exe binary
*.ico binary
*.jpeg binary
*.jpg binary
*.pdf binary
*.png binary

Then: git add --renormalize .

i also decided to be messy and added some general testing to make sure all is actually working :D

@jeremy-visionaid

Copy link
Copy Markdown

i also decided to be messy and added some general testing to make sure all is actually working :D

All good! Nice to get this stuff fixed early to make things easier in the long run 👍

…ent (#53)

- Tests continue on failure — all projects run, nothing skipped
- Per-project result table posted to PR comment (passed/failed/skipped counts)
- Failed test names listed individually under the table
- Combined PR comment: test results + coverage report in one sticky comment
- Job summary also shows both test results and coverage
- Final step fails the job if any tests failed (after all reporting is done)
@github-actions

github-actions Bot commented Jun 10, 2026

Copy link
Copy Markdown

Test Results

All 29 tests passed

Project ✅ Passed ❌ Failed ⏩ Skipped Total
✅ Confuser.CLI.Test 2 0 0 2
✅ Confuser.GUI.Test 3 0 0 3
✅ CrossFramework.Test 24 0 0 24
Cross-Framework Test Details (click to expand)
Test Framework App Type Result
CrossFramework.Test.ConsoleFrameworkTest.Console_Net10_RenameProtection 10 Console
CrossFramework.Test.ConsoleFrameworkTest.Console_Net20_RenameProtection 20 Console
CrossFramework.Test.ConsoleFrameworkTest.Console_Net35_RenameProtection 35 Console
CrossFramework.Test.ConsoleFrameworkTest.Console_Net40_RenameProtection 40 Console
CrossFramework.Test.ConsoleFrameworkTest.Console_Net48_RenameProtection 48 Console
CrossFramework.Test.ConsoleFrameworkTest.Console_Net6_RenameProtection 6 Console
CrossFramework.Test.ConsoleFrameworkTest.Console_Net8_RenameProtection 8 Console
CrossFramework.Test.LibraryFrameworkTest.Library_Net10_RenameProtection 10 Library
CrossFramework.Test.LibraryFrameworkTest.Library_Net48_RenameProtection 48 Library
CrossFramework.Test.LibraryFrameworkTest.Library_Net6_RenameProtection 6 Library
CrossFramework.Test.LibraryFrameworkTest.Library_Net8_RenameProtection 8 Library
CrossFramework.Test.LibraryFrameworkTest.Library_NetStd20_RenameProtection Std20 Library
CrossFramework.Test.WinFormsFrameworkTest.WinForms_Net10_RenameProtection 10 WinForms
CrossFramework.Test.WinFormsFrameworkTest.WinForms_Net35_RenameProtection 35 WinForms
CrossFramework.Test.WinFormsFrameworkTest.WinForms_Net40_RenameProtection 40 WinForms
CrossFramework.Test.WinFormsFrameworkTest.WinForms_Net48_RenameProtection 48 WinForms
CrossFramework.Test.WinFormsFrameworkTest.WinForms_Net6_RenameProtection 6 WinForms
CrossFramework.Test.WinFormsFrameworkTest.WinForms_Net8_RenameProtection 8 WinForms
CrossFramework.Test.WpfFrameworkTest.WPF_Net10_RenameProtection 10 WPF
CrossFramework.Test.WpfFrameworkTest.WPF_Net35_RenameProtection 35 WPF
CrossFramework.Test.WpfFrameworkTest.WPF_Net40_RenameProtection 40 WPF
CrossFramework.Test.WpfFrameworkTest.WPF_Net48_RenameProtection 48 WPF
CrossFramework.Test.WpfFrameworkTest.WPF_Net6_RenameProtection 6 WPF
CrossFramework.Test.WpfFrameworkTest.WPF_Net8_RenameProtection 8 WPF

Summary

Summary
Generated on: 6/10/2026 - 10:37:43 PM
Coverage date: 6/10/2026 - 10:35:16 PM - 6/10/2026 - 10:37:30 PM
Parser: MultiReport (6x Cobertura)
Assemblies: 6
Classes: 326
Files: 243
Line coverage: 25.1% (4160 of 16539)
Covered lines: 4160
Uncovered lines: 12379
Coverable lines: 16539
Total lines: 32233
Branch coverage: 21% (1573 of 7483)
Covered branches: 1573
Total branches: 7483
Method coverage: Feature is only available for sponsors

Coverage

Confuser.CLI - 53.3%
Name Line Branch
Confuser.CLI 53.3% 23.4%
Confuser.CLI.Program 53.3% 23.4%
Confuser.Core - 25.7%
Name Line Branch
Confuser.Core 25.7% 21.9%
Confuser.Core.AfterProtectionAttribute 100%
Confuser.Core.Annotations 72.4% 54.6%
Confuser.Core.API.APIStore 25% 0%
Confuser.Core.BeforeProtectionAttribute 100%
Confuser.Core.CircularDependencyException 0%
Confuser.Core.ConfuserAssemblyResolver 65.2% 69.4%
Confuser.Core.ConfuserContext 45.4% 16.6%
Confuser.Core.ConfuserEngine 63.8% 53.8%
Confuser.Core.ConfuserException 0%
Confuser.Core.ConfuserParameters 100% 83.3%
Confuser.Core.CoreComponent 75%
Confuser.Core.DependencyResolver 97.8% 94.4%
Confuser.Core.DnlibUtils 30% 27.2%
Confuser.Core.DotNetCorePathResolver 60.4% 50%
Confuser.Core.Helpers.ControlFlowBlock 0%
Confuser.Core.Helpers.ControlFlowGraph 0% 0%
Confuser.Core.Helpers.InjectHelper 0% 0%
Confuser.Core.Helpers.KeySequence 0% 0%
Confuser.Core.Helpers.MutationHelper 0% 0%
Confuser.Core.Marker 18.6% 11.6%
Confuser.Core.MarkerResult 100%
Confuser.Core.ModuleSorter 58.9% 55.5%
Confuser.Core.NativeEraser 0% 0%
Confuser.Core.NullLogger 0%
Confuser.Core.ObfAttrMarker 49.8% 41.7%
Confuser.Core.ObfAttrParser 30.5% 29.7%
Confuser.Core.Packer 0% 0%
Confuser.Core.PackerDiscovery 0%
Confuser.Core.PackerLogger 0% 0%
Confuser.Core.PackerMarker 0% 0%
Confuser.Core.PluginDiscovery 59% 94.4%
Confuser.Core.Project.ConfuserProject 53.4% 39.5%
Confuser.Core.Project.InvalidPatternException 0%
Confuser.Core.Project.PatternParser 43.3% 26.9%
Confuser.Core.Project.Patterns.AndOperator 0% 0%
Confuser.Core.Project.Patterns.DeclTypeFunction 0% 0%
Confuser.Core.Project.Patterns.FullNameFunction 0%
Confuser.Core.Project.Patterns.HasAttrFunction 0%
Confuser.Core.Project.Patterns.InheritsFunction 0% 0%
Confuser.Core.Project.Patterns.IsPublicFunction 0% 0%
Confuser.Core.Project.Patterns.IsTypeFunction 0% 0%
Confuser.Core.Project.Patterns.LiteralExpression 50% 0%
Confuser.Core.Project.Patterns.MatchFunction 0%
Confuser.Core.Project.Patterns.MatchNameFunction 0%
Confuser.Core.Project.Patterns.MatchTypeNameFunction 0% 0%
Confuser.Core.Project.Patterns.MemberTypeFunction 0% 0%
Confuser.Core.Project.Patterns.ModuleFunction 0% 0%
Confuser.Core.Project.Patterns.NameFunction 0%
Confuser.Core.Project.Patterns.NamespaceFunction 0% 0%
Confuser.Core.Project.Patterns.NotOperator 0%
Confuser.Core.Project.Patterns.OrOperator 0% 0%
Confuser.Core.Project.Patterns.PatternFunction 0% 0%
Confuser.Core.Project.Patterns.PatternOperator 0% 0%
Confuser.Core.Project.PatternToken 17.3% 0%
Confuser.Core.Project.PatternTokenizer 55.5% 51.2%
Confuser.Core.Project.ProjectModule 47.1% 26%
Confuser.Core.Project.ProjectValidationException 0%
Confuser.Core.Project.Rule 39.5% 25%
Confuser.Core.Project.SettingItem`1 33.3% 16.6%
Confuser.Core.ProtectionParameters 64.2% 43.7%
Confuser.Core.ProtectionPhase 100%
Confuser.Core.ProtectionPipeline 92.8% 87.5%
Confuser.Core.ProtectionSettings 62.5% 50%
Confuser.Core.ServiceRegistry 63.6% 33.3%
Confuser.Core.Services.CompressionService 3.6% 0%
Confuser.Core.Services.MarkerService 68.4% 50%
Confuser.Core.Services.MethodTrace 0% 0%
Confuser.Core.Services.RandomGenerator 62.8% 53.1%
Confuser.Core.Services.RandomService 91.6% 66.6%
Confuser.Core.Services.RuntimeService 83.3% 80%
Confuser.Core.Services.TraceService 50% 0%
Confuser.Core.UnreachableException 0%
Confuser.Core.Utils 80.5% 64%
Confuser.Core.WatermarkingProtection 92.3% 75%
SevenZip.Buffer.InBuffer 0% 0%
SevenZip.Buffer.OutBuffer 0% 0%
SevenZip.Compression.LZ.BinTree 0% 0%
SevenZip.Compression.LZ.InWindow 0% 0%
SevenZip.Compression.LZ.OutWindow 0% 0%
SevenZip.Compression.LZMA.Base 0% 0%
SevenZip.Compression.LZMA.Decoder 0% 0%
SevenZip.Compression.LZMA.Encoder 0% 0%
SevenZip.Compression.RangeCoder.BitDecoder 0% 0%
SevenZip.Compression.RangeCoder.BitEncoder 0% 0%
SevenZip.Compression.RangeCoder.BitTreeDecoder 0% 0%
SevenZip.Compression.RangeCoder.BitTreeEncoder 0% 0%
SevenZip.Compression.RangeCoder.Decoder 0% 0%
SevenZip.Compression.RangeCoder.Encoder 0% 0%
SevenZip.CRC 0% 0%
SevenZip.DataErrorException 0%
SevenZip.InvalidParamException 0%
Confuser.DynCipher - 0.2%
Name Line Branch
Confuser.DynCipher 0.2% 0%
Confuser.DynCipher.AST.ArrayIndexExpression 0%
Confuser.DynCipher.AST.AssignmentStatement 0%
Confuser.DynCipher.AST.BinOpExpression 0% 0%
Confuser.DynCipher.AST.Expression 0%
Confuser.DynCipher.AST.LiteralExpression 0%
Confuser.DynCipher.AST.LoopStatement 0%
Confuser.DynCipher.AST.Statement 0%
Confuser.DynCipher.AST.StatementBlock 0% 0%
Confuser.DynCipher.AST.UnaryOpExpression 0% 0%
Confuser.DynCipher.AST.Variable 0%
Confuser.DynCipher.AST.VariableExpression 0%
Confuser.DynCipher.CodeGenUtils 0% 0%
Confuser.DynCipher.DynCipherComponent 42.8%
Confuser.DynCipher.DynCipherService 0%
Confuser.DynCipher.Elements.AddKey 0%
Confuser.DynCipher.Elements.BinOp 0% 0%
Confuser.DynCipher.Elements.CryptoElement 0%
Confuser.DynCipher.Elements.Matrix 0% 0%
Confuser.DynCipher.Elements.NumOp 0% 0%
Confuser.DynCipher.Elements.RotateBit 0% 0%
Confuser.DynCipher.Elements.Swap 0% 0%
Confuser.DynCipher.Generation.CILCodeGen 0% 0%
Confuser.DynCipher.Generation.CipherGenContext 0% 0%
Confuser.DynCipher.Generation.CipherGenerator 0% 0%
Confuser.DynCipher.Generation.DMCodeGen 0% 0%
Confuser.DynCipher.Generation.ExpressionGenerator 0% 0%
Confuser.DynCipher.Generation.x86CodeGen 0% 0%
Confuser.DynCipher.Generation.x86ImmediateOperand 0%
Confuser.DynCipher.Generation.x86Instruction 0% 0%
Confuser.DynCipher.Generation.x86RegisterOperand 0%
Confuser.DynCipher.MathsUtils 0% 0%
Confuser.DynCipher.Transforms.ConvertVariables 0% 0%
Confuser.DynCipher.Transforms.ExpansionTransform 0% 0%
Confuser.DynCipher.Transforms.MulToShiftTransform 0% 0%
Confuser.DynCipher.Transforms.NormalizeBinOpTransform 0% 0%
Confuser.DynCipher.Transforms.ShuffleTransform 0% 0%
Confuser.Protections - 4.9%
Name Line Branch
Confuser.Protections 4.9% 1.9%
Confuser.Protections.AntiDebugProtection 22% 3.8%
Confuser.Protections.AntiDumpProtection 59% 25%
Confuser.Protections.AntiILDasmProtection 58.8% 50%
Confuser.Protections.AntiTamper.AntiMode 0% 0%
Confuser.Protections.AntiTamper.AntiTamperExtensions 0% 0%
Confuser.Protections.AntiTamper.DynamicDeriver 0% 0%
Confuser.Protections.AntiTamper.JITBodyIndex 0% 0%
Confuser.Protections.AntiTamper.JITMethodBody 0% 0%
Confuser.Protections.AntiTamper.JITMethodBodyWriter 0% 0%
Confuser.Protections.AntiTamper.JITMode 0% 0%
Confuser.Protections.AntiTamper.NormalDeriver 0% 0%
Confuser.Protections.AntiTamper.NormalMode 0% 0%
Confuser.Protections.AntiTamperProtection 48.8% 25%
Confuser.Protections.Compress.CompressorContext 0% 0%
Confuser.Protections.Compress.DynamicDeriver 0% 0%
Confuser.Protections.Compress.ExtractPhase 12.8% 5.5%
Confuser.Protections.Compress.NormalDeriver 0% 0%
Confuser.Protections.Compress.StubProtection 0% 0%
Confuser.Protections.Compressor 1.7% 0%
Confuser.Protections.ConstantProtection 61.5%
Confuser.Protections.Constants.DynamicMode 0% 0%
Confuser.Protections.Constants.EncodePhase 2.7% 1.1%
Confuser.Protections.Constants.InjectPhase 4.3% 1.7%
Confuser.Protections.Constants.NormalMode 0% 0%
Confuser.Protections.Constants.ReferenceReplacer 0% 0%
Confuser.Protections.Constants.x86Mode 0% 0%
Confuser.Protections.ControlFlow.BlockBase 0%
Confuser.Protections.ControlFlow.BlockParser 0% 0%
Confuser.Protections.ControlFlow.CFContext 0% 0%
Confuser.Protections.ControlFlow.ControlFlowPhase 23% 20.5%
Confuser.Protections.ControlFlow.ExpressionPredicate 0% 0%
Confuser.Protections.ControlFlow.InstrBlock 0% 0%
Confuser.Protections.ControlFlow.JumpMangler 0% 0%
Confuser.Protections.ControlFlow.ManglerBase 0% 0%
Confuser.Protections.ControlFlow.NormalPredicate 0% 0%
Confuser.Protections.ControlFlow.ScopeBlock 0% 0%
Confuser.Protections.ControlFlow.SwitchMangler 0% 0%
Confuser.Protections.ControlFlow.x86Predicate 0% 0%
Confuser.Protections.ControlFlowProtection 54.5%
Confuser.Protections.HardeningPhase 25% 3.5%
Confuser.Protections.HardeningProtection 57.1%
Confuser.Protections.InvalidMetadataProtection 21.7% 10%
Confuser.Protections.ReferenceProxy.ExpressionEncoding 0% 0%
Confuser.Protections.ReferenceProxy.MildMode 0% 0%
Confuser.Protections.ReferenceProxy.NormalEncoding 0% 0%
Confuser.Protections.ReferenceProxy.ReferenceProxyPhase 24.1% 6.7%
Confuser.Protections.ReferenceProxy.RPMode 0% 0%
Confuser.Protections.ReferenceProxy.StrongMode 0% 0%
Confuser.Protections.ReferenceProxy.x86Encoding 0% 0%
Confuser.Protections.ReferenceProxyProtection 37.5%
Confuser.Protections.ResourceProtection 62.5%
Confuser.Protections.Resources.DynamicMode 0% 0%
Confuser.Protections.Resources.InjectPhase 5.4% 3.3%
Confuser.Protections.Resources.MDPhase 0% 0%
Confuser.Protections.Resources.NormalMode 0% 0%
Confuser.Protections.TypeScrambler.AnalyzePhase 61.5% 30%
Confuser.Protections.TypeScrambler.ScramblePhase 36.8% 16.6%
Confuser.Protections.TypeScrambler.Scrambler.Analyzers.ContextAnalyzer`1 0%
Confuser.Protections.TypeScrambler.Scrambler.Analyzers.ContextAnalyzerFacto
ry
0% 0%
Confuser.Protections.TypeScrambler.Scrambler.Analyzers.MemberRefAnalyzer 0% 0%
Confuser.Protections.TypeScrambler.Scrambler.Analyzers.MethodDefAnalyzer 0% 0%
Confuser.Protections.TypeScrambler.Scrambler.Analyzers.MethodSpecAnalyzer 0% 0%
Confuser.Protections.TypeScrambler.Scrambler.Analyzers.TypeRefAnalyzer 0%
Confuser.Protections.TypeScrambler.Scrambler.Rewriter.Instructions.FieldDef
InstructionRewriter
0% 0%
Confuser.Protections.TypeScrambler.Scrambler.Rewriter.Instructions.Instruct
ionRewriter`1
0%
Confuser.Protections.TypeScrambler.Scrambler.Rewriter.Instructions.Instruct
ionRewriterFactory
0% 0%
Confuser.Protections.TypeScrambler.Scrambler.Rewriter.Instructions.MemberRe
fInstructionRewriter
0% 0%
Confuser.Protections.TypeScrambler.Scrambler.Rewriter.Instructions.MethodDe
fInstructionRewriter
0% 0%
Confuser.Protections.TypeScrambler.Scrambler.Rewriter.Instructions.MethodSp
ecInstructionRewriter
0% 0%
Confuser.Protections.TypeScrambler.Scrambler.Rewriter.Instructions.TypeDefI
nstructionRewriter
0% 0%
Confuser.Protections.TypeScrambler.Scrambler.Rewriter.Instructions.TypeRefI
nstructionRewriter
0% 0%
Confuser.Protections.TypeScrambler.Scrambler.ScannedItem 0% 0%
Confuser.Protections.TypeScrambler.Scrambler.ScannedMethod 0% 0%
Confuser.Protections.TypeScrambler.Scrambler.ScannedType 0% 0%
Confuser.Protections.TypeScrambler.Scrambler.SignatureUtils 0% 0%
Confuser.Protections.TypeScrambler.Scrambler.TypeRewriter 0% 0%
Confuser.Protections.TypeScrambler.TypeScrambleProtection 75% 50%
Confuser.Protections.TypeScrambler.TypeService 13.3% 0%
Confuser.Protections.Utils 0% 0%
Confuser.Renamer - 42%
Name Line Branch
Confuser.Renamer 42% 37.7%
Confuser.Renamer.AnalyzePhase 66.2% 61.5%
Confuser.Renamer.Analyzers.CaliburnAnalyzer 0% 0%
Confuser.Renamer.Analyzers.CallSiteAnalyzer 22.2% 25.8%
Confuser.Renamer.Analyzers.InterReferenceAnalyzer 87.5% 90%
Confuser.Renamer.Analyzers.JsonAnalyzer 0% 0%
Confuser.Renamer.Analyzers.LdtokenEnumAnalyzer 12.6% 18.5%
Confuser.Renamer.Analyzers.ManifestResourceAnalyzer 35.7% 65.7%
Confuser.Renamer.Analyzers.ReflectionAnalyzer 19.6% 21.2%
Confuser.Renamer.Analyzers.ResourceAnalyzer 27.2% 30%
Confuser.Renamer.Analyzers.TypeBlobAnalyzer 59.5% 53.4%
Confuser.Renamer.Analyzers.VisualBasicRuntimeAnalyzer 0% 0%
Confuser.Renamer.Analyzers.VsCompositionAnalyzer 0% 0%
Confuser.Renamer.Analyzers.VTableAnalyzer 59.1% 55%
Confuser.Renamer.Analyzers.WinFormsAnalyzer 28% 31.7%
Confuser.Renamer.Analyzers.WPFAnalyzer 58.3% 53%
Confuser.Renamer.BAML.AssemblyInfoRecord 100%
Confuser.Renamer.BAML.AttributeInfoRecord 100%
Confuser.Renamer.BAML.BAMLAnalyzer 41.7% 42.7%
Confuser.Renamer.BAML.BamlBinaryReader 100%
Confuser.Renamer.BAML.BamlBinaryWriter 100%
Confuser.Renamer.BAML.BamlDocument 100%
Confuser.Renamer.BAML.BamlElement 77% 71.2%
Confuser.Renamer.BAML.BAMLPropertyReference 0% 0%
Confuser.Renamer.BAML.BamlReader 37.2% 28.7%
Confuser.Renamer.BAML.BamlRecord 100%
Confuser.Renamer.BAML.BAMLStringReference 100% 75%
Confuser.Renamer.BAML.BamlWriter 95.4% 66.6%
Confuser.Renamer.BAML.ConnectionIdRecord 100%
Confuser.Renamer.BAML.ConstructorParametersEndRecord 0%
Confuser.Renamer.BAML.ConstructorParametersStartRecord 0%
Confuser.Renamer.BAML.ConstructorParameterTypeRecord 0%
Confuser.Renamer.BAML.ContentPropertyRecord 100%
Confuser.Renamer.BAML.DefAttributeKeyStringRecord 0% 0%
Confuser.Renamer.BAML.DefAttributeKeyTypeRecord 0% 0%
Confuser.Renamer.BAML.DefAttributeRecord 0%
Confuser.Renamer.BAML.DeferableContentStartRecord 0%
Confuser.Renamer.BAML.DocumentEndRecord 100%
Confuser.Renamer.BAML.DocumentStartRecord 100%
Confuser.Renamer.BAML.ElementEndRecord 100%
Confuser.Renamer.BAML.ElementStartRecord 100%
Confuser.Renamer.BAML.IndexerParamInfo 0%
Confuser.Renamer.BAML.KeyElementEndRecord 0%
Confuser.Renamer.BAML.KeyElementStartRecord 0%
Confuser.Renamer.BAML.KnownThingsv3 0% 0%
Confuser.Renamer.BAML.KnownThingsv4 99.9% 100%
Confuser.Renamer.BAML.LineNumberAndPositionRecord 0%
Confuser.Renamer.BAML.LinePositionRecord 0%
Confuser.Renamer.BAML.LiteralContentRecord 0%
Confuser.Renamer.BAML.NamedElementStartRecord 0% 0%
Confuser.Renamer.BAML.OptimizedStaticResourceRecord 0%
Confuser.Renamer.BAML.PIMappingRecord 0%
Confuser.Renamer.BAML.PresentationOptionsAttributeRecord 0%
Confuser.Renamer.BAML.PropertyArrayEndRecord 0%
Confuser.Renamer.BAML.PropertyArrayStartRecord 0%
Confuser.Renamer.BAML.PropertyComplexEndRecord 0%
Confuser.Renamer.BAML.PropertyComplexStartRecord 0%
Confuser.Renamer.BAML.PropertyCustomRecord 0%
Confuser.Renamer.BAML.PropertyDictionaryEndRecord 0%
Confuser.Renamer.BAML.PropertyDictionaryStartRecord 0%
Confuser.Renamer.BAML.PropertyListEndRecord 0%
Confuser.Renamer.BAML.PropertyListStartRecord 0%
Confuser.Renamer.BAML.PropertyPathIndexUpdater 0% 0%
Confuser.Renamer.BAML.PropertyPathParser 0.7% 0%
Confuser.Renamer.BAML.PropertyPathPartUpdater 0% 0%
Confuser.Renamer.BAML.PropertyPathUpdater 0% 0%
Confuser.Renamer.BAML.PropertyRecord 88.8%
Confuser.Renamer.BAML.PropertyStringReferenceRecord 0%
Confuser.Renamer.BAML.PropertyTypeReferenceRecord 0%
Confuser.Renamer.BAML.PropertyWithConverterRecord 100%
Confuser.Renamer.BAML.PropertyWithExtensionRecord 0%
Confuser.Renamer.BAML.PropertyWithStaticResourceIdRecord 0%
Confuser.Renamer.BAML.RoutedEventRecord 0%
Confuser.Renamer.BAML.SizedBamlRecord 66.6% 12.5%
Confuser.Renamer.BAML.SourceValueInfo 0%
Confuser.Renamer.BAML.StaticResourceEndRecord 0%
Confuser.Renamer.BAML.StaticResourceIdRecord 0%
Confuser.Renamer.BAML.StaticResourceStartRecord 0%
Confuser.Renamer.BAML.StringInfoRecord 0%
Confuser.Renamer.BAML.TextRecord 0%
Confuser.Renamer.BAML.TextWithConverterRecord 0%
Confuser.Renamer.BAML.TextWithIdRecord 0%
Confuser.Renamer.BAML.TypeInfoRecord 100%
Confuser.Renamer.BAML.TypeSerializerInfoRecord 0%
Confuser.Renamer.BAML.XmlnsPropertyRecord 100% 100%
Confuser.Renamer.DisplayNormalizedName 100%
Confuser.Renamer.GenericArgumentResolver 37.8% 40%
Confuser.Renamer.GenericArguments 50% 46.4%
Confuser.Renamer.MessageDeobfuscator 0% 0%
Confuser.Renamer.NameProtection 60.7% 16.6%
Confuser.Renamer.NameService 60.5% 41%
Confuser.Renamer.PostRenamePhase 100% 100%
Confuser.Renamer.Properties.Resources 0% 0%
Confuser.Renamer.RecursionCounter 75% 50%
Confuser.Renamer.References.BAMLAttributeReference 0% 0%
Confuser.Renamer.References.BAMLConverterMemberReference 0% 0%
Confuser.Renamer.References.BAMLConverterTypeReference 0% 0%
Confuser.Renamer.References.BAMLEnumReference 0% 0%
Confuser.Renamer.References.BAMLPathTypeReference 0% 0%
Confuser.Renamer.References.BAMLTypeReference 52.9% 100%
Confuser.Renamer.References.CAMemberReference 0% 0%
Confuser.Renamer.References.MemberOldestSiblingReference 0% 0%
Confuser.Renamer.References.MemberOverrideReference 0% 0%
Confuser.Renamer.References.MemberRefReference 23.5% 0%
Confuser.Renamer.References.MemberSiblingReference 0% 0%
Confuser.Renamer.References.OverrideDirectiveReference 53.8% 50%
Confuser.Renamer.References.RequiredPrefixReference`1 0% 0%
Confuser.Renamer.References.ResourceReference 0% 0%
Confuser.Renamer.References.StringMemberNameReference 0% 0%
Confuser.Renamer.References.StringTypeReference 0% 0%
Confuser.Renamer.References.TypeRefReference 21% 0%
Confuser.Renamer.ReferenceUtilities 0% 0%
Confuser.Renamer.RenamePhase 53.5% 51%
Confuser.Renamer.ReversibleRenamer 0% 0%
Confuser.Renamer.RickRoller 0% 0%
Confuser.Renamer.VTable 90.9% 84.2%
Confuser.Renamer.VTableSignature 80.7% 66.6%
Confuser.Renamer.VTableSlot 87.5%
Confuser.Renamer.VTableStorage 78% 62.5%
Confuser.UnitTest - 0%
Name Line Branch
Confuser.UnitTest 0% ****
AutoGeneratedProgram 0%

RandomCrocodile added 6 commits June 11, 2026 00:17
…kdown (#53)

- Switch from regex parsing to TRX XML parsing for accurate test counts
  (fixes net462 integration tests showing 0/0/0)
- Add collapsible Cross-Framework Test Details section showing each
  framework test individually with TFM and app type columns
- Failed tests show first line of error message
- Upload TRX files as test-results artifact for debugging
- Coverage collected to separate directory from TRX results
…il (#53)

dotnet test was called with --results-directory twice (once for coverage,
once for TRX). .NET 10 SDK rejects this with "expects a single argument
but 2 were provided". Consolidated to a single results directory per project.
- Add actions/cache@v4 for NuGet global packages folder
- Set NUGET_PACKAGES to workspace-relative path for reliable caching
- Cache key hashes all .csproj and .vcxproj files
- Fallback restore-key reuses partial cache on package changes
- Applied to both ci and test workflows
- First run populates cache, subsequent runs skip most of restore
@mcpolo99
mcpolo99 marked this pull request as ready for review June 10, 2026 22:38
@mcpolo99

Copy link
Copy Markdown
Owner Author

i also decided to be messy and added some general testing to make sure all is actually working :D

All good! Nice to get this stuff fixed early to make things easier in the long run 👍

if you are willing to take a look you are free to do, will leave it for today. the majority of the changes is just formatting, or we just squash merge and take it as a pre-release test and take it as it comes.

@jeremy-visionaid

Copy link
Copy Markdown

It's hard to evaluate in conjunction with the formatting changes, I can say at least that it runs OK and the obfuscated app still works. The best bit is that it's roughly 2x faster at obfuscating 😎 Looking forward to using it for real. Great work!

@jeremy-visionaid

Copy link
Copy Markdown

LGTM 👍

@mcpolo99

Copy link
Copy Markdown
Owner Author

It's hard to evaluate in conjunction with the formatting changes, I can say at least that it runs OK and the obfuscated app still works. The best bit is that it's roughly 2x faster at obfuscating 😎 Looking forward to using it for real. Great work!

was not expecting the speed improvements but that is just a bonus i guess! will merge into pre-release branch so a pre release package will be made🙌

@mcpolo99
mcpolo99 merged commit 4755b98 into pre-release Jun 11, 2026
5 checks passed
mcpolo99 added a commit that referenced this pull request Jun 11, 2026
* feat: retarget ConfuserEx from .NET Framework 4.6.1 to .NET 10 (#71)

* perf(ci): eliminate duplicate build — test workflow reuses CI build output (#78)

Before: ci.yml and test.yml each did a full MSBuild restore + build (~4 min each)
After: ci.yml builds + uploads artifacts, test.yml downloads and runs tests only

Changes:
- ci.yml: add build-output artifact upload (1-day retention)
- ci.yml: add paths-ignore (skip on docs-only changes)
- ci.yml: add concurrency (cancel in-progress on new push)
- test.yml: trigger on workflow_run (waits for CI completion)
- test.yml: download build-output instead of building
- test.yml: no more restore/build steps
- format.yml: only trigger when .cs/.vb/.editorconfig files change

Saves ~4 min of Windows runner time per push by not building twice.
All 3 workflows remain separate with their own status checks.

Co-authored-by: RandomCrocodile <mawi@polosab.com>

* fix(ci): update CodeQL to windows-2025 for MSBuild 18 / .NET 10 support

CodeQL was still on windows-2022 (MSBuild 17) which can't resolve
.NET 10 SDK from global.json. Also removed obsolete .NET 4.6.1
targeting pack install (net48 doesn't need it) and bumped checkout to v5.

* chore: update repo references from mkaring to mcpolo99/ConfuserExx

- Issue template config: point discussions to our repo, add Ideas + General links
- CODEOWNERS: mkaring → mcpolo99
- FUNDING.yml: mkaring → mcpolo99
- MSBuild.Tasks PackageProjectUrl: point to our repo
- Test [Trait("Issue")] attributes kept as upstream attribution (historical)

* fix(ci): revert test workflow to direct triggers for reliable PR comments

workflow_run doesn't associate with PRs reliably — test results and
coverage comments were not posted on PR #79. Reverted to direct
push/pull_request triggers with its own build step.

Still optimized with:
- paths-ignore (skip on docs-only changes)
- concurrency (cancel in-progress on new push)
- NuGet cache (shared cache key with ci.yml)
- Removed build-output artifact from ci.yml (no longer needed)

---------

Co-authored-by: RandomCrocodile <mawi@polosab.com>
@mcpolo99
mcpolo99 deleted the feat/issue-53-net10-retarget branch June 11, 2026 09:17
mcpolo99 added a commit that referenced this pull request Jun 11, 2026
* feat: retarget ConfuserEx from .NET Framework 4.6.1 to .NET 10 (#71)

* perf(ci): eliminate duplicate build — test workflow reuses CI build output (#78)

Before: ci.yml and test.yml each did a full MSBuild restore + build (~4 min each)
After: ci.yml builds + uploads artifacts, test.yml downloads and runs tests only

Changes:
- ci.yml: add build-output artifact upload (1-day retention)
- ci.yml: add paths-ignore (skip on docs-only changes)
- ci.yml: add concurrency (cancel in-progress on new push)
- test.yml: trigger on workflow_run (waits for CI completion)
- test.yml: download build-output instead of building
- test.yml: no more restore/build steps
- format.yml: only trigger when .cs/.vb/.editorconfig files change

Saves ~4 min of Windows runner time per push by not building twice.
All 3 workflows remain separate with their own status checks.

Co-authored-by: RandomCrocodile <mawi@polosab.com>

* fix(ci): update CodeQL to windows-2025 for MSBuild 18 / .NET 10 support

CodeQL was still on windows-2022 (MSBuild 17) which can't resolve
.NET 10 SDK from global.json. Also removed obsolete .NET 4.6.1
targeting pack install (net48 doesn't need it) and bumped checkout to v5.

* chore: update repo references from mkaring to mcpolo99/ConfuserExx

- Issue template config: point discussions to our repo, add Ideas + General links
- CODEOWNERS: mkaring → mcpolo99
- FUNDING.yml: mkaring → mcpolo99
- MSBuild.Tasks PackageProjectUrl: point to our repo
- Test [Trait("Issue")] attributes kept as upstream attribution (historical)

* fix(ci): revert test workflow to direct triggers for reliable PR comments

workflow_run doesn't associate with PRs reliably — test results and
coverage comments were not posted on PR #79. Reverted to direct
push/pull_request triggers with its own build step.

Still optimized with:
- paths-ignore (skip on docs-only changes)
- concurrency (cancel in-progress on new push)
- NuGet cache (shared cache key with ci.yml)
- Removed build-output artifact from ci.yml (no longer needed)

* chore: adopt GitHub branch conventions — master→main, pre-release→develop (#82)

* chore: rename master→main, pre-release→develop, adopt GitHub branch conventions

Branch renames:
- master → main (default branch)
- pre-release → develop (integration branch)

All references updated:
- ci.yml: triggers, release jobs, dev-release job (was pre-release)
- test.yml, format.yml, codeql-analysis.yml: branch triggers
- dependabot.yml: target branch
- README.md: contributing section, CI badge
- CONTRIBUTING.md: branch naming convention, PR target

New branch naming convention (documented in CONTRIBUTING.md):
- Issue-linked: {number}-{slug} via gh issue develop
- Feature: feature/{description}
- Chore: chore/{description}
- Docs: docs/{description}
- Hotfix: hotfix/{description} (from main)
- Experiment: experiment/{description}

* feat(ci): lightweight lint on push, full CI on PR only (#81)

New workflow layout:
- lint.yml (NEW): every push + PR — format + style + Roslyn analyzers
  without building. Posts results to PR comment or issue comment
  (parses issue number from branch name). ~2 min.
- ci.yml: PR + main/develop push only — full build + package
- test.yml: PR only — full build + test + coverage
- codeql: weekly (Mon 3am, skips if no commits) + manual trigger
- format.yml: DELETED — replaced by lint.yml

Cost per event:
- Feature branch push: ~2 min (was ~9 min) — 77% reduction
- PR: ~11 min (lint + ci + test, unchanged)
- Merge to main: ~5 min (ci only)
- CodeQL: weekly conditional, not on every push/PR

---------

Co-authored-by: RandomCrocodile <mawi@polosab.com>

* docs: update commit convention to match branch naming — full words, no scopes

---------

Co-authored-by: RandomCrocodile <mawi@polosab.com>
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.

2 participants