Check VelopackApp on all platforms / better error messages

This commit is contained in:
Caelan Sayler
2024-01-10 22:42:47 +00:00
parent 14965a5259
commit 8d56e78d99
6 changed files with 46 additions and 43 deletions

View File

@@ -57,7 +57,7 @@ public class WindowsPackCommandRunner : PackageBuilder<WindowsPackOptions>
return Task.FromResult(packDir);
}
protected override string GenerateNuspecContent(string packId, string packTitle, string packAuthors, string packVersion, string releaseNotes, string packDir)
protected override string GenerateNuspecContent(string packId, string packTitle, string packAuthors, string packVersion, string releaseNotes, string packDir, string mainExeName)
{
// check provided runtimes
IEnumerable<Runtimes.RuntimeInfo> requiredFrameworks = Enumerable.Empty<Runtimes.RuntimeInfo>();
@@ -66,34 +66,12 @@ public class WindowsPackCommandRunner : PackageBuilder<WindowsPackOptions>
.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries)
.Select(Runtimes.GetRuntimeByName);
}
if (requiredFrameworks.Where(f => f == null).Any())
throw new ArgumentException("Invalid target frameworks string.");
// check that the main executable exists
var mainExeName = Options.EntryExecutableName ?? Options.PackId + ".exe";
var mainExe = Path.Combine(packDir, mainExeName);
if (!File.Exists(mainExe))
throw new ArgumentException($"--exeName '{mainExeName}' does not exist in package. Searched at: '{mainExe}'");
// verify that the main executable is a valid velopack app
try {
var psi = new ProcessStartInfo(mainExe);
psi.AppendArgumentListSafe(new[] { "--veloapp-version" }, out var _);
var output = psi.Output(3000);
if (String.IsNullOrWhiteSpace(output)) {
throw new Exception("Process exited with no output.");
}
var version = SemanticVersion.Parse(output.Trim());
if (version != VelopackRuntimeInfo.VelopackNugetVersion) {
Log.Warn($"VelopackApp version '{version}' does not match CLI version '{VelopackRuntimeInfo.VelopackNugetVersion}'.");
}
} catch {
Log.Error("Failed to verify VelopackApp. Ensure you have added the startup code to your Program.Main(): VelopackApp.Build().Run();");
throw;
}
// generate nuspec
var initial = base.GenerateNuspecContent(packId, packTitle, packAuthors, packVersion, releaseNotes, packDir);
var initial = base.GenerateNuspecContent(packId, packTitle, packAuthors, packVersion, releaseNotes, packDir, mainExeName);
var tmpPath = Path.Combine(TempDir.FullName, "tmpwin.nuspec");
File.WriteAllText(tmpPath, initial);
NuspecManifest.SetMetadata(tmpPath, mainExeName, requiredFrameworks.Select(r => r.Id), Options.TargetRuntime, null);

View File

@@ -1,18 +1,11 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection.Metadata.Ecma335;
using System.Diagnostics;
using System.Security;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Channels;
using System.Threading.Tasks;
using System.Xml;
using Microsoft.Extensions.Logging;
using NuGet.Versioning;
using Spectre.Console;
using Velopack.Compression;
using Velopack.NuGet;
namespace Velopack.Packaging
{
@@ -22,6 +15,7 @@ namespace Velopack.Packaging
DirectoryInfo ReleaseDir { get; }
string Channel { get; }
DeltaMode DeltaMode { get; }
string EntryExecutableName { get; }
}
public abstract class PackageBuilder<T> : ICommand<T>
@@ -46,7 +40,8 @@ namespace Velopack.Packaging
public async Task Run(T options)
{
if (options.TargetRuntime?.BaseRID != SupportedTargetOs)
throw new ArgumentException($"Target runtime must be {SupportedTargetOs}.", nameof(options.TargetRuntime));
throw new UserErrorException($"To build packages for {SupportedTargetOs.GetOsLongName()}, " +
$"the target rid must be {SupportedTargetOs} (actually was {options.TargetRuntime?.BaseRID}).");
var now = DateTime.UtcNow;
@@ -65,6 +60,36 @@ namespace Velopack.Packaging
var packDirectory = options.PackDirectory;
var packVersion = options.PackVersion;
// check that entry exe exists
var mainExeName = options.EntryExecutableName ?? (options.PackId + ".exe");
var mainExePath = Path.Combine(packDirectory, mainExeName);
if (!File.Exists(mainExePath)) {
throw new UserErrorException(
$"Could not find main application executable (the one that runs 'VelopackApp.Build().Run()'). " + Environment.NewLine +
$"I searched for '{mainExeName}' in {packDirectory}." + Environment.NewLine +
$"If your main binary is not named '{mainExeName}', please specify the name with the argument: --exeName {{yourBinary.exe}}");
}
// verify that the main executable is a valid velopack app
try {
var psi = new ProcessStartInfo(mainExePath);
psi.AppendArgumentListSafe(new[] { "--veloapp-version" }, out var _);
var output = psi.Output(5000);
if (String.IsNullOrWhiteSpace(output)) {
throw new UserErrorException(
"Failed to verify VelopackApp (Exited with no output). " +
"Ensure you have add the startup code to your Program.Main(): VelopackApp.Build().Run(); and then re-compile your application.");
}
var version = SemanticVersion.Parse(output.Trim());
if (version != VelopackRuntimeInfo.VelopackNugetVersion) {
Log.Warn($"VelopackApp version '{version}' does not match CLI version '{VelopackRuntimeInfo.VelopackNugetVersion}'.");
}
} catch (TimeoutException) {
throw new UserErrorException(
"Failed to verify VelopackApp (Timed out). " +
"Ensure you have add the startup code to your Program.Main(): VelopackApp.Build().Run(); and then re-compile your application.");
}
var suffix = ReleaseEntryHelper.GetPkgSuffix(SupportedTargetOs, channel);
if (!String.IsNullOrWhiteSpace(suffix)) {
packVersion += suffix;
@@ -95,7 +120,7 @@ namespace Velopack.Packaging
await WrapTask(ctx, "Pre-process steps", async (progress) => {
prev = entryHelper.GetPreviousFullRelease(NuGetVersion.Parse(packVersion), channel);
nuspecText = GenerateNuspecContent(
packId, packTitle, packAuthors, packVersion, options.ReleaseNotes, packDirectory);
packId, packTitle, packAuthors, packVersion, options.ReleaseNotes, packDirectory, mainExeName);
packDirectory = await PreprocessPackDir(progress, packDirectory, nuspecText);
});
@@ -188,7 +213,7 @@ namespace Velopack.Packaging
Log.Debug($"[bold]Complete: {name}[/]");
}
protected virtual string GenerateNuspecContent(string packId, string packTitle, string packAuthors, string packVersion, string releaseNotes, string packDir)
protected virtual string GenerateNuspecContent(string packId, string packTitle, string packAuthors, string packVersion, string releaseNotes, string packDir, string mainExeName)
{
var releaseNotesText = String.IsNullOrEmpty(releaseNotes)
? "" // no releaseNotes

View File

@@ -42,10 +42,10 @@ namespace Velopack.Packaging
foreach (var release in _releases[channel]) {
if (release.Rid != rid) {
throw new ArgumentException("All releases in a channel must have the same RID. Please correct RELEASES file or change channel name: " + GetReleasePath(channel));
throw new UserErrorException("All releases in a channel must have the same RID. Please correct RELEASES file or change channel name: " + GetReleasePath(channel));
}
if (version <= release.Version) {
throw new ArgumentException($"Release {release.OriginalFilename} is equal or newer to the current version {version}. Please increase the current package version or remove that release.");
throw new UserErrorException($"Release {release.OriginalFilename} is equal or newer to the current version {version}. Please increase the current package version or remove that release.");
}
}
}

View File

@@ -68,7 +68,7 @@ namespace Velopack.Vpk.Commands
.SetArgumentHelpName("NAME");
AddOption<FileInfo>((v) => Icon = v.ToFullNameOrNull(), "-i", "--icon")
.SetDescription("Path to the .icns file for this bundle.")
.SetDescription("Path to the icon file for this bundle.")
.SetArgumentHelpName("PATH")
.MustExist()
.SetRequired();

View File

@@ -65,7 +65,7 @@ namespace Velopack
var p = Process.Start(psi);
if (!p.WaitForExit(timeoutMs)) {
p.Kill();
throw new TimeoutException("Process did not exit within alloted time.");
throw new TimeoutException("Process did not exit within allotted time.");
}
return p.StandardOutput.ReadToEnd().Trim();

View File

@@ -184,7 +184,7 @@ public class WindowsPackTests
var runner = new WindowsPackCommandRunner(logger);
runner.Run(options).GetAwaiterResult();
Assert.Throws<ArgumentException>(() => runner.Run(options).GetAwaiterResult());
Assert.Throws<UserErrorException>(() => runner.Run(options).GetAwaiterResult());
}
[SkippableFact]
@@ -222,7 +222,7 @@ public class WindowsPackTests
runner.Run(options).GetAwaiterResult();
options.TargetRuntime = RID.Parse("win10.0.19043-x86");
Assert.Throws<ArgumentException>(() => runner.Run(options).GetAwaiterResult());
Assert.Throws<UserErrorException>(() => runner.Run(options).GetAwaiterResult());
}
[SkippableFact]
@@ -253,7 +253,7 @@ public class WindowsPackTests
};
var runner = new WindowsPackCommandRunner(logger);
Assert.Throws<Exception>(() => runner.Run(options).GetAwaiterResult());
Assert.Throws<UserErrorException>(() => runner.Run(options).GetAwaiterResult());
}
[SkippableFact]