Skip to content

ci: pin docfx and isolate .NET SDKs in the client release build - #359

Merged
tanderson-ld merged 1 commit into
mainfrom
tanderson/pin-docfx-isolate-sdk
Sep 24, 2026
Merged

tanderson-ld merged 1 commit into
mainfrom
tanderson/pin-docfx-isolate-sdk

Conversation

@tanderson-ld

@tanderson-ld tanderson-ld commented Sep 24, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Fixes the failure that blocked the ClientSdk 5.10.1 release (failed run): the Build Documentation step died with NETSDK1147: To build this project, the following workloads must be installed: android ... under SDK 10.0.400, so sign/publish were skipped. The 5.10.1 tag and GitHub release exist but the package is unpublished; after this merges, re-dispatching Publish SDK Client Package (dry run first) completes the release.

Root cause (two layered problems)

  1. docfx resolves MSBuild from the highest SDK on the machine, ignoring global.json (which the ci/build-release composites also delete when they finish). The macOS runner image preinstalls .NET SDK 10.0.400, whose band has no mobile workloads installed — dotnet workload restore in this workflow provisions the 8.x band only (workloads are per-SDK-band). So docfx metadata has been failing restore with NETSDK1147 for weeks.
  2. The docfx install floats (dotnet tool update -g docfx). Through 2.78.5, docfx tolerated the restore failure and fell back to generating metadata from prebuilt assemblies with exit 0 — visible as ##[error] annotations in the successful 5.10.0 release logs. docfx 2.80.1 (released 2026-09-18) makes restore failure fatal (dotnet/docfx#11146, fixing dotnet/docfx#10970). The first release attempt after that (Sept 23) failed.

Fix

  • release-sdk-client.yml build job: set DOTNET_INSTALL_DIR to an isolated directory. Every setup-dotnet in the job (including inside composites) installs there, so the only SDKs visible are the ones the workflow provisions (6/7/8 bands) and docfx resolves the workload-provisioned 8.x band. This also makes the job independent of runner-image SDK churn.
  • build-docs action: pin docfx to 2.80.1 so tool upgrades are deliberate. This action is shared with the server-family full-release path; 2.80.1 is already proven there (plain TFMs restore fine under any band).

The fail-fast behavior of docfx 2.80.1 is kept intentionally — with the SDK isolation, restore succeeds, and any future regression fails the build loudly instead of silently publishing docs generated from stale assemblies.

Same pattern elsewhere (not in this PR — separate repos)

The identical floating dotnet tool update -g docfx exists in build-docs actions in: dotnet-eventsource, dotnet-logging, dotnet-logging-adapter-{ms,nlog,log4net,commonlogging}, openfeature-dotnet-server, and observability-sdk's dotnet Makefile. Only mobile-TFM builds are exposed to the workload variant, but all are exposed to floating-docfx behavior changes. Happy to open matching pins as follow-up PRs.


Note

Overview
Unblocks the Client SDK release pipeline where Build Documentation failed with NETSDK1147 because docfx picked the runner’s preinstalled .NET 10 SDK (no mobile workloads) instead of the workflow-provisioned 8.x band.

The release-sdk-client build job now sets DOTNET_INSTALL_DIR under the runner temp dir so all setup-dotnet installs are isolated from image SDKs and docfx/MSBuild resolves an SDK band that has workloads restored.

The shared build-docs composite pins docfx to 2.80.1 (with a comment on deliberate upgrades and fail-fast restore behavior per dotnet/docfx#11146), replacing a floating dotnet tool update -g docfx—so docfx behavior changes are controlled across client release, CI, and server full-release paths that reuse this action.

Reviewed by Cursor Bugbot for commit 6098cc7. Bugbot is set up for automated code reviews on this repo. Configure here.

The client release docs step failed with NETSDK1147: docfx resolves
MSBuild from the highest SDK installed on the runner image (currently
10.0.400), whose band has no mobile workloads installed. docfx 2.80.1
(released 2026-09-18, picked up automatically because the tool install
floated) turned that previously-tolerated restore failure into a fatal
one (dotnet/docfx#11146).

Isolating DOTNET_INSTALL_DIR keeps only the SDK bands this workflow
installs (6/7/8) visible, so docfx resolves the workload-provisioned
8.x band. Pinning docfx removes the floating input.
@tanderson-ld
tanderson-ld requested a review from a team as a code owner September 24, 2026 17:20
@tanderson-ld
tanderson-ld merged commit 52d3ef7 into main Sep 24, 2026
29 checks passed
@tanderson-ld
tanderson-ld deleted the tanderson/pin-docfx-isolate-sdk branch September 24, 2026 17:37
tanderson-ld added a commit that referenced this pull request Sep 24, 2026
…ob env (#360)

## Summary

Fixes a defect I introduced in #359: the job-level `env` used `${{
runner.temp }}`, but the `runner` context is not available in job-level
`env`, so `release-sdk-client.yml` fails to parse — `workflow_dispatch`
is rejected with HTTP 422 (`Unrecognized named-value: 'runner'` at line
28) and the ClientSdk 5.10.1 re-publish is blocked. GitHub only
validates workflow syntax at trigger time, so #359's PR checks had no
signal.

The fix exports the variable from a first step instead (`echo
"DOTNET_INSTALL_DIR=$RUNNER_TEMP/dotnet" >> "$GITHUB_ENV"`), which is
the pattern the setup-dotnet README documents. Behavior is identical:
the variable is set before any `setup-dotnet` invocation in the job,
including those inside composite actions.

## Verification (local, via actionlint + act)

| Check | main (#359, broken) | this branch |
|---|---|---|
| `actionlint` | `context "runner" is not allowed here` at line 28 |
clean (only pre-existing shellcheck style notes elsewhere) |
| `act workflow_dispatch --list` (parse) | `Line: 28 Column 27: Unknown
Variable Access runner` — reproduces the 422 locally | parses; lists
build/sign-dlls/publish |
| `act ... -j build` (execution, Linux container) | n/a — cannot parse |
`Isolate dotnet SDK installs` step succeeds, `::set-env::
DOTNET_INSTALL_DIR=/tmp/dotnet` exported, checkout runs; job proceeds
until the macOS-only `xcode-select` step (expected in a Linux container)
|

## Follow-up worth taking

`actionlint` catches this class statically (see table) — adding it to
this repo's CI would have flagged #359 in review. Noted for the
release-workflow hygiene follow-up.

After merge: dispatch `Publish SDK Client Package` with `dry_run: true`,
then `dry_run: false` to complete the 5.10.1 release.

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Overview**
> Fixes **Publish SDK Client Package** so `workflow_dispatch` parses
again after #359 broke the workflow with job-level `env:
DOTNET_INSTALL_DIR: ${{ runner.temp }}/dotnet` — GitHub rejects that
because the **`runner` context is not allowed in job `env`**, which
blocked ClientSdk 5.10.1 re-publish (HTTP 422).
> 
> **`DOTNET_INSTALL_DIR`** is now set in a first step **`Isolate dotnet
SDK installs`**, exporting `DOTNET_INSTALL_DIR=$RUNNER_TEMP/dotnet` to
**`GITHUB_ENV`** before checkout and any **`setup-dotnet`** usage.
Isolation behavior is unchanged: dotnet installs stay under the runner
temp dir so docfx/MSBuildLocator cannot pick an SDK band without mobile
workloads.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
93fa342. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
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.

2 participants