feat(nv-modem): sync current GTU settings behavior #14
Workflow file for this run
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: Cross-platform release | |
| on: | |
| push: | |
| tags: ['v*'] | |
| workflow_dispatch: | |
| permissions: | |
| contents: write | |
| jobs: | |
| resolve-version: | |
| runs-on: ubuntu-latest | |
| outputs: | |
| base: ${{ steps.version.outputs.base }} | |
| date: ${{ steps.version.outputs.date }} | |
| commit: ${{ steps.version.outputs.commit }} | |
| revision: ${{ steps.version.outputs.revision }} | |
| version: ${{ steps.version.outputs.version }} | |
| artifact: ${{ steps.version.outputs.artifact }} | |
| prerelease: ${{ steps.version.outputs.prerelease }} | |
| steps: | |
| - uses: actions/checkout@v7 | |
| with: | |
| fetch-depth: 0 | |
| - name: Resolve and validate release identity | |
| id: version | |
| shell: bash | |
| run: | | |
| PRERELEASE=false | |
| if [[ "$GITHUB_REF" == refs/tags/* ]]; then | |
| VALUE="${GITHUB_REF_NAME#v}" | |
| if [[ ! "$VALUE" =~ ^([0-9]+\.[0-9]+\.[0-9]+)-([0-9]{8})\.([0-9a-fA-F]{8})(-beta(\.[0-9]+)?)?$ ]]; then | |
| echo "::error::Tag must be v<MP-version>-<yyyyMMdd>.<8-char-hash>[-beta[.N]]." | |
| exit 1 | |
| fi | |
| export MISSIONPLANNER_UPSTREAM_VERSION="${BASH_REMATCH[1]}" | |
| export MISSIONPLANNER_BUILD_DATE="${BASH_REMATCH[2]}" | |
| export MISSIONPLANNER_COMMIT="${BASH_REMATCH[3],,}" | |
| [[ -n "${BASH_REMATCH[4]}" ]] && PRERELEASE=true | |
| ACTUAL_VERSION=$(sed -nE 's/.*AssemblyFileVersion\("([0-9]+\.[0-9]+\.[0-9]+)"\).*/\1/p' \ | |
| Properties/AssemblyInfo.cs | head -1) | |
| ACTUAL_COMMIT=$(git rev-parse --short=8 HEAD) | |
| test "$MISSIONPLANNER_UPSTREAM_VERSION" = "$ACTUAL_VERSION" || { | |
| echo "::error::Tag version does not match Properties/AssemblyInfo.cs"; exit 1; } | |
| test "$MISSIONPLANNER_COMMIT" = "$ACTUAL_COMMIT" || { | |
| echo "::error::Tag hash does not match HEAD"; exit 1; } | |
| fi | |
| export MISSIONPLANNER_DIRTY_SUFFIX="" | |
| source build/version.sh | |
| { | |
| echo "base=$MP_UPSTREAM_VERSION" | |
| echo "date=$MP_BUILD_DATE" | |
| echo "commit=$MP_COMMIT" | |
| echo "revision=$MP_PORT_REVISION" | |
| echo "version=$MP_PACKAGE_VERSION" | |
| echo "artifact=$MP_ARTIFACT_VERSION" | |
| echo "prerelease=$PRERELEASE" | |
| } >> "$GITHUB_OUTPUT" | |
| package: | |
| needs: resolve-version | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - os: ubuntu-latest | |
| rid: linux-x64 | |
| - os: windows-latest | |
| rid: win-x64 | |
| - os: macos-15 | |
| rid: osx-x64 | |
| - os: macos-15 | |
| rid: osx-arm64 | |
| runs-on: ${{ matrix.os }} | |
| env: | |
| MP_RELEASE_BASE: ${{ needs.resolve-version.outputs.base }} | |
| MP_RELEASE_DATE: ${{ needs.resolve-version.outputs.date }} | |
| MP_RELEASE_COMMIT: ${{ needs.resolve-version.outputs.commit }} | |
| MP_RELEASE_REVISION: ${{ needs.resolve-version.outputs.revision }} | |
| MP_RELEASE_VERSION: ${{ needs.resolve-version.outputs.version }} | |
| MP_RELEASE_ARTIFACT: ${{ needs.resolve-version.outputs.artifact }} | |
| steps: | |
| - uses: actions/checkout@v7 | |
| with: | |
| fetch-depth: 0 | |
| - uses: actions/setup-dotnet@v5 | |
| with: | |
| dotnet-version: '10.0.x' | |
| - name: Package Linux | |
| if: matrix.rid == 'linux-x64' | |
| shell: bash | |
| run: | | |
| MISSIONPLANNER_UPSTREAM_VERSION="$MP_RELEASE_BASE" \ | |
| MISSIONPLANNER_BUILD_DATE="$MP_RELEASE_DATE" \ | |
| MISSIONPLANNER_COMMIT="$MP_RELEASE_COMMIT" \ | |
| MISSIONPLANNER_PORT_REVISION="$MP_RELEASE_REVISION" \ | |
| MISSIONPLANNER_DIRTY_SUFFIX="" \ | |
| PACKAGE_VERSION="$MP_RELEASE_VERSION" \ | |
| OUTPUT_DIR="$GITHUB_WORKSPACE/upload" \ | |
| PUBLISH_PARENT="$GITHUB_WORKSPACE/out" \ | |
| ./build/linux/package.sh all | |
| - name: Package Windows ZIP and MSI | |
| if: matrix.rid == 'win-x64' | |
| shell: bash | |
| env: | |
| WINDOWS_SIGNING_PFX_BASE64: ${{ secrets.WINDOWS_SIGNING_PFX }} | |
| WINDOWS_SIGN_PASSWORD: ${{ secrets.WINDOWS_SIGNING_PASSWORD }} | |
| run: | | |
| if [[ -n "$WINDOWS_SIGNING_PFX_BASE64" ]]; then | |
| printf '%s' "$WINDOWS_SIGNING_PFX_BASE64" | base64 --decode > "$RUNNER_TEMP/windows-signing.pfx" | |
| export WINDOWS_SIGN_PFX="$RUNNER_TEMP/windows-signing.pfx" | |
| fi | |
| MISSIONPLANNER_UPSTREAM_VERSION="$MP_RELEASE_BASE" \ | |
| MISSIONPLANNER_BUILD_DATE="$MP_RELEASE_DATE" \ | |
| MISSIONPLANNER_COMMIT="$MP_RELEASE_COMMIT" \ | |
| MISSIONPLANNER_PORT_REVISION="$MP_RELEASE_REVISION" \ | |
| MISSIONPLANNER_DIRTY_SUFFIX="" \ | |
| OUTPUT_DIR="$GITHUB_WORKSPACE/upload" \ | |
| PUBLISH_PARENT="$GITHUB_WORKSPACE/out" \ | |
| ./build/windows/package.sh all | |
| rm -f "$RUNNER_TEMP/windows-signing.pfx" | |
| - name: Package macOS app | |
| if: startsWith(matrix.rid, 'osx-') | |
| shell: bash | |
| env: | |
| MACOS_CERT_P12: ${{ secrets.MACOS_CERT_P12 }} | |
| MACOS_CERT_PASSWORD: ${{ secrets.MACOS_CERT_PASSWORD }} | |
| MACOS_SIGN_IDENTITY: ${{ secrets.MACOS_SIGN_IDENTITY }} | |
| MACOS_NOTARY_KEY: ${{ secrets.MACOS_NOTARY_KEY }} | |
| MACOS_NOTARY_KEY_ID: ${{ secrets.MACOS_NOTARY_KEY_ID }} | |
| MACOS_NOTARY_ISSUER: ${{ secrets.MACOS_NOTARY_ISSUER }} | |
| run: | | |
| RID=${{ matrix.rid }} | |
| mkdir -p out/macos dist upload | |
| dotnet publish MissionPlanner.csproj -c Release -r "$RID" --self-contained true \ | |
| -m:1 -p:DebugType=none -p:StripSymbols=true \ | |
| -p:MissionPlannerUpstreamVersion="$MP_RELEASE_BASE" \ | |
| -p:MissionPlannerBuildDate="$MP_RELEASE_DATE" \ | |
| -p:MissionPlannerCommit="$MP_RELEASE_COMMIT" \ | |
| -o out/macos | |
| if [[ -n "$MACOS_CERT_P12" && -n "$MACOS_SIGN_IDENTITY" ]]; then | |
| PASSWORD=$(uuidgen) | |
| KEYCHAIN="$RUNNER_TEMP/build.keychain-db" | |
| security create-keychain -p "$PASSWORD" "$KEYCHAIN" | |
| security set-keychain-settings -lut 21600 "$KEYCHAIN" | |
| security unlock-keychain -p "$PASSWORD" "$KEYCHAIN" | |
| printf '%s' "$MACOS_CERT_P12" | base64 -D > "$RUNNER_TEMP/cert.p12" | |
| security import "$RUNNER_TEMP/cert.p12" -k "$KEYCHAIN" \ | |
| -P "$MACOS_CERT_PASSWORD" -T /usr/bin/codesign | |
| security set-key-partition-list -S apple-tool:,apple:,codesign: \ | |
| -s -k "$PASSWORD" "$KEYCHAIN" >/dev/null | |
| security list-keychains -d user -s "$KEYCHAIN" | |
| export SIGN_IDENTITY="$MACOS_SIGN_IDENTITY" | |
| rm -f "$RUNNER_TEMP/cert.p12" | |
| fi | |
| ./build/macos/make-app.sh out/macos "$MP_RELEASE_BASE" "dist/Mission Planner 10.app" | |
| ZIP="upload/MissionPlanner10-$MP_RELEASE_ARTIFACT-$RID.zip" | |
| (cd dist && ditto -c -k --sequesterRsrc --keepParent "Mission Planner 10.app" "../$ZIP") | |
| NOTARY_KEY_PATH="" | |
| if [[ -n "$MACOS_NOTARY_KEY" && -n "$MACOS_NOTARY_KEY_ID" && -n "$MACOS_NOTARY_ISSUER" ]]; then | |
| NOTARY_KEY_PATH="$RUNNER_TEMP/notary.p8" | |
| printf '%s' "$MACOS_NOTARY_KEY" | base64 -D > "$NOTARY_KEY_PATH" | |
| xcrun notarytool submit "$ZIP" --key "$NOTARY_KEY_PATH" \ | |
| --key-id "$MACOS_NOTARY_KEY_ID" --issuer "$MACOS_NOTARY_ISSUER" --wait | |
| xcrun stapler staple "dist/Mission Planner 10.app" | |
| rm -f "$ZIP" | |
| (cd dist && ditto -c -k --sequesterRsrc --keepParent "Mission Planner 10.app" "../$ZIP") | |
| fi | |
| DMG="upload/MissionPlanner10-$MP_RELEASE_ARTIFACT-$RID.dmg" | |
| ./build/macos/make-dmg.sh "dist/Mission Planner 10.app" "$DMG" | |
| if [[ -n "$NOTARY_KEY_PATH" ]]; then | |
| xcrun notarytool submit "$DMG" --key "$NOTARY_KEY_PATH" \ | |
| --key-id "$MACOS_NOTARY_KEY_ID" --issuer "$MACOS_NOTARY_ISSUER" --wait | |
| xcrun stapler staple "$DMG" | |
| xcrun stapler validate "$DMG" | |
| rm -f "$NOTARY_KEY_PATH" | |
| fi | |
| - name: Build signed GitHub-release update manifest | |
| shell: bash | |
| env: | |
| UPDATE_SIGNING_KEY: ${{ secrets.UPDATE_SIGNING_KEY }} | |
| run: | | |
| test -n "$UPDATE_SIGNING_KEY" || { | |
| echo "::error::UPDATE_SIGNING_KEY is required for release validation"; exit 1; } | |
| RID=${{ matrix.rid }} | |
| case "$RID" in | |
| linux-x64) PUB="out/MissionPlanner10-$MP_RELEASE_ARTIFACT-linux-x64" ;; | |
| win-x64) PUB="out/MissionPlanner10-$MP_RELEASE_ARTIFACT-win-x64" ;; | |
| osx-x64|osx-arm64) PUB="out/macos" ;; | |
| esac | |
| if [[ "$RID" == osx-* ]]; then | |
| BUNDLE="upload/MissionPlanner10-$MP_RELEASE_ARTIFACT-$RID.zip" | |
| else | |
| BUNDLE="upload/MissionPlanner10-$MP_RELEASE_ARTIFACT-$RID-update.zip" | |
| # Keep one release-only legacy apphost alias so the pre-brand portable updater can | |
| # consume the first MissionPlanner10 bundle. Human packages contain only the new name. | |
| UPDATE_PUB="$RUNNER_TEMP/missionplanner10-update-$RID" | |
| mkdir -p "$UPDATE_PUB" | |
| cp -a "$PUB/." "$UPDATE_PUB/" | |
| if [[ "$RID" == win-* ]]; then | |
| cp "$UPDATE_PUB/MissionPlanner10.exe" "$UPDATE_PUB/MissionPlanner.exe" | |
| else | |
| cp "$UPDATE_PUB/MissionPlanner10" "$UPDATE_PUB/MissionPlanner" | |
| fi | |
| python3 build/make-update-bundle.py "$UPDATE_PUB" "$BUNDLE" | |
| fi | |
| BUNDLE_NAME=$(basename "$BUNDLE") | |
| BUNDLE_URL="https://github.com/${GITHUB_REPOSITORY}/releases/download/${GITHUB_REF_NAME}/$BUNDLE_NAME" | |
| BUNDLE_SHA=$(python3 -c \ | |
| 'import hashlib,sys; print(hashlib.file_digest(open(sys.argv[1], "rb"), "sha256").hexdigest())' \ | |
| "$BUNDLE") | |
| BUNDLE_SIZE=$(python3 -c 'import os,sys; print(os.path.getsize(sys.argv[1]))' "$BUNDLE") | |
| NOTES="https://github.com/${GITHUB_REPOSITORY}/releases/tag/${GITHUB_REF_NAME}" | |
| python3 build/gen-manifest.py "$PUB" "$MP_RELEASE_VERSION" "$NOTES" \ | |
| "upload/$RID-manifest.json" --bundle-url "$BUNDLE_URL" \ | |
| --bundle-sha256 "$BUNDLE_SHA" --bundle-size "$BUNDLE_SIZE" | |
| OPENSSL_BIN=openssl | |
| if [[ "$RUNNER_OS" == "macOS" ]]; then | |
| OPENSSL_BIN="$(brew --prefix openssl@3)/bin/openssl" | |
| fi | |
| test -x "$(command -v "$OPENSSL_BIN")" || { | |
| echo "::error::OpenSSL 3 is required to sign Ed25519 update manifests"; exit 1; } | |
| "$OPENSSL_BIN" version | |
| printf '%s' "$UPDATE_SIGNING_KEY" > "$RUNNER_TEMP/update-key.pem" | |
| ACTUAL_PUBLIC=$("$OPENSSL_BIN" pkey -in "$RUNNER_TEMP/update-key.pem" -pubout -outform DER \ | |
| 2>/dev/null | tail -c 32 | base64 | tr -d '\r\n') | |
| EXPECTED_PUBLIC=$(tr -d '\r\n' < build/update-public-key.txt) | |
| test "$ACTUAL_PUBLIC" = "$EXPECTED_PUBLIC" || { | |
| echo "::error::UPDATE_SIGNING_KEY does not match build/update-public-key.txt"; exit 1; } | |
| "$OPENSSL_BIN" pkeyutl -sign -rawin -inkey "$RUNNER_TEMP/update-key.pem" \ | |
| -in "upload/$RID-manifest.json" -out "$RUNNER_TEMP/update.sig" | |
| base64 < "$RUNNER_TEMP/update.sig" | tr -d '\r\n' > "upload/$RID-manifest.sig" | |
| rm -f "$RUNNER_TEMP/update-key.pem" "$RUNNER_TEMP/update.sig" | |
| - uses: actions/upload-artifact@v7 | |
| with: | |
| name: dist-${{ matrix.rid }} | |
| path: upload/* | |
| if-no-files-found: error | |
| release: | |
| needs: [resolve-version, package] | |
| if: startsWith(github.ref, 'refs/tags/') | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/download-artifact@v8 | |
| with: | |
| pattern: dist-* | |
| path: artifacts | |
| - name: Generate SHA-256 checksums | |
| shell: bash | |
| run: | | |
| mkdir release-files | |
| while IFS= read -r -d '' source; do | |
| target="release-files/$(basename "$source")" | |
| test ! -e "$target" || { | |
| echo "::error::Duplicate release asset name: $(basename "$source")" | |
| exit 1 | |
| } | |
| cp "$source" "$target" | |
| done < <(find artifacts -type f -print0) | |
| ( | |
| cd release-files | |
| find . -maxdepth 1 -type f ! -name SHA256SUMS -print0 | | |
| sort -z | xargs -0 sha256sum | |
| ) > release-files/SHA256SUMS | |
| - uses: softprops/action-gh-release@v3 | |
| with: | |
| files: release-files/* | |
| generate_release_notes: true | |
| prerelease: ${{ needs.resolve-version.outputs.prerelease == 'true' }} |