This replaces the blocked history in PR #3 with one properly attributed, signed/DCO commit. The owner personally reviewed and approved PR #3 in the release session. **No file changes from the approved candidate:** bothbaee14f492ande605df62c4have exact Git treea85912cbad. Original PR #3 and its commits are preserved for review history. Historical commits were locally signed but GitHub reported no_user; protected merge checks those introduced commits even for squash merging. This commit resolves attribution without bypassing or weakening signature rules. The reader, Settings, themes, source highlighting/split, live reload, file associations, Print/PDF, About credits, toolbar/footer/editor fixes, user-first README/screenshots and developer guides are exactly the approved implementation. Stable/dev separation and protected Azure signing caller are unchanged. Evidence: - Approved treebaee14f/ CI38285775463 passes all checks. Downloaded focused29/29, published111/111, stable110/110 and dev110/110 TRXs have zero failures/skips. Core coverage100% lines/98.86% branches; actual update/restart/coexistence/default-preservation receipts verify. - New single-commit hooks, online workflow security, signing and DCO pass. GitHub must rerun all required checks on this commit; results are not copied across SHAs. - Live repository setup validates18 Actions-bound checks, with only fuzzing added and all prior protections preserved. - OpenSSF project15417 is now owner-reviewed and saved at70% under owner-confirmed CDLA-Permissive2.0. This is an in-progress assessment, not a passing badge. - Production CI OIDC and signed1.0/dev publication remain required; local representative signing is not CI proof. Substantial AI assistance: Codex (GPT-6). Supersedes PR #3. Release work remains tracked in #33. Closes #4, #6, #7, #8, #9, #10, #11, #12, #13, #14, #15, #16, #17, #18, #19, #20, #21, #22, #23, #24, #25, #26, #27, #28, #29, #32, #34. Refs #1, #5, #30, #31, #33. Signed-off-by: James Maes <james@kof22.com> Co-authored-by: Codex GPT-6 <noreply@openai.com>
95 lines
3.5 KiB
C#
95 lines
3.5 KiB
C#
/*
|
|
* Copyright (c) 2026 James Maes
|
|
* SPDX-License-Identifier: MIT
|
|
*/
|
|
|
|
using System.Text.Json;
|
|
using KofTwentyTwo.AppKit.Updates;
|
|
using Velopack;
|
|
using Velopack.Locators;
|
|
using Velopack.Sources;
|
|
|
|
|
|
namespace MarkdownViewr.Windows.UpdateProbe;
|
|
|
|
/// <summary>Exercises AppKit's public installed update flow with offline GitHub release fixtures.</summary>
|
|
internal static class Program
|
|
{
|
|
/// <summary>Records the installed channel, update offer and requests; optionally downloads and applies it.</summary>
|
|
private static async Task<int> Main(string[] args)
|
|
{
|
|
if(Environment.GetEnvironmentVariable("MARKDOWNVIEWR_EDITOR_PROBE_RESULT") is { Length: > 0 } editorResult)
|
|
{
|
|
return WriteEditorResult(editorResult, args);
|
|
}
|
|
VelopackStartup.Run();
|
|
if(args.Length != 3 || args[2] is not ("check" or "apply"))
|
|
{
|
|
throw new ArgumentException("Usage: UpdateProbe <fixture-directory> <result-json> <check|apply>", nameof(args));
|
|
}
|
|
|
|
var repository = new Uri("https://github.com/Example/InstalledProbe");
|
|
var publicService = new VelopackUpdateService(repository);
|
|
var downloader = new FixtureDownloader(args[0]);
|
|
(UpdateManager manager, GithubSource source) = OfflineService.Attach(publicService, downloader);
|
|
UpdateCheckResult update = await publicService.CheckAsync().ConfigureAwait(false);
|
|
if(update.Error is not null && (manager.IsInstalled || !string.Equals(update.Error, UpdateText.NotSupported, StringComparison.Ordinal)))
|
|
{
|
|
throw new InvalidOperationException(update.Error);
|
|
}
|
|
|
|
bool applyCalled = false;
|
|
string? applyError = null;
|
|
// Apply exits this process. Record every download request synchronously before that happens.
|
|
Action saveResult = () => File.WriteAllText(args[1], JsonSerializer.Serialize(new
|
|
{
|
|
UpdateDriver = "AppKit",
|
|
Installed = manager.IsInstalled,
|
|
AppKitSupported = publicService.IsSupported,
|
|
AppKitVersion = publicService.CurrentVersion,
|
|
Version = manager.CurrentVersion?.ToString(),
|
|
VelopackLocator.Current.Channel,
|
|
manager.IsPortable,
|
|
IncludePrereleases = source.Prerelease,
|
|
UpdateVersion = update.AvailableVersion,
|
|
AppKitCheckError = update.Error,
|
|
AppKitApplyCalled = applyCalled,
|
|
AppKitApplyError = applyError,
|
|
downloader.Requests
|
|
}));
|
|
downloader.RequestRecorded = saveResult;
|
|
saveResult();
|
|
|
|
if(string.Equals(args[2], "apply", StringComparison.Ordinal))
|
|
{
|
|
if(!update.IsUpdateAvailable)
|
|
{
|
|
throw new InvalidOperationException("No update was offered to apply.");
|
|
}
|
|
applyCalled = true;
|
|
saveResult();
|
|
applyError = await publicService.DownloadAndApplyAsync().ConfigureAwait(false);
|
|
saveResult();
|
|
if(applyError is not null)
|
|
{
|
|
throw new InvalidOperationException(applyError);
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
/// <summary>Records only the owned fixture's actual process arguments; it never opens or reads the document.</summary>
|
|
private static int WriteEditorResult(string resultPath, string[] args)
|
|
{
|
|
if(args.Length != 1)
|
|
{
|
|
throw new ArgumentException("The editor fixture expects one literal document argument.", nameof(args));
|
|
}
|
|
File.WriteAllText(resultPath + ".tmp", JsonSerializer.Serialize(new { Arguments = args, WorkingDirectory = Environment.CurrentDirectory }));
|
|
File.Move(resultPath + ".tmp", resultPath, overwrite: true);
|
|
return 0;
|
|
}
|
|
}
|