Migrate testing to native Microsoft.Testing.Platform and update test packages - #549
Migrate testing to native Microsoft.Testing.Platform and update test packages#549ptr727 wants to merge 1 commit into
Conversation
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. 🗂️ Base branches to auto review (2)
Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Comment |
PR Summary by QodoMigrate tests and coverage collection to native MTP
AI Description
Diagram
High-Level Assessment
Files changed (5)
|
Code Review by Qodo🐞 Bugs (0) 📘 Rule violations (0) 📎 Requirement gaps (0)
Great, no issues found!Qodo reviewed your code and found no material issues that require reviewTip of the day💡 Did you know, you can enable the Remediation agent and Qodo fixes findings in a dedicated fix PR |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## resync/eol-lf #549 +/- ##
=================================================
- Coverage 57.28% 57.01% -0.27%
=================================================
Files 15 15
Lines 1386 1375 -11
Branches 89 108 +19
=================================================
- Hits 794 784 -10
Misses 573 573
+ Partials 19 18 -1 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
🟢 Approval recommended
The changes are small, consistent across docs/tests/CI, and fully remove the incompatible VSTest-based coverage invocation needed for .NET 10 + xunit.v3 4.0.0.
Pull request overview
This PR migrates the repository’s unit test execution from the legacy VSTest-based flow to the native Microsoft.Testing.Platform runner (required for .NET 10 + xunit.v3 4.0.0), unblocking current and future Dependabot NuGet upgrades and restoring CI coverage generation.
Changes:
- Opt into the Microsoft.Testing.Platform runner via
global.json. - Update the test project’s package set for xUnit v3 4.0.0 compatibility (drop VSTest adapter/collector; use
coverlet.MTP). - Update CI to run
dotnet testwith Coverlet MTP arguments and ignore generated coverage artifacts in git.
File summaries
| File | Description |
|---|---|
| global.json | Opts dotnet test into the native Microsoft.Testing.Platform runner. |
| CreateMatrixTests/CreateMatrixTests.csproj | Updates test dependencies for xUnit v3 4.0.0 and switches coverage to coverlet.MTP. |
| AGENTS.md | Documents the repo’s testing/coverage invocation under the native MTP runner. |
| .gitignore | Prevents accidental staging of generated coverage output files. |
| .github/workflows/validate-task.yml | Replaces --collect (VSTest) with MTP-compatible Coverlet flags and preserves Codecov ingestion path. |
Review details
- Files reviewed: 4/5 changed files
- Comments generated: 0
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
…packages xunit.v3 4.0.0 drops the VSTest bridge, so `dotnet test --collect:"XPlat Code Coverage"` fails outright on the .NET 10 SDK with "Testing with VSTest target is no longer supported by Microsoft.Testing.Platform". That is what has been blocking the nuget-deps bumps in #545 and #546, and it blocks every later bump until the runner moves. Follow WORKFLOW.md D1.6 as the hub settled it in ptr727/ProjectTemplate#1111, which chose Microsoft.Testing.Extensions.CodeCoverage over coverlet: - `global.json` opts into the `Microsoft.Testing.Platform` runner. It carries no `sdk` section, so SDK resolution and roll-forward are untouched. - `xunit.runner.visualstudio` is dropped, the VSTest adapter having no role under native MTP. - `coverlet.collector` becomes `Microsoft.Testing.Extensions.CodeCoverage` 18.9.0, whose predecessor's VSTest data collector MTP ignores without failing. The floor is load-bearing rather than cautionary: below 18.1.0 the extension is built against Microsoft.Testing.Platform 1.x and throws a `TypeLoadException` against the 2.x platform xunit.v3 4.0.0 carries, running zero tests while still writing a well-formed Cobertura file that reports full coverage. - The CI unit-test step becomes `dotnet test --coverage --coverage-output-format cobertura --results-directory ./coverage`, then prefixes each report to `coverage-<guid>.cobertura.xml`. Both halves are load-bearing and neither reds the job on its own: `--coverage-output` stays unset so a second test project could not overwrite the first, and the default `<guid>.cobertura.xml` that produces is a name codecov-cli's finder does not match, its patterns being `*coverage*.*` and an exact `cobertura.xml`. Bundle the four package bumps the runner change unblocks: AwesomeAssertions 9.5.0 -> 9.6.0, xunit.analyzers 1.27.0 -> 2.0.0, xunit.v3 3.2.2 -> 4.0.0, and `xunit.runner.visualstudio` removed rather than bumped to 4.0.0. `.gitignore` gains the hub's coverage block. The output was untracked and unignored, so a blanket `git add -A` after a local coverage run would have staged it. Verified against the real invocation, not the documented one: 21 tests ran and passed (not the zero the version-floor trap produces), the extension resolved at 18.9.0 on Microsoft.Testing.Platform 2.3.3, the run wrote `<guid>.cobertura.xml` and the prefix step renamed it as intended, both filename shapes are ignored while nothing tracked is, and the build, CSharpier, `dotnet format style --verify-no-changes`, editorconfig-checker, actionlint, markdownlint and cspell gates are all clean.
355975c to
dc48c3b
Compare
There was a problem hiding this comment.
🟢 Approval recommended
The runner/package/workflow changes are internally consistent (docs, CI invocation, and ignores match) and no remaining --collect/coverlet adapter usage is present in the repo.
Review details
- Files reviewed: 4/5 changed files
- Comments generated: 0 new
- Review effort level: Lite
|
Superseded by #553. GitHub closed this automatically when its base branch #553 is the same branch and the same content, targeting |
…packages (#553) Unblocks the Dependabot nuget PRs (#545, #546) and every later nuget bump. **Replaces #549**, which GitHub closed automatically when its base branch `resync/eol-lf` was deleted on #547's merge. Same branch, same content, same review history on the closed PR. This one targets `develop` directly. The branch carries a `-s ours` merge of `develop` recorded after #547 squashed. That is lossless here and was verified before recording: `git diff origin/develop 2efaeb2` is empty, so the squash reproduced this branch's own ancestor exactly, and that ancestor is reachable from this branch, so `develop` carries nothing the branch lacks. The diff against `develop` is the five files below and nothing else. > Reworked after ptr727/ProjectTemplate#1111 merged. The first revision used > `coverlet.MTP`, which was the open recommendation at the time. The hub has since > settled WORKFLOW.md D1.6 on `Microsoft.Testing.Extensions.CodeCoverage`, and this > PR now follows that instead. ## The problem `xunit.v3` 4.0.0 removed the VSTest bridge, so the CI unit-test step's `dotnet test --collect:"XPlat Code Coverage"` now fails outright on the .NET 10 SDK: ```text error : Testing with VSTest target is no longer supported by Microsoft.Testing.Platform on .NET 10 SDK and later. If you use dotnet test, you should opt-in to the new dotnet test experience. ``` That is what #545 and #546 have been red on, and it blocks every later bump until the runner moves. ## The fix, per WORKFLOW.md D1.6 | Change | Why | | --- | --- | | `global.json` with `{"test":{"runner":"Microsoft.Testing.Platform"}}` | opts into the native MTP runner. No `sdk` section, so SDK resolution and roll-forward are untouched. | | drop `xunit.runner.visualstudio` | the VSTest adapter MTP replaces | | `coverlet.collector` -> `Microsoft.Testing.Extensions.CodeCoverage` 18.9.0 | coverlet's VSTest data collector is ignored under MTP without failing | | CI step -> `dotnet test --coverage --coverage-output-format cobertura --results-directory ./coverage`, then prefix each report to `coverage-<guid>.cobertura.xml` | matches the hub's `validate-task.yml` byte for byte | Three details are load-bearing, and none of them reds the job on its own: - **The 18.9.0 floor.** Below 18.1.0 the extension is built against Microsoft.Testing.Platform 1.x and throws `TypeLoadException` against the 2.x platform xunit.v3 4.0.0 carries. It then runs **zero tests** and still writes a well-formed Cobertura file reporting full coverage. - **`--coverage-output` stays unset.** Pinning one filename would give every test project in a solution the same path, and the last to finish would overwrite the rest. - **The prefix rename.** The default `<guid>.cobertura.xml` that the unset flag produces is a name codecov-cli's finder does not match (its patterns are `*coverage*.*` and an exact `cobertura.xml`), so an unprefixed report uploads nothing while the step still exits green. Package bumps the runner change unblocks: AwesomeAssertions 9.5.0 -> 9.6.0, xunit.analyzers 1.27.0 -> 2.0.0, xunit.v3 3.2.2 -> 4.0.0. `Microsoft.NET.Test.Sdk` stays at 18.9.0 (already current). `.gitignore` gains the hub's dotnet coverage block verbatim. The output was untracked and unignored, so a blanket `git add -A` after a local coverage run would have staged it. ## Verification Against the real invocation, not the documented one: - 21 tests **ran** and passed, which is the check that matters given the zero-test failure mode above. - Resolved graph (from `obj/project.assets.json`, not the csproj text): `Microsoft.Testing.Extensions.CodeCoverage/18.9.0`, `Microsoft.Testing.Platform/2.3.3`, `xunit.v3/4.0.0` with the `mtp-v2` variants. No coverlet, no `xunit.runner.visualstudio`. - The run wrote `bbfde807-....cobertura.xml` and the prefix step renamed it to `coverage-bbfde807-....cobertura.xml`, confirming the rename is genuinely needed rather than defensive. - `git check-ignore` covers both filename shapes; `git ls-files -z | xargs -0 git check-ignore -v` is empty. - `validate-task.yml` is the only `dotnet test` caller; `publish-release.yml` and `test-pull-request.yml` both reach it via `uses:`, so the publish gate and the PR gate move together. No `--collect` survives anywhere. - Build, CSharpier, `dotnet format style --verify-no-changes`, editorconfig-checker, actionlint, markdownlint and cspell all clean. **One thing worth knowing:** the reported coverage number moves, because the engine does. Line rate goes from 0.59 under coverlet to 0.26 here, with lines-valid 1350 -> 3143, since this engine instruments more of the graph. It cannot gate anything: `codecov.yml` sets `informational: true` on both project and patch, and the only ruleset-required check is `Check pull request workflow status job`. ## Notes - Dependabot dual-targets `develop` and `main`, so #546 (the `main` copy) stays blocked until this reaches `main` via the promotion PR. `main`'s tree is not broken in the meantime, it just cannot take the bump. - The fleet audit flags this repo's local `validate-task.yml` as `hub-only`. Now that ptr727/ProjectTemplate#1111 has landed MTP support in the hub's reusable workflow, that migration is unblocked, but it is a separate interface change covering five workflow files and belongs in its own PR rather than here. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Improvements** * Improved automated test execution and code coverage reporting in continuous integration. * Coverage reports are now generated in a standardized format for more reliable analysis. * **Documentation** * Added guidance for running tests locally and understanding coverage validation. * **Chores** * Updated testing tools and configuration to use the modern test platform. * Added rules to keep generated test and coverage files out of source control. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
…nfig (#550) The mechanical half of the ProjectTemplate resync. Audit run `2026-08-30T03:26:30Z | hub a378121`, re-measured against hub `f3b4cc9`. Stacked on #549 (which is stacked on #547), so this PR is based on `resync/dotnet-mtp` and will retarget as its parents merge. Its own diff is the five items below. ## What changed **`.github/skills/` (37 files), carried whole.** A manifest-owned tree, applied with the hub's own `scripts/carry.py apply` rather than by hand. `carry.py check` now reports `sourceDigest == targetDigest == c5475deb46bfbf1f9253bc6128a40b7686687597ebe38a6cd1c580a39817f03e` with `extra`, `missing` and `modified` all empty, so this is the hub's content byte for byte. **`host-tools.json`**, the repo's own tighten-only overlay on the fleet host-tool declaration. The `tools` list is empty because this repo needs nothing the fleet declaration does not already carry, and the file is present anyway so the declaration is somewhere a reader can find rather than somewhere they have to know to look. The hub's `$schema` pointer is deliberately not carried: it is a relative path to a hub-only schema, and the hub's own note instructs a copying repo to leave it behind. **`.markdownlint-cli2.jsonc`** re-vendored whole, it being `verbatim` fidelity. The only real change is two comment lines, `markdown` -> `Markdown`. **`.editorconfig-checker.json`** takes the hub's `Exclude` list. The entries are Python cache directories, inert here, carried whole per the fleet's config-carry model. `Exclude` is additive to the tool's built-in defaults, so it can only narrow the scan, never widen it. The `Disable` block is untouched. **`cspell.json` becomes the single source of truth.** It is now the union of three lists: the hub's 134 words, this repo's existing 164, and the 97-word `cSpell.words` block that lived in `NxWitness.code-workspace`, 29 of which existed nowhere else. That workspace block is deleted, per CODESTYLE.md "Markdown and Spelling". ## Verification - Set-checked the word union against all three sources: **zero words dropped**, zero extras not traceable to a source, zero exact duplicates. Every non-`words` key (`version`, `language`, `ignorePaths`, `ignoreRegExpList`) preserved with its value and position. The original carried no JSONC comment to lose. - `NxWitness.code-workspace` still parses as JSONC. Diffing the parsed objects before and after, `settings` differs by exactly one removed key and nothing else; `folders` and `extensions` are identical. The `streetsidesoftware.code-spell-checker` recommendation is retained, so the editor still reads `cspell.json` from the workspace root. - `.markdownlint-cli2.jsonc` byte-matches the hub, as `verbatim` requires. - `host_gate.py --repo <this checkout>` returns `0 issue(s) over 8 declared tool(s)`, and the file validates against the hub's `spec/host-tools-local.schema.json`, which marks `$schema` optional. - markdownlint clean across all 45 markdown files (up from 8), cspell clean at the CI scope, editorconfig-checker clean, every touched JSON/JSONC file parses, and no tracked file carries a CR. ## Deliberately not in this PR Three audit findings are real but do not belong to the mechanical class, and one is not a defect at all: - **The `AGENTS.md` split** into `CLAUDE.md`, `GOVERNANCE.md`, `ARCHITECTURE.md` and `OPERATIONS.md`. A distinctive-phrase probe against the hub canonical found that this repo's `AGENTS.md` predates the router split and mixes stale fleet law with substantial local content, including the entire "Template adaptations" record of deliberate deviations. Re-vendoring over it would delete that silently, which is the exact incident the fleet's `carried-instruction-file-guard` exists to prevent. That needs its own PR and its own review. - **The `repo-config/` retirement.** `spec/divergences.json` marks the whole tree `retire`, but the deletion owes a tree-wide reference sweep, and the live inbound references are in `AGENTS.md` and `WORKFLOW.md`, both of which the split PR rewrites. Doing the deletion here would edit those files twice. - **README structure** (10 letter-class findings). Content work, grouped with the doc PR. - **The two `interface` findings are not drift to fix.** `publish-release.yml` "missing required job `publish`" and `merge-bot-pull-request.yml` "missing required job `merge-bot`" both resolve to *calling a hub-hosted task workflow* (`build-release-task.yml`, `merge-bot-task.yml`) that this repo has not adopted. `spec/divergences.json` states adoption "is a separate, later change per repo". This repo's multi-image, shared-base fan-out is a documented deviation, so renaming jobs to satisfy the checker would misreport the state rather than fix it. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Documentation** * Added guidance for repository setup, coding standards, testing, reviews, releases, worktrees, contributions, host tools, and instruction preservation. * Added references for Markdown links, line endings, project configuration, testing, release publishing, and workflow guarantees. * **Maintenance** * Expanded spelling and Markdown terminology coverage. * Excluded Python caches and virtual environments from configuration checks. * Added a repository-level host-tools configuration placeholder. * Removed the workspace-specific spelling dictionary. * **Security** * Restricted validation workflows to read-only repository permissions. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
…551) The judgment half of the ProjectTemplate resync: the `AGENTS.md` split, and the `repo-config/` retirement that depends on it. Stacked on #550 (which is stacked on #549 and #547), so this PR is based on `resync/hub-conformance` and will retarget as its parents merge. ## Why this is not a re-vendor This repo's `AGENTS.md` predated the hub's `AGENTS.md`/`GOVERNANCE.md` router split, so it held two different things in one 243-line file: stale copies of fleet law, and local rules written for faults the fleet has not seen elsewhere. Copying the hub canonical over it would have deleted the second kind silently, with no error and nothing in the diff that looks wrong. That is the exact incident the fleet's `carried-instruction-file-guard` exists to prevent. So every unit was probed by distinctive phrase against the hub canonical first, and each one that turned out to be local got a destination rather than a deletion. A 29-phrase preservation checklist taken from the pre-split file confirms every unit has a home. ## What moved where | | | | --- | --- | | `AGENTS.md` | 243 lines -> 115. Only the three declared sections, all three byte-identical to the hub. | | `CLAUDE.md` | New, byte-matches the hub. Claude Code reads `CLAUDE.md` and never `AGENTS.md`, so without it that provider had no rules at all. | | `GOVERNANCE.md` | New, 21 sections. The 18 verbatim ones byte-match the hub; `Devcontainer` and `Repository Layout` are intent-fidelity and written for this repo. | | `ARCHITECTURE.md` | New. Product and variant matrix, codegen data flow, base/derived image relationship, CI pipeline with its do-not-reintroduce list, and the Template Adaptations record. | | `OPERATIONS.md` | New. The six mandated headings, `Local Verification` first. | | `CODESTYLE.md` | Gains the encoding rule and the human-authored-comment rule, both stated in the old `AGENTS.md`. | **`Where the Rules Live` is carried unedited.** The first draft added two table rows pointing at the new docs. That section is declared `verbatim`, and `spec/fidelity-model.md` normalizes only line endings, action pins and job `needs:`, so those rows would have made it modified fixed content with no disposition on file, rendering UNTRIAGED in the divergence report. The two docs are routed from the preamble instead, which is not a declared section. **The Template Adaptations record is the piece that most needed preserving.** All ten bullets survive. Without them, every one of this repo's deliberate deviations from the fleet template reads as unexplained drift to the next audit. **Two rules were nearly lost and are restored.** "Leave human-authored comments exactly as written" is now a `CODESTYLE.md` item, and it matters because the carried comment rules push the other way: they tell an agent to collapse a short two-line comment, with nothing telling it to leave a maintainer's alone. The encoding rule survived only as `.editorconfig`'s `charset` and is now stated. **One claim the old file carried is false and is corrected, not copied.** "Linting is editor-only (no CI lint job)" is contradicted by `validate-task.yml`, which runs markdownlint, cspell, actionlint and editorconfig-checker inside the required check. `OPERATIONS.md` says what actually runs. ## The `repo-config/` retirement `spec/divergences.json` marks the payloads, the script and the reference as hub-hosted, so this repo reaches them rather than carrying a copy that drifts. The deletion swept every inbound reference: - six sites in `WORKFLOW.md`, which now name the behavior and the hub-hosted command instead of a local path, - a comment in `test-pull-request.yml`, - and the `Repo Config` solution folder in `NxWitness.slnx`, which would otherwise have shown five missing files in Visual Studio while `dotnet sln list` stayed silent about it. ## Pointers that moved with the sections Splitting a file moves the anchors other files point into, so those move too: four anchors in `.github/copilot-instructions.md` and three in `CODESTYLE.md` now resolve to `GOVERNANCE.md`, `WORKFLOW.md`'s D3.3 aside names the section that holds the rule, and `publish-release.yml`'s comment names `ARCHITECTURE.md`. `.github/copilot-instructions.md` also gains its declared `Reviewing Carried Fleet Content` section, and its closing paragraph states the behavior rather than naming the template repo and an anchor that no longer exists, which closes the audit's `carried:` finding against that file. ## Verification - The 29-phrase preservation checklist: every unit has a home. - All three `AGENTS.md` sections, all 18 verbatim `GOVERNANCE.md` sections, and `CLAUDE.md` byte-match the hub. Only the two declared-`intent` sections differ. - `OPERATIONS.md` carries exactly the six mandated headings in the mandated order, each with content. - `NxWitness.slnx` still parses as XML and the solution still builds clean. - Every relative Markdown link in a changed file resolves. - No `repo-config/` reference survives outside carried hub content that legitimately means the hub's own copy. - markdownlint (48 files), cspell, editorconfig-checker and actionlint all clean. ## Known, not fixed here `README.md` has a pre-existing broken relative link (`./LSIO/etc/s6-overlay/s6-rc.d/init-nx-relocate/run`). It is untouched by this commit and belongs with the README-structure work, which is the last audit class still open. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **Documentation** - Added architecture and operations guides covering products, build workflows, verification, CI/CD, troubleshooting, and recovery. - Added governance guidance for repository standards, releases, security, reviews, tooling, and supported platforms. - Added a Claude Code entry point and updated contributor guidance, workflow documentation, and coding standards. - Expanded the spelling dictionary with project-specific terminology. - **Chores** - Moved repository-configuration references from local files to centrally maintained configuration. - Removed obsolete repository configuration files and solution-folder entries. - Updated workflow comments and documentation links to reflect the new structure. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
The last audit class: eleven `readme-structure` findings. Audit run `2026-08-30T03:26:30Z | hub a378121`. Stacked on #551, so this PR is based on `resync/docs-split` and will retarget as its parents merge. ## The eleven findings | Finding | Fix | | --- | --- | | H1 is not the repo name | `# NxWitness` | | Tagline carries Markdown links | Link-free plain text, one sentence, 72 chars. The original sentence survives as the free prose below it, where links are allowed. | | No `## Questions or Issues` | Added. Carries the support routing moved out of `## Troubleshooting`, which keeps its own subsections. | | No `## 3rd Party Tools` | Added. The fleet's fixed lead line, then 23 entries alphabetized. | | No `### Releases` | Added under Build and Distribution, with the base class's GitHub release and pre-release shields plus the 40 Docker version shields moved up from the old `## Releases`. | | `[license-link]` points at a repo path | `[license]`, bare, since an in-repo path takes no suffix. | | Ten `[hub<name>-link]` references | Renamed to `<target>-docker-hub-link`, the shape that covers a repo shipping one image and one shipping ten. | | 161 definitions ungrouped | Grouped under the five declared headers in spec order, sorted by label within each. | The tagline is also mirrored into `HISTORY.md`, which the spec requires and which the old pair could never satisfy at once, since the shared sentence carried a Markdown link. Its now-orphaned `networkoptix-link` definition goes with it. For the tool list, every tool the hub catalogs uses the catalog's link and description verbatim; the rest are described as what the tool is rather than as what this repo does with it. ## Defects found while restructuring - The NxGo-LSIO install bullet linked the **Nx Witness** LSIO image. - The Products list linked **Wisenet WAVE** at `dwspectrum.com`. - A display filename read `Test.yaml` where the file is `Test.yml`. - `./LSIO/etc/s6-overlay/s6-rc.d/init-nx-relocate/run` resolved to nothing. Fixing the README alone would have been a symptom fix: `CreateMatrix/Dockerfile.cs` emits that comment into every LSIO Dockerfile, so the next codegen run reproduces it. The generator and the five generated files now name `Docker/s6-overlay/...`. Those files carry only that comment change; the upstream version bump a full regeneration also produces belongs to the codegen bot. - `Docker/README.md`, the Docker Hub overview, still opened with the retired title and tagline, so it disagreed with every other surface about the project's name. - A spaced hyphen joining two clauses, which the character-set rule bans in the same terms as an em dash. ## A correction to #549's stated verification `OPERATIONS.md` asserted that the local test command is plain `dotnet test`. That is unverified and false on at least one machine: a pristine checkout of the migration commit reports `Zero tests ran` and exit 5 there, while CI runs the same command on the same SDK (10.0.400, runtime 10.0.11) and reports 21 passed. My earlier local "21/21" came from a build tree still carrying state from the coverlet configuration it replaced. The configuration is correct, and CI is the evidence. The runbook now states the invocation CI actually runs as the one to reproduce locally, says that an MTP run discovering nothing exits 5 rather than passing silently so the count is what to read, and names the direct `dotnet CreateMatrixTests/bin/Debug/net10.0/CreateMatrixTests.dll` run as the way to separate a driver problem from a test-project problem. The `net10.0` versus `net10.0|x64` target string is the tell. Filed upstream as ptr727/ProjectTemplate#1122, since D1.6 governs this for the whole fleet and the remaining dotnet repos will hit it. ## Verification - Every label has a definition and every definition is used, 161 of 161, no duplicates. Every relative target exists, every in-page anchor resolves, the five group headers appear in spec order with labels sorted within each. - The Table of Contents matches the actual headings one for one, in order. - The ten image names match `Make/Matrix.json`; the base images match the two base Dockerfiles. - Build clean, markdownlint (48 files), cspell, editorconfig-checker and actionlint clean, no new cspell word needed. ## The 2.15 release is now documented This started as "reported, not fixed", and changed after the maintainer ruled on it. Recording the sequence, because the PR title does not suggest a release-notes change. `version.json` has declared 2.15 since 2026-06-29 and releases 2.15.43 through 2.15.59 have published since 2026-07-27, but neither `HISTORY.md` nor the README's Release Notes ever gained an entry, so both still described 2.14 as current. The bump came from #461, a large CI/CD migration that listed `version floor 2.14 -> 2.15` as one line item and added no changelog entry. The entry is derived rather than invented. Reading every merge between the 2.14 entry and now, 2.15 is the branch-scoped triggered-Docker CI/CD migration, the Codecov upload, multi-arch on `main` only, the lint-architecture standardization, and workflow hygiene. Nothing in it changes a published image, and the entry says exactly that rather than dressing infrastructure work up as a product release: ```text - Version 2.15: - Build, CI, and repository tooling changes only. No functional change to the published images. ``` **The floor is not rolled back**, per the maintainer: forward only once a release is cut. That is also the only mechanically safe answer, since NBGV derives the patch from git height, so a lower floor would generate versions sorting below what is already published. #437 could revert a bump cleanly because nothing had shipped at it; that window is closed here. The wider question, that agents have moved this repo's floor five times under a develop-leads-main cadence the fleet has since retired, is filed as ptr727/ProjectTemplate#1124 rather than addressed here. ## Reported, not fixed - The GitHub About description still carries the retired sentence. It feeds the Docker Hub short description through the docker-readme task, so that surface will disagree with the README until it is set by hand. `registry/repos.json` declares no `description` for this repo, so `configure.sh apply` cannot write it. - `HISTORY.md`'s 2.11 entry carries a lowercase `docker` in prose. It is a shipped changelog record rather than current prose, so it was left rather than edited for casing. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Documentation** * Expanded setup, installation, image variants, release channels, publishing, build workflows, troubleshooting, and support guidance. * Clarified supported NxWitness and OEM-branded VMS products. * Added testing, diagnostics, architecture checks, and coverage instructions. * Updated release history for version 2.15, corrected links, and removed an obsolete reference. * **Chores** * Updated documentation references for relocated runtime initialization paths. * Improved spell-check dictionary consistency. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
Unblocks the Dependabot nuget PRs (#545, #546) and every later nuget bump.
Stacked on #547, so this PR is based on
resync/eol-lfand will retarget todevelopautomatically once #547 merges. Its own diff is the five files below.The problem
xunit.v34.0.0 removed the VSTest bridge, so the CI unit-test step'sdotnet test --collect:"XPlat Code Coverage"now fails outright on the .NET 10SDK:
That is what #545 and #546 have been red on, and it blocks every later bump until
the runner moves.
The fix, per WORKFLOW.md D1.6
global.jsonwith{"test":{"runner":"Microsoft.Testing.Platform"}}sdksection, so SDK resolution and roll-forward are untouched.xunit.runner.visualstudiocoverlet.collector->Microsoft.Testing.Extensions.CodeCoverage18.9.0dotnet test --coverage --coverage-output-format cobertura --results-directory ./coverage, then prefix each report tocoverage-<guid>.cobertura.xmlvalidate-task.ymlbyte for byteThree details are load-bearing, and none of them reds the job on its own:
Microsoft.Testing.Platform 1.x and throws
TypeLoadExceptionagainst the 2.xplatform xunit.v3 4.0.0 carries. It then runs zero tests and still writes a
well-formed Cobertura file reporting full coverage.
--coverage-outputstays unset. Pinning one filename would give every testproject in a solution the same path, and the last to finish would overwrite the
rest.
<guid>.cobertura.xmlthat the unset flagproduces is a name codecov-cli's finder does not match (its patterns are
*coverage*.*and an exactcobertura.xml), so an unprefixed report uploadsnothing while the step still exits green.
Package bumps the runner change unblocks: AwesomeAssertions 9.5.0 -> 9.6.0,
xunit.analyzers 1.27.0 -> 2.0.0, xunit.v3 3.2.2 -> 4.0.0.
Microsoft.NET.Test.Sdkstays at 18.9.0 (already current)..gitignoregains the hub's dotnet coverage block verbatim. The output wasuntracked and unignored, so a blanket
git add -Aafter a local coverage runwould have staged it.
Verification
Against the real invocation, not the documented one:
zero-test failure mode above.
obj/project.assets.json, not the csproj text):Microsoft.Testing.Extensions.CodeCoverage/18.9.0,Microsoft.Testing.Platform/2.3.3,xunit.v3/4.0.0with themtp-v2variants.No coverlet, no
xunit.runner.visualstudio.bbfde807-....cobertura.xmland the prefix step renamed it tocoverage-bbfde807-....cobertura.xml, confirming the rename is genuinelyneeded rather than defensive.
git check-ignorecovers both filename shapes;git ls-files -z | xargs -0 git check-ignore -vis empty.validate-task.ymlis the onlydotnet testcaller;publish-release.ymlandtest-pull-request.ymlboth reach it viauses:, so the publish gate and thePR gate move together. No
--collectsurvives anywhere.dotnet format style --verify-no-changes,editorconfig-checker, actionlint, markdownlint and cspell all clean.
One thing worth knowing: the reported coverage number moves, because the
engine does. Line rate goes from 0.59 under coverlet to 0.26 here, with
lines-valid 1350 -> 3143, since this engine instruments more of the graph. It
cannot gate anything:
codecov.ymlsetsinformational: trueon both projectand patch, and the only ruleset-required check is
Check pull request workflow status job.Notes
developandmain, so Bump AwesomeAssertions and 3 others #546 (themaincopy) staysblocked until this reaches
mainvia the promotion PR.main's tree is notbroken in the meantime, it just cannot take the bump.
validate-task.ymlashub-only.Now that Promote develop to main ProjectTemplate#1111 has landed MTP support in the hub's
reusable workflow, that migration is unblocked, but it is a separate interface
change covering five workflow files and belongs in its own PR rather than here.