9 Commits
Author SHA1 Message Date
james.maes 96fc48d04a Merge pull request 'ci: first run on ci-workflows v1' (#37) from ci/first-run-v1 into main
windows / windows (push) Successful in 1m1s
build / windows (push) Successful in 1m1s
2026-11-08 23:13:50 +00:00
James MaesandClaude Opus 5.5 23ffa01b16 ci: first run on ci-workflows v1 (native workflows)
windows / windows (push) Successful in 59s
build / windows (push) Successful in 59s
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-08 08:26:23 -06:00
james.maes 3ae4a77e22 Merge pull request 'ci: build on the shared ci-workflows Windows workflow' (#36) from ci/shared-windows into main 2026-11-08 13:49:52 +00:00
James MaesandClaude Opus 5.5 5dcbe6a1cd ci: pin the shared workflow to v1
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-08 07:49:39 -06:00
James MaesandClaude Opus 5.5 cbec0cd623 ci: call the shared workflow from ci-workflows main
windows / windows (push) Successful in 59s
build / windows (push) Successful in 59s
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-08 07:46:01 -06:00
James MaesandClaude Opus 5.5 9c97b06cb5 ci: pack the tag version on vX.Y.Z tags
windows / windows (push) Canceled after 0s
build / windows (push) Canceled after 0s
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-08 07:43:19 -06:00
James MaesandClaude Opus 5.5 7d951a618d ci: run the coverage gate as a separate pwsh process
windows / windows (push) Successful in 58s
build / windows (push) Successful in 58s
Assert-Coverage.ps1 reports a shortfall with exit 1, which only stops the
build when the script runs as a native process.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-08 07:35:34 -06:00
James MaesandClaude Opus 5.5 1abae0aa71 ci: build on the shared ci-workflows Windows workflow
windows / windows (push) Canceled after 0s
build / windows (push) Canceled after 0s
Locked restore, warnings-as-errors build, dotnet format, tests with the 100%
coverage gate and the NuGet pack run on the KOF Windows host runner; v* tags
attach the packages and SHA256SUMS to the Gitea release. Removes the note on
the retired central native verification.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-08 07:33:17 -06:00
forge-recovery aecd0cfe2d docs(ci): document centralized native verification (#32)
KofTwentyTwo/ci-policy: ci / fork-guard (push) Skipped
KofTwentyTwo/ci-policy: ci / gradle-0 (push) Skipped
KofTwentyTwo/ci-policy: ci / gradle-1 (push) Skipped
KofTwentyTwo/ci-policy: ci / java-docker-2 (push) Skipped
KofTwentyTwo/ci-policy: ci / java-maven-3 (push) Skipped
KofTwentyTwo/ci-policy: ci / manifests-4 (push) Skipped
KofTwentyTwo/ci-policy: ci / node-5 (push) Skipped
KofTwentyTwo/ci-policy: ci / rust-6 (push) Skipped
KofTwentyTwo/ci-policy: ci / rust-7 (push) Skipped
KofTwentyTwo/ci-policy: ci / rust-8 (push) Skipped
KofTwentyTwo/ci-policy: ci / not-enrolled (push) Skipped
KofTwentyTwo/ci-policy: native / fork-deny (push) Skipped
KofTwentyTwo/ci-policy: native / swift-1 (push) Skipped
KofTwentyTwo/ci-policy: native / swift-2 (push) Skipped
KofTwentyTwo/ci-policy: native / swift-3 (push) Skipped
KofTwentyTwo/ci-policy: Shared source and config CI / verify (push) Successful in 21s
KofTwentyTwo/ci-policy: Shared source and config CI / secrets (push) Successful in 24s
KofTwentyTwo/ci-policy: Shared .NET CI / secrets (push) Successful in 31s
KofTwentyTwo/ci-policy: Shared source and config CI / gate (push) Successful in 22s
KofTwentyTwo/ci-policy: ci / source-config-9 (push) Successful in 50s
KofTwentyTwo/ci-policy: ci / ci-result (push) Successful in 8s
KofTwentyTwo/ci-policy: Shared .NET CI / verify (push) Successful in 1m24s
KofTwentyTwo/ci-policy: Shared .NET CI / gate (push) Successful in 18s
KofTwentyTwo/ci-policy: native / dotnet-0 (push) Successful in 1m46s
KofTwentyTwo/ci-policy: native / native-result (push) Successful in 7s
2026-11-01 19:52:24 +00:00
9 changed files with 27 additions and 141 deletions

No files matched your search

+24
View File
@@ -0,0 +1,24 @@
name: build
on:
push:
branches: ['**']
tags: ['v*']
jobs:
windows:
uses: self:KofTwentyTwo/ci-workflows/.gitea/workflows/windows.yaml@v1
secrets: inherit
with:
commands: |
dotnet restore AppKit.slnx -p:Platform=x64 --locked-mode
dotnet build AppKit.slnx -p:Platform=x64 -warnaserror --no-restore
# The WinUI sample is built directly so the format workspace can load its generated XAML code.
dotnet build samples/AppKit.Sample.WinUI/AppKit.Sample.WinUI.csproj -p:Platform=x64 -warnaserror --no-restore
$env:Platform = 'x64'
dotnet format AppKit.slnx --verify-no-changes --severity warn --no-restore
Remove-Item Env:Platform
dotnet test tests/KofTwentyTwo.AppKit.Tests --no-build --settings coverage.runsettings --collect:"XPlat Code Coverage" --logger trx --results-directory TestResults
pwsh -NoProfile -File ./build/Assert-Coverage.ps1 -ResultsDirectory TestResults -Packages KofTwentyTwo.AppKit,KofTwentyTwo.AppKit.Updates
# A vX.Y.Z tag packs that version; other pushes pack the 0.1.0-dev default.
$version = if ($env:GITHUB_REF_TYPE -eq 'tag') { @("-p:Version=$($env:GITHUB_REF_NAME.TrimStart('v'))") } else { @() }
dotnet pack AppKit.slnx -c Release -p:Platform=x64 -o artifacts/nuget @version
artifacts: artifacts/nuget/*.nupkg
-6
View File
@@ -53,12 +53,6 @@ its build targets) and copies its brand assets (`Assets/Brand/app-icon.svg`,
## Usage
The default sample/starter Help menus include **View on GitHub**,
**Submit an issue…** and **Community support…**, matching gclo. Derive the issue
chooser (`/issues/new/choose`) and Discussions (`/discussions`) from the app's
`AppInfo.RepositoryUrl`; enable GitHub Discussions during repository setup.
Both WinUI and WPF samples show the wiring without requiring a new AppKit API.
New apps should start from the KofTwentyTwo Windows app template, which has everything
below in place; the design is the
[Windows desktop reference architecture](https://github.com/KofTwentyTwo/standards/blob/main/architecture/windows-desktop-app.md).
@@ -1,45 +0,0 @@
/*
* Copyright (c) 2026 James Maes
* SPDX-License-Identifier: MIT
*/
using Microsoft.UI.Xaml;
namespace AppKit.Sample.WinUI;
/// <summary>Opens only the app's fixed public Help destinations after deliberate native menu actions.</summary>
public sealed partial class MainWindow
{
/// <summary>Shows this Windows app's repository in the user's default browser.</summary>
private async void GitHub_Click(object sender, RoutedEventArgs args) => await OpenHelpPageAsync(SampleApp.Info.RepositoryUrl!);
/// <summary>Offers the app's issue templates without sending private document data.</summary>
private async void SubmitIssue_Click(object sender, RoutedEventArgs args) => await OpenHelpPageAsync(SampleApp.IssuesUrl);
/// <summary>Opens community questions and tips in this app's repository.</summary>
private async void CommunitySupport_Click(object sender, RoutedEventArgs args) => await OpenHelpPageAsync(SampleApp.SupportUrl);
/// <summary>A missing browser or OS launch failure is visible; no document path/content is included.</summary>
private async Task OpenHelpPageAsync(Uri target)
{
try
{
if(!await global::Windows.System.Launcher.LaunchUriAsync(target))
{
StatusText.Text = "The link could not be opened. Check your default browser.";
}
}
catch(Exception exception) when(exception is System.Runtime.InteropServices.COMException or InvalidOperationException or ArgumentException)
{
StatusText.Text = "The link could not be opened. Check your default browser.";
App.Log.Warning(FormattableString.Invariant($"A Help link could not be opened ({exception.GetType().Name}, 0x{exception.HResult:X8})."));
}
}
}
+1 -5
View File
@@ -25,11 +25,7 @@
<MenuFlyoutSeparator />
<ToggleMenuFlyoutItem x:Name="SplashToggle" Text="Show splash at startup" Click="Splash_Click" />
</MenuBarItem>
<MenuBarItem Title="Help" AccessKey="H">
<MenuFlyoutItem Text="View on GitHub" AccessKey="G" AutomationProperties.AutomationId="MenuGitHub" Click="GitHub_Click" />
<MenuFlyoutItem Text="Submit an issue…" AccessKey="I" AutomationProperties.AutomationId="MenuSubmitIssue" ToolTipService.ToolTip="Report a bug or request a feature on GitHub" Click="SubmitIssue_Click" />
<MenuFlyoutItem Text="Community support…" AccessKey="S" AutomationProperties.AutomationId="MenuCommunitySupport" ToolTipService.ToolTip="Ask a question or share tips in GitHub Discussions" Click="CommunitySupport_Click" />
<MenuFlyoutSeparator />
<MenuBarItem Title="Help">
<MenuFlyoutItem x:Name="CheckForUpdatesMenuItem" Text="Check for updates" Click="CheckForUpdates_Click" />
<MenuFlyoutItem x:Name="ActivityLogMenuItem" Text="Activity log" Click="ActivityLog_Click" />
<MenuFlyoutSeparator />
@@ -1,43 +0,0 @@
/*
* Copyright (c) 2026 James Maes (KofTwentyTwo)
* SPDX-License-Identifier: MIT
*/
using System.Diagnostics;
using System.Windows;
namespace AppKit.Sample.Wpf;
/// <summary>Opens the sample's fixed public Help destinations using the Windows default browser.</summary>
public partial class MainWindow
{
/// <summary>Shows the sample's source repository.</summary>
private void GitHub_Click(object sender, RoutedEventArgs args) => OpenHelpPage(SampleApp.Info.RepositoryUrl!);
/// <summary>Offers the repository's bug/feature templates.</summary>
private void SubmitIssue_Click(object sender, RoutedEventArgs args) => OpenHelpPage(SampleApp.IssuesUrl);
/// <summary>Opens the sample's community support destination.</summary>
private void CommunitySupport_Click(object sender, RoutedEventArgs args) => OpenHelpPage(SampleApp.SupportUrl);
/// <summary>Surfaces OS/browser launch failure without passing private app data to the shell.</summary>
private void OpenHelpPage(Uri target)
{
try
{
using var process = Process.Start(new ProcessStartInfo(target.AbsoluteUri) { UseShellExecute = true });
}
catch(Exception exception) when(exception is System.ComponentModel.Win32Exception or InvalidOperationException)
{
StatusText.Text = "The link could not be opened. Check your default browser.";
Program.Log.Warning(FormattableString.Invariant($"A Help link could not be opened ({exception.GetType().Name}, 0x{exception.HResult:X8})."));
}
}
}
@@ -25,10 +25,6 @@
<MenuItem x:Name="SplashToggle" Header="Show splash at startup" IsCheckable="True" Click="Splash_Click" />
</MenuItem>
<MenuItem Header="_Help">
<MenuItem Header="View on _GitHub" AutomationProperties.AutomationId="MenuGitHub" Click="GitHub_Click" />
<MenuItem Header="Submit an _issue…" AutomationProperties.AutomationId="MenuSubmitIssue" ToolTip="Report a bug or request a feature on GitHub" Click="SubmitIssue_Click" />
<MenuItem Header="Community _support…" AutomationProperties.AutomationId="MenuCommunitySupport" ToolTip="Ask a question or share tips in GitHub Discussions" Click="CommunitySupport_Click" />
<Separator />
<MenuItem x:Name="CheckForUpdatesMenuItem" Header="Check for _updates" Click="CheckForUpdates_Click" />
<MenuItem x:Name="ActivityLogMenuItem" Header="Activity _log" Click="ActivityLog_Click" />
<Separator />
-12
View File
@@ -36,17 +36,5 @@ internal static class SampleApp
public static AppPaths Paths { get; } = new(Info);
/// <summary>The app's bug/feature templates, independent of any upstream project credited in About.</summary>
public static Uri IssuesUrl { get; } = new(Info.RepositoryUrl!.AbsoluteUri.TrimEnd('/') + "/issues/new/choose");
/// <summary>Community questions and tips in the app's own repository.</summary>
public static Uri SupportUrl { get; } = new(Info.RepositoryUrl!.AbsoluteUri.TrimEnd('/') + "/discussions");
public static SettingsStore<SampleSettings> SettingsStore { get; } = new(Paths.SettingsFile, SampleSettingsContext.Default.SampleSettings);
}
@@ -152,12 +152,7 @@ public sealed class AppSession : IDisposable
/// expand (its flyout opens before the menu is ready), so the menu is re-opened
/// until the item appears.
/// </summary>
public void InvokeMenuItem(string menuName, string itemAutomationId) => Invoke(OpenMenuItem(menuName, itemAutomationId));
/// <summary>Opens an owned native menu and returns its item without launching an external destination.</summary>
public AutomationElement OpenMenuItem(string menuName, string itemAutomationId)
public void InvokeMenuItem(string menuName, string itemAutomationId)
{
AutomationElement menu = WaitFor(
() => MainWindow.FindFirstDescendant(cf => cf.ByControlType(ControlType.MenuItem).And(cf.ByName(menuName))),
@@ -176,7 +171,7 @@ public sealed class AppSession : IDisposable
Wait.UntilInputIsProcessed();
item = Retry.WhileNull(() => FindInApp(cf => cf.ByAutomationId(itemAutomationId)), timeout: TimeSpan.FromSeconds(3), interval: s_pollInterval, ignoreException: true).Result;
}
return item ?? throw new TimeoutException($"Menu item '{itemAutomationId}' never appeared under '{menuName}'. (app exited: {App.HasExited})");
Invoke(item ?? throw new TimeoutException($"Menu item '{itemAutomationId}' never appeared under '{menuName}'. (app exited: {App.HasExited})"));
}
@@ -28,25 +28,6 @@ public class SampleAppTests
/// <summary>The real Help menu exposes the app's repository, issue reporting and community commands without launching a browser.</summary>
[Theory]
[InlineData(SampleKind.WinUI)]
[InlineData(SampleKind.Wpf)]
public void Help_PublicDestinations_AreAvailableInTheNativeMenu(SampleKind kind)
{
using var session = new AppSession(kind);
_ = session.OpenMenuItem("Help", "MenuGitHub");
foreach((string identity, string label) in new[] { ("MenuGitHub", "GitHub"), ("MenuSubmitIssue", "issue"), ("MenuCommunitySupport", "support") })
{
AutomationElement item = session.WaitForElement(identity);
Assert.True(item.IsEnabled);
Assert.False(item.IsOffscreen);
Assert.Contains(label, item.Name, StringComparison.OrdinalIgnoreCase);
}
}
/// <summary>About: shows the build version.</summary>
[Theory]
[InlineData(SampleKind.WinUI)]