Skip to content

Commit 28608da

Browse files
Geeven SinghCopilot
andcommitted
Stamp dev builds 0.0.0-dev and suppress update notifications for them
Two related fixes: 1. Dev / from-source builds were stamping MSBuild's default 1.0.0 (no <Version> in csproj), which masqueraded as a real release version in the new Settings > Updates > Current version row. Now stamps 0.0.0-dev. CI's release workflow stamps the real tag via -p:Version=, which wins over the csproj default. 2. With 0.0.0 stamped, BrowserNotifyUpdateService.CheckAsync would otherwise compare against the latest GitHub release (e.g. v1.6.0) and tell the dev they need to update -- a false signal, because tip-of-master is by definition either at or ahead of the most recent published tag. Added a dev-build sentinel check at the top of CheckAsync: when current version is 0.0.0[.0], short-circuit to NoUpdateAvailable without hitting the network. Added IsDevBuild helper (internal, visible to tests) so the policy lives next to the version comparison rather than scattered. Tested across Version(0,0,0) vs Version(0,0,1)/etc and the corner-case Version(0,0) where Build = -1. Verified end-to-end locally: dotnet publish -c Release stamps ProductVersion as '0.0.0-dev+<git-hash>' (SourceLink-style hash suffix is automatic when building in a git repo; AppVersionInfo.GetDisplayVersion strips it for display so users see plain '0.0.0-dev'). Tests: 1448 passing (+8 from IsDevBuild theories + the zero-version short-circuit test), 1 skipped. 0 warnings, 0 errors in dotnet build -c Release. CHANGELOG [Unreleased] documents both changes. AI-Local-Session: 4519f6b6-393a-4476-8efa-410e5396c3a9 AI-Cloud-Session: 72f9e474-60ab-42c2-b2a0-28fee827cbbb Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 3d2b534 commit 28608da

4 files changed

Lines changed: 95 additions & 0 deletions

File tree

CHANGELOG.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,19 @@ body. Keep section headings exact and write notes in Markdown.
2020
for prereleases), so users can answer "what version am I on?"
2121
alongside the auto-update settings without leaving the dialog.
2222

23+
### Changed
24+
25+
- **Dev / from-source builds now stamp `0.0.0-dev` as the version**
26+
instead of MSBuild's misleading default of `1.0.0`. CI release
27+
builds are unaffected — the workflow's `-p:Version=$tag` still
28+
wins. Local `dotnet publish` builds now identify themselves
29+
honestly in the new Settings → Updates → Current version row.
30+
- **Dev builds no longer trigger update notifications.** When the
31+
current version is `0.0.0`, the update check short-circuits
32+
without hitting the GitHub Releases API, so a developer running
33+
`dotnet run` against tip-of-master doesn't get a false
34+
"update available" banner every launch.
35+
2336
## [1.6.0] - 2026-05-31
2437

2538
### Added

DiffViewer.Tests/Services/BrowserNotifyUpdateServiceTests.cs

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,48 @@ public void TryParseVersion_StripsTagPrefixAndSemVerSuffixes(string input, strin
233233
BrowserNotifyUpdateService.TryParseVersion(input)!.ToString().Should().Be(expected);
234234
}
235235

236+
[Theory]
237+
[InlineData(0, 0, 0, true)]
238+
[InlineData(0, 0, 1, false)]
239+
[InlineData(0, 1, 0, false)]
240+
[InlineData(1, 0, 0, false)]
241+
[InlineData(1, 6, 0, false)]
242+
public void IsDevBuild_Identifies_ZeroVersion(int major, int minor, int build, bool expected)
243+
{
244+
BrowserNotifyUpdateService.IsDevBuild(new Version(major, minor, build))
245+
.Should().Be(expected);
246+
}
247+
248+
[Fact]
249+
public void IsDevBuild_Handles_TwoComponentVersion()
250+
{
251+
// System.Version with only Major.Minor gives Build = -1.
252+
// The dev-marker check must accept that as "also dev" so
253+
// a hypothetical Version(0, 0) sentinel still short-circuits.
254+
BrowserNotifyUpdateService.IsDevBuild(new Version(0, 0))
255+
.Should().BeTrue();
256+
}
257+
258+
[Fact]
259+
public async Task CheckAsync_WhenCurrentVersionIs0_0_0_ReturnsNoUpdateWithoutHittingNetwork()
260+
{
261+
// Dev builds (csproj defaults Version to 0.0.0-dev). The
262+
// service must short-circuit before any HTTP call so
263+
// developers running `dotnet run` don't get a false
264+
// "update available" banner every launch.
265+
var handler = new FakeHttpHandler(new[]
266+
{
267+
ReleasesJson(new GhRelease("v1.6.0", "https://example/v160", Draft: false, Prerelease: false)),
268+
});
269+
using var http = new HttpClient(handler);
270+
var sut = new BrowserNotifyUpdateService(http, new Version(0, 0, 0), includePreReleases: false);
271+
272+
var result = await sut.CheckAsync(CancellationToken.None);
273+
274+
result.Should().BeSameAs(UpdateCheckResult.NoUpdateAvailable);
275+
handler.SendCount.Should().Be(0);
276+
}
277+
236278
[Theory]
237279
[InlineData("notaversion")]
238280
[InlineData("")]
@@ -288,13 +330,16 @@ private sealed class FakeHttpHandler : HttpMessageHandler
288330
{
289331
private readonly Queue<FakeResponse> _responses;
290332

333+
public int SendCount { get; private set; }
334+
291335
public FakeHttpHandler(IEnumerable<FakeResponse> responses)
292336
{
293337
_responses = new Queue<FakeResponse>(responses);
294338
}
295339

296340
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken ct)
297341
{
342+
SendCount++;
298343
if (_responses.Count == 0)
299344
{
300345
// Simulate a network outage for tests that want it.

DiffViewer/DiffViewer.csproj

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,18 @@
99
<LangVersion>latest</LangVersion>
1010
<RootNamespace>DiffViewer</RootNamespace>
1111
<AssemblyName>DiffViewer</AssemblyName>
12+
13+
<!-- Dev / from-source builds stamp 0.0.0-dev so the running
14+
version is unambiguously "not a real release". CI's release
15+
workflow passes -p:Version=$tag which overrides this at
16+
release time. The update services treat 0.0.0 as a dev
17+
marker and skip the GitHub / Velopack check entirely, so
18+
developers don't see a false "update available" banner on
19+
every dotnet run. -->
20+
<Version>0.0.0-dev</Version>
21+
<FileVersion>0.0.0.0</FileVersion>
22+
<InformationalVersion>0.0.0-dev</InformationalVersion>
23+
1224
<ApplicationIcon>Assets\diffviewer.ico</ApplicationIcon>
1325

1426
<!-- Velopack requires a hook (VelopackApp.Build().Run()) that

DiffViewer/Services/BrowserNotifyUpdateService.cs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,18 @@ public BrowserNotifyUpdateService(
6363

6464
public async Task<UpdateCheckResult> CheckAsync(CancellationToken ct)
6565
{
66+
// Dev builds (csproj defaults to 0.0.0-dev when no Version is
67+
// stamped) short-circuit the check. A developer on tip-of-master
68+
// is by definition either at or ahead of the most recent
69+
// published release, so a banner saying "update available" would
70+
// be misleading. CI's release workflow stamps a real version
71+
// via -p:Version=$tag, so this only affects developer machines
72+
// and bespoke from-source builds.
73+
if (IsDevBuild(_currentVersion))
74+
{
75+
return UpdateCheckResult.NoUpdateAvailable;
76+
}
77+
6678
try
6779
{
6880
using var req = new HttpRequestMessage(HttpMethod.Get, GitHubApiUrl + "?per_page=10");
@@ -162,6 +174,19 @@ private static void OpenUrlInDefaultBrowser(string url)
162174
return Version.TryParse(trimmed, out var v) ? v : null;
163175
}
164176

177+
/// <summary>
178+
/// True when <paramref name="version"/> is the 0.0.0[.0] sentinel
179+
/// stamped on dev / from-source builds by
180+
/// <c>DiffViewer.csproj</c>'s default <c>&lt;Version&gt;</c>.
181+
/// Major == Minor == Build == 0 is sufficient; Revision varies
182+
/// by stamping path (AssemblyVersion gives 0.0.0.0; the
183+
/// informational-version Version.Parse path gives 0.0.0). A
184+
/// genuinely-released v0.0.0 would also match, but DiffViewer
185+
/// will never tag one, so the trade-off is acceptable.
186+
/// </summary>
187+
internal static bool IsDevBuild(Version version) =>
188+
version.Major == 0 && version.Minor == 0 && version.Build <= 0;
189+
165190
private static readonly JsonSerializerOptions SerializerOptions = new()
166191
{
167192
PropertyNameCaseInsensitive = true,

0 commit comments

Comments
 (0)