Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions .github/workflows/deploy-web.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ on:
paths:
- 'src/PlanViewer.Core/**'
- 'src/PlanViewer.Web/**'
- 'src/PlanViewer.App/PlanViewer.App.csproj'
- '.github/workflows/deploy-web.yml'
workflow_dispatch:

Expand Down Expand Up @@ -36,6 +37,17 @@ jobs:
- name: Install WASM workload
run: dotnet workload install wasm-tools

- name: Sync web version with app version
shell: pwsh
run: |
$appVersion = ([xml](Get-Content src/PlanViewer.App/PlanViewer.App.csproj)).Project.PropertyGroup.Version | Where-Object { $_ }
Write-Host "App version: $appVersion"
$webCsproj = 'src/PlanViewer.Web/PlanViewer.Web.csproj'
$content = Get-Content $webCsproj -Raw
Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

.Project.PropertyGroup.Version is fragile: when a csproj has multiple <PropertyGroup> blocks (e.g. a Debug/Release conditional group), PropertyGroup becomes an array and .Version returns an array of values. Where-Object { $_ } filters empty strings but not duplicates — if a future PropertyGroup also declares <Version>, $appVersion becomes an array and the regex replacement below interpolates something like System.Object[] into the web csproj. Consider Select-Xml -XPath '/Project/PropertyGroup/Version' | Select-Object -First 1 -ExpandProperty Node | ForEach-Object InnerText or similar, and assert a single scalar result before proceeding.


Generated by Claude Code

$content = [regex]::Replace($content, '<Version>[^<]+</Version>', "<Version>$appVersion</Version>")
Set-Content -Path $webCsproj -Value $content -NoNewline
Write-Host "Synced web csproj to $appVersion"
Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

The regex <Version>[^<]+</Version> is unanchored, so if a <PackageReference ... Version="..."> ever gets rewritten to the child-element form (<PackageReference ...><Version>...</Version></PackageReference>), or any other <Version> element is added, this replaces all of them. Safer to anchor inside a PropertyGroup or load the csproj as XML and set the node directly, matching how $appVersion is read.


Generated by Claude Code


- name: Publish Blazor WASM
run: dotnet publish src/PlanViewer.Web/PlanViewer.Web.csproj -c Release -o publish

Expand Down
2 changes: 1 addition & 1 deletion src/PlanViewer.App/PlanViewer.App.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<ApplicationManifest>app.manifest</ApplicationManifest>
<ApplicationIcon>EDD.ico</ApplicationIcon>
<AvaloniaUseCompiledBindingsByDefault>true</AvaloniaUseCompiledBindingsByDefault>
<Version>1.7.2</Version>
<Version>1.7.3</Version>
<Authors>Erik Darling</Authors>
<Company>Darling Data LLC</Company>
<Product>Performance Studio</Product>
Expand Down
10 changes: 9 additions & 1 deletion src/PlanViewer.Web/Pages/Index.razor
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<div class="landing-content">
<h2>Free SQL Server Query Plan Analysis</h2>
<p class="privacy">Paste or upload a .sqlplan file. Your plan XML never leaves your browser.</p>
<p class="powered-by">Powered by the same analysis engine in the <a href="https://github.com/erikdarlingdata/PerformanceStudio" target="_blank" rel="noopener">Performance Studio</a> app.</p>
<p class="powered-by">Powered by the same analysis engine in the <a href="https://github.com/erikdarlingdata/PerformanceStudio" target="_blank" rel="noopener">Performance Studio</a> app. <span class="app-version">@AppVersion</span></p>

@if (errorMessage != null)
{
Expand Down Expand Up @@ -57,6 +57,7 @@ else
{
<span class="toolbar-version">@result.SqlServerBuild</span>
}
<span class="toolbar-app-version" title="Performance Studio web viewer version">@AppVersion</span>
@if (shareUrl != null)
{
<span class="share-url"><a href="@shareUrl" target="_blank">@shareUrl</a></span>
Expand Down Expand Up @@ -1664,6 +1665,13 @@ else
@code {
private const string ShareApiBase = "https://stats.erikdarling.com";

private static readonly string AppVersion = GetAppVersion();
private static string GetAppVersion()
{
var v = typeof(Index).Assembly.GetName().Version;
Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Assembly.GetName().Version returns the AssemblyVersion, which defaults to Major.Minor.Build.0 when only <Version> is set — so 1.7.31.7.3.0 and Major.Minor.Build renders 1.7.3 correctly. Just note that if anyone later sets <AssemblyVersion> explicitly (e.g. 1.0.0.0 for binary-compat reasons, common in libraries), this falls out of sync with the displayed version. AssemblyInformationalVersionAttribute (read via Assembly.GetCustomAttribute<AssemblyInformationalVersionAttribute>()?.InformationalVersion) tracks <Version> directly and is the more robust source for user-facing version strings.


Generated by Claude Code

return v == null ? "?" : $"v{v.Major}.{v.Minor}.{v.Build}";
}

private string activeTab = "paste";
private string planXml = "";
private string? errorMessage;
Expand Down
2 changes: 1 addition & 1 deletion src/PlanViewer.Web/PlanViewer.Web.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<RootNamespace>PlanViewer.Web</RootNamespace>
<Version>1.4.0</Version>
<Version>1.7.3</Version>
Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Now that the workflow rewrites this value at publish time, the committed value is purely decorative. Worth a one-line comment here (or in the sync step) noting that the source of truth is PlanViewer.App.csproj so the next person bumping the app version doesn't also update this by hand and get confused when CI still overwrites it.


Generated by Claude Code

<Authors>Erik Darling</Authors>
<Company>Darling Data LLC</Company>
<Product>SQL Performance Studio</Product>
Expand Down
17 changes: 17 additions & 0 deletions src/PlanViewer.Web/wwwroot/css/app.css
Original file line number Diff line number Diff line change
Expand Up @@ -451,6 +451,23 @@ textarea::placeholder {
color: var(--text-muted);
}

.toolbar-app-version {
font-size: 0.75rem;
font-weight: 600;
color: var(--text-muted);
padding: 0.1rem 0.4rem;
border-radius: 3px;
background: rgba(0, 0, 0, 0.05);
Comment on lines +454 to +460
Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Both badges bind color: var(--text-muted), which resolves to #999999 (app.css:12). That's in the dim-grey range the desktop side explicitly rejected (ForegroundMutedBrush was moved to #B0B6C0 for readability). .toolbar-app-version additionally puts that grey on a rgba(0,0,0,0.05) tint, which reduces contrast further on light toolbars. Not introduced by this PR — the variable is already widespread — but the new badges are intentionally a "reviewers need to see the version at a glance" affordance, so it's worth either bumping them up (e.g. closer to --text-secondary/primary) or giving the pill a stronger background. Otherwise the thing that's supposed to be visible is the hardest-to-read label on the page.


Generated by Claude Code

margin-left: auto;
}

.app-version {
font-size: 0.8rem;
font-weight: 600;
color: var(--text-muted);
margin-left: 0.25rem;
}

/* === Statement Tabs === */
.statement-tabs {
display: flex;
Expand Down
Loading