|
48 | 48 | release_hash: ${{ steps.pipeline.outputs.release_hash }} |
49 | 49 | should_release: ${{ steps.pipeline.outputs.should_release }} |
50 | 50 |
|
51 | | - env: |
52 | | - # SixLabors.ImageSharp 4.0 requires a build-time license key (ImGui.App is a |
53 | | - # direct dependency). Directory.Build.props maps this into the |
54 | | - # SixLaborsLicenseKey MSBuild property. Set the SIXLABORS_LICENSE_KEY repo secret. |
55 | | - SIXLABORS_LICENSE_KEY: ${{ secrets.SIXLABORS_LICENSE_KEY }} |
56 | | - |
57 | 51 | steps: |
58 | 52 | - name: Set up JDK 17 |
59 | 53 | uses: actions/setup-java@v4 |
@@ -197,261 +191,6 @@ jobs: |
197 | 191 | ./coverage/* |
198 | 192 | retention-days: 7 |
199 | 193 |
|
200 | | - ios-build: |
201 | | - # Compile-only verification that the net10.0-ios stub keeps building on Mac. |
202 | | - # No tests — Apple Simulator boot from CI is a separate problem (see plan §5 Task 2). |
203 | | - # Runs in parallel with `build`; failure here is independent and does not gate release. |
204 | | - name: Build net10.0-ios (macOS) |
205 | | - runs-on: macos-14 |
206 | | - timeout-minutes: 20 |
207 | | - permissions: |
208 | | - contents: read |
209 | | - |
210 | | - env: |
211 | | - # ImGui.App directly references SixLabors.ImageSharp 4.0 on net10.0-ios too, |
212 | | - # so this compile-only job needs the license key as well. |
213 | | - SIXLABORS_LICENSE_KEY: ${{ secrets.SIXLABORS_LICENSE_KEY }} |
214 | | - |
215 | | - steps: |
216 | | - - name: Checkout Repository |
217 | | - uses: actions/checkout@v4 |
218 | | - with: |
219 | | - fetch-depth: 1 |
220 | | - lfs: true |
221 | | - submodules: recursive |
222 | | - persist-credentials: false |
223 | | - |
224 | | - - name: Setup .NET SDK ${{ env.DOTNET_VERSION }} |
225 | | - uses: actions/setup-dotnet@v4 |
226 | | - with: |
227 | | - dotnet-version: ${{ env.DOTNET_VERSION }}.x |
228 | | - |
229 | | - - name: Install iOS workload |
230 | | - # No caching yet — get the install path working first; caching workload manifests |
231 | | - # is a known-finicky follow-up (manifests need both the file tree and a metadata |
232 | | - # registration to "count" as installed). |
233 | | - run: dotnet workload install ios |
234 | | - |
235 | | - # The csproj cross-targets net10.0;net9.0;net8.0;net10.0-ios on macOS AND ktsu.Sdk |
236 | | - # forces RuntimeIdentifiers=win-x64;win-x86;win-arm64;osx-x64;osx-arm64;linux-x64;linux-arm64 |
237 | | - # on every project. The combination asks NuGet for the matching |
238 | | - # Microsoft.NETCore.App.Runtime.Mono.<rid> pack at the SDK version — those packs are |
239 | | - # workload-delivered in .NET 10 and no longer on nuget.org, so restore 404s. Windows |
240 | | - # CI gets away with it because the Windows runner has the Mono packs bundled with |
241 | | - # its dotnet install; setup-dotnet on the Mac runner does not. Scoping the restore |
242 | | - # to net10.0-ios alone AND clearing the RID matrix sidesteps the issue — we're only |
243 | | - # compile-checking the IL, no RID-specific output needed. |
244 | | - - name: Restore ImGui.App (net10.0-ios, no RID matrix) |
245 | | - run: dotnet restore ImGui.App/ImGui.App.csproj -p:TargetFrameworks=net10.0-ios -p:RuntimeIdentifiers= |
246 | | - |
247 | | - # EnforceCodeStyleInBuild=false bypasses the IDE0055 formatting analyser: the repo's |
248 | | - # working-tree files are LF, .editorconfig demands CRLF, and Windows checkouts get |
249 | | - # auto-converted to CRLF by git's core.autocrlf — macOS checkouts don't, so IDE0055 |
250 | | - # fires here on baseline code that's untouched by this PR. The Windows job is the |
251 | | - # authoritative formatter; the macOS job is a compile-check. |
252 | | - - name: Build ImGui.App (net10.0-ios) |
253 | | - run: dotnet build ImGui.App/ImGui.App.csproj -c Release -p:TargetFrameworks=net10.0-ios -p:RuntimeIdentifiers= -p:EnforceCodeStyleInBuild=false --no-restore |
254 | | - |
255 | | - ios-simulator: |
256 | | - # Runtime verification: build the headless smoke app AND the curated ImGuiAppDemo.iOS for the |
257 | | - # simulator, boot a sim, launch each, and assert the lifecycle ticks (the app prints a marker and |
258 | | - # exits after N frames via the IMGUIAPP_IOS_SMOKE_FRAMES hook). Runs in parallel; does not gate |
259 | | - # release. Building+launching two apps after a cold cimgui cache approaches the old 30-min cap, so |
260 | | - # the budget is 50 min (a warm-cache run is ~20). |
261 | | - name: iOS Simulator Smoke Test |
262 | | - # The .NET 10 iOS workload (Microsoft.iOS 26.5) requires Xcode 26.5 to build a runnable .app. |
263 | | - # macos-15 only carries up to Xcode 26.3; macos-26 (Tahoe) ships the matching Xcode 26.5+. |
264 | | - # (The compile-only ios-build job needs no Xcode, so it stays on macos-14.) |
265 | | - runs-on: macos-26 |
266 | | - timeout-minutes: 50 |
267 | | - # HARD GATE: the .NET 10 + Xcode 26 symlinked-developer-dir bug that broke native linking |
268 | | - # (`xcodebuild -find` -> errno=Invalid argument) is worked around by the "Resolve and pin the |
269 | | - # real Xcode" step below (readlink -f + xcode-select/DEVELOPER_DIR pin; dotnet/macios#21762), so |
270 | | - # this runtime smoke test now reliably passes and gates the PR like any other required check. |
271 | | - permissions: |
272 | | - contents: read |
273 | | - |
274 | | - env: |
275 | | - # The smoke app and ImGuiAppDemo.iOS build ImGui.App (a direct SixLabors.ImageSharp |
276 | | - # 4.0 dependency) and decode an image via ImageSharp, so this job needs the key too. |
277 | | - SIXLABORS_LICENSE_KEY: ${{ secrets.SIXLABORS_LICENSE_KEY }} |
278 | | - |
279 | | - steps: |
280 | | - - name: Checkout Repository |
281 | | - uses: actions/checkout@v4 |
282 | | - with: |
283 | | - fetch-depth: 1 |
284 | | - lfs: true |
285 | | - submodules: recursive |
286 | | - persist-credentials: false |
287 | | - |
288 | | - - name: Setup .NET SDK ${{ env.DOTNET_VERSION }} |
289 | | - uses: actions/setup-dotnet@v4 |
290 | | - with: |
291 | | - dotnet-version: ${{ env.DOTNET_VERSION }}.x |
292 | | - |
293 | | - - name: Install iOS workload |
294 | | - run: dotnet workload install ios |
295 | | - |
296 | | - # Diagnostics: this job can only be debugged from CI (no local Mac), so dump the runner's |
297 | | - # actual SDK, workload, iOS runtime-pack, Xcode, and simulator state up front. Never fails. |
298 | | - - name: iOS toolchain diagnostics |
299 | | - run: | |
300 | | - set -x |
301 | | - dotnet --info || true |
302 | | - dotnet workload list || true |
303 | | - echo "--- installed packs ---" |
304 | | - ls -1 "$HOME/.dotnet/packs" 2>/dev/null | grep -i ios || true |
305 | | - ls -1 /usr/local/share/dotnet/packs 2>/dev/null | grep -i ios || true |
306 | | - echo "--- installed Xcodes ---" |
307 | | - ls -d /Applications/Xcode*.app 2>/dev/null || true |
308 | | - echo "--- xcode / sdk ---" |
309 | | - xcodebuild -version || true |
310 | | - xcrun --sdk iphonesimulator --show-sdk-version || true |
311 | | - echo "--- simulator device types ---" |
312 | | - xcrun simctl list devicetypes | grep -i iphone || true |
313 | | - echo "--- simulator runtimes ---" |
314 | | - xcrun simctl list runtimes || true |
315 | | - continue-on-error: true |
316 | | - |
317 | | - # ROOT CAUSE: the hosted Xcode_26.5.0.app is a SYMLINK, and on .NET 10 + Xcode 26 hosted runners |
318 | | - # `xcodebuild -find` intermittently fails to resolve the toolchain through a symlinked developer |
319 | | - # dir - dying with `errno=Invalid argument` (NOT "No such file or directory"; the SDK exists). |
320 | | - # The managed build and IL strip never call `xcrun -find` so they pass, but native clang linking |
321 | | - # (and `-find actool`) do, so they die with clang exit 72. Fix: resolve the .app symlink to its |
322 | | - # REAL path with `readlink -f` and pin BOTH xcode-select and DEVELOPER_DIR to it. `readlink -f` |
323 | | - # is a no-op on an already-real path, so this is safe either way; writing DEVELOPER_DIR to |
324 | | - # $GITHUB_ENV overrides any workflow/job-level value for later steps. |
325 | | - # Refs: dotnet/macios#21762, actions/runner-images#13347. |
326 | | - - name: Resolve and pin the real Xcode 26.5 path (symlink workaround) |
327 | | - run: | |
328 | | - set -uxo pipefail |
329 | | - XC=/Applications/Xcode_26.5.app |
330 | | - [ -d "$XC" ] || XC=/Applications/Xcode_26.5.0.app |
331 | | - [ -d "$XC" ] || XC="$(dirname "$(dirname "$(xcode-select -p)")")" |
332 | | - XC="$(readlink -f "$XC")" |
333 | | - echo "Resolved real Xcode: $XC" |
334 | | - sudo xcode-select -switch "$XC/Contents/Developer" |
335 | | - echo "DEVELOPER_DIR=$XC/Contents/Developer" >> "$GITHUB_ENV" |
336 | | - xcodebuild -version |
337 | | - # Informational: confirm the host link tool now resolves through the real path. |
338 | | - xcrun --find install_name_tool || echo "WARN: install_name_tool did not resolve via $XC" |
339 | | -
|
340 | | - # Hexa.NET.ImGui ships no native cimgui for iOS, so build it from source (Dear ImGui 1.92.2b, |
341 | | - # matching Hexa 2.2.9) into a simulator static lib that ImGui.App statically links via a |
342 | | - # NativeReference. Cached by the build script's hash so it only rebuilds when the recipe changes. |
343 | | - # Runs after the Xcode pin so xcrun resolves the toolchain; before the build so the |
344 | | - # NativeReference's Exists() condition is satisfied when ImGui.App compiles. |
345 | | - - name: Cache native cimgui (iOS simulator) |
346 | | - uses: actions/cache@v4 |
347 | | - with: |
348 | | - path: ImGui.App/Platform/iOS/native |
349 | | - key: cimgui-sim-arm64-dylib-imgui1.92.3-${{ hashFiles('scripts/build-cimgui-ios.sh') }} |
350 | | - |
351 | | - - name: Build native cimgui for the simulator |
352 | | - run: | |
353 | | - set -euxo pipefail |
354 | | - bash scripts/build-cimgui-ios.sh |
355 | | - # Stash the dylib outside the repo tree: the in-tree native/ dir is gitignored and gets |
356 | | - # wiped (by ktsu.Sdk/dotnet cleaning untracked files) before the embed step runs, so the |
357 | | - # embed step copies from this stable location instead. |
358 | | - cp ImGui.App/Platform/iOS/native/cimgui.dylib "$RUNNER_TEMP/cimgui.dylib" |
359 | | -
|
360 | | - # The smoke app is Microsoft.NET.Sdk, but it references ImGui.App (ktsu.Sdk), which forces a |
361 | | - # desktop RuntimeIdentifiers matrix whose Mono RID packs 404 on macOS (see the ios-build job). |
362 | | - # Clearing RuntimeIdentifiers and pinning the single simulator RID sidesteps that while still |
363 | | - # producing a runnable .app bundle. The install step provisions the iossimulator-x64 Mono |
364 | | - # runtime, so we target that RID; workload restore pulls the matching Microsoft.iOS runtime pack. |
365 | | - - name: Restore iOS workload packs for the smoke app |
366 | | - run: dotnet workload restore tests/ImGui.App.iOS.SmokeTest/ImGui.App.iOS.SmokeTest.csproj |
367 | | - continue-on-error: true |
368 | | - |
369 | | - # The referenced ImGui.App is a *library*; in .NET 10 libraries default to the OLDEST iOS |
370 | | - # platform version (_26.0), whose runtime packs aren't installed on the runner (only the |
371 | | - # latest _26.5 packs are) — hence NU1102 on ImGui.App.csproj. UseFloatingTargetPlatformVersion |
372 | | - # makes the library use the latest platform version (26.5) like the executable, aligning both |
373 | | - # on the installed runtime packs. See https://learn.microsoft.com/dotnet/ios/building-apps/build-properties#usefloatingtargetplatformversion |
374 | | - # ktsu.Sdk pins RuntimeFrameworkVersion=10.0.0 (for the desktop .NETCore.App runtime). On iOS |
375 | | - # that bogus version is inherited by the Apple runtime pack (Microsoft.iOS.Runtime.*, actually |
376 | | - # versioned 26.5.x), causing NU1102. Clearing RuntimeFrameworkVersion lets the iOS workload |
377 | | - # resolve the real pack version. Combined with UseFloatingTargetPlatformVersion (library -> |
378 | | - # latest _26.5 packs, which are the ones installed on the runner). |
379 | | - - name: Restore smoke app (net10.0-ios, simulator RID) |
380 | | - run: dotnet restore tests/ImGui.App.iOS.SmokeTest/ImGui.App.iOS.SmokeTest.csproj -p:TargetFrameworks=net10.0-ios -p:RuntimeIdentifiers= -p:RuntimeFrameworkVersion= -p:UseFloatingTargetPlatformVersion=true -r iossimulator-arm64 |
381 | | - |
382 | | - - name: Build smoke app (.app for simulator) |
383 | | - run: dotnet build tests/ImGui.App.iOS.SmokeTest/ImGui.App.iOS.SmokeTest.csproj -c Release -f net10.0-ios -r iossimulator-arm64 -p:RuntimeIdentifiers= -p:RuntimeFrameworkVersion= -p:UseFloatingTargetPlatformVersion=true -p:EnforceCodeStyleInBuild=false --no-restore |
384 | | - |
385 | | - - name: Locate built .app bundle |
386 | | - id: findapp |
387 | | - run: | |
388 | | - set -euxo pipefail |
389 | | - APP=$(find tests/ImGui.App.iOS.SmokeTest/bin -type d -name "*.app" | head -1) |
390 | | - test -n "$APP" |
391 | | - echo "app=$APP" >> "$GITHUB_OUTPUT" |
392 | | -
|
393 | | - # Embed cimgui.dylib into the built .app. Hexa.NET.ImGui ships no native cimgui for iOS, and a |
394 | | - # NativeReference did not link it into this Microsoft.NET.Sdk app, so copy the dylib into the |
395 | | - # bundle directly; the runtime resolver dlopens it by bundle path. The simulator does not enforce |
396 | | - # code signing, so an unsigned bundled dylib loads. |
397 | | - - name: Embed cimgui.dylib into the .app bundle |
398 | | - run: cp "$RUNNER_TEMP/cimgui.dylib" "${{ steps.findapp.outputs.app }}/cimgui.dylib" |
399 | | - |
400 | | - - name: Boot simulator |
401 | | - run: | |
402 | | - set -euxo pipefail |
403 | | - UDID=$(xcrun simctl create imguiapp-smoke "iPhone 15" 2>/dev/null \ |
404 | | - || xcrun simctl create imguiapp-smoke com.apple.CoreSimulator.SimDeviceType.iPhone-15) |
405 | | - echo "SIM_UDID=$UDID" >> "$GITHUB_ENV" |
406 | | - xcrun simctl boot "$UDID" |
407 | | - xcrun simctl bootstatus "$UDID" -b |
408 | | -
|
409 | | - - name: Install, launch, and assert lifecycle ticked |
410 | | - run: | |
411 | | - set -euxo pipefail |
412 | | - xcrun simctl install "$SIM_UDID" "${{ steps.findapp.outputs.app }}" |
413 | | - # simctl forwards SIMCTL_CHILD_* env vars (prefix stripped) to the launched app. |
414 | | - SIMCTL_CHILD_IMGUIAPP_IOS_SMOKE_FRAMES=30 \ |
415 | | - xcrun simctl launch --console-pty --terminate-running-process "$SIM_UDID" dev.ktsu.imguiapp.smoketest 2>&1 | tee /tmp/smoke.log |
416 | | - grep -q "IMGUIAPP_IOS_SMOKE_OK" /tmp/smoke.log |
417 | | -
|
418 | | - # --- Curated iOS demo (examples/ImGuiAppDemo.iOS) --- |
419 | | - # A richer showcase than the headless smoke app: widgets, Unicode/emoji, a GPU texture, animation, |
420 | | - # and the input/IO surface, all using the iOS-safe non-variadic ImGui subset. It reuses this job's |
421 | | - # booted simulator, cimgui dylib, and the IMGUIAPP_IOS_SMOKE_FRAMES hook (baked into ImGui.App's |
422 | | - # view controller), so the same minimal SDK + restore flags as the smoke app apply. |
423 | | - - name: Restore demo app (net10.0-ios, simulator RID) |
424 | | - run: dotnet restore examples/ImGuiAppDemo.iOS/ImGuiAppDemo.iOS.csproj -p:TargetFrameworks=net10.0-ios -p:RuntimeIdentifiers= -p:RuntimeFrameworkVersion= -p:UseFloatingTargetPlatformVersion=true -r iossimulator-arm64 |
425 | | - |
426 | | - - name: Build demo app (.app for simulator) |
427 | | - run: dotnet build examples/ImGuiAppDemo.iOS/ImGuiAppDemo.iOS.csproj -c Release -f net10.0-ios -r iossimulator-arm64 -p:RuntimeIdentifiers= -p:RuntimeFrameworkVersion= -p:UseFloatingTargetPlatformVersion=true -p:EnforceCodeStyleInBuild=false --no-restore |
428 | | - |
429 | | - - name: Locate built demo .app bundle |
430 | | - id: finddemo |
431 | | - run: | |
432 | | - set -euxo pipefail |
433 | | - APP=$(find examples/ImGuiAppDemo.iOS/bin -type d -name "*.app" | head -1) |
434 | | - test -n "$APP" |
435 | | - echo "app=$APP" >> "$GITHUB_OUTPUT" |
436 | | -
|
437 | | - - name: Embed cimgui.dylib into the demo .app bundle |
438 | | - run: cp "$RUNNER_TEMP/cimgui.dylib" "${{ steps.finddemo.outputs.app }}/cimgui.dylib" |
439 | | - |
440 | | - - name: Install, launch, and assert the demo ticked + uploaded its texture |
441 | | - run: | |
442 | | - set -euxo pipefail |
443 | | - xcrun simctl install "$SIM_UDID" "${{ steps.finddemo.outputs.app }}" |
444 | | - SIMCTL_CHILD_IMGUIAPP_IOS_SMOKE_FRAMES=30 \ |
445 | | - xcrun simctl launch --console-pty --terminate-running-process "$SIM_UDID" dev.ktsu.imguiapp.demo 2>&1 | tee /tmp/demo.log |
446 | | - # The lifecycle ticked N frames without crashing in the Metal pipeline... |
447 | | - grep -q "IMGUIAPP_IOS_SMOKE_OK" /tmp/demo.log |
448 | | - # ...and the bundled image decoded (ImageSharp) + uploaded on Metal — PR-2 textures end-to-end. |
449 | | - grep -q "IMGUIAPP_DEMO logo loaded" /tmp/demo.log |
450 | | -
|
451 | | - - name: Cleanup simulator |
452 | | - if: always() |
453 | | - run: xcrun simctl delete "${SIM_UDID:-imguiapp-smoke}" || true |
454 | | - |
455 | 194 | winget: |
456 | 195 | name: Update Winget Manifests |
457 | 196 | needs: build |
|
0 commit comments