Skip to content

Commit 0833c9e

Browse files
committed
tests
1 parent 75120a7 commit 0833c9e

11 files changed

Lines changed: 936 additions & 140 deletions
Lines changed: 6 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
name: Validation Pipeline
1+
name: Build Validation
22

33
on:
44
push:
@@ -17,15 +17,12 @@ permissions:
1717
contents: read
1818

1919
concurrency:
20-
group: ci-${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
20+
group: build-validation-${{ github.event.pull_request.number || github.ref }}
2121
cancel-in-progress: true
2222

23-
env:
24-
STEP_TIMEOUT_MINUTES: 60
25-
2623
jobs:
2724
build:
28-
name: Build
25+
name: Quality Gate
2926
runs-on: windows-latest
3027
timeout-minutes: 60
3128
steps:
@@ -50,7 +47,7 @@ jobs:
5047
run: dotnet build DotPilot.slnx -warnaserror
5148

5249
unit_tests:
53-
name: Unit Tests
50+
name: Unit Test Suite
5451
runs-on: windows-latest
5552
timeout-minutes: 60
5653
needs:
@@ -69,7 +66,7 @@ jobs:
6966
run: dotnet test ./DotPilot.Tests/DotPilot.Tests.csproj --logger GitHubActions --blame-crash
7067

7168
coverage:
72-
name: Coverage
69+
name: Coverage Suite
7370
runs-on: windows-latest
7471
timeout-minutes: 60
7572
needs:
@@ -88,7 +85,7 @@ jobs:
8885
run: dotnet test ./DotPilot.Tests/DotPilot.Tests.csproj --settings ./DotPilot.Tests/coverlet.runsettings --logger GitHubActions --blame-crash --collect:"XPlat Code Coverage"
8986

9087
ui_tests:
91-
name: UI Tests
88+
name: UI Test Suite
9289
runs-on: windows-latest
9390
timeout-minutes: 60
9491
needs:
@@ -105,50 +102,3 @@ jobs:
105102
- name: Run UI Tests
106103
shell: pwsh
107104
run: dotnet test ./DotPilot.UITests/DotPilot.UITests.csproj --logger GitHubActions --blame-crash
108-
109-
desktop_artifacts:
110-
name: Desktop Artifact (${{ matrix.name }})
111-
runs-on: ${{ matrix.runner }}
112-
timeout-minutes: 60
113-
needs:
114-
- build
115-
- unit_tests
116-
- coverage
117-
- ui_tests
118-
strategy:
119-
fail-fast: false
120-
matrix:
121-
include:
122-
- name: macOS
123-
runner: macos-latest
124-
artifact_name: dotpilot-desktop-macos
125-
output_path: artifacts/publish/macos
126-
- name: Windows
127-
runner: windows-latest
128-
artifact_name: dotpilot-desktop-windows
129-
output_path: artifacts/publish/windows
130-
- name: Linux
131-
runner: ubuntu-latest
132-
artifact_name: dotpilot-desktop-linux
133-
output_path: artifacts/publish/linux
134-
steps:
135-
- uses: actions/checkout@v4
136-
with:
137-
fetch-depth: 0
138-
139-
- name: Setup .NET SDK from global.json
140-
uses: actions/setup-dotnet@v4
141-
with:
142-
global-json-file: global.json
143-
144-
- name: Publish Desktop App
145-
shell: pwsh
146-
run: dotnet publish ./DotPilot/DotPilot.csproj -c Release -f net10.0-desktop -o ./${{ matrix.output_path }}
147-
148-
- name: Upload Desktop Artifact
149-
uses: actions/upload-artifact@v4
150-
with:
151-
name: ${{ matrix.artifact_name }}
152-
path: ./${{ matrix.output_path }}
153-
if-no-files-found: error
154-
retention-days: 14
Lines changed: 222 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,222 @@
1+
name: Desktop Release
2+
3+
on:
4+
workflow_dispatch:
5+
inputs:
6+
version_bump:
7+
description: Version bump type for DotPilot desktop releases
8+
required: true
9+
default: patch
10+
type: choice
11+
options:
12+
- patch
13+
- minor
14+
- major
15+
prerelease:
16+
description: Publish the GitHub Release as a prerelease
17+
required: true
18+
default: false
19+
type: boolean
20+
21+
permissions:
22+
contents: write
23+
24+
concurrency:
25+
group: desktop-release-${{ github.ref_name }}
26+
cancel-in-progress: false
27+
28+
jobs:
29+
validate_release_ref:
30+
name: Validate Release Ref
31+
runs-on: ubuntu-latest
32+
steps:
33+
- name: Enforce Supported Release Branches
34+
shell: bash
35+
run: |
36+
if [[ "${GITHUB_REF_NAME}" == "main" || "${GITHUB_REF_NAME}" == release/* ]]; then
37+
exit 0
38+
fi
39+
40+
echo "Desktop releases may only run from main or release/* branches." >&2
41+
exit 1
42+
43+
prepare_release:
44+
name: Prepare Release
45+
runs-on: ubuntu-latest
46+
needs:
47+
- validate_release_ref
48+
outputs:
49+
application_version: ${{ steps.bump_version.outputs.application_version }}
50+
previous_tag: ${{ steps.previous_tag.outputs.value }}
51+
release_tag: ${{ steps.bump_version.outputs.release_tag }}
52+
release_version: ${{ steps.bump_version.outputs.display_version }}
53+
steps:
54+
- uses: actions/checkout@v4
55+
with:
56+
fetch-depth: 0
57+
58+
- name: Configure Git Identity
59+
shell: bash
60+
run: |
61+
git config user.name "github-actions[bot]"
62+
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
63+
64+
- name: Fetch Tags
65+
shell: bash
66+
run: git fetch --tags --force
67+
68+
- name: Capture Previous Tag
69+
id: previous_tag
70+
shell: bash
71+
run: |
72+
previous_tag="$(git tag --list 'v*' --sort=-version:refname | head -n 1)"
73+
echo "value=${previous_tag}" >> "$GITHUB_OUTPUT"
74+
75+
- name: Bump App Version
76+
id: bump_version
77+
shell: bash
78+
run: |
79+
python3 ./scripts/release/update_app_version.py \
80+
--project-file ./DotPilot/DotPilot.csproj \
81+
--bump-type '${{ inputs.version_bump }}' \
82+
--github-output "$GITHUB_OUTPUT"
83+
84+
- name: Commit Version Bump
85+
shell: bash
86+
run: |
87+
git add DotPilot/DotPilot.csproj
88+
git commit -m "chore(release): v${{ steps.bump_version.outputs.display_version }}"
89+
90+
- name: Create Release Tag
91+
shell: bash
92+
run: git tag "${{ steps.bump_version.outputs.release_tag }}"
93+
94+
- name: Push Release Commit And Tag
95+
shell: bash
96+
run: |
97+
git push origin "HEAD:${GITHUB_REF_NAME}"
98+
git push origin "${{ steps.bump_version.outputs.release_tag }}"
99+
100+
publish_desktop:
101+
name: Publish Desktop (${{ matrix.name }})
102+
runs-on: ${{ matrix.runner }}
103+
needs:
104+
- prepare_release
105+
strategy:
106+
fail-fast: false
107+
matrix:
108+
include:
109+
- name: macOS
110+
runner: macos-latest
111+
artifact_name: dotpilot-release-macos
112+
archive_name: dotpilot-desktop-macos.zip
113+
output_path: artifacts/publish/macos
114+
- name: Windows
115+
runner: windows-latest
116+
artifact_name: dotpilot-release-windows
117+
archive_name: dotpilot-desktop-windows.zip
118+
output_path: artifacts/publish/windows
119+
- name: Linux
120+
runner: ubuntu-latest
121+
artifact_name: dotpilot-release-linux
122+
archive_name: dotpilot-desktop-linux.zip
123+
output_path: artifacts/publish/linux
124+
steps:
125+
- uses: actions/checkout@v4
126+
with:
127+
fetch-depth: 0
128+
ref: ${{ needs.prepare_release.outputs.release_tag }}
129+
130+
- name: Install Dependencies
131+
timeout-minutes: 60
132+
uses: "./.github/steps/install_dependencies"
133+
134+
- name: Publish Desktop App
135+
shell: pwsh
136+
run: dotnet publish ./DotPilot/DotPilot.csproj -c Release -f net10.0-desktop -o ./${{ matrix.output_path }}
137+
138+
- name: Archive Desktop Publish Output
139+
shell: pwsh
140+
run: |
141+
New-Item -ItemType Directory -Force -Path ./artifacts/releases | Out-Null
142+
$archivePath = "./artifacts/releases/${{ matrix.archive_name }}"
143+
if (Test-Path $archivePath) {
144+
Remove-Item $archivePath -Force
145+
}
146+
147+
Compress-Archive -Path "./${{ matrix.output_path }}/*" -DestinationPath $archivePath
148+
149+
- name: Upload Release Artifact
150+
uses: actions/upload-artifact@v4
151+
with:
152+
name: ${{ matrix.artifact_name }}
153+
path: ./artifacts/releases/${{ matrix.archive_name }}
154+
if-no-files-found: error
155+
retention-days: 14
156+
157+
create_release:
158+
name: Create GitHub Release
159+
runs-on: ubuntu-latest
160+
needs:
161+
- prepare_release
162+
- publish_desktop
163+
steps:
164+
- uses: actions/checkout@v4
165+
with:
166+
fetch-depth: 0
167+
ref: ${{ needs.prepare_release.outputs.release_tag }}
168+
169+
- name: Fetch Tags
170+
shell: bash
171+
run: git fetch --tags --force
172+
173+
- name: Download Release Artifacts
174+
uses: actions/download-artifact@v4
175+
with:
176+
path: ./artifacts/release-assets
177+
178+
- name: Generate Feature Summary
179+
shell: bash
180+
run: |
181+
python3 ./scripts/release/get_release_summary.py \
182+
--repository '${{ github.repository }}' \
183+
--release-tag '${{ needs.prepare_release.outputs.release_tag }}' \
184+
--previous-tag '${{ needs.prepare_release.outputs.previous_tag }}' \
185+
--output-path ./artifacts/release-summary.md
186+
187+
- name: Publish GitHub Release
188+
shell: bash
189+
env:
190+
GH_TOKEN: ${{ github.token }}
191+
PREVIOUS_TAG: ${{ needs.prepare_release.outputs.previous_tag }}
192+
RELEASE_TAG: ${{ needs.prepare_release.outputs.release_tag }}
193+
RELEASE_VERSION: ${{ needs.prepare_release.outputs.release_version }}
194+
REPOSITORY: ${{ github.repository }}
195+
PRERELEASE: ${{ inputs.prerelease }}
196+
run: |
197+
mapfile -t release_assets < <(find ./artifacts/release-assets -type f -name '*.zip' | sort)
198+
if [[ ${#release_assets[@]} -eq 0 ]]; then
199+
echo "No release assets were downloaded." >&2
200+
exit 1
201+
fi
202+
203+
release_notes="$(cat ./artifacts/release-summary.md)"
204+
release_command=(
205+
gh release create "${RELEASE_TAG}"
206+
"${release_assets[@]}"
207+
--repo "${REPOSITORY}"
208+
--verify-tag
209+
--title "DotPilot ${RELEASE_VERSION}"
210+
--generate-notes
211+
--notes "${release_notes}"
212+
)
213+
214+
if [[ -n "${PREVIOUS_TAG}" ]]; then
215+
release_command+=(--notes-start-tag "${PREVIOUS_TAG}")
216+
fi
217+
218+
if [[ "${PRERELEASE}" == "true" ]]; then
219+
release_command+=(--prerelease)
220+
fi
221+
222+
"${release_command[@]}"

AGENTS.md

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ This file defines how AI agents work in this solution.
1414
- Root `AGENTS.md` holds the global workflow, shared commands, cross-cutting rules, and global skill catalog.
1515
- In multi-project solutions, each project or module root MUST have its own local `AGENTS.md`.
1616
- Local `AGENTS.md` files add project-specific entry points, boundaries, commands, risks, and applicable skills.
17+
- `dotPilot` is a desktop control plane for agents in general. Coding agents are first-class, but repository governance, architecture, and planning must also support research, analysis, orchestration, operator, and mixed-provider agent flows.
1718

1819
## Solution Topology
1920

@@ -129,16 +130,21 @@ For this app:
129130

130131
- unit tests currently use `NUnit` through the default `VSTest` runner
131132
- 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
133+
- a canceled, timed-out, or hanging `DotPilot.UITests` run is a harness failure to fix, not an acceptable substitute for a real pass or fail result in CI
132134
- `format` uses `dotnet format --verify-no-changes`
133135
- 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 GitHub Actions validation pipeline must run in the order `build -> tests -> desktop artifacts` while uploading publish outputs for macOS, Windows, and Linux
136+
- desktop release publishing uses `dotnet publish DotPilot/DotPilot.csproj -c Release -f net10.0-desktop`; the validation workflow stays focused on build and automated tests, while the release workflow owns desktop publish outputs for macOS, Windows, and Linux
135137
- `LangVersion` is pinned to `latest` at the root
136138
- the repo-root lowercase `.editorconfig` is the source of truth for formatting, naming, style, and analyzer severity
137139
- `Directory.Build.props` owns the shared analyzer and warning policy for future projects
138140
- `Directory.Packages.props` owns centrally managed package versions
139141
- `global.json` pins the .NET SDK and Uno SDK version used by the app and tests
140142
- `DotPilot/DotPilot.csproj` keeps `GenerateDocumentationFile=true` with `CS1591` suppressed so `IDE0005` stays enforceable in CI across all target frameworks without inventing command-line-only build flags
141-
- GitHub Actions validation workflows should use a descriptive workflow name instead of the generic `CI`
143+
- GitHub Actions workflows must use descriptive names and filenames that reflect their purpose; do not use a generic `ci.yml` catch-all because build validation and release automation are separate operator flows
144+
- GitHub Actions must be split into at least one validation workflow for normal builds/tests and one release workflow for version bumping, release-note generation, desktop publishing, and GitHub Release publication
145+
- prefer MIT-licensed GitHub and NuGet dependencies when they materially accelerate delivery and align with the current architecture
146+
- prefer official `.NET` AI evaluation libraries under `Microsoft.Extensions.AI.Evaluation*` for response-quality, tool-usage, and safety evaluation instead of custom or third-party evaluation stacks by default
147+
- prefer `Microsoft Agent Framework` telemetry and observability patterns with OpenTelemetry-first instrumentation and optional Azure Monitor or Foundry export later
142148

143149
### Project AGENTS Policy
144150

@@ -315,7 +321,12 @@ Ask first:
315321
- Keep one `.NET` test framework active in the solution at a time unless a documented migration is in progress.
316322
- Validate UI changes through runnable `DotPilot.UITests` on every relevant verification pass, instead of relying only on manual browser inspection or conditional local setup.
317323
- 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.
318-
- Keep the main GitHub Actions workflow name descriptive and keep its job order readable: `Build`, then tests, then desktop artifact publishing.
324+
- Keep validation and release GitHub Actions separate, with descriptive names and filenames instead of a generic `ci.yml`.
325+
- Keep the validation workflow focused on build and automated test feedback, and keep release responsibilities in a dedicated workflow that bumps versioning, publishes desktop artifacts, and creates the GitHub Release with feature notes.
326+
- Keep `dotPilot` positioned as a general agent control plane, not a coding-only shell.
327+
- Reuse the current Uno desktop shell direction instead of replacing it with a wholly different layout when evolving the product.
328+
- Keep provider integrations SDK-first where good typed SDKs already exist.
329+
- Keep evaluation and observability aligned with official Microsoft `.NET` AI guidance when building agent-quality and trust features.
319330

320331
### Dislikes
321332

@@ -324,3 +335,4 @@ Ask first:
324335
- Mixing multiple `.NET` test frameworks in the active solution without a documented migration plan.
325336
- 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.
326337
- Adding extra UI-test orchestration complexity when the actual goal is simply to run the tests and get an honest pass or fail result.
338+
- Planning `MLXSharp` into the first product wave before it is ready for real use.

0 commit comments

Comments
 (0)