From 20a1e5fc6c78132c4f80a78a507c9ec77ae8a9ce Mon Sep 17 00:00:00 2001 From: Alexandre Zollinger Chohfi Date: Fri, 25 Sep 2026 15:55:51 -0700 Subject: [PATCH 1/3] Run the packaged template smoke on framework changes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR #1277 replaced the deleted CreateTemplateTests with a packaged scaffold → build → launch smoke in the Bootstrap job, which asserts what no other suite does: that the loose-layout MSIX registers, the app activates with identity, and the Reactor UI renders. Every other suite runs unpackaged. But that job is path-filtered, and `src/Reactor/**` was not in the list — so the smoke only ran when bootstrap's own inputs changed. The test it replaced lived in Reactor.IntegrationTests, gated on `non-md`, so it ran on any framework change. Coverage did not disappear, but its reach narrowed: a framework regression that broke packaged startup, identity activation or first render would not have been caught. Adds `src/Reactor/**` and `src/Reactor.Devtools/**`. Devtools is not incidental — the scaffolded template references both packages at `$ReactorVersion$` (verified in the shipped template's ProjectTemplate.csproj), and CI builds the app against the source-built 0.0.0-local packages, so a Devtools break fails the smoke too. Also excludes markdown, so a doc-only edit to one of the three .md files now inside those paths doesn't spin a 12-minute job. Negations are order-sensitive and kept last; a PR touching both a .cs and a .md still runs. Verified by modelling GitHub's filter semantics over eight cases: framework, devtools and bootstrap inputs trigger; doc-only under those paths does not; mixed .cs + .md still triggers; unrelated docs, tests and samples do not. Found via a cross-repo review from the WindowsAppSDK side, which noted that the upstream template harness builds every App template with `-p:WindowsPackageType=None` (dev/Templates/Dotnet/Test-DotnetNewTemplates.ps1 line 370) and launches the raw exe rather than `dotnet run` — so packaging is validated in neither repo by that path. Reactor does own it, via this job; it just wasn't watching the input most likely to break it. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: b893b2b8-78f8-46c6-9227-515e1dc3a563 --- .github/workflows/bootstrap.yml | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/.github/workflows/bootstrap.yml b/.github/workflows/bootstrap.yml index 76b6e7e00..0b46045cd 100644 --- a/.github/workflows/bootstrap.yml +++ b/.github/workflows/bootstrap.yml @@ -13,20 +13,35 @@ on: - 'bootstrap.ps1' - 'tools/BootstrapFeedResolver.ps1' - 'src/Reactor.Cli/**' + # The scaffolded TestApp is built and launched by this job's packaged + # smoke, against the source-built 0.0.0-local packages. The template + # references Microsoft.UI.Reactor and Microsoft.UI.Reactor.Devtools (both + # at $ReactorVersion$), so a change to either can break packaged startup, + # identity activation or first render without failing any other job — + # every other suite runs unpackaged. + - 'src/Reactor/**' + - 'src/Reactor.Devtools/**' - 'Directory.Build.props' - 'Directory.Build.targets' - 'Directory.Packages.props' - '.github/workflows/bootstrap.yml' + # Nothing markdown should spin a 12-minute bootstrap. Negations are + # order-sensitive and must stay last: a PR touching both a .cs and a .md + # under src/Reactor still matches on the .cs and runs, which is correct. + - '!**/*.md' push: branches: [main] paths: - 'bootstrap.ps1' - 'tools/BootstrapFeedResolver.ps1' - 'src/Reactor.Cli/**' + - 'src/Reactor/**' + - 'src/Reactor.Devtools/**' - 'Directory.Build.props' - 'Directory.Build.targets' - 'Directory.Packages.props' - '.github/workflows/bootstrap.yml' + - '!**/*.md' workflow_dispatch: # Cancel in-progress runs against the same ref when a new push arrives. From f4fcae9c90df3735db572e2943889726c41354b0 Mon Sep 17 00:00:00 2001 From: Alexandre Zollinger Chohfi Date: Fri, 25 Sep 2026 16:10:19 -0700 Subject: [PATCH 2/3] Add Reactor.Advanced, and stop overstating the gap MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Copilot review on #1289 — both findings correct. Reactor.Devtools project-references Reactor.Advanced, and the scaffolded template references Devtools, so an Advanced change flows into the package graph this smoke builds and runs. Added to both trigger lists; verified the reference in src/Reactor.Devtools/Reactor.Devtools.csproj rather than assuming it from the pack-local output. The comment also claimed "every other suite runs unpackaged", which is wrong: ci.yml's Packaged Selftests run the in-repo host under MSIX identity on every non-md change. Reworded to state the actual, narrower gap — the *scaffolded template* path: a fresh app from the external template pack, built against local packages, registering and rendering. That is what no other job covers. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: b893b2b8-78f8-46c6-9227-515e1dc3a563 --- .github/workflows/bootstrap.yml | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/.github/workflows/bootstrap.yml b/.github/workflows/bootstrap.yml index 0b46045cd..807c44cfd 100644 --- a/.github/workflows/bootstrap.yml +++ b/.github/workflows/bootstrap.yml @@ -16,11 +16,18 @@ on: # The scaffolded TestApp is built and launched by this job's packaged # smoke, against the source-built 0.0.0-local packages. The template # references Microsoft.UI.Reactor and Microsoft.UI.Reactor.Devtools (both - # at $ReactorVersion$), so a change to either can break packaged startup, - # identity activation or first render without failing any other job — - # every other suite runs unpackaged. + # at $ReactorVersion$), and Reactor.Devtools project-references + # Reactor.Advanced — so a change under any of the three can break the + # scaffolded app's restore, packaged startup, identity activation or + # first render. + # + # Narrower than "packaged testing" in general: ci.yml's Packaged Selftests + # already run the in-repo host under MSIX identity on every non-md change. + # What only this job covers is the *scaffolded template* path — a fresh + # app from the external template pack, built against local packages. - 'src/Reactor/**' - 'src/Reactor.Devtools/**' + - 'src/Reactor.Advanced/**' - 'Directory.Build.props' - 'Directory.Build.targets' - 'Directory.Packages.props' @@ -37,6 +44,7 @@ on: - 'src/Reactor.Cli/**' - 'src/Reactor/**' - 'src/Reactor.Devtools/**' + - 'src/Reactor.Advanced/**' - 'Directory.Build.props' - 'Directory.Build.targets' - 'Directory.Packages.props' From 3fbcd62310f2032b762b00ee028b16b1d6d279fa Mon Sep 17 00:00:00 2001 From: Alexandre Zollinger Chohfi Date: Fri, 25 Sep 2026 16:16:34 -0700 Subject: [PATCH 3/3] Invert the src/ filter: default-on, minus what cannot matter MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Copilot review round 2 on #1289. The finding is right, and understates itself: Reactor.csproj project-references six projects whose output is packed into the Microsoft.UI.Reactor package consumers compile against — Analyzers, Analyzers.Internal, and the Localization / Wrappers / SourceMap generators, plus Wrappers.Abstractions. The review listed five; Analyzers.Internal is referenced too. The deeper problem is the shape, not the contents. Counting Reactor itself, Devtools (referenced by the template), Advanced (project-referenced by Devtools) and the CLI, that is 10 of the 14 projects under src/. My allowlist had already drifted twice inside this one PR — it shipped without Advanced, then without those six — and each miss is invisible: it surfaces as a packaged regression nobody caught, never as a red build. So the filter is now `src/**` minus the four that cannot affect a scaffolded app: Reactor.Compile.Analyzer, Reactor.Interop.WinForms, vs-reactor, vscode-reactor. A generator added to Reactor.csproj tomorrow is covered by default; the failure mode becomes an occasional unnecessary 12-minute run rather than a silent hole, which is the right way round for this job. Verified over 19 cases, 0 mismatches: all ten package inputs trigger; the four excluded projects, markdown, docs, tests and samples do not; a mixed .cs + .md change still runs. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: b893b2b8-78f8-46c6-9227-515e1dc3a563 --- .github/workflows/bootstrap.yml | 43 ++++++++++++++++++++------------- 1 file changed, 26 insertions(+), 17 deletions(-) diff --git a/.github/workflows/bootstrap.yml b/.github/workflows/bootstrap.yml index 807c44cfd..204a41a0c 100644 --- a/.github/workflows/bootstrap.yml +++ b/.github/workflows/bootstrap.yml @@ -12,43 +12,52 @@ on: paths: - 'bootstrap.ps1' - 'tools/BootstrapFeedResolver.ps1' - - 'src/Reactor.Cli/**' + # Default-on for src/, rather than an allowlist of package inputs. + # # The scaffolded TestApp is built and launched by this job's packaged - # smoke, against the source-built 0.0.0-local packages. The template - # references Microsoft.UI.Reactor and Microsoft.UI.Reactor.Devtools (both - # at $ReactorVersion$), and Reactor.Devtools project-references - # Reactor.Advanced — so a change under any of the three can break the - # scaffolded app's restore, packaged startup, identity activation or - # first render. + # smoke against the source-built 0.0.0-local packages. Its inputs are + # wider than they look: the template references Microsoft.UI.Reactor and + # Microsoft.UI.Reactor.Devtools, Devtools project-references + # Reactor.Advanced, and Reactor.csproj packs six more projects into the + # package consumers compile against (Analyzers, Analyzers.Internal, the + # Localization/Wrappers/SourceMap generators, Wrappers.Abstractions). + # That is 10 of the 14 projects under src/, and an allowlist of them + # drifts silently every time one is added — a miss shows up as a + # packaged regression nobody caught, not as a red build. + # + # So: include src/ and subtract the four that cannot affect the + # scaffolded app. Negations are order-sensitive and must stay last. # # Narrower than "packaged testing" in general: ci.yml's Packaged Selftests # already run the in-repo host under MSIX identity on every non-md change. # What only this job covers is the *scaffolded template* path — a fresh # app from the external template pack, built against local packages. - - 'src/Reactor/**' - - 'src/Reactor.Devtools/**' - - 'src/Reactor.Advanced/**' + - 'src/**' - 'Directory.Build.props' - 'Directory.Build.targets' - 'Directory.Packages.props' - '.github/workflows/bootstrap.yml' - # Nothing markdown should spin a 12-minute bootstrap. Negations are - # order-sensitive and must stay last: a PR touching both a .cs and a .md - # under src/Reactor still matches on the .cs and runs, which is correct. + - '!src/Reactor.Compile.Analyzer/**' + - '!src/Reactor.Interop.WinForms/**' + - '!src/vs-reactor/**' + - '!src/vscode-reactor/**' + # Nothing markdown should spin a 12-minute bootstrap. A PR touching both + # a .cs and a .md under src/ still matches on the .cs and runs. - '!**/*.md' push: branches: [main] paths: - 'bootstrap.ps1' - 'tools/BootstrapFeedResolver.ps1' - - 'src/Reactor.Cli/**' - - 'src/Reactor/**' - - 'src/Reactor.Devtools/**' - - 'src/Reactor.Advanced/**' + - 'src/**' - 'Directory.Build.props' - 'Directory.Build.targets' - 'Directory.Packages.props' - '.github/workflows/bootstrap.yml' + - '!src/Reactor.Compile.Analyzer/**' + - '!src/Reactor.Interop.WinForms/**' + - '!src/vs-reactor/**' + - '!src/vscode-reactor/**' - '!**/*.md' workflow_dispatch: