|
1 | 1 | # Versioning in OpenClaw Windows Hub |
2 | 2 |
|
3 | | -## How Versioning Works |
| 3 | +## Source of truth |
4 | 4 |
|
5 | | -This project uses GitVersion for automatic semantic versioning based on git tags and commit history. The version is used in multiple places: |
| 5 | +OpenClaw uses GitVersion and git tags for application versioning. Product |
| 6 | +project files must not hardcode release versions with `<Version>` elements. |
6 | 7 |
|
7 | | -### Version Properties in .csproj |
| 8 | +Canonical release tags use: |
8 | 9 |
|
9 | | -The project file (`OpenClaw.Tray.WinUI.csproj`) defines only the `<Version>` property: |
| 10 | +- Stable: `vX.Y.Z` |
| 11 | +- Alpha: `vX.Y.Z-alpha.N` |
10 | 12 |
|
11 | | -```xml |
12 | | -<Version>0.3.0</Version> |
13 | | -``` |
14 | | - |
15 | | -Other version-related properties (`FileVersion` and `AssemblyVersion`) are **not** explicitly set in the csproj files. This is intentional. |
| 13 | +`GitVersion.yml` controls how tag history becomes SemVer. The product build |
| 14 | +imports GitVersion through `src\Directory.Build.props`, so normal `dotnet build`, |
| 15 | +`.\build.ps1`, `.\run-app-local.ps1`, and CI builds all derive assembly metadata |
| 16 | +from the same tag history. |
16 | 17 |
|
17 | | -### Automatic Version Derivation |
| 18 | +## Assembly metadata |
18 | 19 |
|
19 | | -When only `<Version>` is set in a .NET project: |
20 | | -- **AssemblyVersion**: Automatically set to the numeric part of `Version` (e.g., `0.3.0` → `0.3.0.0`) |
21 | | -- **FileVersion**: Automatically set to the numeric part of `Version` (e.g., `0.3.0` → `0.3.0.0`) |
22 | | -- **InformationalVersion**: Set to the full `Version` value including suffixes (e.g., `0.3.0-beta.1`) |
| 20 | +GitVersion-derived builds set: |
23 | 21 |
|
24 | | -This ensures all version properties stay in sync automatically. |
| 22 | +- `AssemblyVersion` and `FileVersion` to numeric versions Windows/.NET can |
| 23 | + compare. |
| 24 | +- `AssemblyInformationalVersion` to the SemVer identity used by user-visible |
| 25 | + surfaces. |
25 | 26 |
|
26 | | -### CI Build Process |
| 27 | +`OpenClaw.Shared.AppVersionInfo` reads `AssemblyInformationalVersionAttribute` |
| 28 | +from the tray assembly and exposes: |
27 | 29 |
|
28 | | -During CI builds (`.github/workflows/ci.yml`), GitVersion determines the semantic version from git history and passes it to the build: |
29 | | - |
30 | | -```bash |
31 | | -dotnet build -p:Version=${{ needs.test.outputs.semVer }} |
32 | | -``` |
| 30 | +- `AppVersionInfo.Version` -> bare SemVer, for example `1.2.3-alpha.4` |
| 31 | +- `AppVersionInfo.DisplayVersion` -> `v`-prefixed SemVer, for example |
| 32 | + `v1.2.3-alpha.4` |
33 | 33 |
|
34 | | -This `-p:Version=...` argument overrides the `<Version>` property in the csproj, and consequently also sets `FileVersion` and `AssemblyVersion` to match. |
| 34 | +Build metadata after `+` is stripped before display, but prerelease labels are |
| 35 | +preserved. That makes alpha builds identify themselves precisely in About, |
| 36 | +diagnostics, support context, `device.info`, MCP handshake metadata, and update |
| 37 | +diagnostics. |
35 | 38 |
|
36 | | -### Auto-Updater Version Detection |
| 39 | +## CI release flow |
37 | 40 |
|
38 | | -The Updatum auto-updater determines the current application version by reading the **AssemblyVersion** from the running executable using: |
| 41 | +The release workflow computes GitVersion in the `test` job for workflow outputs |
| 42 | +and artifact naming. Product builds themselves also use GitVersion-backed |
| 43 | +MSBuild metadata; CI should not pass a competing hardcoded `-p:Version=...` |
| 44 | +value that could hide drift. |
39 | 45 |
|
40 | | -```csharp |
41 | | -Assembly.GetExecutingAssembly().GetName().Version |
42 | | -``` |
| 46 | +Release build jobs must check out full git history (`fetch-depth: 0`) so |
| 47 | +GitVersion can see tags. |
43 | 48 |
|
44 | | -This is why it's critical that `AssemblyVersion` (and `FileVersion`) match the semantic version - otherwise, the updater will get confused and keep offering the same update repeatedly. |
| 49 | +## Local scripts |
45 | 50 |
|
46 | | -## Historical Issue |
| 51 | +`scripts\Get-OpenClawVersion.ps1` uses the repository-local |
| 52 | +`.config\dotnet-tools.json` manifest and `GitVersion.Tool` to print the same |
| 53 | +GitVersion value local scripts need outside MSBuild. |
47 | 54 |
|
48 | | -Previously, the csproj files had hardcoded values: |
| 55 | +For example: |
49 | 56 |
|
50 | | -```xml |
51 | | -<Version>0.3.0</Version> |
52 | | -<FileVersion>0.2.0</FileVersion> |
53 | | -<AssemblyVersion>0.2.0</AssemblyVersion> |
| 57 | +```powershell |
| 58 | +.\scripts\Get-OpenClawVersion.ps1 -Variable SemVer |
| 59 | +.\scripts\Get-OpenClawVersion.ps1 -Variable MajorMinorPatch |
54 | 60 | ``` |
55 | 61 |
|
56 | | -This caused a version mismatch: |
57 | | -- The semantic version was 0.3.0 |
58 | | -- But the file and assembly versions were stuck at 0.2.0 |
59 | | -- Updatum would read 0.2.0 from the running EXE |
60 | | -- It would see 0.4.0 available on GitHub |
61 | | -- It would offer to update from "0.2.0" to "0.4.0" even though the user was already on 0.3.0 or 0.4.0 |
62 | | - |
63 | | -## Solution |
64 | | - |
65 | | -By removing the hardcoded `FileVersion` and `AssemblyVersion` properties, they now automatically derive from `Version`. When CI overrides `Version` via command-line, all three properties are set correctly and consistently. |
66 | | - |
67 | | -## Best Practices |
| 62 | +`scripts\build-inno-local.ps1` uses that helper for Inno's `AppVersion` when |
| 63 | +`-Version` is not explicitly supplied. |
68 | 64 |
|
69 | | -1. **Never hardcode `FileVersion` or `AssemblyVersion` in the csproj** - let them auto-derive from `Version` |
70 | | -2. **Let GitVersion and CI control the version** - the csproj's `<Version>` is just a fallback for local development builds |
71 | | -3. **Test version detection** - after building, check the EXE properties to ensure FileVersion matches expectations |
72 | | -4. **Use semantic versioning** - tags should follow `v{major}.{minor}.{patch}` format (e.g., `v0.4.0`) |
73 | | -5. **Use `OpenClaw.Shared.AppVersionInfo` for any user-visible or wire-exposed version string** - never re-roll |
74 | | - `typeof(...).Assembly.GetName().Version` or hardcode literals like `"v0.1.0"`. `AppVersionInfo` is the single |
75 | | - source of truth driven by `<Version>`, used by the About page, Update dialog, support-context dump, |
76 | | - `device.info` capability, MCP `serverVersion` handshake, and the update-check diagnostics. |
| 65 | +## Guardrails |
77 | 66 |
|
78 | | -## Runtime Version Resolution (AppVersionInfo) |
79 | | - |
80 | | -`src/OpenClaw.Shared/AppVersionInfo.cs` exposes: |
81 | | - |
82 | | -- `AppVersionInfo.Version` → bare string, e.g. `"0.4.7"` |
83 | | -- `AppVersionInfo.DisplayVersion` → `"v"` prefix, e.g. `"v0.4.7"` |
84 | | - |
85 | | -It resolves the version by: |
86 | | - |
87 | | -1. Looking for the `OpenClaw.Tray.WinUI` assembly in the current `AppDomain` (so `dotnet test` and CLI siblings |
88 | | - still report the tray's version rather than the testhost / dotnet host). |
89 | | -2. Falling back to `Assembly.GetEntryAssembly()`, then to the Shared assembly. |
90 | | -3. Reading `AssemblyInformationalVersionAttribute` (preferred) or `AssemblyVersion`. |
91 | | -4. Stripping SourceLink build metadata (`+abc123`) **and** the SemVer pre-release suffix (`-beta.1`) so the |
92 | | - displayed value matches what Updatum compares (Updatum reads the numeric `AssemblyVersion` only). |
93 | | - |
94 | | -For tests that need a deterministic value regardless of host process, set the `internal` test hook: |
95 | | - |
96 | | -```csharp |
97 | | -AppVersionInfo.TestOverride = "9.9.9"; |
98 | | -``` |
| 67 | +- Do not add `<Version>` release literals to product `.csproj` files. |
| 68 | +- Do not hardcode user-visible version strings like `vX.Y.Z` in active code or |
| 69 | + tests; use `AppVersionInfo`. |
| 70 | +- Keep release tags and `GitVersion.yml` as the versioning contract. |
99 | 71 |
|
100 | 72 | ## References |
101 | 73 |
|
|
0 commit comments