Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
115 changes: 96 additions & 19 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -162,31 +162,16 @@ jobs:
with:
dotnet-version: 9.0.x

- name: Install Android/iOS/macOS/MAUI workloads
run: dotnet workload install android ios macos maui

# For the sample build below - the workload alone stops at XA5207 without the platform.
- name: Set up the Android SDK
uses: android-actions/setup-android@v3
with:
packages: 'platforms;android-35'

# No MAUI/platform workloads here any more: the unit and package tests are plain net9 and
# inspect the packed .nupkg files, and the sample build that needed them moved to its own
# build-samples matrix (below), which exercises the net8 and net10 extremes rather than the
# single net9 pair this step used to.
- name: Run unit tests
run: dotnet test tests/FFmpegKit.Net.UnitTests --logger 'trx;LogFileName=unit-tests.trx'

- name: Run package tests
run: dotnet test tests/FFmpegKit.Net.PackageTests --logger 'trx;LogFileName=package-tests.trx'

# The sample consumes FFmpegKit.Net.Full.Maui through a PackageReference exactly as a user
# would, so it is what catches an API that no longer matches what the README documents -
# nothing else here builds against the packed packages the way an actual consumer does.
# Build only, both target frameworks: proving it links is the point, not running it.
- name: Build the sample against the packed packages
run: |
dotnet build samples/FFmpegKit.Net.Sample/FFmpegKit.Net.Sample.csproj \
--configuration Release \
-p:FFmpegKitVersion="${{ inputs.version }}"

- name: Upload test results
if: always()
uses: actions/upload-artifact@v4
Expand All @@ -196,6 +181,98 @@ jobs:
if-no-files-found: ignore
retention-days: 7

build-samples:
name: sample build (${{ matrix.tfm }})
# Release iOS AOT statically links the native FFmpeg per framework and is slow; the legs run
# concurrently, so wall-clock is one leg. Android legs are much faster on Linux.
timeout-minutes: 90
needs: pack
runs-on: ${{ matrix.os }}
strategy:
# fail-fast off: proving which heads are consumable is the point, and net8-vs-net10 or
# android-vs-ios failures have very different causes - a partial result is still a result.
fail-fast: false
matrix:
# The net8 and net10 extremes on each platform - the whole point of the cross-platform
# layer is that one MAUI sample drives both, so both are exercised on the oldest and
# newest asset sets, in Release, where the AOT/trimmer/R8 link runs. The Android legs go on
# a Linux runner (the sample drops its iOS head there); the iOS legs need macOS + Xcode.
include:
- band: net8
platform: android
os: ubuntu-latest
tfm: net8.0-android34.0
- band: net10
platform: android
os: ubuntu-latest
tfm: net10.0-android36.0
- band: net8
platform: ios
os: macos-15
tfm: net8.0-ios18.0
build-args: -p:RuntimeIdentifier=iossimulator-arm64
- band: net10
platform: ios
os: macos-15
tfm: net10.0-ios26.0
build-args: -p:RuntimeIdentifier=iossimulator-arm64
steps:
- uses: actions/checkout@v4

- name: Select Xcode
if: matrix.platform == 'ios'
uses: ./.github/actions/select-xcode

- name: Set up .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: |
8.0.x
9.0.x
10.0.x

- name: Pin the ${{ matrix.band }} SDK band and install workloads
id: band
run: |
# The sample targets one framework per platform per band (SampleSdkBand), pinned through
# a scratch global.json since the repository global.json is .NET 9. `dotnet build -f`
# still restores every framework the band lists, so an iOS leg on macOS needs both the
# iOS and Android workloads; an Android leg on Linux (iOS head dropped) needs only
# Android.
major="$(printf '%s' '${{ matrix.band }}' | sed 's/net//')"
sdk="$(dotnet --list-sdks | grep "^${major}\." | tail -1 | cut -d' ' -f1)"
dir="${RUNNER_TEMP}/band-${{ matrix.band }}-${{ matrix.platform }}"
mkdir -p "${dir}"
printf '{ "sdk": { "version": "%s", "rollForward": "latestFeature" } }\n' "${sdk}" > "${dir}/global.json"
echo "dir=${dir}" >> "$GITHUB_OUTPUT"
if [ '${{ matrix.platform }}' = 'ios' ]; then
( cd "${dir}" && dotnet workload install maui-ios maui-android )
else
( cd "${dir}" && dotnet workload install maui-android )
fi

- name: Set up the Android SDK platforms
if: matrix.platform == 'android'
uses: android-actions/setup-android@v3
with:
packages: 'platforms;android-34 platforms;android-36'

- name: Download packages
uses: actions/download-artifact@v4
with:
name: nuget-packages
path: artifacts

- name: Build the ${{ matrix.tfm }} sample against the packed packages
run: |
# The sample consumes FFmpegKit.Net.Full.Maui through a PackageReference exactly as a
# consumer would, so it catches an API that no longer matches the README - nothing else
# here builds against the packed packages the way an actual app does.
( cd "${{ steps.band.outputs.dir }}" && dotnet build "${GITHUB_WORKSPACE}/samples/FFmpegKit.Net.Sample/FFmpegKit.Net.Sample.csproj" \
--configuration Release -f "${{ matrix.tfm }}" ${{ matrix.build-args }} \
-p:SampleSdkBand="${{ matrix.band }}" \
-p:FFmpegKitVersion="${{ inputs.version }}" )

# The device tests consume the packed FFmpegKit.Net.<Variant> package - including its pinned
# dependency on the external platform binding from nuget.org - and drive real FFmpeg commands
# through the cross-platform API on each platform. The bindings' own repositories smoke-test
Expand Down
55 changes: 41 additions & 14 deletions samples/FFmpegKit.Net.Sample/FFmpegKit.Net.Sample.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,22 @@

<PropertyGroup>
<!--
Both platforms the .NET 9 SDK band can build in one go, so the sample proves
FFmpegKit.Net.Full.Maui resolves and runs the same code on Android and iOS - which is the
entire point of the cross-platform layer. net10.0-* is deliberately left out: it would mean
a second SDK and workload set to compile a sample that exercises the same API the device
tests already run against net10 for.
One target framework per platform per SDK band, selected by SampleSdkBand, so the CI sample
matrix builds the net8 and net10 extremes on each platform, each on its own band. Unset
locally it is the net9 dev band, so `dotnet build` just works. On Linux the iOS head is
dropped: `dotnet build -f <android tfm>` still restores every listed framework, and the iOS
workload does not exist on Linux (NETSDK1178), so the Android matrix leg can run on a cheap
Linux runner.
-->
<TargetFrameworks>net9.0-android35.0;net9.0-ios18.0</TargetFrameworks>
<SampleSdkBand Condition=" '$(SampleSdkBand)' == '' ">net9</SampleSdkBand>
<SampleAndroidTfm Condition=" '$(SampleSdkBand)' == 'net8' ">net8.0-android34.0</SampleAndroidTfm>
<SampleAndroidTfm Condition=" '$(SampleSdkBand)' == 'net9' ">net9.0-android35.0</SampleAndroidTfm>
<SampleAndroidTfm Condition=" '$(SampleSdkBand)' == 'net10' ">net10.0-android36.0</SampleAndroidTfm>
<SampleIosTfm Condition=" '$(SampleSdkBand)' == 'net8' ">net8.0-ios18.0</SampleIosTfm>
<SampleIosTfm Condition=" '$(SampleSdkBand)' == 'net9' ">net9.0-ios18.0</SampleIosTfm>
<SampleIosTfm Condition=" '$(SampleSdkBand)' == 'net10' ">net10.0-ios26.0</SampleIosTfm>
<TargetFrameworks>$(SampleAndroidTfm);$(SampleIosTfm)</TargetFrameworks>
<TargetFrameworks Condition="$([MSBuild]::IsOSPlatform('Linux'))">$(SampleAndroidTfm)</TargetFrameworks>

<OutputType>Exe</OutputType>
<RootNamespace>FFmpegKit.Net.Sample</RootNamespace>
Expand Down Expand Up @@ -56,19 +65,37 @@
<MauiAsset Include="Resources\Raw\**" LogicalName="%(RecursiveDir)%(Filename)%(Extension)" />
</ItemGroup>

<ItemGroup>
<!--
Microsoft.Maui.Controls pinned above the workload's own bundled 9.0.0: both UseMaui=true's
implicit reference and an explicit $(MauiVersion) one resolve to exactly that version, which
is older than what CommunityToolkit.Maui 11 requires (NU1605 package downgrade error).
Controls itself is an ordinary NuGet package independent of which workload pack version is
installed, so pinning it higher here restores cleanly without reinstalling the workload.
-->
<!--
CommunityToolkit.Maui and its MediaElement (the before/after video preview) have no single
version spanning net8 and net10, so they - and the Microsoft.Maui.Controls version each one
requires, and a matching Microsoft.Extensions.Logging.Debug - are selected per band.
Controls is pinned to the highest floor anything in the graph declares: the workload's own
bundled Controls is older, so relying on $(MauiVersion) trips NU1605, and Controls is an
ordinary NuGet package independent of the installed workload pack, so pinning it restores
cleanly. On net8 that floor is FFmpegKit.Net.Maui's own 8.0.100 rather than the toolkit's
8.0.71 - see FFmpegKitMauiControlsVersion in src/FFmpegKit.Net.Maui/FFmpegKit.Net.Maui.csproj;
a sample pinned under the package it consumes fails restore with NU1605.
-->
<ItemGroup Condition="$(TargetFramework.StartsWith('net8.0'))">
<PackageReference Include="CommunityToolkit.Maui" Version="9.1.1" />
<PackageReference Include="CommunityToolkit.Maui.MediaElement" Version="4.1.2" />
<PackageReference Include="Microsoft.Maui.Controls" Version="8.0.100" />
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="8.0.1" />
</ItemGroup>
<ItemGroup Condition="$(TargetFramework.StartsWith('net9.0'))">
<PackageReference Include="CommunityToolkit.Maui" Version="11.0.0" />
<PackageReference Include="CommunityToolkit.Maui.MediaElement" Version="6.0.1" />
<PackageReference Include="Microsoft.Maui.Controls" Version="9.0.30" />
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="9.0.0" />
</ItemGroup>
<ItemGroup Condition="$(TargetFramework.StartsWith('net10.0'))">
<PackageReference Include="CommunityToolkit.Maui" Version="15.0.0" />
<PackageReference Include="CommunityToolkit.Maui.MediaElement" Version="10.0.0" />
<PackageReference Include="Microsoft.Maui.Controls" Version="10.0.60" />
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="10.0.0" />
</ItemGroup>

<ItemGroup>
<!--
The locally built package, resolved from ./artifacts via the local-artifacts source in the
repository's NuGet.config. Run build/BuildNugets.sh first - this deliberately does not come
Expand Down
7 changes: 7 additions & 0 deletions samples/FFmpegKit.Net.Sample/MauiProgram.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,18 @@
public static MauiApp CreateMauiApp()
{
var builder = MauiApp.CreateBuilder();
builder

Check warning on line 12 in samples/FFmpegKit.Net.Sample/MauiProgram.cs

View workflow job for this annotation

GitHub Actions / build / sample build (net10.0-ios26.0)

This call site is reachable on: 'iOS' 12.2 and later, 'maccatalyst' 12.2 and later. 'AppBuilderExtensions.UseMauiCommunityToolkitMediaElement(MauiAppBuilder, bool, Action<MediaElementOptions>?)' is only supported on: 'Android' 26.0 and later, 'iOS' 15.0 and later, 'maccatalyst' 15.0 and later, 'Tizen' 6.5 and later, 'Windows' 10.0.17763 and later. (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1416)

Check warning on line 12 in samples/FFmpegKit.Net.Sample/MauiProgram.cs

View workflow job for this annotation

GitHub Actions / build / sample build (net10.0-ios26.0)

This call site is reachable on: 'iOS' 12.2 and later, 'maccatalyst' 12.2 and later. 'AppBuilderExtensions.UseMauiCommunityToolkit(MauiAppBuilder, Action<Options>?)' is only supported on: 'Android' 21.0 and later, 'iOS' 15.0 and later, 'maccatalyst' 15.0 and later, 'Tizen' 6.5 and later, 'Windows' 10.0.17763 and later. (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1416)

Check warning on line 12 in samples/FFmpegKit.Net.Sample/MauiProgram.cs

View workflow job for this annotation

GitHub Actions / build / sample build (net10.0-ios26.0)

This call site is reachable on: 'iOS' 12.2 and later, 'maccatalyst' 12.2 and later. 'AppBuilderExtensions.UseMauiCommunityToolkitMediaElement(MauiAppBuilder, bool, Action<MediaElementOptions>?)' is only supported on: 'Android' 26.0 and later, 'iOS' 15.0 and later, 'maccatalyst' 15.0 and later, 'Tizen' 6.5 and later, 'Windows' 10.0.17763 and later. (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1416)

Check warning on line 12 in samples/FFmpegKit.Net.Sample/MauiProgram.cs

View workflow job for this annotation

GitHub Actions / build / sample build (net10.0-ios26.0)

This call site is reachable on: 'iOS' 12.2 and later, 'maccatalyst' 12.2 and later. 'AppBuilderExtensions.UseMauiCommunityToolkit(MauiAppBuilder, Action<Options>?)' is only supported on: 'Android' 21.0 and later, 'iOS' 15.0 and later, 'maccatalyst' 15.0 and later, 'Tizen' 6.5 and later, 'Windows' 10.0.17763 and later. (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1416)
.UseMauiApp<App>()
.UseFFmpegKit()
.UseMauiCommunityToolkit()
#if NET10_0_OR_GREATER
// MediaElement 10.0.0 made the Android foreground-service opt-in a required argument.
// This sample previews a local file while in the foreground, and opting in would also
// require FOREGROUND_SERVICE_MEDIA_PLAYBACK in the manifest.
.UseMauiCommunityToolkitMediaElement(isAndroidForegroundServiceEnabled: false)
#else
.UseMauiCommunityToolkitMediaElement()
#endif
.ConfigureFonts(fonts =>
{
fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
Expand Down
Loading