Skip to content

Commit 0a58df4

Browse files
committed
Fix CI validation and publish desktop artifacts
1 parent ed8ab95 commit 0a58df4

File tree

16 files changed

+681
-64
lines changed

16 files changed

+681
-64
lines changed

.github/steps/install_dependencies/action.yml

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,6 @@ inputs:
66
description: 'The platform to install dependencies for. #See available values at https://platform.uno/docs/articles/external/uno.check/doc/using-uno-check.html'
77
required: false
88
default: 'all'
9-
dotnet-version:
10-
description: 'Installs and sets the .NET SDK Version'
11-
required: false
12-
default: '10.0.x'
139
sdkVersion:
1410
description: 'The version of the Windows Sdk'
1511
required: false
@@ -19,10 +15,10 @@ runs:
1915
using: "composite"
2016
steps:
2117
# Install .NET
22-
- name: Setup .NET ${{ inputs.dotnet-version }}
23-
uses: actions/setup-dotnet@v3
18+
- name: Setup .NET SDK from global.json
19+
uses: actions/setup-dotnet@v4
2420
with:
25-
dotnet-version: '${{ inputs.dotnet-version }}'
21+
global-json-file: 'global.json'
2622

2723
# Install Windows SDK
2824
- name: Install Windows SDK ${{ inputs.sdkVersion }}

.github/workflows/ci.yml

Lines changed: 101 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -7,54 +7,137 @@ on:
77
- release/**
88

99
pull_request:
10-
types: [opened, synchronize, reopened]
10+
types: [opened, synchronize, reopened, ready_for_review]
1111
branches:
1212
- main
1313
- release/**
14+
workflow_dispatch:
15+
16+
permissions:
17+
contents: read
18+
19+
concurrency:
20+
group: ci-${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
21+
cancel-in-progress: true
22+
1423
env:
1524
STEP_TIMEOUT_MINUTES: 60
1625

1726
jobs:
18-
smoke_test:
19-
name: Smoke Test (Debug Build of DotPilot)
27+
quality:
28+
name: Quality
2029
runs-on: windows-latest
30+
timeout-minutes: ${{ fromJSON(env.STEP_TIMEOUT_MINUTES) }}
2131
steps:
22-
- uses: actions/checkout@v3
32+
- uses: actions/checkout@v4
2333
with:
2434
fetch-depth: 0
2535

2636
- name: Install Dependencies
2737
timeout-minutes: ${{ fromJSON(env.STEP_TIMEOUT_MINUTES) }}
2838
uses: "./.github/steps/install_dependencies"
2939

30-
# Add MSBuild to the PATH: https://github.com/microsoft/setup-msbuild
31-
- name: Setup MSBuild
32-
uses: microsoft/setup-msbuild@v1.3.1
40+
- name: Format
41+
shell: pwsh
42+
run: dotnet format DotPilot.slnx --verify-no-changes
43+
44+
- name: Build
45+
shell: pwsh
46+
run: dotnet build DotPilot.slnx
3347

34-
- name: Build DotPilot (Debug)
48+
- name: Analyze
3549
shell: pwsh
36-
run: msbuild ./DotPilot/DotPilot.csproj /r
50+
run: dotnet build DotPilot.slnx -warnaserror
3751

38-
unit_test:
52+
unit_tests:
3953
name: Unit Tests
4054
runs-on: windows-latest
55+
timeout-minutes: ${{ fromJSON(env.STEP_TIMEOUT_MINUTES) }}
4156
steps:
42-
- uses: actions/checkout@v3
57+
- uses: actions/checkout@v4
4358
with:
4459
fetch-depth: 0
4560

4661
- name: Install Dependencies
4762
timeout-minutes: ${{ fromJSON(env.STEP_TIMEOUT_MINUTES) }}
4863
uses: "./.github/steps/install_dependencies"
4964

50-
# Add MSBuild to the PATH: https://github.com/microsoft/setup-msbuild
51-
- name: Setup MSBuild
52-
uses: microsoft/setup-msbuild@v1.3.1
65+
- name: Run Unit Tests
66+
shell: pwsh
67+
run: dotnet test ./DotPilot.Tests/DotPilot.Tests.csproj --logger GitHubActions --blame-crash
5368

54-
- name: Build DotPilot.Tests (Release)
69+
coverage:
70+
name: Coverage
71+
runs-on: windows-latest
72+
timeout-minutes: ${{ fromJSON(env.STEP_TIMEOUT_MINUTES) }}
73+
steps:
74+
- uses: actions/checkout@v4
75+
with:
76+
fetch-depth: 0
77+
78+
- name: Install Dependencies
79+
timeout-minutes: ${{ fromJSON(env.STEP_TIMEOUT_MINUTES) }}
80+
uses: "./.github/steps/install_dependencies"
81+
82+
- name: Run Coverage
5583
shell: pwsh
56-
run: msbuild ./DotPilot.Tests/DotPilot.Tests.csproj /p:Configuration=Release /p:OverrideTargetFramework=net10.0 /r
84+
run: dotnet test ./DotPilot.Tests/DotPilot.Tests.csproj --settings ./DotPilot.Tests/coverlet.runsettings --logger GitHubActions --blame-crash --collect:"XPlat Code Coverage"
5785

58-
- name: Run Unit Tests
86+
ui_tests:
87+
name: UI Tests
88+
runs-on: windows-latest
89+
timeout-minutes: ${{ fromJSON(env.STEP_TIMEOUT_MINUTES) }}
90+
steps:
91+
- uses: actions/checkout@v4
92+
with:
93+
fetch-depth: 0
94+
95+
- name: Install Dependencies
96+
timeout-minutes: ${{ fromJSON(env.STEP_TIMEOUT_MINUTES) }}
97+
uses: "./.github/steps/install_dependencies"
98+
99+
- name: Run UI Tests
100+
shell: pwsh
101+
run: dotnet test ./DotPilot.UITests/DotPilot.UITests.csproj --logger GitHubActions --blame-crash
102+
103+
desktop_artifacts:
104+
name: Desktop Artifact (${{ matrix.name }})
105+
runs-on: ${{ matrix.runner }}
106+
timeout-minutes: ${{ fromJSON(env.STEP_TIMEOUT_MINUTES) }}
107+
strategy:
108+
fail-fast: false
109+
matrix:
110+
include:
111+
- name: macOS
112+
runner: macos-latest
113+
artifact_name: dotpilot-desktop-macos
114+
output_path: artifacts/publish/macos
115+
- name: Windows
116+
runner: windows-latest
117+
artifact_name: dotpilot-desktop-windows
118+
output_path: artifacts/publish/windows
119+
- name: Linux
120+
runner: ubuntu-latest
121+
artifact_name: dotpilot-desktop-linux
122+
output_path: artifacts/publish/linux
123+
steps:
124+
- uses: actions/checkout@v4
125+
with:
126+
fetch-depth: 0
127+
128+
- name: Setup .NET SDK from global.json
129+
uses: actions/setup-dotnet@v4
130+
with:
131+
global-json-file: global.json
132+
133+
- name: Publish Desktop App
59134
shell: pwsh
60-
run: dotnet test ./DotPilot.Tests/DotPilot.Tests.csproj --no-build -c Release --logger GitHubActions --blame-crash --collect:"XPlat Code Coverage" -- DataCollectionRunSettings.DataCollectors.DataCollector.Configuration.Format=opencover
135+
run: dotnet publish ./DotPilot/DotPilot.csproj -c Release -f net10.0-desktop -o ./${{ matrix.output_path }}
136+
137+
- name: Upload Desktop Artifact
138+
uses: actions/upload-artifact@v4
139+
with:
140+
name: ${{ matrix.artifact_name }}
141+
path: ./${{ matrix.output_path }}
142+
if-no-files-found: error
143+
retention-days: 14

AGENTS.md

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# AGENTS.md
22

33
Project: dotPilot
4-
Stack: .NET 10 `Uno Platform` desktop app with central package management, `NUnit` unit tests, and `Uno.UITest` smoke coverage
4+
Stack: .NET 10 `Uno Platform` desktop app with central package management, `NUnit` unit tests, and `Uno.UITest` browser UI coverage
55

66
Follows [MCAF](https://mcaf.managed-code.com/)
77

@@ -122,14 +122,16 @@ Skill-management rules for this `.NET` solution:
122122
- `test`: `dotnet test DotPilot.slnx`
123123
- `format`: `dotnet format DotPilot.slnx --verify-no-changes`
124124
- `analyze`: `dotnet build DotPilot.slnx -warnaserror`
125-
- `coverage`: `dotnet test DotPilot.Tests/DotPilot.Tests.csproj --collect:"XPlat Code Coverage"`
125+
- `coverage`: `dotnet test DotPilot.Tests/DotPilot.Tests.csproj --settings DotPilot.Tests/coverlet.runsettings --collect:"XPlat Code Coverage"`
126+
- `publish-desktop`: `dotnet publish DotPilot/DotPilot.csproj -c Release -f net10.0-desktop`
126127

127128
For this app:
128129

129130
- unit tests currently use `NUnit` through the default `VSTest` runner
130-
- UI smoke tests live in `DotPilot.UITests` and are a mandatory part of normal verification; the harness must provision or resolve browser-driver prerequisites automatically instead of skipping when local setup is missing
131+
- UI tests live in `DotPilot.UITests` and are a mandatory part of normal verification; the harness must provision or resolve browser-driver prerequisites automatically instead of skipping when local setup is missing
131132
- `format` uses `dotnet format --verify-no-changes`
132-
- coverage uses the `coverlet.collector` integration on `DotPilot.Tests`
133+
- coverage uses the `coverlet.collector` integration on `DotPilot.Tests` with the repo runsettings file to keep generated Uno artifacts out of the coverage path
134+
- desktop artifact validation uses `dotnet publish DotPilot/DotPilot.csproj -c Release -f net10.0-desktop` and the CI workflow must upload publish outputs for macOS, Windows, and Linux
133135
- `LangVersion` is pinned to `latest` at the root
134136
- the repo-root lowercase `.editorconfig` is the source of truth for formatting, naming, style, and analyzer severity
135137
- `Directory.Build.props` owns the shared analyzer and warning policy for future projects
@@ -250,7 +252,10 @@ Local `AGENTS.md` files may tighten these values, but they must not loosen them
250252
- Repository or module coverage must not decrease without an explicit written exception. Coverage after the change must stay at least at the previous baseline or improve.
251253
- Coverage is for finding gaps, not gaming a number. Coverage numbers do not replace scenario coverage or user-flow verification.
252254
- The task is not done until the full relevant test suite is green, not only the newly added tests.
253-
- UI smoke tests are mandatory for this repository and must run in normal agent verification; missing local browser-driver setup is a harness bug to fix, not a reason to skip the suite.
255+
- UI tests are mandatory for this repository and must run in normal agent verification; missing local browser-driver setup is a harness bug to fix, not a reason to skip the suite.
256+
- GitHub Actions PR validation is mandatory for every PR and must enforce the real repo verification path so test failures are caught in CI, not only locally.
257+
- GitHub Actions PR validation must run full automated test verification, especially the real UI suite; build-only or smoke-only checks are not an acceptable substitute for pull-request gating.
258+
- GitHub Actions validation must also produce downloadable app artifacts for macOS, Windows, and Linux so every PR and mainline run has test results plus installable build outputs.
254259
- For `.NET`, keep the active framework and runner model explicit so agents do not mix `TUnit`, `Microsoft.Testing.Platform`, and legacy `VSTest` assumptions.
255260
- After changing production code, run the repo-defined quality pass: format, build, analyze, focused tests, broader tests, coverage, and any configured extra gates.
256261

@@ -306,10 +311,12 @@ Ask first:
306311
- Use central package management for shared test and tooling packages.
307312
- Keep one `.NET` test framework active in the solution at a time unless a documented migration is in progress.
308313
- Validate UI changes through runnable `DotPilot.UITests` on every relevant verification pass, instead of relying only on manual browser inspection or conditional local setup.
314+
- Keep the UI-test execution path minimal: one normal test command should produce a real result without extra harness indirection or side-effect-heavy setup.
309315

310316
### Dislikes
311317

312318
- Installing stale, non-canonical, or non-`mcaf-*` skills into the repo-local agent skill directory.
313319
- Moving root governance out of the repository root.
314320
- Mixing multiple `.NET` test frameworks in the active solution without a documented migration plan.
315321
- Switching desktop Uno pages into stacked or mobile-style responsive layouts during resize work unless the user explicitly asks for a different composition; desktop pages must stay desktop-first and protect geometry through sizing constraints instead.
322+
- Adding extra UI-test orchestration complexity when the actual goal is simply to run the tests and get an honest pass or fail result.

Directory.Packages.props

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,12 @@
99
See https://aka.platform.uno/using-uno-sdk#implicit-packages for more information regarding the Implicit Packages.
1010
-->
1111
<ItemGroup>
12-
<PackageVersion Include="coverlet.collector" Version="6.0.2" />
12+
<PackageVersion Include="coverlet.collector" Version="8.0.0" />
1313
<PackageVersion Include="FluentAssertions" Version="6.12.0" />
14-
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.9.0" />
15-
<PackageVersion Include="NUnit" Version="4.1.0" />
16-
<PackageVersion Include="NUnit3TestAdapter" Version="4.5.0" />
17-
<PackageVersion Include="GitHubActionsTestLogger" Version="2.3.3" />
14+
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="18.3.0" />
15+
<PackageVersion Include="NUnit" Version="4.5.1" />
16+
<PackageVersion Include="NUnit3TestAdapter" Version="6.1.0" />
17+
<PackageVersion Include="GitHubActionsTestLogger" Version="3.0.1" />
1818
<PackageVersion Include="Newtonsoft.Json" Version="13.0.3" />
1919
<PackageVersion Include="Uno.UITest.Helpers" Version="1.1.0-dev.70" />
2020
<PackageVersion Include="Xamarin.UITest" Version="4.3.4" />

DotPilot.Tests/AGENTS.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ Stack: `.NET 10`, `NUnit`, `FluentAssertions`, `coverlet.collector`
2222
## Local Commands
2323

2424
- `test`: `dotnet test DotPilot.Tests/DotPilot.Tests.csproj`
25-
- `coverage`: `dotnet test DotPilot.Tests/DotPilot.Tests.csproj --collect:"XPlat Code Coverage"`
25+
- `coverage`: `dotnet test DotPilot.Tests/DotPilot.Tests.csproj --settings DotPilot.Tests/coverlet.runsettings --collect:"XPlat Code Coverage"`
2626
- `build`: `dotnet build DotPilot.Tests/DotPilot.Tests.csproj`
2727

2828
## Applicable Skills
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<RunSettings>
3+
<DataCollectionRunSettings>
4+
<DataCollectors>
5+
<DataCollector friendlyName="XPlat Code Coverage">
6+
<Configuration>
7+
<Include>[DotPilot]*</Include>
8+
<Exclude>[DotPilot.Tests]*,[coverlet.*]*</Exclude>
9+
<ExcludeByAttribute>CompilerGeneratedAttribute,GeneratedCodeAttribute,ExcludeFromCodeCoverageAttribute,ObsoleteAttribute</ExcludeByAttribute>
10+
<ExcludeByFile>**/obj/**,**/*.g.cs,**/*.g.i.cs,**/*HotReloadInfo*.cs</ExcludeByFile>
11+
<IncludeTestAssembly>false</IncludeTestAssembly>
12+
<SkipAutoProps>true</SkipAutoProps>
13+
<SingleHit>true</SingleHit>
14+
<DeterministicReport>true</DeterministicReport>
15+
<ExcludeAssembliesWithoutSources>MissingAny</ExcludeAssembliesWithoutSources>
16+
</Configuration>
17+
</DataCollector>
18+
</DataCollectors>
19+
</DataCollectionRunSettings>
20+
</RunSettings>

DotPilot.UITests/AGENTS.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
# AGENTS.md
22

33
Project: `DotPilot.UITests`
4-
Stack: `.NET 10`, `NUnit`, `Uno.UITest`, browser-driven smoke tests
4+
Stack: `.NET 10`, `NUnit`, `Uno.UITest`, browser-driven UI tests
55

66
## Purpose
77

8-
- This project owns UI smoke coverage for `DotPilot` through the `Uno.UITest` harness.
8+
- This project owns browser-driven UI coverage for `DotPilot` through the `Uno.UITest` harness.
99
- It is intended for app-launch and visible-flow verification once the external test prerequisites are satisfied.
1010

1111
## Entry Points
@@ -17,10 +17,11 @@ Stack: `.NET 10`, `NUnit`, `Uno.UITest`, browser-driven smoke tests
1717

1818
## Boundaries
1919

20-
- Keep this project focused on end-to-end or smoke-level verification only.
20+
- Keep this project focused on end-to-end browser verification only.
2121
- Do not add app business logic or test-only production hooks here unless they are required for stable automation.
2222
- Treat browser-driver setup and app-launch prerequisites as part of the harness, not as assumptions inside individual tests.
2323
- The harness must make `dotnet test DotPilot.UITests/DotPilot.UITests.csproj` runnable without manual driver-path export and must fail loudly instead of silently skipping coverage.
24+
- Keep the harness direct and minimal; prefer the smallest deterministic setup needed to run the suite and return a real result.
2425

2526
## Local Commands
2627

0 commit comments

Comments
 (0)