Skip to content

version: generate IoxideRuntime.Version from the csproj instead of writing it twice - #237

Merged
MDA2AV merged 1 commit into
mainfrom
fix/version-derived-from-assembly
Sep 20, 2026
Merged

MDA2AV merged 1 commit into
mainfrom
fix/version-derived-from-assembly

Conversation

@MDA2AV

@MDA2AV MDA2AV commented Sep 20, 2026

Copy link
Copy Markdown
Owner

Closes #224.

The problem

The version was stated four ways and all four disagreed — README 0.4.169, IoxideRuntime.Version "0.0.17", csprojs 0.13.218, nuget.org 0.7.211. Every release moved the csprojs and left the rest, because nothing tied them together. IoxideRuntime.Version is the one a program can read at run time, and it had been wrong since the 0.0.x days.

The fix

A target in ioxide.csproj writes a const into obj/ from the Version property sitting a few lines above it:

<Target Name="GenerateVersionSource" BeforeTargets="BeforeCompile;CoreCompile">
  ...
  <_IoxideVersionLines Include="    public const string Value = &quot;$(Version)&quot;%3B" />
public const string Version = IoxideVersion.Value;

So the single <Version> element a release already edits is now the only statement of the number in the source tree.

Why generated and not read off the assembly

The issue suggests AssemblyInformationalVersionAttribute or Assembly.GetName().Version, which is the obvious answer — and the wrong one here, because reflecting over assembly attributes is exactly what Native AOT trims. A generated const costs nothing at run time and survives trimming.

It also keeps Version a const. Reading it at run time would have forced it to a property, which is a source break for anyone using it in a const context and a binary break for everyone else, since consts inline at the call site.

And it sidesteps something that would otherwise have shipped quietly: the SDK appends the commit sha to the informational version from the repo's git metadata, so that attribute currently reads

0.14.236+75c9bf68fade3bd289081d129a54d154132d16a5

Deriving from it would have needed that suffix stripped, and nobody would have noticed until a caller compared the value against a package version.

README

The blockquote loses its version literal:

-> Linux 6.1+ · .NET 10 / .NET 11 · `0.14.236` - experimental
+> Linux 6.1+ · .NET 10 / .NET 11 · experimental

The nuget badge at the top of the file already renders the live version from nuget.org, so the blockquote was the only hand-maintained copy left.

Tests

Three, and none of them use reflection — a test reaching for the attribute would be exercising something the shipped configuration cannot do. The one that matters reads <Version> out of ioxide.csproj and compares it against the const, so it fails both if the generator stops running and if someone puts a literal back.

Proven by putting the literal back:

FAIL  version: IoxideRuntime.Version matches ioxide.csproj: expected [0.14.236], got [0.0.17]
45 passed, 1 failed

which is the exact drift #224 is about. The other two pin that the value parses and isn't a placeholder, and that no build metadata reaches it.

All suites green: Unit 46, E2E 185, Http 44, Tls 142, Chaos 47, File 4.

The issue's third item needs nothing

#224 also asks to check build.yml's publish step, on the grounds that 0.13.218 never reached nuget.org. It did, since. The flat-container index now lists 0.7.211, 0.13.218, 0.13.225, 0.13.233 and 0.14.236, and every main run since has been green. Nothing to fix there.

Left out

#224 closes with a related note that the README's linux 6.1+ badge is not accurate given the io_uring_setup fallback. That is a factual claim about which kernels the fallback actually supports, which belongs with #220 rather than being changed on the strength of a passing remark.

…iting it twice

Closes #224.

The version was stated four ways and all four disagreed: README said 0.4.169,
IoxideRuntime.Version said "0.0.17" - untouched since the 0.0.x days - the
csprojs said 0.13.218, and nuget.org's newest was 0.7.211. Each release moved
the csprojs and left the rest, because nothing tied them together.

IoxideRuntime.Version is now generated. A target in ioxide.csproj writes a const
into obj/ from the Version property beside it, so the single Version element a
release already edits is the only statement of the number in the source tree.

Generated rather than read back off AssemblyInformationalVersionAttribute, which
is the obvious answer and the wrong one here: reflecting over assembly attributes
is exactly what Native AOT trims. A generated const costs nothing at run time,
survives trimming, and keeps Version a const - so this is not an API break for
anyone using it in a const context, which reading it at run time would have been.

It also sidesteps a detail that would have shipped: the SDK appends the commit
sha to the informational version from the repo's git metadata, so that attribute
currently reads "0.14.236+75c9bf6...". Deriving from it would have needed the
suffix stripped, and nobody would have noticed until a caller compared the value
against a package version.

The README's blockquote loses its literal. The nuget badge at the top of the file
already renders the live version from nuget.org, so the blockquote was the only
hand-maintained copy left.

Three tests, none of them using reflection - a test reaching for the attribute
would be exercising something the shipped configuration cannot do. The one that
matters reads <Version> out of ioxide.csproj and compares: putting the literal
back fails it with "expected [0.14.236], got [0.0.17]", which is the exact drift
being guarded.

The issue's third item, that build.yml's publish step may not have run for
0.13.218, needs nothing: the flat-container index now lists 0.7.211, 0.13.218,
0.13.225, 0.13.233 and 0.14.236, and every main run since has been green.

All suites green: Unit 46, E2E 185, Http 44, Tls 142, Chaos 47, File 4.
@MDA2AV
MDA2AV merged commit 3993496 into main Sep 20, 2026
1 check passed
@MDA2AV MDA2AV mentioned this pull request Sep 20, 2026
MDA2AV added a commit that referenced this pull request Sep 20, 2026
All twelve published packages share one version, as always.

First release since #237, so the bump really is only the twelve Version elements:
IoxideRuntime.Version is generated from ioxide.csproj now, and the README's
blockquote literal is gone in favour of the nuget badge that was already there.
Nothing else in the tree states the number.

Carries #239 (recv buffers a reader or stream still holds are reclaimed at
teardown, on both TCP and QUIC), #238 (the PipeReader contract under test) and
#237 itself.

E2E 194, Unit 46, Http 44, Tls 142, Chaos 47, File 4.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

docs: the version is stated four ways - README 0.4.169, IoxideRuntime.Version 0.0.17, csproj 0.13.218, nuget.org 0.7.211

1 participant