From 248d4bd664fb7e13858e04f57fca2cc8d4f42afa Mon Sep 17 00:00:00 2001 From: Florian Rappl Date: Fri, 4 Sep 2026 15:19:07 +0200 Subject: [PATCH] Updated and improved migration checks #946 --- Changelog.md | 3 + docs/Core/Migration-Checks.md | 55 ++++++++- .../Tests/MigrationChecksTargetsTests.cs | 105 ++++++++++++++++++ .../build/ElectronNET.MigrationChecks.targets | 103 +++++++++++++---- 4 files changed, 241 insertions(+), 25 deletions(-) diff --git a/Changelog.md b/Changelog.md index 11e3fa2..38d8202 100644 --- a/Changelog.md +++ b/Changelog.md @@ -3,15 +3,18 @@ ## ElectronNET.Core - Updated dependencies +- Improved migration checks to honor custom output paths and to detect `ProjectGuid` in publish profiles (#946) - Fixed single instance handling on macOS (#1040) - Fixed slow socket bridge startup by binding to an explicit loopback address (#1103) - Fixed socket bridge connection when a system proxy is configured (#1105) - Fixed electron-builder using the host RID instead of the target RID (#1097) - Fixed cross-compilation behavior on same platform (#1098) @epsnm - Fixed resolution of unrelated target (#1099) @epsnm +- Fixed false alarm for `ELECTRON001` on a root `package-lock.json` (#946) - Added target framework customization (#1095) @epsnm - Added configurable Electron root directory for custom packaging layouts (#1106) @DYH1319 - Added ability for `custom_main.js` to modify command line switches (#1029) @AeonSake +- Added migration checks for incomplete `ElectronHostHook` folders (`ELECTRON010`, `ELECTRON011`) (#946) - Added `ElectronExecutableName` to separate the product name from the executable name (#1003) @AeonSake - Added build extensibility properties `ElectronSkipExecCommands` and `ElectronIntermediatePublishDir` (#1106) @DYH1319 diff --git a/docs/Core/Migration-Checks.md b/docs/Core/Migration-Checks.md index e07902f..211faa0 100644 --- a/docs/Core/Migration-Checks.md +++ b/docs/Core/Migration-Checks.md @@ -17,6 +17,10 @@ When you build an Electron.NET project, the following validation checks are perf | [ELECTRON005](#4-parent-paths-not-allowed-in-electron-builderjson) | Parent paths not allowed | Checks for `..` references in config | | [ELECTRON006](#5-publish-profile-validation) | ASP.NET publish profile mismatch | Warns when ASP.NET projects have console-style profiles | | [ELECTRON007](#5-publish-profile-validation) | Console publish profile mismatch | Warns when console projects have ASP.NET-style profiles | +| [ELECTRON010](#6-electronhosthook-folder-validation) | ElectronHostHook without package.json | Warns when hook TypeScript files exist without a `package.json` | +| [ELECTRON011](#6-electronhosthook-folder-validation) | ElectronHostHook without tsconfig.json | Warns when hook TypeScript files exist without a `tsconfig.json` | + +All checks skip the build output folders (`bin`, `obj`, `publish`, `.electron`, `node_modules`) as well as any custom output paths configured via `BaseOutputPath` / `BaseIntermediateOutputPath` (for example the .NET `artifacts` output layout). --- @@ -32,7 +36,7 @@ Rules: - **ELECTRON001**: `package.json` / `package-lock.json` must not exist in the project directory or subdirectories - Exception: `ElectronHostHook` folder is allowed - - Note: a **root** `package.json` is **excluded** from `ELECTRON001` and validated by `ELECTRON008` / `ELECTRON009` + - Note: a **root** `package.json` (and its `package-lock.json`) is **excluded** from `ELECTRON001` and validated by `ELECTRON008` / `ELECTRON009` - **ELECTRON008**: If a root `package.json` exists, it must **not** contain electron-related dependencies or configuration. @@ -208,7 +212,7 @@ The build system examines `.pubxml` files in the `Properties/PublishProfiles` fo - **ELECTRON006**: For **ASP.NET projects** (using `Microsoft.NET.Sdk.Web`), checks that publish profiles include `WebPublishMethod`. This property is required for proper ASP.NET publishing. -- **ELECTRON007**: For **console/other projects** (not using the Web SDK), checks that publish profiles do NOT include the `WebPublishMethod` property. These ASP.NET-specific properties are incorrect for non-web applications. +- **ELECTRON007**: For **console/other projects** (not using the Web SDK), checks that publish profiles do NOT include the `WebPublishMethod` or `ProjectGuid` property. These ASP.NET-specific properties are incorrect for non-web applications. ### Why this matters @@ -233,9 +237,54 @@ For correct publish profile examples for both ASP.NET and Console applications, --- +## 6. ElectronHostHook Folder Validation + +**Warning Codes:** `ELECTRON010`, `ELECTRON011` + +### What is checked + +If the project contains an `ElectronHostHook` folder with TypeScript files: + +- **ELECTRON010**: The folder must contain a `package.json` +- **ELECTRON011**: The folder must contain a `tsconfig.json` + +### Why this matters + +Custom host hook code is only compiled and packaged when the `ElectronHostHook` folder declares its npm dependencies in a `package.json`. If that file is missing, the hook is silently dropped and the corresponding `Electron.HostHook` calls fail at runtime. The `tsconfig.json` is required so the hook sources are compiled with the expected settings. + +### How to fix + +Add the missing files to the `ElectronHostHook` folder: + +```json +{ + "name": "electron-host-hook", + "version": "1.0.0", + "main": "index.js", + "dependencies": { + "socket.io": "^4.8.1" + }, + "devDependencies": { + "typescript": "^5.9.3" + } +} +``` + +> **See also:** [HostHook API](../API/HostHook.md) + +--- + ## Disabling Migration Checks -If you need to disable specific migration checks (not recommended), you can set the following properties in your `.csproj` file: +Individual checks can be downgraded to messages by their warning code: + +```xml + + $(MSBuildWarningsAsMessages);ELECTRON005 + +``` + +If you need to disable all migration checks (not recommended), you can set the following property in your `.csproj` file: ```xml diff --git a/src/ElectronNET.IntegrationTests/Tests/MigrationChecksTargetsTests.cs b/src/ElectronNET.IntegrationTests/Tests/MigrationChecksTargetsTests.cs index 93b1817..2f42ade 100644 --- a/src/ElectronNET.IntegrationTests/Tests/MigrationChecksTargetsTests.cs +++ b/src/ElectronNET.IntegrationTests/Tests/MigrationChecksTargetsTests.cs @@ -145,6 +145,111 @@ public class MigrationChecksTargetsTests } } + [Fact] + public async Task MigrationChecksTargets_BuildWithRootPackageLockJson_ShouldNotEmitELECTRON001Warning() + { + // A root package.json is validated by ELECTRON008/ELECTRON009 and therefore allowed. + // Its accompanying package-lock.json must not be reported by ELECTRON001. + + var tempDir = CreateTempProjectDirectory(); + try + { + await File.WriteAllTextAsync( + Path.Combine(tempDir, "package.json"), + """{ "devDependencies": { "vite": "^5.0.0" } }"""); + await File.WriteAllTextAsync( + Path.Combine(tempDir, "package-lock.json"), + """{ "lockfileVersion": 3 }"""); + + await WriteMinimalCsprojAsync(tempDir); + + var (exitCode, output) = await RunDotnetBuildAsync(tempDir); + + exitCode.Should().Be(0, $"Full build output:\n{output}"); + + output.Should().NotContain( + "ELECTRON001", + $"a root package-lock.json belongs to the allowed root package.json. " + + $"Full build output:\n{output}"); + } + finally + { + Directory.Delete(tempDir, recursive: true); + } + } + + [Fact] + public async Task MigrationChecksTargets_BuildWithIncompleteHostHookFolder_ShouldEmitELECTRON010AndELECTRON011Warnings() + { + // Host hook TypeScript sources are silently ignored when package.json/tsconfig.json + // are missing, so the migration checks must point that out. + + var tempDir = CreateTempProjectDirectory(); + try + { + var hookDir = Path.Combine(tempDir, "ElectronHostHook"); + Directory.CreateDirectory(hookDir); + await File.WriteAllTextAsync(Path.Combine(hookDir, "index.ts"), "export class HookService {}"); + + await WriteMinimalCsprojAsync(tempDir); + + var (exitCode, output) = await RunDotnetBuildAsync(tempDir); + + exitCode.Should().Be(0, $"Full build output:\n{output}"); + + output.Should().Contain( + "ELECTRON010", + $"the ElectronHostHook folder has TypeScript files but no package.json. " + + $"Full build output:\n{output}"); + output.Should().Contain( + "ELECTRON011", + $"the ElectronHostHook folder has TypeScript files but no tsconfig.json. " + + $"Full build output:\n{output}"); + } + finally + { + Directory.Delete(tempDir, recursive: true); + } + } + + [Fact] + public async Task MigrationChecksTargets_BuildWithConsoleProfileContainingProjectGuid_ShouldEmitELECTRON007Warning() + { + // ProjectGuid is an ASP.NET publish profile property and must be reported for + // non-web projects, just like WebPublishMethod. + + var tempDir = CreateTempProjectDirectory(); + try + { + var profilesDir = Path.Combine(tempDir, "Properties", "PublishProfiles"); + Directory.CreateDirectory(profilesDir); + await File.WriteAllTextAsync( + Path.Combine(profilesDir, "FolderProfile.pubxml"), + """ + + + 00000000-0000-0000-0000-000000000000 + + + """); + + await WriteMinimalCsprojAsync(tempDir); + + var (exitCode, output) = await RunDotnetBuildAsync(tempDir); + + exitCode.Should().Be(0, $"Full build output:\n{output}"); + + output.Should().Contain( + "ELECTRON007", + $"a console project must not use an ASP.NET publish profile. " + + $"Full build output:\n{output}"); + } + finally + { + Directory.Delete(tempDir, recursive: true); + } + } + // ----------------------------------------------------------------------- // Helpers // ----------------------------------------------------------------------- diff --git a/src/ElectronNET/build/ElectronNET.MigrationChecks.targets b/src/ElectronNET/build/ElectronNET.MigrationChecks.targets index ab138a5..d928e7f 100644 --- a/src/ElectronNET/build/ElectronNET.MigrationChecks.targets +++ b/src/ElectronNET/build/ElectronNET.MigrationChecks.targets @@ -9,10 +9,22 @@ ElectronCheckNoManifestJson; ElectronCheckElectronBuilderJson; ElectronCheckNoParentPaths; - ElectronCheckPubxmlFiles + ElectronCheckPubxmlFiles; + ElectronCheckHostHookFolder + + + <_ElectronCheckExcludes>$(MSBuildProjectDirectory)\bin\**\*;$(MSBuildProjectDirectory)\obj\**\*;$(MSBuildProjectDirectory)\publish\**\*;$(MSBuildProjectDirectory)\node_modules\**\*;$(MSBuildProjectDirectory)\.electron\**\* + <_ElectronCheckExcludes Condition="'$(BaseOutputPath)' != ''">$(_ElectronCheckExcludes);$([MSBuild]::NormalizeDirectory('$(MSBuildProjectDirectory)', '$(BaseOutputPath)'))**\* + <_ElectronCheckExcludes Condition="'$(BaseIntermediateOutputPath)' != ''">$(_ElectronCheckExcludes);$([MSBuild]::NormalizeDirectory('$(MSBuildProjectDirectory)', '$(BaseIntermediateOutputPath)'))**\* + + + $(_ElectronCheckExcludes)" /> + <_InvalidPackageLockJson Include="$(MSBuildProjectDirectory)\**\package-lock.json" - Exclude="$(MSBuildProjectDirectory)\ElectronHostHook\**\package-lock.json; - $(MSBuildProjectDirectory)\bin\**\package-lock.json; - $(MSBuildProjectDirectory)\obj\**\package-lock.json; - $(MSBuildProjectDirectory)\publish\**\package-lock.json; - $(MSBuildProjectDirectory)\node_modules\**\package-lock.json" /> + Exclude="$(MSBuildProjectDirectory)\package-lock.json; + $(MSBuildProjectDirectory)\ElectronHostHook\**\package-lock.json; + $(_ElectronCheckExcludes)" /> @@ -141,10 +150,7 @@ For more information, see: https://github.com/ElectronNET/Electron.NET/wiki/Migr <_InvalidManifestJson Include="$(MSBuildProjectDirectory)\**\electron.manifest.json;$(MSBuildProjectDirectory)\**\electron-manifest.json" - Exclude="$(MSBuildProjectDirectory)\bin\**\*; - $(MSBuildProjectDirectory)\obj\**\*; - $(MSBuildProjectDirectory)\publish\**\*; - $(MSBuildProjectDirectory)\node_modules\**\*" /> + Exclude="$(_ElectronCheckExcludes)" /> @@ -187,10 +193,7 @@ MIGRATION REQUIRED: <_ElectronBuilderJsonWrongLocation Include="$(MSBuildProjectDirectory)\**\electron-builder.json" Exclude="$(MSBuildProjectDirectory)\Properties\electron-builder.json; - $(MSBuildProjectDirectory)\bin\**\*; - $(MSBuildProjectDirectory)\obj\**\*; - $(MSBuildProjectDirectory)\publish\**\*; - $(MSBuildProjectDirectory)\node_modules\**\*" /> + $(_ElectronCheckExcludes)" /> @@ -296,10 +299,11 @@ For more information, see: https://github.com/ElectronNET/Electron.NET/wiki/Migr - + <_PubxmlFileInfoWithFlags Include="@(_PubxmlFileInfo)" Condition="'%(Identity)' != ''"> $([System.Text.RegularExpressions.Regex]::IsMatch('%(FileContent)', '<WebPublishMethod>')) + $([System.Text.RegularExpressions.Regex]::IsMatch('%(FileContent)', '<ProjectGuid>')) @@ -309,10 +313,10 @@ For more information, see: https://github.com/ElectronNET/Electron.NET/wiki/Migr Condition="'$(_IsAspNetProject)' == 'true' AND '%(HasWebPublishMethod)' == 'False'" /> - + <_ConsolePubxmlWithAspNetProperties Include="@(_PubxmlFileInfoWithFlags)" - Condition="'$(_IsAspNetProject)' != 'true' AND '%(HasWebPublishMethod)' == 'True'" /> + Condition="'$(_IsAspNetProject)' != 'true' AND ('%(HasWebPublishMethod)' == 'True' OR '%(HasProjectGuid)' == 'True')" /> @@ -336,7 +340,7 @@ For more information, see: https://github.com/ElectronNET/Electron.NET/wiki/Migr + + + + + <_HostHookTsFiles Include="$(MSBuildProjectDirectory)\ElectronHostHook\*.ts" /> + + + + <_HasHostHookTsFiles>false + <_HasHostHookTsFiles Condition="@(_HostHookTsFiles->Count()) > 0">true + + + + + + + +