Skip to content

Limit template update checks to once a day for winapp new - #757

Open
Zach Teutsch (zateutsch) wants to merge 4 commits into
mainfrom
zateutsch-754-template-update-limit
Open

Limit template update checks to once a day for winapp new#757
Zach Teutsch (zateutsch) wants to merge 4 commits into
mainfrom
zateutsch-754-template-update-limit

Conversation

@zateutsch

Copy link
Copy Markdown
Contributor

Summary

winapp new ran the WinUI template-pack staleness check (dotnet new update --check-only, a NuGet feed round-trip) on every invocation, adding a few seconds of latency each time. Listing templates and then immediately scaffolding paid that cost twice.

This throttles the feed check to at most once a day, following the same pattern UpdateNotificationService already uses for the CLI self-update notice. Between checks, the last result is reused, so back-to-back new runs are fast.

What changed

  • New TemplateUpdateCheckThrottle service (ITemplateUpdateCheckThrottle + impl) that persists a hidden .template-update-check file in the global winapp directory (timestamp, installed pack version, last-seen latest version).
  • NewCommand (Default version mode) now reuses a cached result when a check ran within the last 24h against the same installed pack version; otherwise it performs the feed check and records the result. Update prompts for a stale pack still fire — only the redundant network latency is removed.
  • The cache is keyed on the installed pack version, so if the pack changes the stale cached "latest" is discarded and a fresh check runs.

Behavior notes

  • A failed feed check (offline, non-zero exit) is not cached — the next run retries rather than suppressing update detection for a day.
  • --template-version latest still forces the newest pack immediately, bypassing the throttle.
  • No new commands, options, or flags; no CLI schema/doc surface changed. The throttle logs only at Debug, so default/--verbose/--quiet/--json output is unaffected.

Testing

  • New unit tests for the throttle: freshness window, expiry after the interval, version-keyed invalidation, up-to-date reuse, hidden-file persistence.
  • New NewCommand handler tests: recent cache skips the feed check (while still offering an available update), up-to-date cache skips both check and install, and a failed check is not cached.
  • dotnet build clean; template/handler tests (67) and AtomicFile tests (5) all pass.

Review follow-ups (already applied)

  • Only cache checks that actually reached the feed, so a transient failure retries next run instead of being cached as "up-to-date" for 24h.
  • Route the cache write through a new AtomicFile.WriteAllText helper instead of a hand-rolled temp+move, removing duplicated atomic-write logic and a shared-temp-name collision risk.

The 'new' command ran 'dotnet new update --check-only' (a NuGet feed round-trip) on every invocation, adding latency to each run. Introduce TemplateUpdateCheckThrottle, mirroring UpdateNotificationService's .update-check pattern, so the staleness check runs at most once per day and reuses the cached result otherwise.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 314ff851-0510-4289-b605-a545cfb453a2
M1 (correctness): GetLatestAvailableVersionAsync now reports whether the feed check actually succeeded, and NewCommand only records the throttle result on success. A transient 'dotnet new update --check-only' failure is no longer cached as 'up-to-date', so the next run retries instead of suppressing update detection for 24h.

L1 (dedup): route the throttle's cache write through a new AtomicFile.WriteAllText helper instead of a hand-rolled fixed-'.tmp' temp+move, removing duplicated atomic-write logic and the shared-temp collision risk.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 314ff851-0510-4289-b605-a545cfb453a2
Comment thread src/winapp-CLI/WinApp.Cli/Services/TemplateUpdateCheckThrottle.cs Fixed
Comment thread src/winapp-CLI/WinApp.Cli/Services/TemplateUpdateCheckThrottle.cs Fixed
Comment thread src/winapp-CLI/WinApp.Cli/Services/TemplateUpdateCheckThrottle.cs Fixed
Comment thread src/winapp-CLI/WinApp.Cli.Tests/TemplateUpdateCheckThrottleTests.cs Fixed
Comment thread src/winapp-CLI/WinApp.Cli/Services/TemplateUpdateCheckThrottle.cs Fixed
Comment thread src/winapp-CLI/WinApp.Cli.Tests/NewCommandHandlerTests.cs Fixed
Comment thread src/winapp-CLI/WinApp.Cli.Tests/NewCommandHandlerTests.cs Fixed
Comment thread src/winapp-CLI/WinApp.Cli.Tests/TemplateUpdateCheckThrottleTests.cs Fixed
Comment thread src/winapp-CLI/WinApp.Cli.Tests/TemplateUpdateCheckThrottleTests.cs Fixed
@github-actions

github-actions Bot commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

Build Metrics Report

Binary Sizes

Artifact Baseline Current Delta
CLI (ARM64) 38.62 MB 38.62 MB 📉 -3.0 KB (-0.01%)
CLI (x64) 38.74 MB 38.73 MB 📉 -3.0 KB (-0.01%)
MSIX (ARM64) 16.02 MB 16.02 MB 📈 +1.7 KB (+0.01%)
MSIX (x64) 17.02 MB 17.01 MB 📉 -4.4 KB (-0.03%)
NPM Package 33.42 MB 33.42 MB 📉 -1.9 KB (-0.01%)
NuGet Package 33.46 MB 33.46 MB 📉 -4.1 KB (-0.01%)

Test Results

4586 passed, 5 skipped out of 4591 tests in 618.9s (+10 tests, +5.0s vs. baseline)

Test Coverage

89.1% line coverage, 82.4% branch coverage · ✅ no change vs. baseline

CLI Startup Time

52ms median (x64, winapp --version) · ✅ +6ms vs. baseline

Try This Build

Installs the MSIX for your architecture, replacing any previously installed build. Needs the GitHub CLI — the command offers to install it and sign you in if it is missing.

& ([scriptblock]::Create((irm https://raw.githubusercontent.com/microsoft/winappCli/main/scripts/winapp-pr.ps1))) 757
Switching between builds often?

Put the tool on your PATH once:

& ([scriptblock]::Create((irm https://raw.githubusercontent.com/microsoft/winappCli/main/scripts/winapp-pr.ps1))) -AddToPath

Then this build is just:

winapp-pr 757

Run winapp-pr with no arguments to pick from a list of open PRs.


Updated 2026-08-14 21:36:59 UTC · commit 1cdf4f9 · workflow run

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Throttles winapp new template update checks with a version-aware, daily cache.

Changes:

  • Adds and registers a file-backed update-check throttle.
  • Integrates cached results into template resolution.
  • Adds atomic text writing and related tests.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
TemplateUpdateCheckThrottle.cs Implements cache persistence and expiry.
ITemplateUpdateCheckThrottle.cs Defines the throttle contract.
HostBuilderExtensions.cs Registers the service.
AtomicFile.cs Adds atomic text writes.
NewCommand.cs Reuses cached update results.
TemplateUpdateCheckThrottleTests.cs Tests cache behavior.
NewCommandHandlerTests.cs Tests handler integration and failures.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread src/winapp-CLI/WinApp.Cli/Commands/NewCommand.cs Outdated
…ow catches

Copilot: ParseUpdateCheck returned (null, null) both for an up-to-date pack and
for output it couldn't parse, so an exit-0 run with a changed/truncated
`dotnet new update` format was cached as "up-to-date" and suppressed retries for
a day. It now returns an UpdateCheckOutcome (UpdateAvailable / UpToDate /
Unrecognized); GetLatestAvailableVersionAsync reports failure for Unrecognized
so it isn't recorded.

Code quality: replace generic catch (Exception) blocks in
TemplateUpdateCheckThrottle (and the test cleanup) with filtered catches over
expected filesystem/parse exceptions, and switch Path.Combine to Path.Join so a
rooted second segment can't silently drop the directory.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 314ff851-0510-4289-b605-a545cfb453a2
@zateutsch
Zach Teutsch (zateutsch) marked this pull request as ready for review August 15, 2026 20:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants