Skip to content

Initial version of sipsorcery cli console app #298

Initial version of sipsorcery cli console app

Initial version of sipsorcery cli console app #298

name: unity-smoke-test
on:
workflow_dispatch:
push:
branches:
- master
pull_request:
branches:
- master
jobs:
smoke-test:
name: Unity ${{ matrix.unityVersion }} PlayMode smoke test (Linux)
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
unityVersion:
- 6000.4.7f1
testMode:
- playmode
steps:
- name: Check for Unity license secret
id: license_check
env:
UNITY_LICENSE: ${{ secrets.UNITY_LICENSE }}
UNITY_EMAIL: ${{ secrets.UNITY_EMAIL }}
UNITY_PASSWORD: ${{ secrets.UNITY_PASSWORD }}
run: |
if [ -z "$UNITY_LICENSE" ] || [ -z "$UNITY_EMAIL" ] || [ -z "$UNITY_PASSWORD" ]; then
echo "has_license=false" >> "$GITHUB_OUTPUT"
echo "::warning::Unity license secrets (UNITY_LICENSE + UNITY_EMAIL + UNITY_PASSWORD) are not all set; skipping Unity smoke test. See test/Unity/README.md for setup."
else
echo "has_license=true" >> "$GITHUB_OUTPUT"
fi
- name: Checkout
if: steps.license_check.outputs.has_license == 'true'
uses: actions/checkout@v4
with:
lfs: false
- name: Setup .NET
if: steps.license_check.outputs.has_license == 'true'
uses: actions/setup-dotnet@v4
with:
dotnet-version: '10.0.x'
- name: Build SIPSorcery and stage Unity plugin DLLs
if: steps.license_check.outputs.has_license == 'true'
env:
PLUGINS_DIR: test/Unity/SipSorceryUnitySmokeTest/Assets/Plugins
run: |
set -euo pipefail
mkdir -p staging "$PLUGINS_DIR"
dotnet publish src/SIPSorcery/SIPSorcery.csproj \
--configuration Release \
--framework netstandard2.1 \
--output staging
# Copy DLLs into Assets/Plugins, excluding ones Unity already
# provides as built-in reference assemblies (the duplicates cause
# CS1703 "Multiple assemblies with equivalent identity").
unity_provided=(
Microsoft.CSharp.dll
)
for dll in staging/*.dll; do
name=$(basename "$dll")
skip=false
for provided in "${unity_provided[@]}"; do
if [ "$name" = "$provided" ]; then skip=true; break; fi
done
if [ "$skip" = "false" ]; then
cp -v "$dll" "$PLUGINS_DIR/"
else
echo "Skipping Unity-provided $name"
fi
done
- name: Generate plugin .meta files
if: steps.license_check.outputs.has_license == 'true'
env:
PLUGINS_DIR: test/Unity/SipSorceryUnitySmokeTest/Assets/Plugins
# Without these, Unity defaults validateReferences=true and refuses
# to load plugins with unresolved transitive refs (notably
# Makaretu.Dns.Multicast -> Tmds.LibC). Pre-authoring the .meta
# files lets the smoke test run in a single Unity invocation.
run: |
set -euo pipefail
for dll in "$PLUGINS_DIR"/*.dll; do
meta="$dll.meta"
if [ -f "$meta" ]; then continue; fi
guid=$(printf "%s" "$(basename "$dll")" | md5sum | cut -c1-32)
cat > "$meta" <<EOF
fileFormatVersion: 2
guid: $guid
PluginImporter:
externalObjects: {}
serializedVersion: 3
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 0
isExplicitlyReferenced: 0
validateReferences: 0
platformData:
Any:
enabled: 1
settings: {}
Editor:
enabled: 1
settings:
DefaultValueInitialized: true
WindowsStoreApps:
enabled: 0
settings:
CPU: AnyCPU
userData:
assetBundleName:
assetBundleVariant:
EOF
done
- name: Cache Unity Library
if: steps.license_check.outputs.has_license == 'true'
uses: actions/cache@v4
with:
path: test/Unity/SipSorceryUnitySmokeTest/Library
key: Library-SipSorceryUnitySmokeTest-${{ matrix.unityVersion }}-${{ hashFiles('test/Unity/SipSorceryUnitySmokeTest/Packages/manifest.json', 'test/Unity/SipSorceryUnitySmokeTest/ProjectSettings/ProjectVersion.txt') }}
restore-keys: |
Library-SipSorceryUnitySmokeTest-${{ matrix.unityVersion }}-
Library-SipSorceryUnitySmokeTest-
- name: Run Unity ${{ matrix.testMode }} tests
if: steps.license_check.outputs.has_license == 'true'
uses: game-ci/unity-test-runner@v4
env:
UNITY_LICENSE: ${{ secrets.UNITY_LICENSE }}
UNITY_EMAIL: ${{ secrets.UNITY_EMAIL }}
UNITY_PASSWORD: ${{ secrets.UNITY_PASSWORD }}
with:
projectPath: test/Unity/SipSorceryUnitySmokeTest
unityVersion: ${{ matrix.unityVersion }}
testMode: ${{ matrix.testMode }}
artifactsPath: test/Unity/SipSorceryUnitySmokeTest/artifacts
githubToken: ${{ secrets.GITHUB_TOKEN }}
checkName: Unity ${{ matrix.testMode }} results
- name: Upload test results
if: always() && steps.license_check.outputs.has_license == 'true'
uses: actions/upload-artifact@v4
with:
name: unity-test-results-${{ matrix.unityVersion }}-${{ matrix.testMode }}
path: test/Unity/SipSorceryUnitySmokeTest/artifacts
smoke-test-windows:
# Windows-runner job that actually reproduces issue #1614 — the bug is
# in Unity's Windows-shipped Mono runtime (NetworkInformation.NetworkChange
# throws PlatformNotSupportedException), and the GameCI Linux container
# runs Linux Mono where the same code path works. Without this job the
# smoke test passes even when the bug is present.
#
# Manual-only: this job runs ~20 min on a cold Unity install, is flaky
# against the unity-setup cache, and burns Windows runner minutes on
# every PR / push. Gate it behind workflow_dispatch so it only fires
# when a maintainer explicitly triggers it from the Actions tab.
if: github.event_name == 'workflow_dispatch'
name: Unity ${{ matrix.unityVersion }} PlayMode smoke test (Windows)
runs-on: windows-latest
strategy:
fail-fast: false
matrix:
unityVersion:
- 6000.4.7f1
steps:
- name: Check for Unity license secret
id: license_check
shell: bash
env:
UNITY_EMAIL: ${{ secrets.UNITY_EMAIL }}
UNITY_PASSWORD: ${{ secrets.UNITY_PASSWORD }}
run: |
if [ -z "$UNITY_EMAIL" ] || [ -z "$UNITY_PASSWORD" ]; then
echo "has_license=false" >> "$GITHUB_OUTPUT"
echo "::warning::UNITY_EMAIL / UNITY_PASSWORD secrets are not set; skipping Unity Windows smoke test. See test/Unity/README.md for setup."
else
echo "has_license=true" >> "$GITHUB_OUTPUT"
fi
- name: Checkout
if: steps.license_check.outputs.has_license == 'true'
uses: actions/checkout@v4
with:
lfs: false
- name: Setup .NET
if: steps.license_check.outputs.has_license == 'true'
uses: actions/setup-dotnet@v4
with:
dotnet-version: '10.0.x'
- name: Build SIPSorcery and stage Unity plugin DLLs
if: steps.license_check.outputs.has_license == 'true'
shell: bash
env:
PLUGINS_DIR: test/Unity/SipSorceryUnitySmokeTest/Assets/Plugins
run: |
set -euo pipefail
mkdir -p staging "$PLUGINS_DIR"
dotnet publish src/SIPSorcery/SIPSorcery.csproj \
--configuration Release \
--framework netstandard2.1 \
--output staging
unity_provided=(
Microsoft.CSharp.dll
)
for dll in staging/*.dll; do
name=$(basename "$dll")
skip=false
for provided in "${unity_provided[@]}"; do
if [ "$name" = "$provided" ]; then skip=true; break; fi
done
if [ "$skip" = "false" ]; then
cp -v "$dll" "$PLUGINS_DIR/"
else
echo "Skipping Unity-provided $name"
fi
done
- name: Generate plugin .meta files
if: steps.license_check.outputs.has_license == 'true'
shell: bash
env:
PLUGINS_DIR: test/Unity/SipSorceryUnitySmokeTest/Assets/Plugins
run: |
set -euo pipefail
for dll in "$PLUGINS_DIR"/*.dll; do
meta="$dll.meta"
if [ -f "$meta" ]; then continue; fi
guid=$(printf "%s" "$(basename "$dll")" | md5sum | cut -c1-32)
cat > "$meta" <<EOF
fileFormatVersion: 2
guid: $guid
PluginImporter:
externalObjects: {}
serializedVersion: 3
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 0
isExplicitlyReferenced: 0
validateReferences: 0
platformData:
Any:
enabled: 1
settings: {}
Editor:
enabled: 1
settings:
DefaultValueInitialized: true
WindowsStoreApps:
enabled: 0
settings:
CPU: AnyCPU
userData:
assetBundleName:
assetBundleVariant:
EOF
done
- name: Cache Unity Library
if: steps.license_check.outputs.has_license == 'true'
uses: actions/cache@v4
with:
path: test/Unity/SipSorceryUnitySmokeTest/Library
key: Library-Windows-SipSorceryUnitySmokeTest-${{ matrix.unityVersion }}-${{ hashFiles('test/Unity/SipSorceryUnitySmokeTest/Packages/manifest.json', 'test/Unity/SipSorceryUnitySmokeTest/ProjectSettings/ProjectVersion.txt') }}
restore-keys: |
Library-Windows-SipSorceryUnitySmokeTest-${{ matrix.unityVersion }}-
Library-Windows-SipSorceryUnitySmokeTest-
- name: Install Unity ${{ matrix.unityVersion }}
id: unity
if: steps.license_check.outputs.has_license == 'true'
uses: RageAgainstThePixel/unity-setup@v2
with:
unity-version: ${{ matrix.unityVersion }}
build-targets: StandaloneWindows64
cache-installation: true
- name: Activate Unity license
if: steps.license_check.outputs.has_license == 'true'
uses: RageAgainstThePixel/activate-unity-license@v2
with:
license: Personal
username: ${{ secrets.UNITY_EMAIL }}
password: ${{ secrets.UNITY_PASSWORD }}
- name: Run Unity PlayMode tests
if: steps.license_check.outputs.has_license == 'true'
timeout-minutes: 30
shell: pwsh
run: |
$proj = "$env:GITHUB_WORKSPACE\test\Unity\SipSorceryUnitySmokeTest"
$unity = "${{ steps.unity.outputs.unity-editor-path }}"
if (-not (Test-Path $unity)) {
throw "Unity editor path not found: $unity"
}
New-Item -ItemType Directory -Path "$proj\artifacts" -Force | Out-Null
$results = "$proj\artifacts\playmode-results.xml"
$log = "$proj\artifacts\playmode.log"
Write-Host "Running: $unity"
# Unity.exe is a Windows-subsystem app, so PowerShell's call
# operator (`&`) returns immediately without waiting. Use
# Start-Process -Wait -PassThru to actually block on it and
# capture the exit code.
$unityArgs = @(
'-batchmode',
'-projectPath', $proj,
'-runTests',
'-testPlatform', 'PlayMode',
'-testResults', $results,
'-logFile', $log
)
$proc = Start-Process -FilePath $unity -ArgumentList $unityArgs `
-NoNewWindow -PassThru -Wait
$unityExit = $proc.ExitCode
Write-Host "Unity process exit code: $unityExit"
if (-not (Test-Path $results)) {
Write-Host "::error::No test-results.xml produced — Unity likely crashed before tests ran."
if (Test-Path $log) { Get-Content $log -Tail 100 }
exit 1
}
[xml]$xml = Get-Content $results
$run = $xml.'test-run'
$passed = [int]$run.passed
$failed = [int]$run.failed
$total = [int]$run.total
Write-Host "Results: total=$total passed=$passed failed=$failed result=$($run.result)"
if ($failed -gt 0) {
Write-Host "::error::$failed Unity PlayMode test(s) failed"
# Surface the failure messages, plus the tail of the Unity log
# for diagnosis.
$xml.SelectNodes("//test-case[@result='Failed']") | ForEach-Object {
Write-Host "----- FAILED: $($_.fullname) -----"
Write-Host $_.failure.message.InnerText
Write-Host $_.failure.'stack-trace'.InnerText
}
exit 1
}
if ($total -eq 0) {
Write-Host "::error::0 tests were discovered — plugin import or compile likely failed."
if (Test-Path $log) { Get-Content $log -Tail 100 }
exit 1
}
- name: Upload test results
if: always() && steps.license_check.outputs.has_license == 'true'
uses: actions/upload-artifact@v4
with:
name: unity-test-results-windows-${{ matrix.unityVersion }}-playmode
path: test/Unity/SipSorceryUnitySmokeTest/artifacts