fix(flight-planner): display one-based waypoint numbers (#33) #131
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Avalonia CI and packages | |
| on: | |
| push: | |
| branches: [master, 'port/**', 'cleanup/**'] | |
| pull_request: | |
| branches: [master] | |
| workflow_dispatch: | |
| permissions: | |
| contents: read | |
| concurrency: | |
| group: avalonia-ci-${{ github.ref }} | |
| cancel-in-progress: true | |
| # A CI checkout is an immutable commit even when restore/build tools create runner-local files. | |
| # Keep those files from leaking a misleading `.dirty` suffix into packages and app metadata. | |
| env: | |
| MISSIONPLANNER_DIRTY_SUFFIX: '' | |
| jobs: | |
| build-test-linux: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v7 | |
| with: | |
| fetch-depth: 0 | |
| - uses: actions/setup-dotnet@v5 | |
| with: | |
| dotnet-version: '10.0.x' | |
| - name: Validate frozen native surface manifest | |
| run: ./build/porting/check-native-surface.sh | |
| - name: Build complete solution graph | |
| run: dotnet build MissionPlanner.slnx -c Release -m:1 --nologo | |
| - name: Run complete test suite | |
| run: >- | |
| dotnet test MissionPlannerTests/Avalonia/MissionPlanner.Tests/MissionPlanner.Tests.csproj | |
| -c Release -m:1 --no-build --nologo | |
| - name: Install Linux package validators | |
| run: sudo apt-get update && sudo apt-get install -y lintian xvfb | |
| - name: Build Linux portable archive and Debian package | |
| run: ./build/linux/package.sh all | |
| - name: Validate and smoke Debian payload | |
| shell: bash | |
| run: | | |
| test -z "$(find out/packages -maxdepth 1 -type f -name '*.dirty*' -print -quit)" | |
| DEB=$(find out/packages -maxdepth 1 -type f -name 'missionplanner10_*_amd64.deb' -print -quit) | |
| test -n "$DEB" | |
| lintian --tag-display-limit 0 "$DEB" | |
| ROOT=$(mktemp -d "$RUNNER_TEMP/missionplanner-deb.XXXXXXXX") | |
| dpkg-deb --extract "$DEB" "$ROOT" | |
| test -x "$ROOT/usr/lib/missionplanner10/MissionPlanner10" | |
| test -s "$ROOT/usr/lib/missionplanner10/airports.csv" | |
| test ! -e "$ROOT/usr/lib/missionplanner10/simpleble-c.dll" | |
| test ! -e "$ROOT/usr/lib/missionplanner10/simpleble.dll" | |
| test ! -e "$ROOT/usr/lib/missionplanner10/libusb-1.0.dll" | |
| set +e | |
| timeout 12s xvfb-run -a "$ROOT/usr/lib/missionplanner10/MissionPlanner10" | |
| STATUS=$? | |
| set -e | |
| test "$STATUS" -eq 0 -o "$STATUS" -eq 124 | |
| - uses: actions/upload-artifact@v7 | |
| with: | |
| name: missionplanner10-linux-x64 | |
| path: out/packages/*linux-x64.tar.gz | |
| if-no-files-found: error | |
| - uses: actions/upload-artifact@v7 | |
| with: | |
| name: missionplanner10-deb-amd64 | |
| path: out/packages/missionplanner10_*_amd64.deb | |
| if-no-files-found: error | |
| package-windows: | |
| runs-on: windows-latest | |
| steps: | |
| - uses: actions/checkout@v7 | |
| with: | |
| fetch-depth: 0 | |
| - uses: actions/setup-dotnet@v5 | |
| with: | |
| dotnet-version: '10.0.x' | |
| - name: Build Windows portable archive and MSI | |
| shell: bash | |
| run: ./build/windows/package.sh all | |
| - name: Validate ZIP and MSI installation | |
| shell: pwsh | |
| run: | | |
| $zip = Get-ChildItem out/packages/*win-x64.zip | Select-Object -First 1 | |
| $msi = Get-ChildItem out/packages/*win-x64.msi | Select-Object -First 1 | |
| if (-not $zip -or -not $msi) { throw "Windows artifacts are missing" } | |
| if ($zip.Name -match '\.dirty' -or $msi.Name -match '\.dirty') { | |
| throw "Clean CI artifacts must not contain the .dirty version suffix" | |
| } | |
| $zipRoot = Join-Path $env:RUNNER_TEMP "zip" | |
| Expand-Archive -Path $zip.FullName -DestinationPath $zipRoot | |
| $requiredFiles = @( | |
| 'MissionPlanner10.exe', | |
| 'e_sqlite3.dll', | |
| 'airports.csv', | |
| 'COPYING.txt', | |
| 'NOTICE.md', | |
| 'LICENSE', | |
| 'SimpleBLE-0.7.3-NOTICE.txt' | |
| ) | |
| foreach ($requiredFile in $requiredFiles) { | |
| if (-not (Get-ChildItem $zipRoot -Recurse -File -Filter $requiredFile)) { | |
| throw "Portable ZIP does not contain $requiredFile" | |
| } | |
| } | |
| # Exercise the real per-machine directory authored in Package.wxs. Overriding a | |
| # directory property from msiexec does not validate the installer's production path | |
| # and can be ignored during maintenance-mode directory resolution. | |
| $msiRoot = Join-Path $env:ProgramFiles "MissionPlanner10" | |
| $installLog = Join-Path $env:RUNNER_TEMP "msi-install.log" | |
| try { | |
| $process = Start-Process msiexec.exe -Wait -PassThru -ArgumentList @( | |
| '/i', $msi.FullName, '/qn', '/norestart', '/L*V', $installLog | |
| ) | |
| if ($process.ExitCode -ne 0) { | |
| Get-Content $installLog -Tail 200 | |
| throw "MSI installation failed: $($process.ExitCode)" | |
| } | |
| foreach ($requiredFile in $requiredFiles) { | |
| if (-not (Get-ChildItem $msiRoot -Recurse -File -Filter $requiredFile)) { | |
| Get-Content $installLog | | |
| Select-String -Pattern 'INSTALLFOLDER|Feature: Main|Component:' | | |
| Select-Object -Last 100 | |
| throw "Installed MSI does not contain $requiredFile" | |
| } | |
| } | |
| } finally { | |
| $process = Start-Process msiexec.exe -Wait -PassThru -ArgumentList @( | |
| '/x', $msi.FullName, '/qn', '/norestart' | |
| ) | |
| if ($process.ExitCode -ne 0 -and $process.ExitCode -ne 1605) { | |
| throw "MSI cleanup failed: $($process.ExitCode)" | |
| } | |
| } | |
| - uses: actions/upload-artifact@v7 | |
| if: always() | |
| with: | |
| name: missionplanner10-windows-x64 | |
| path: | | |
| out/packages/*win-x64.zip | |
| out/packages/*win-x64.msi | |
| if-no-files-found: error | |
| package-macos: | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| rid: [osx-x64, osx-arm64] | |
| runs-on: macos-15 | |
| steps: | |
| - uses: actions/checkout@v7 | |
| with: | |
| fetch-depth: 0 | |
| - uses: actions/setup-dotnet@v5 | |
| with: | |
| dotnet-version: '10.0.x' | |
| - name: Publish macOS self-contained application | |
| shell: bash | |
| run: | | |
| RID=${{ matrix.rid }} | |
| source build/version.sh | |
| dotnet publish MissionPlanner.csproj -c Release -r "$RID" --self-contained true \ | |
| -m:1 -p:DebugType=none -p:StripSymbols=true \ | |
| -p:MissionPlannerUpstreamVersion="$MP_UPSTREAM_VERSION" \ | |
| -p:MissionPlannerLocalBuildNumber="$MP_LOCAL_BUILD_NUMBER" \ | |
| -p:MissionPlannerCommit="$MP_COMMIT" \ | |
| -o "out/$RID" | |
| test -s "out/$RID/libsimpleble-c.dylib" | |
| test -s "out/$RID/libsimpleble.0.dylib" | |
| test -s "out/$RID/lib/libvlc.5.dylib" | |
| test -d "out/$RID/plugins" | |
| - name: Build ad-hoc signed app archive and DMG | |
| shell: bash | |
| run: | | |
| RID=${{ matrix.rid }} | |
| source build/version.sh | |
| test "$MP_DIRTY_SUFFIX" = "" | |
| mkdir -p dist upload | |
| ./build/macos/make-app.sh "out/$RID" "$MP_UPSTREAM_VERSION" \ | |
| "$MP_LOCAL_BUILD_NUMBER" \ | |
| "dist/Mission Planner 10.app" | |
| ditto -c -k --sequesterRsrc --keepParent "dist/Mission Planner 10.app" \ | |
| "upload/MissionPlanner10-${RID}.zip" | |
| DMG="upload/MissionPlanner10-${RID}.dmg" | |
| ./build/macos/make-dmg.sh "dist/Mission Planner 10.app" "$DMG" | |
| MOUNT_POINT=$(mktemp -d "$RUNNER_TEMP/missionplanner-dmg.XXXXXXXX") | |
| DMG_MOUNTED=false | |
| cleanup_dmg_mount() { | |
| if [[ "$DMG_MOUNTED" == true ]]; then | |
| hdiutil detach -quiet "$MOUNT_POINT" || true | |
| fi | |
| rmdir "$MOUNT_POINT" 2>/dev/null || true | |
| } | |
| trap cleanup_dmg_mount EXIT | |
| hdiutil attach -quiet -readonly -nobrowse -mountpoint "$MOUNT_POINT" "$DMG" | |
| DMG_MOUNTED=true | |
| test -x "$MOUNT_POINT/Mission Planner 10.app/Contents/MacOS/MissionPlanner10" | |
| test -L "$MOUNT_POINT/Applications" | |
| hdiutil detach -quiet "$MOUNT_POINT" | |
| DMG_MOUNTED=false | |
| rmdir "$MOUNT_POINT" | |
| trap - EXIT | |
| - uses: actions/upload-artifact@v7 | |
| with: | |
| name: missionplanner10-${{ matrix.rid }} | |
| path: | | |
| upload/*.zip | |
| upload/*.dmg | |
| if-no-files-found: error |