Skip to content

Ergonomics round 2 - #7

Merged
sbokatuk merged 10 commits into
mainfrom
ergonomics-round-2
Jul 26, 2026
Merged

sbokatuk merged 10 commits into
mainfrom
ergonomics-round-2

Conversation

@sbokatuk

Copy link
Copy Markdown
Owner

No description provided.

sbokatuk and others added 10 commits July 26, 2026 13:41
The RUM, Logs and Trace descriptions ended with "The managed DD* API
lives in DatadogNet.Objc.iOS; this package ships the native feature" -
true of 2.x, where DatadogObjc held every DD* type, but wrong since 3.0:
each package binds its own surface (RUM's ApiDefinitions.cs alone is
7400 lines) and DatadogNet.Objc.iOS is a dependency-only meta-package
with no assembly. A reader on nuget.org following that sentence would
install a package that contains nothing.

Same story for the rationale comment in Datadog.Binding.props, which
still described Logs, RUM and Trace as having an empty ApiDefinitions.cs
on purpose - it is Flags, Profiling and OpenTelemetryApi that are empty,
and for a different reason (no Objective-C projection upstream).

The package tests now reject any description that claims the API "lives
in DatadogNet.Objc.iOS", so the claim cannot come back with a paste.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The same README.md is packed into every .nupkg and rendered on each
package's nuget.org page, where its eleven repo-relative links - the
sample, checksums.txt, the regeneration guide, the Flags shim, the
licence and friends - resolve against nuget.org and render as dead text.
Every repository link is now absolute (blob/main for files, tree/main
for directories); in-page anchors stay as they are, since those work
everywhere the file renders.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
build/checksums.txt guards ~116 MB of native code, but its pins were
recorded trust-on-first-use: the instructions said to download the
archive and write down whatever hash you got - so a tampered first
download would have minted the poisoned hash as the truth.

The releases API reports the digest GitHub computed for every asset at
upload time. The new build/UpdateChecksums.sh records that digest as
the pin, downloads the asset, and requires the bytes to hash to the
same value before anything is written - two independent paths to one
number - and warns loudly when a pin CHANGES for an unchanged version,
which is the asset-replacement event the pins exist to catch. It also
owns the checksums.txt header, so the instructions cannot drift from
what it does. (Run against 3.14.0: the digest equals the pin already
recorded, which is a nice retroactive check on the old flow.)

FetchXcFrameworks.sh now cross-checks the pin against the live digest
before downloading anything: a mismatch is a hard failure either way
it happened, while an unreachable API - offline, rate-limited - is a
one-line note and the pinned hash keeps guarding the download, so the
build never grows a network dependency it did not have.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The check guarded the install-snippet pins and the device-check example,
but the dd-sdk-ios badge - which names the native version three times
over: label, shields.io image path and release link - and the "Built
against **dd-sdk-ios 3.14.0**" intro line were exactly the hardcoded
spots the README's own upgrade guide warned "nothing else will notice
when it goes stale". Now something does: each spot is matched by its
own anchored pattern (so the historical "dd-sdk-ios 3.0 deleted that
framework" prose stays exempt), required to exist, and verified against
DatadogNativeVersion. The upgrade guide's warning is updated to say so.

Also retire GenerateBindings.sh's usage example of binding DatadogObjc,
a framework dd-sdk-ios 3.0 deleted - the one-framework example is now
DatadogRUM, which is in the script's own FRAMEWORKS list.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The tag alone drives which dd-sdk-ios line a release binds, so a
mistyped v3.15.0.1 pushed while the props - and the committed
ApiDefinitions.cs - are still on 3.14.0 would have published packages
whose version does not describe their contents. The version job now
compares the tag's native prefix against DatadogNativeVersion and its
fourth component (when present) against DatadogBindingRevision, and
fails before anything builds, with the fix spelled out: correct the
tag or bump the props.

Releasing a different line on purpose remains possible - that is a
documented feature - through the RELEASE_ALLOW_VERSION_MISMATCH
repository variable, set for the one release and unset after. The
README's Releasing section covers both halves.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Nothing announced a new dd-sdk-ios release to this repository - the gap
between upstream shipping and anyone here noticing was however long it
took someone to look. A weekly workflow (plus workflow_dispatch for
checking on demand) now compares DatadogNativeVersion against the
latest upstream release tag and opens an issue when upstream is newer,
linking the release and the upgrade ritual - BumpNativeVersion.sh,
UpdateChecksums.sh, DiffSwiftHeaders.sh.

Idempotent by exact title match against the open issues, so a pending
upgrade collects one issue however many Mondays it stays open, and
sort -V ordering means a yanked or re-cut older "latest" never prompts
a downgrade.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
An accidental API break - a regenerated binding quietly dropping a
member is the likely shape of it - would today reach nuget.org and be
found by a consumer's compiler. EnablePackageValidation with a
PackageValidationBaselineVersion catches it at pack time instead,
comparing every assembly against the version already published.

The baseline lives once, in Directory.Build.props, and advances to the
just-shipped version while preparing the next release. Validation is
opt-in through RunPackageValidation=true - the baseline restores from
nuget.org, and a local offline pack must not depend on that - and the
CI pack job opts in via the environment. Only the net9 band validates:
the net10-band pass alone packs an intermediate that legitimately
lacks the net8/net9 assets the baseline ships (merge-packages.py
reassembles the full set afterwards), so the baseline comparison there
would fail by design rather than by defect.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The mechanical half of a dd-sdk-ios upgrade was six hand-edits across
four files, each individually forgettable: the props version and
revision, the checksum pin, the README badge and prose and pins, the
release-notes file, and now the package-validation baseline. The script
does all of it - UpdateChecksums.sh for the digest-anchored pin, the
baseline pointed at the version being left behind, the release notes
scaffolded with TODOs in the established format - and finishes by
running CheckReadmeVersions.sh on its own output.

The README's upgrade ritual now leads with it, and puts
DiffSwiftHeaders.sh BEFORE FetchXcFrameworks.sh: the diff reads libs/
as the old side, so fetching first - the previous step order - would
have diffed the new release against itself and produced an empty
porting list.

Exercised end to end against a real release (3.13.0 in a scratch copy
of the repo): props, pins, badge, prose, scaffold and self-check all
came out right.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Binding revision to 4 - the native SDK stays at 3.14.0 - with curated
release notes covering the round: corrected package descriptions,
README links that survive nuget.org, digest-anchored checksum pins,
package validation against the published baseline, and the release
machinery (tag guard, upstream watch, bump script, wider README
checks). PackageValidationBaselineVersion stays at 3.14.0.3, the last
version actually on nuget.org, and advances only once this one ships.

README pins move to 3.14.0.4; CheckReadmeVersions.sh agrees.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The MSBuild-time gate proved structurally wrong at its first real run:
each band's pack pass produces an intermediate lacking the other band's
frameworks, so ApiCompat mapped the published baseline's net10
assemblies onto the pass's net9 ones and reported every band-to-band
difference as an API break (DDCoreLoggerLevel's members, concretely).
Only the merged artifact carries the baseline's framework set.

build/ValidatePackageApi.sh now runs the same comparison with the
standalone apicompat tool, pinned, against the finished artifacts/ -
downloading each package's published baseline from nuget.org, skipping
a package that has never shipped (its first release IS the baseline).
CI runs it right after the package tests; locally it is an explicit
network-using invocation, never part of an offline pack.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@sbokatuk
sbokatuk merged commit 7767401 into main Jul 26, 2026
6 checks passed
@sbokatuk
sbokatuk deleted the ergonomics-round-2 branch July 26, 2026 19:35

This branch was previously deployed

1 inactive deployment
nuget.org — 83f72352 Deployed Jul 26, 2026 by sbokatuk via publish beta to nuget.org #16
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