From ff5b3064a761cd81ebb5ff0ded83dae2f36979c8 Mon Sep 17 00:00:00 2001 From: ahall Date: Tue, 7 Jul 2026 13:39:30 +0100 Subject: [PATCH 1/3] ci: add build-samples workflow for Phase 3 mobile heads (#511) Adds CI coverage for the Android/iOS/Uno mobile build heads deferred from Phase 1 (#509/#512) and Phase 2 (#510/#514): - build-samples-todoapp-avalonia.yml: add android (ubuntu-latest) and ios (macos-latest) jobs for TodoApp.Avalonia.Android/.iOS. - build-samples-todoapp-maui.yml (new): android and ios jobs for TodoApp.MAUI, each scoped to a single TargetFramework via -p:TargetFramework / -f (the Windows head remains in build-samples-todoapp-windows.yml from Phase 2). - build-samples-todoapp-uno.yml (new): one job per TodoApp.Uno head (android, ios+maccatalyst, windows, browserwasm, desktop), each restoring/building the single multi-TFM project scoped to one TargetFramework at a time. - build-samples.yml: wire the two new sample workflows into the orchestrator and the all-samples-built gate. The desktop head is intentionally NOT marked continue-on-error here. #506's NU1903 (Tmds.DBus) finding is a NuGet audit warning only and this repo does not configure NuGet audit to fail builds. #506 also reports a NU1605 hit while investigating that warning, but that has not been confirmed to reproduce today or to be desktop-specific (CommunityToolkit.WinUI.Behaviors is referenced unconditionally in TodoApp.Uno.csproj), so all Uno heads are left as normal, blocking jobs pending real CI signal. actionlint passes on all 5 changed/new workflow files. Verified 'dotnet restore/build Datasync.Toolkit.sln --configuration Release' still succeeds with 0 warnings/errors (no regression to the core library). The mobile/Uno workload installs and builds themselves cannot be verified locally (no Android SDK, no full Xcode, no Windows) and will be confirmed once CI runs on this branch. --- .../build-samples-todoapp-avalonia.yml | 60 ++++++- .../workflows/build-samples-todoapp-maui.yml | 72 ++++++++ .../workflows/build-samples-todoapp-uno.yml | 160 ++++++++++++++++++ .../build-samples-todoapp-windows.yml | 4 +- .github/workflows/build-samples.yml | 11 +- 5 files changed, 298 insertions(+), 9 deletions(-) create mode 100644 .github/workflows/build-samples-todoapp-maui.yml create mode 100644 .github/workflows/build-samples-todoapp-uno.yml diff --git a/.github/workflows/build-samples-todoapp-avalonia.yml b/.github/workflows/build-samples-todoapp-avalonia.yml index f84d0413..a5e5a08 100644 --- a/.github/workflows/build-samples-todoapp-avalonia.yml +++ b/.github/workflows/build-samples-todoapp-avalonia.yml @@ -8,18 +8,21 @@ env: DOTNET_SKIP_FIRST_TIME_EXPERIENCE: 1 DOTNET_NOLOGO: true DOTNET_CONFIGURATION: 'Release' - # NOTE: This sample's solution (TodoApp.Avalonia.sln) also contains Android and iOS - # heads (net10.0-android / net10.0-ios), which require mobile workloads and are tracked - # separately in https://github.com/CommunityToolkit/Datasync/issues/511 (Phase 3). Only - # the shared and Desktop (net10.0) projects are built directly here, not the full .sln. + # NOTE: This sample's solution (TodoApp.Avalonia.sln) also contains Android and iOS heads + # (net10.0-android / net10.0-ios). Only the shared and Desktop (net10.0) projects are built + # directly here, not the full .sln - the Android and iOS heads are built by their own jobs + # below, each restoring/building its own project directly so only the workload needed for + # that head is installed on that runner. SharedProjectFile: 'samples/todoapp/TodoApp.Avalonia/TodoApp.Avalonia/TodoApp.Avalonia.csproj' DesktopProjectFile: 'samples/todoapp/TodoApp.Avalonia/TodoApp.Avalonia.Desktop/TodoApp.Avalonia.Desktop.csproj' + AndroidProjectFile: 'samples/todoapp/TodoApp.Avalonia/TodoApp.Avalonia.Android/TodoApp.Avalonia.Android.csproj' + iOSProjectFile: 'samples/todoapp/TodoApp.Avalonia/TodoApp.Avalonia.iOS/TodoApp.Avalonia.iOS.csproj' permissions: contents: read jobs: - build: + desktop: runs-on: ubuntu-latest steps: - name: Checkout Repository @@ -47,3 +50,50 @@ jobs: dotnet build ${{ env.DesktopProjectFile }} --configuration ${{ env.DOTNET_CONFIGURATION }} --no-restore + + android: + runs-on: ubuntu-latest + steps: + - name: Checkout Repository + uses: actions/checkout@v7 + + - name: Setup .NET + uses: actions/setup-dotnet@v5 + with: + dotnet-version: ${{ env.DOTNET_VERSION }} + + - name: Install Android workload + run: dotnet workload install android + + - name: Restore Android project + run: dotnet restore ${{ env.AndroidProjectFile }} + + - name: Build Android project + run: > + dotnet build ${{ env.AndroidProjectFile }} + --configuration ${{ env.DOTNET_CONFIGURATION }} + --no-restore + + ios: + # iOS builds require Xcode, which is only available on macOS runners. + runs-on: macos-latest + steps: + - name: Checkout Repository + uses: actions/checkout@v7 + + - name: Setup .NET + uses: actions/setup-dotnet@v5 + with: + dotnet-version: ${{ env.DOTNET_VERSION }} + + - name: Install iOS workload + run: dotnet workload install ios + + - name: Restore iOS project + run: dotnet restore ${{ env.iOSProjectFile }} + + - name: Build iOS project + run: > + dotnet build ${{ env.iOSProjectFile }} + --configuration ${{ env.DOTNET_CONFIGURATION }} + --no-restore diff --git a/.github/workflows/build-samples-todoapp-maui.yml b/.github/workflows/build-samples-todoapp-maui.yml new file mode 100644 index 0000000..5f03eda --- /dev/null +++ b/.github/workflows/build-samples-todoapp-maui.yml @@ -0,0 +1,72 @@ +name: Build Sample - TodoApp MAUI (Android / iOS) + +on: + workflow_call: + +env: + DOTNET_VERSION: '10.0.x' + DOTNET_SKIP_FIRST_TIME_EXPERIENCE: 1 + DOTNET_NOLOGO: true + DOTNET_CONFIGURATION: 'Release' + # TodoApp.MAUI.csproj targets net10.0-android;net10.0-ios, with net10.0-windows10.0.19041.0 + # conditionally appended only when building on Windows (that head is built separately in + # build-samples-todoapp-windows.yml). Restore/build here is explicitly scoped to one mobile + # TargetFramework per job so each runner only needs the workload for its own head. + MauiProjectFile: 'samples/todoapp/TodoApp.MAUI/TodoApp.MAUI.csproj' + AndroidTargetFramework: 'net10.0-android' + iOSTargetFramework: 'net10.0-ios' + +permissions: + contents: read + +jobs: + android: + runs-on: ubuntu-latest + steps: + - name: Checkout Repository + uses: actions/checkout@v7 + + - name: Setup .NET + uses: actions/setup-dotnet@v5 + with: + dotnet-version: ${{ env.DOTNET_VERSION }} + + - name: Install MAUI Android workload + run: dotnet workload install maui-android + + - name: Restore MAUI project (Android TFM only) + # NOTE: 'dotnet restore' has no -f|--framework option (-f means --force there, unlike + # 'dotnet build'). Use the MSBuild property directly to scope restore to one TFM. + run: dotnet restore ${{ env.MauiProjectFile }} -p:TargetFramework=${{ env.AndroidTargetFramework }} + + - name: Build MAUI project (Android TFM only) + run: > + dotnet build ${{ env.MauiProjectFile }} + -f ${{ env.AndroidTargetFramework }} + --configuration ${{ env.DOTNET_CONFIGURATION }} + --no-restore + + ios: + # iOS builds require Xcode, which is only available on macOS runners. + runs-on: macos-latest + steps: + - name: Checkout Repository + uses: actions/checkout@v7 + + - name: Setup .NET + uses: actions/setup-dotnet@v5 + with: + dotnet-version: ${{ env.DOTNET_VERSION }} + + - name: Install MAUI iOS workload + run: dotnet workload install maui-ios + + - name: Restore MAUI project (iOS TFM only) + run: dotnet restore ${{ env.MauiProjectFile }} -p:TargetFramework=${{ env.iOSTargetFramework }} + + - name: Build MAUI project (iOS TFM only) + run: > + dotnet build ${{ env.MauiProjectFile }} + -f ${{ env.iOSTargetFramework }} + --configuration ${{ env.DOTNET_CONFIGURATION }} + --no-restore diff --git a/.github/workflows/build-samples-todoapp-uno.yml b/.github/workflows/build-samples-todoapp-uno.yml new file mode 100644 index 0000000..63ec1b7 --- /dev/null +++ b/.github/workflows/build-samples-todoapp-uno.yml @@ -0,0 +1,160 @@ +name: Build Sample - TodoApp Uno + +on: + workflow_call: + +env: + DOTNET_VERSION: '10.0.x' + DOTNET_SKIP_FIRST_TIME_EXPERIENCE: 1 + DOTNET_NOLOGO: true + DOTNET_CONFIGURATION: 'Release' + # TodoApp.Uno.csproj is a single Uno.Sdk project with a multi-head TargetFrameworks list + # (net10.0-android;net10.0-ios;net10.0-maccatalyst;net10.0-windows10.0.26100; + # net10.0-browserwasm;net10.0-desktop). No single runner can build every head (mobile heads + # need Android/iOS workloads, the Windows head needs windows-latest, etc.), so each job below + # restores/builds one head at a time, scoped via the MSBuild TargetFramework property. + UnoProjectFile: 'samples/todoapp/TodoApp.Uno/TodoApp.Uno/TodoApp.Uno.csproj' + AndroidTargetFramework: 'net10.0-android' + iOSTargetFramework: 'net10.0-ios' + MacCatalystTargetFramework: 'net10.0-maccatalyst' + WindowsTargetFramework: 'net10.0-windows10.0.26100' + BrowserWasmTargetFramework: 'net10.0-browserwasm' + DesktopTargetFramework: 'net10.0-desktop' + +permissions: + contents: read + +jobs: + android: + runs-on: ubuntu-latest + steps: + - name: Checkout Repository + uses: actions/checkout@v7 + + - name: Setup .NET + uses: actions/setup-dotnet@v5 + with: + dotnet-version: ${{ env.DOTNET_VERSION }} + + - name: Install Android workload + run: dotnet workload install android + + - name: Restore Uno project (Android TFM only) + # NOTE: 'dotnet restore' has no -f|--framework option (-f means --force there, unlike + # 'dotnet build'). Use the MSBuild property directly to scope restore to one TFM. + run: dotnet restore ${{ env.UnoProjectFile }} -p:TargetFramework=${{ env.AndroidTargetFramework }} + + - name: Build Uno project (Android TFM only) + run: > + dotnet build ${{ env.UnoProjectFile }} + -f ${{ env.AndroidTargetFramework }} + --configuration ${{ env.DOTNET_CONFIGURATION }} + --no-restore + + ios-maccatalyst: + # iOS and Mac Catalyst builds both require Xcode, which is only available on macOS runners. + runs-on: macos-latest + steps: + - name: Checkout Repository + uses: actions/checkout@v7 + + - name: Setup .NET + uses: actions/setup-dotnet@v5 + with: + dotnet-version: ${{ env.DOTNET_VERSION }} + + - name: Install iOS and Mac Catalyst workloads + run: dotnet workload install ios maccatalyst + + - name: Restore Uno project (iOS TFM only) + run: dotnet restore ${{ env.UnoProjectFile }} -p:TargetFramework=${{ env.iOSTargetFramework }} + + - name: Build Uno project (iOS TFM only) + run: > + dotnet build ${{ env.UnoProjectFile }} + -f ${{ env.iOSTargetFramework }} + --configuration ${{ env.DOTNET_CONFIGURATION }} + --no-restore + + - name: Restore Uno project (Mac Catalyst TFM only) + run: dotnet restore ${{ env.UnoProjectFile }} -p:TargetFramework=${{ env.MacCatalystTargetFramework }} + + - name: Build Uno project (Mac Catalyst TFM only) + run: > + dotnet build ${{ env.UnoProjectFile }} + -f ${{ env.MacCatalystTargetFramework }} + --configuration ${{ env.DOTNET_CONFIGURATION }} + --no-restore + + windows: + runs-on: windows-latest + steps: + - name: Checkout Repository + uses: actions/checkout@v7 + + - name: Setup .NET + uses: actions/setup-dotnet@v5 + with: + dotnet-version: ${{ env.DOTNET_VERSION }} + + - name: Restore Uno project (Windows TFM only) + run: dotnet restore ${{ env.UnoProjectFile }} -p:TargetFramework=${{ env.WindowsTargetFramework }} + + - name: Build Uno project (Windows TFM only) + run: > + dotnet build ${{ env.UnoProjectFile }} + -f ${{ env.WindowsTargetFramework }} + --configuration ${{ env.DOTNET_CONFIGURATION }} + --no-restore + + browserwasm: + runs-on: ubuntu-latest + steps: + - name: Checkout Repository + uses: actions/checkout@v7 + + - name: Setup .NET + uses: actions/setup-dotnet@v5 + with: + dotnet-version: ${{ env.DOTNET_VERSION }} + + - name: Install WebAssembly build tools workload + run: dotnet workload install wasm-tools + + - name: Restore Uno project (Browser WebAssembly TFM only) + run: dotnet restore ${{ env.UnoProjectFile }} -p:TargetFramework=${{ env.BrowserWasmTargetFramework }} + + - name: Build Uno project (Browser WebAssembly TFM only) + run: > + dotnet build ${{ env.UnoProjectFile }} + -f ${{ env.BrowserWasmTargetFramework }} + --configuration ${{ env.DOTNET_CONFIGURATION }} + --no-restore + + desktop: + # NOTE: https://github.com/CommunityToolkit/Datasync/issues/506 is investigating a NU1903 + # audit warning (Tmds.DBus) for this head; that alone does not fail restore/build since this + # repo does not configure NuGet audit to fail on warnings. That investigation separately + # reported hitting a NU1605 package-downgrade error (Uno.WinUI version floor conflict via + # CommunityToolkit.WinUI.Behaviors) while digging into the warning - if that reproduces here + # and fails this job, do not silently mark it continue-on-error; comment on #506 with the + # concrete failure first, since that conflict is not confirmed to be desktop-specific. + runs-on: ubuntu-latest + steps: + - name: Checkout Repository + uses: actions/checkout@v7 + + - name: Setup .NET + uses: actions/setup-dotnet@v5 + with: + dotnet-version: ${{ env.DOTNET_VERSION }} + + - name: Restore Uno project (Desktop TFM only) + run: dotnet restore ${{ env.UnoProjectFile }} -p:TargetFramework=${{ env.DesktopTargetFramework }} + + - name: Build Uno project (Desktop TFM only) + run: > + dotnet build ${{ env.UnoProjectFile }} + -f ${{ env.DesktopTargetFramework }} + --configuration ${{ env.DOTNET_CONFIGURATION }} + --no-restore diff --git a/.github/workflows/build-samples-todoapp-windows.yml b/.github/workflows/build-samples-todoapp-windows.yml index 73fba07..dd8c2e4 100644 --- a/.github/workflows/build-samples-todoapp-windows.yml +++ b/.github/workflows/build-samples-todoapp-windows.yml @@ -14,8 +14,8 @@ env: WpfProjectFile: 'samples/todoapp/TodoApp.WPF/TodoApp.WPF.csproj' # TodoApp.MAUI.csproj targets net10.0-android;net10.0-ios, with net10.0-windows10.0.19041.0 # conditionally appended only when building on Windows. Android/iOS heads require separate - # workloads and are tracked in https://github.com/CommunityToolkit/Datasync/issues/511 (Phase 3), - # so restore/build here is explicitly scoped to the Windows TargetFramework only. + # workloads and are built by build-samples-todoapp-maui.yml instead, so restore/build here is + # explicitly scoped to the Windows TargetFramework only. MauiProjectFile: 'samples/todoapp/TodoApp.MAUI/TodoApp.MAUI.csproj' MauiWindowsTargetFramework: 'net10.0-windows10.0.19041.0' diff --git a/.github/workflows/build-samples.yml b/.github/workflows/build-samples.yml index 31faae6..1fb39ae 100644 --- a/.github/workflows/build-samples.yml +++ b/.github/workflows/build-samples.yml @@ -34,9 +34,14 @@ jobs: todoapp-windows: uses: ./.github/workflows/build-samples-todoapp-windows.yml + todoapp-maui: + uses: ./.github/workflows/build-samples-todoapp-maui.yml + + todoapp-uno: + uses: ./.github/workflows/build-samples-todoapp-uno.yml + # Single aggregation point so branch protection only needs to require one check, - # regardless of how many sample workflows are added over time (see Phase 3 - # follow-up: https://github.com/CommunityToolkit/Datasync/issues/511). + # regardless of how many sample workflows are added over time. all-samples-built: name: All samples built if: always() @@ -48,6 +53,8 @@ jobs: - todoapp-tutorial - todoapp-avalonia - todoapp-windows + - todoapp-maui + - todoapp-uno runs-on: ubuntu-latest steps: - name: Check sample build results From bfc7dc08f8293d53741b4088268b6f4eec94bf3c Mon Sep 17 00:00:00 2001 From: ahall Date: Tue, 7 Jul 2026 13:44:32 +0100 Subject: [PATCH 2/3] fix: align Info.plist MinimumOSVersion with SupportedOSPlatformVersion for TodoApp.Avalonia.iOS CI (added in #511) surfaced a pre-existing mismatch: Info.plist declared MinimumOSVersion 13.0 while TodoApp.Avalonia.iOS.csproj declares SupportedOSPlatformVersion 15.0, which the iOS build task hard-fails on ('The MinimumOSVersion value in the Info.plist (13.0) does not match the SupportedOSPlatformVersion value (15.0) in the project file'). Bump Info.plist's MinimumOSVersion to 15.0 to match the csproj, which is treated as the source of truth here. Unrelated to this fix: the same CI run also surfaced a pre-existing CS8604 nullable-reference warning in the shared LoggingHandler.cs. It does not fail the build (the run reported 1 warning, 1 error - only the Info.plist mismatch was the error) and is left untouched to keep this change scoped to the actual build failure. --- .../todoapp/TodoApp.Avalonia/TodoApp.Avalonia.iOS/Info.plist | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/todoapp/TodoApp.Avalonia/TodoApp.Avalonia.iOS/Info.plist b/samples/todoapp/TodoApp.Avalonia/TodoApp.Avalonia.iOS/Info.plist index 8446c28..643284c 100644 --- a/samples/todoapp/TodoApp.Avalonia/TodoApp.Avalonia.iOS/Info.plist +++ b/samples/todoapp/TodoApp.Avalonia/TodoApp.Avalonia.iOS/Info.plist @@ -13,7 +13,7 @@ LSRequiresIPhoneOS MinimumOSVersion - 13.0 + 15.0 UIDeviceFamily 1 From d7e68fc46c11d6b6a1887cb376b34180c43a921a Mon Sep 17 00:00:00 2001 From: ahall Date: Tue, 7 Jul 2026 14:55:18 +0100 Subject: [PATCH 3/3] ci: disable todoapp-uno job pending #506 CI confirmed the NU1605 (Uno.WinUI 5.5.87 vs 5.4.22, driven by CommunityToolkit.WinUI.Behaviors' floor vs. the Uno.Sdk pin in global.json) is not desktop-specific as originally suspected in #511 - it fails restore for every TodoApp.Uno head (confirmed via the android-head CI log and locally reproduced on net10.0-desktop, no workload required), since CommunityToolkit.WinUI.Behaviors is referenced unconditionally in TodoApp.Uno.csproj. Comment out the todoapp-uno job in build-samples.yml's orchestrator (and drop it from all-samples-built's needs) rather than trying to patch around it here. build-samples-todoapp-uno.yml itself is left fully intact (one job per head, TFM-scoped restore/build) and just needs to be wired back in once #506 lands a fix and TodoApp.Uno.csproj restores cleanly. Posted the concrete reproduction details to #506 so the fix for that issue also covers re-enabling this CI job. --- .../workflows/build-samples-todoapp-uno.yml | 19 ++++++++++++------- .github/workflows/build-samples.yml | 14 +++++++++++--- 2 files changed, 23 insertions(+), 10 deletions(-) diff --git a/.github/workflows/build-samples-todoapp-uno.yml b/.github/workflows/build-samples-todoapp-uno.yml index 63ec1b7..635a486 100644 --- a/.github/workflows/build-samples-todoapp-uno.yml +++ b/.github/workflows/build-samples-todoapp-uno.yml @@ -1,5 +1,12 @@ name: Build Sample - TodoApp Uno +# NOTE: This workflow is NOT currently wired into build-samples.yml. TodoApp.Uno.csproj fails +# to restore on every head with NU1605 (Uno.WinUI version downgrade caused by +# CommunityToolkit.WinUI.Behaviors' floor vs. the Uno.Sdk pin in global.json) - see the jobs +# below and https://github.com/CommunityToolkit/Datasync/issues/506, which is tracking the fix. +# Re-add the `todoapp-uno` job to build-samples.yml (and to all-samples-built's `needs`) once +# #506 is resolved and TodoApp.Uno.csproj restores cleanly. + on: workflow_call: @@ -132,13 +139,11 @@ jobs: --no-restore desktop: - # NOTE: https://github.com/CommunityToolkit/Datasync/issues/506 is investigating a NU1903 - # audit warning (Tmds.DBus) for this head; that alone does not fail restore/build since this - # repo does not configure NuGet audit to fail on warnings. That investigation separately - # reported hitting a NU1605 package-downgrade error (Uno.WinUI version floor conflict via - # CommunityToolkit.WinUI.Behaviors) while digging into the warning - if that reproduces here - # and fails this job, do not silently mark it continue-on-error; comment on #506 with the - # concrete failure first, since that conflict is not confirmed to be desktop-specific. + # NOTE: this head (along with every other head in this file) currently fails to restore + # with NU1605 - see the file-level NOTE above and #506. #506 originally reported the NU1903 + # Tmds.DBus audit warning for this head specifically; that warning alone is harmless (this + # repo does not configure NuGet audit to fail on warnings), but the NU1605 uncovered while + # investigating it turned out to be project-wide, not desktop-specific. runs-on: ubuntu-latest steps: - name: Checkout Repository diff --git a/.github/workflows/build-samples.yml b/.github/workflows/build-samples.yml index 1fb39ae..aa7de6d 100644 --- a/.github/workflows/build-samples.yml +++ b/.github/workflows/build-samples.yml @@ -37,8 +37,17 @@ jobs: todoapp-maui: uses: ./.github/workflows/build-samples-todoapp-maui.yml - todoapp-uno: - uses: ./.github/workflows/build-samples-todoapp-uno.yml + # NOTE: todoapp-uno (build-samples-todoapp-uno.yml) is intentionally NOT wired in here. + # TodoApp.Uno.csproj fails to restore on every head with: + # NU1605: Detected package downgrade: Uno.WinUI from 5.5.87 to 5.4.22 + # TodoApp.Uno -> CommunityToolkit.WinUI.Behaviors 8.2.250402 -> Uno.WinUI (>= 5.5.87) + # TodoApp.Uno -> Uno.WinUI (>= 5.4.22) + # This is unconditional (CommunityToolkit.WinUI.Behaviors has no TFM condition on its + # PackageReference), so it blocks every TFM, not just the desktop head as originally + # suspected. See https://github.com/CommunityToolkit/Datasync/issues/506, which is tracking + # the underlying Uno.WinUI/CommunityToolkit.WinUI.Behaviors version conflict. Re-enable this + # job (add it back to the jobs list and to all-samples-built's needs below) once #506 is + # resolved and TodoApp.Uno.csproj restores cleanly. # Single aggregation point so branch protection only needs to require one check, # regardless of how many sample workflows are added over time. @@ -54,7 +63,6 @@ jobs: - todoapp-avalonia - todoapp-windows - todoapp-maui - - todoapp-uno runs-on: ubuntu-latest steps: - name: Check sample build results