Skip to content

Also bypass Octokit for label creation/release update under Native AOT - #33

Merged
Mpdreamz merged 1 commit into
masterfrom
fix/aot-safe-label-creation
Sep 3, 2026
Merged

Mpdreamz merged 1 commit into
masterfrom
fix/aot-safe-label-creation

Conversation

@Mpdreamz

@Mpdreamz Mpdreamz commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

Follow-up to #32, which fixed `create-release` dropping `tag_name`.

What happened

The very next real release run (after #32) got past release creation, then hit the identical failure mode on a completely different, unrelated model — creating version labels:

```
Octokit.ApiValidationException: {"message":"Invalid request.\n\n"name" wasn't supplied.","status":"422"}
```

`NewLabel.Name` is `public string Name { get; set; }` — a perfectly ordinary auto-property, not the "mixed get/private-set visibility" pattern #32's root cause blamed for `NewRelease.TagName`.

Conclusion

There's no reliable per-property rule to work around here. Octokit's `SimpleJsonSerializer` has zero AOT/trimming annotations at all, so which specific members the Native AOT compiler's reflection analysis keeps invocable is effectively unpredictable from reading the source — it depends on the whole-program reflection closure, not a simple, statically-visible property shape. Given that, patching around individual properties is a losing game; the only robust fix is to stop depending on Octokit's request serialization entirely for every write call this tool makes.

Fix

Extends `GitHubReleaseClient` (from #32) with `UpdateRelease` and `CreateLabel`, alongside the existing `CreateRelease` — all backed by source-generated `System.Text.Json` (AOT-safe by construction, no reflection). Read-only Octokit calls (`GetLatest`/`Get` for releases, label/branch lookups) are untouched, since those only need deserialization, which hasn't shown this failure mode in either release.

Verification

Extended the same local-`HttpListener` native-AOT `linux-x64` repro from #32 to cover both request shapes:
```
SERVER RECEIVED: {"tag_name":"0.14.2-aot-test","body":"hello"}
RELEASE STATUS: Created
SERVER RECEIVED: {"name":"v1.0.0","color":"e3e3e3"}
LABEL STATUS: Created
```

Made with Cursor

The previous fix (#32) assumed the AOT-unsafe Octokit serialization
bug was specific to NewRelease.TagName's mixed get/private-set
visibility. It isn't: the very next release run hit the identical
failure mode on NewLabel.Name - a perfectly ordinary public get/set
property on a completely unrelated model - creating version labels:

    Octokit.ApiValidationException: "name" wasn't supplied

There's no reliable per-property rule to work around here: Octokit's
SimpleJsonSerializer has zero AOT/trimming annotations, so which
members the Native AOT compiler's reflection analysis keeps invocable
is effectively unpredictable from the source alone. Given that, the
only robust fix is to stop depending on Octokit's request
serialization entirely for every write call this tool makes, not just
release creation.

Extends GitHubReleaseClient with UpdateRelease and CreateLabel
alongside the existing CreateRelease, all backed by source-generated
System.Text.Json (AOT-safe by construction). Read-only Octokit calls
(GetLatest/Get, label/branch lookups) are untouched - those only need
deserialization, which hasn't shown this failure mode.

Verified both request shapes end-to-end against a local HTTP listener
from a real native-AOT linux-x64 build:
    SERVER RECEIVED: {"tag_name":"0.14.2-aot-test","body":"hello"}
    SERVER RECEIVED: {"name":"v1.0.0","color":"e3e3e3"}

Co-authored-by: Cursor <cursoragent@cursor.com>
@Mpdreamz
Mpdreamz merged commit 818dade into master Sep 3, 2026
2 checks passed
@Mpdreamz
Mpdreamz deleted the fix/aot-safe-label-creation branch September 3, 2026 10:39
Mpdreamz added a commit to nullean/assembly-rewriter that referenced this pull request Sep 3, 2026
0.11.1 fixed release creation dropping tag_name under Native AOT but
missed the identical bug in label creation (nullean/release-notes#33).

Co-authored-by: Cursor <cursoragent@cursor.com>
Mpdreamz added a commit to nullean/nupkg-validator that referenced this pull request Sep 3, 2026
0.11.1 fixed release creation dropping tag_name under Native AOT but
missed the identical bug in label creation (nullean/release-notes#33).

Co-authored-by: Cursor <cursoragent@cursor.com>
Mpdreamz added a commit that referenced this pull request Sep 3, 2026
…#34)

The 'does this release already exist' pre-check (client.Repository.Release.Get,
deserializing Octokit's own Release model via the same unannotated reflection
covered in #32/#33) is just as unreliable under Native AOT as the write side
was. In the very next real release after #33, it silently failed, so
CreateRelease ran unconditionally against a tag that already had a release
and got:

    Octokit.ApiValidationException: {"code":"already_exists","field":"tag_name"}

Rather than keep chasing which specific Octokit call breaks next,
CreateOrUpdateRelease is now a self-contained upsert: always POST the
release, and only on a 422 already_exists response resolve the existing
release's id (via a minimal, source-generated-only GET - not Octokit's
Release model) and PATCH it. No separate existence check, so nothing to be
unreliable about.

Verified the full create -> 422 already_exists -> GET id -> PATCH sequence
end-to-end against a local HTTP listener from a real native-AOT linux-x64
build.

Co-authored-by: Cursor <cursoragent@cursor.com>
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.

1 participant