From d7f6decb51520204115a869a0445bda0c8f0bf3f Mon Sep 17 00:00:00 2001 From: HarryCordewener Date: Tue, 11 Aug 2026 15:19:09 -0500 Subject: [PATCH] fix(build): pin the SDK feature band so releases can't roll onto an untested one MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The v1.5 release build failed with MAUIX2000 ("Cannot resolve type clr-namespace:SharpClient.App.Components:Routes") 13 minutes after the same commit went green in CI. Nothing in the tree changed: global.json used rollForward: latestFeature, the 10.0.400 band was published in between, and setup-dotnet rolled onto it. That band had no workload set yet, so 'dotnet workload restore' fell back to its baseline maui manifest (10.0.0), whose XAML source generator cannot resolve the Razor-generated Routes type — CI had built on 10.0.302 / maui 10.0.20. Pin to latestPatch so CI, the release pipeline, and dev machines all build on 10.0.3xx, and bump the band deliberately with a green Android head build. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_015MPRzndB5egy4F2A3q5852 --- .github/workflows/release-apk.yml | 6 ++++++ docs/store/release-checklist.md | 30 ++++++++++++++++++++++++------ global.json | 2 +- 3 files changed, 31 insertions(+), 7 deletions(-) diff --git a/.github/workflows/release-apk.yml b/.github/workflows/release-apk.yml index 49adacd..f4a1266 100644 --- a/.github/workflows/release-apk.yml +++ b/.github/workflows/release-apk.yml @@ -38,6 +38,12 @@ jobs: distribution: temurin java-version: "17" + # global.json pins the SDK *feature band* (rollForward: latestPatch), not + # just the major version. A release must not silently jump onto a band the + # code has never been built against: when 10.0.400 first appeared, its + # baseline maui manifest (10.0.0) regressed XAML source generation and this + # workflow failed with MAUIX2000 while CI on 10.0.302 was green. Bump the + # band deliberately — see docs/store/release-checklist.md. - name: Set up .NET (from global.json) uses: actions/setup-dotnet@v4 with: diff --git a/docs/store/release-checklist.md b/docs/store/release-checklist.md index 2f793e5..4d08344 100644 --- a/docs/store/release-checklist.md +++ b/docs/store/release-checklist.md @@ -41,9 +41,9 @@ tag (`vMAJOR.MINOR.PATCH`): `versionCode = major*100000000 + minor*10000 + patch`. - [ ] Choose the version by **continuing the existing release-tag line**, not - restarting. The GitHub release tags run `v0.1 … v1.3` (v1.3 = - `versionName 1.3 / versionCode 100030000`), so the next release is **`v1.4`** - (→ versionCode `100040000`). A `v0.x` reset would derive a *lower* code and is + restarting. The GitHub release tags run `v0.1 … v1.5` (v1.5 = + `versionName 1.5 / versionCode 100050000`), so the next release is **`v1.6`** + (→ versionCode `100060000`). A `v0.x` reset would derive a *lower* code and is wrong. A Play `versionCode` can never be reused or decreased. - [ ] Publish a **GitHub Release** with that tag. This triggers the workflow, which builds and attaches a **signed `.aab`** (for Play) and a signed `.apk` @@ -80,17 +80,35 @@ tag (`vMAJOR.MINOR.PATCH`): --- +### Toolchain pinning (why the release build is reproducible) + +`global.json` pins the SDK **feature band**, not just the major version: + +```json +{ "sdk": { "version": "10.0.300", "rollForward": "latestPatch" } } +``` + +`latestPatch` accepts 10.0.3xx and nothing higher. This matters because +`dotnet workload restore` resolves the MAUI manifest per band: a band with no +published workload set yet falls back to the SDK's *baseline* manifest, which can +be far older than the band suggests. That is exactly how `v1.5` failed — the +10.0.400 band appeared mid-afternoon, its baseline maui manifest (10.0.0) +regressed XAML source generation (`MAUIX2000: Cannot resolve type ...:Routes`), +and the release build broke minutes after CI had been green on 10.0.302. + +To move bands, bump `version` **and** get a green Android head build on the new +band first — never by loosening `rollForward`. + ### What's already done in-repo - Signed `.aab` + `.apk` CI pipeline (`release-apk.yml`), tag→version derivation. +- Keystore generated + repository secrets uploaded (step 2). - Target API 35 (net10 android default), minSdk 24, `allowBackup=false`. - Final package name `com.sharpmush.sharpclient`. - Adaptive icon fixed (`ForegroundScale=0.65`) + 512 listing icon. - Privacy policy + data-safety content. +- Releases `v1.0` … `v1.5` tagged and built (step 3). ### Still needs a human decision / action -- Keystore generation + secret upload (step 2). -- Version choice + tagging (step 3) — next in line is **`v1.4`**; held pending - keystore secrets + your go-ahead. - Play Console account, listing copy, feature graphic, content rating (steps 4–6). diff --git a/global.json b/global.json index 34cc7a1..50baaf1 100644 --- a/global.json +++ b/global.json @@ -1,6 +1,6 @@ { "sdk": { "version": "10.0.300", - "rollForward": "latestFeature" + "rollForward": "latestPatch" } }