Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
9c237b2
start verify target impl
AnakinRaW Dec 13, 2025
b4829cb
update deps
AnakinRaW Dec 13, 2025
6b00425
update sub
AnakinRaW Dec 13, 2025
e1b7832
make app running again
AnakinRaW Dec 13, 2025
2772bb5
reorganize solution
AnakinRaW Dec 13, 2025
fdd9e38
basic support for VerificationTarget type
AnakinRaW Dec 13, 2025
4e04252
start refactoring verification target selection
AnakinRaW Dec 14, 2025
3f79964
rename stuff
AnakinRaW Dec 14, 2025
0a674e6
start testing automatic selector
AnakinRaW Dec 16, 2025
0887111
fix and test automatic selector
AnakinRaW Dec 23, 2025
327c026
update to new deps
AnakinRaW Jan 16, 2026
fd80856
update to new deps (just to make it compile)
AnakinRaW Jan 16, 2026
68453c2
make everything compile at least
AnakinRaW Jan 16, 2026
371b5eb
to weekly deps check
AnakinRaW Jan 16, 2026
5ae5aed
update license year
AnakinRaW Jan 16, 2026
30641ed
rename class
AnakinRaW Jan 16, 2026
47ae702
make compile and run again
AnakinRaW Jan 16, 2026
b4ffd06
local deploy script
AnakinRaW Jan 16, 2026
c36a406
update gitignore
AnakinRaW Jan 16, 2026
9721fa0
polishing
AnakinRaW Jan 16, 2026
95cfd74
update module
AnakinRaW Jan 17, 2026
45ca2e6
various little changes
AnakinRaW Jan 18, 2026
6283424
update deps
AnakinRaW Jan 19, 2026
641b1c7
use filed keyword
AnakinRaW Jan 19, 2026
9fa87e4
do not thorw stepfailure exception if verification errors occured.
AnakinRaW Jan 19, 2026
8dc022d
Fail fast should print any error to console
AnakinRaW Jan 19, 2026
1cb1275
major refactorings
AnakinRaW Jan 22, 2026
abf5a38
allow skip location in baselines
AnakinRaW Jan 22, 2026
c2b11da
only search for baselines of the correct engine type
AnakinRaW Jan 22, 2026
c1506c7
Support argument validation
AnakinRaW Jan 22, 2026
30c1381
Setting appFailure does not terminate the verifiers on first error.
AnakinRaW Jan 22, 2026
ae1273b
udpate assert reporting
AnakinRaW Jan 22, 2026
6e63260
make tests compile again
AnakinRaW Jan 22, 2026
685093b
pretty print verify info
AnakinRaW Jan 24, 2026
28e34a3
do not print location if not exists
AnakinRaW Jan 24, 2026
972131c
simply automatic selector
AnakinRaW Jan 24, 2026
f81f1de
extract to file
AnakinRaW Jan 24, 2026
3e1f33e
nicer console output
AnakinRaW Jan 24, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "daily"
interval: "weekly"
groups:
actions-deps:
patterns:
Expand All @@ -19,7 +19,7 @@ updates:
- package-ecosystem: "nuget"
directory: "/"
schedule:
interval: "daily"
interval: "weekly"
target-branch: "develop"
open-pull-requests-limit: 1
groups:
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -396,3 +396,6 @@ FodyWeavers.xsd

# JetBrains Rider
*.sln.iml
.idea

.local_deploy
4 changes: 2 additions & 2 deletions Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
<PropertyGroup>
<Product>ModVerify</Product>
<Authors>Alamo Engine Tools and Contributors</Authors>
<Copyright>Copyright © 2025 Alamo Engine Tools and contributors. All rights reserved.</Copyright>
<Copyright>Copyright © 2026 Alamo Engine Tools and contributors. All rights reserved.</Copyright>
<PackageProjectUrl>https://github.com/AlamoEngine-Tools/ModVerify</PackageProjectUrl>
<LicenseFile>$(RepoRootPath)LICENSE</LicenseFile>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
Expand All @@ -33,7 +33,7 @@

<ItemGroup>
<PackageReference Update="SauceControl.InheritDoc" Version="2.0.2" />
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="8.0.0">
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="10.0.102">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
Expand Down
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
MIT License

Copyright (c) 2024 Alamo Engine Tools
Copyright (c) 2026 Alamo Engine Tools

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
75 changes: 75 additions & 0 deletions deploy-local.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
# Local deployment script for ModVerify to test the update feature.
# This script builds the application, creates an update manifest, and "deploys" it to a local directory.

$ErrorActionPreference = "Stop"

$root = $PSScriptRoot
if ([string]::IsNullOrEmpty($root)) { $root = Get-Location }

$deployRoot = Join-Path $root ".local_deploy"
$stagingDir = Join-Path $deployRoot "staging"
$serverDir = Join-Path $deployRoot "server"
$installDir = Join-Path $deployRoot "install"

$toolProj = Join-Path $root "src\ModVerify.CliApp\ModVerify.CliApp.csproj"
$creatorProj = Join-Path $root "modules\ModdingToolBase\src\AnakinApps\ApplicationManifestCreator\ApplicationManifestCreator.csproj"
$uploaderProj = Join-Path $root "modules\ModdingToolBase\src\AnakinApps\FtpUploader\FtpUploader.csproj"

$toolExe = "ModVerify.exe"
$updaterExe = "AnakinRaW.ExternalUpdater.exe"
$manifestCreatorDll = "AnakinRaW.ApplicationManifestCreator.dll"
$uploaderDll = "AnakinRaW.FtpUploader.dll"

# 1. Clean and Create directories
if (Test-Path $deployRoot) { Remove-Item -Recurse -Force $deployRoot }
New-Item -ItemType Directory -Path $stagingDir | Out-Null
New-Item -ItemType Directory -Path $serverDir | Out-Null
New-Item -ItemType Directory -Path $installDir | Out-Null

Write-Host "--- Building ModVerify (net481) ---" -ForegroundColor Cyan
dotnet build $toolProj --configuration Release -f net481 --output "$deployRoot\bin\tool" /p:DebugType=None /p:DebugSymbols=false

Write-Host "--- Building Manifest Creator ---" -ForegroundColor Cyan
dotnet build $creatorProj --configuration Release --output "$deployRoot\bin\creator"

Write-Host "--- Building Local Uploader ---" -ForegroundColor Cyan
dotnet build $uploaderProj --configuration Release --output "$deployRoot\bin\uploader"

# 2. Prepare staging
Write-Host "--- Preparing Staging ---" -ForegroundColor Cyan
Copy-Item "$deployRoot\bin\tool\$toolExe" $stagingDir
Copy-Item "$deployRoot\bin\tool\$updaterExe" $stagingDir

# 3. Create Manifest
# Origin must be an absolute URI for the manifest creator.
# Using 127.0.0.1 and file:// is tricky with Flurl/DownloadManager sometimes.
# We'll use the local path and ensure it's formatted correctly.
$serverPath = (Resolve-Path $serverDir).Path
$serverUri = "file:///$($serverPath.Replace('\', '/'))"
# If we have 3 slashes, Flurl/DownloadManager might still fail on Windows if it expects a certain format.
# However, the ManifestCreator just needs a valid URI for the 'Origin' field in the manifest.
Write-Host "--- Creating Manifest (Origin: $serverUri) ---" -ForegroundColor Cyan
dotnet "$deployRoot\bin\creator\$manifestCreatorDll" `
-a "$stagingDir\$toolExe" `
--appDataFiles "$stagingDir\$updaterExe" `
--origin "$serverUri" `
-o "$stagingDir" `
-b "beta"

# 4. "Deploy" to server using the local uploader
Write-Host "--- Deploying to Local Server ---" -ForegroundColor Cyan
dotnet "$deployRoot\bin\uploader\$uploaderDll" local --base "$serverDir" --source "$stagingDir"

# 5. Setup a "test" installation
Write-Host "--- Setting up Test Installation ---" -ForegroundColor Cyan
Copy-Item "$deployRoot\bin\tool\*" $installDir -Recurse

Write-Host "`nLocal deployment complete!" -ForegroundColor Green
Write-Host "Server directory: $serverDir"
Write-Host "Install directory: $installDir"
Write-Host "`nTo test the update:"
Write-Host "1. (Optional) Modify the version in version.json and run this script again to 'push' a new version to the local server."
Write-Host "2. Run ModVerify from the install directory with the following command:"
Write-Host " cd '$installDir'"
Write-Host " .\ModVerify.exe updateApplication --updateManifestUrl '$serverUri'"
Write-Host "`n Note: You can also specify a different branch using --updateBranch if needed."
2 changes: 1 addition & 1 deletion modules/ModdingToolBase
Submodule ModdingToolBase updated 24 files
+1 −1 Directory.Build.props
+150 −16 src/AnakinApps/ApplicationBase.CommandLine/ConsoleUtilities.cs
+1 −1 src/AnakinApps/ApplicationBase.WPF/ApplicationBase.WPF.csproj
+7 −7 src/AnakinApps/ApplicationBase/ApplicationBase.csproj
+2 −2 src/AnakinApps/ApplicationBase/SelfUpdateableAppLifecycle.cs
+5 −5 src/AnakinApps/ApplicationManifestCreator/ApplicationManifestCreator.csproj
+5 −5 src/AnakinApps/FtpUploader/FtpUploader.csproj
+3 −3 src/CommonUtilities/CommonUtilities.WPF.ApplicationFramework/CommonUtilities.WPF.ApplicationFramework.csproj
+3 −3 src/CommonUtilities/CommonUtilities.WPF.Controls/CommonUtilities.WPF.Controls.csproj
+6 −6 src/CommonUtilities/CommonUtilities.WPF.Core/CommonUtilities.WPF.Core.csproj
+1 −1 src/CommonUtilities/CommonUtilities.WPF.Core/DPI/DisplayHelper.cs
+3 −3 src/CommonUtilities/CommonUtilities.WPF.Core/DPI/DisplayInfo.cs
+3 −3 src/CommonUtilities/CommonUtilities.WPF.Core/DPI/DpiHelper.cs
+1 −1 src/CommonUtilities/CommonUtilities.Windows/CommonUtilities.Windows.csproj
+2 −2 src/Updater/AppUpdaterFramework.Manifest/AppUpdaterFramework.Manifest.csproj
+1 −1 src/Updater/AppUpdaterFramework.WPF/AppUpdaterFramework.WPF.csproj
+6 −6 src/Updater/AppUpdaterFramework/AppUpdaterFramework.csproj
+0 −2 src/Updater/AppUpdaterFramework/Updater/Internal/ApplicationUpdater.cs
+4 −4 src/Updater/AppUpdaterFramework/Updater/Internal/UpdateCleanPipeline.cs
+35 −27 src/Updater/AppUpdaterFramework/Updater/Internal/UpdatePipeline.cs
+11 −9 src/Updater/AppUpdaterFramework/Updater/Tasks/DownloadStep.cs
+10 −6 src/Updater/AppUpdaterFramework/Updater/Tasks/InstallStep.cs
+7 −7 src/Updater/ExternalUpdater.App/ExternalUpdater.App.csproj
+3 −3 src/Updater/ExternalUpdater.Core/ExternalUpdater.Core.csproj
56 changes: 56 additions & 0 deletions src/ModVerify.CliApp/App/CreateBaselineAction.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
using AET.ModVerify.App.Reporting;
using AET.ModVerify.App.Settings;
using AET.ModVerify.App.Utilities;
using AET.ModVerify.Reporting;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.IO.Abstractions;
using System.Threading.Tasks;

namespace AET.ModVerify.App;

internal sealed class CreateBaselineAction(AppBaselineSettings settings, IServiceProvider serviceProvider)
: ModVerifyApplicationAction<AppBaselineSettings>(settings, serviceProvider)
{
private readonly IFileSystem _fileSystem = serviceProvider.GetRequiredService<IFileSystem>();

protected override void PrintAction(VerificationTarget target)
{
Console.WriteLine();
Console.ForegroundColor = ConsoleColor.DarkGreen;
Console.WriteLine($"Creating baseline for {target.Name}...");
Console.WriteLine();
ModVerifyConsoleUtilities.WriteSelectedTarget(target);
Console.WriteLine();
}

protected override async Task<int> ProcessVerifyFindings(
VerificationTarget verificationTarget,
IReadOnlyCollection<VerificationError> allErrors)
{
var baselineFactory = ServiceProvider.GetRequiredService<IBaselineFactory>();
var baseline = baselineFactory.CreateBaseline(verificationTarget, Settings, allErrors);

var fullPath = _fileSystem.Path.GetFullPath(Settings.NewBaselinePath);
Logger?.LogInformation(ModVerifyConstants.ConsoleEventId,
"Writing Baseline to '{FullPath}' with {Number} findings", fullPath, allErrors.Count);

await baselineFactory.WriteBaselineAsync(baseline, Settings.NewBaselinePath);

Logger?.LogDebug("Baseline successfully created.");

Console.WriteLine();
Console.ForegroundColor = ConsoleColor.DarkGreen;
Console.WriteLine($"Baseline for {verificationTarget.Name} created.");
Console.ResetColor();

return ModVerifyConstants.Success;
}

protected override VerificationBaseline GetBaseline(VerificationTarget verificationTarget)
{
return VerificationBaseline.Empty;
}
}
8 changes: 8 additions & 0 deletions src/ModVerify.CliApp/App/IModVerifyAppAction.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
using System.Threading.Tasks;

namespace AET.ModVerify.App;

internal interface IModVerifyAppAction
{
Task<int> ExecuteAsync();
}
68 changes: 68 additions & 0 deletions src/ModVerify.CliApp/App/ModVerifyApplication.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
using AET.ModVerify.App.Settings;
using AnakinRaW.ApplicationBase;
using AnakinRaW.ApplicationBase.Utilities;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Serilog;
using System;
using System.Threading.Tasks;
using ILogger = Microsoft.Extensions.Logging.ILogger;

namespace AET.ModVerify.App;

internal sealed class ModVerifyApplication(AppSettingsBase settings, IServiceProvider services)
{
private readonly ILogger? _logger = services.GetService<ILoggerFactory>()?.CreateLogger(typeof(ModVerifyApplication));

public async Task<int> RunAsync()
{
using (new UnhandledExceptionHandler(services))
using (new UnobservedTaskExceptionHandler(services))
return await RunCoreAsync().ConfigureAwait(false);
}

private async Task<int> RunCoreAsync()
{
_logger?.LogDebug("Raw command line: {CommandLine}", Environment.CommandLine);

try
{
var action = CreateAppAction();
return await action.ExecuteAsync().ConfigureAwait(false);
}
catch (Exception e)
{
_logger?.LogCritical(e, e.Message);
ConsoleUtilities.WriteApplicationFatalError(ModVerifyConstants.AppNameString, e);
return e.HResult;
}
finally
{
#if NET
await Log.CloseAndFlushAsync();
#else
Log.CloseAndFlush();
#endif
if (settings is AppVerifySettings { IsInteractive: true })
{
Console.WriteLine();
ConsoleUtilities.WriteHorizontalLine('-');
Console.WriteLine("Press any key to exit");
Console.ReadLine();
}
}
}

private IModVerifyAppAction CreateAppAction()
{
switch (settings)
{
case AppVerifySettings verifySettings:
return new VerifyAction(verifySettings, services);
case AppBaselineSettings baselineSettings:
return new CreateBaselineAction(baselineSettings, services);
default:
throw new InvalidOperationException("Unknown settings");
}
}
}
Loading
Loading