Range FEA 1.0.0 #15
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: CI (Linux/macOS/Windows) | |
| on: | |
| push: | |
| branches: [ main ] | |
| tags: ['v*'] | |
| release: | |
| types: [published] | |
| pull_request: | |
| permissions: | |
| contents: write | |
| jobs: | |
| build: | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - os: ubuntu-latest | |
| arch: x86_64 | |
| qt_host: linux | |
| qt_arch: linux_gcc_64 | |
| - os: macos-latest | |
| arch: arm64 | |
| qt_host: mac | |
| qt_arch: clang_64 | |
| - os: windows-latest | |
| arch: x64 | |
| qt_host: windows | |
| qt_arch: win64_msvc2022_64 | |
| runs-on: ${{ matrix.os }} | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| submodules: recursive | |
| fetch-depth: 0 | |
| # Prep | |
| - name: Prep Linux | |
| if: startsWith(matrix.os, 'ubuntu-') | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y ninja-build | |
| - name: Prep macOS | |
| if: startsWith(matrix.os, 'macos-') | |
| run: | | |
| brew update | |
| brew install ninja libomp || true | |
| - name: Set up MSVC (Windows) | |
| if: startsWith(matrix.os, 'windows-') | |
| uses: ilammy/msvc-dev-cmd@v1 | |
| - name: Ensure Ninja (Windows) | |
| if: startsWith(matrix.os, 'windows-') | |
| run: choco install ninja -y || echo "Ninja already present" | |
| shell: pwsh | |
| # Qt | |
| - name: Install Qt 6.10.0 + QtIFW | |
| uses: jurplel/install-qt-action@v4 | |
| with: | |
| version: '6.10.0' | |
| host: ${{ matrix.qt_host }} | |
| target: desktop | |
| arch: ${{ matrix.qt_arch }} | |
| cache: true | |
| aqtversion: '==3.3.*' | |
| modules: 'qthttpserver qtwebsockets qtimageformats qtmultimedia' | |
| tools: 'tools_ifw' | |
| - name: Show versions (Unix) | |
| if: matrix.os != 'windows-latest' | |
| run: | | |
| cmake --version | |
| qmake -v || true | |
| - name: Show versions (Windows) | |
| if: startsWith(matrix.os, 'windows-') | |
| run: | | |
| cmake --version | |
| qmake -v || Write-Host "qmake not on PATH (ok)" | |
| shell: pwsh | |
| # --- Import Developer ID cert into an ephemeral keychain --- | |
| - name: Create and unlock keychain | |
| if: startsWith(matrix.os, 'macos-') | |
| run: | | |
| security create-keychain -p "$MAC_KEYCHAIN_PASSWORD" build.keychain | |
| security set-keychain-settings -lut 21600 build.keychain | |
| security unlock-keychain -p "$MAC_KEYCHAIN_PASSWORD" build.keychain | |
| security list-keychains -s build.keychain login.keychain | |
| env: | |
| MAC_KEYCHAIN_PASSWORD: ${{ secrets.MAC_KEYCHAIN_PASSWORD }} | |
| - name: Import Developer ID certificate (macOS) | |
| if: startsWith(matrix.os, 'macos-') | |
| run: | | |
| base64 -d <<< "$MAC_CERT_P12" > dev.p12 | |
| security import dev.p12 -k build.keychain -P "$MAC_CERT_P12_PASSWORD" -T /usr/bin/codesign -T /usr/bin/security | |
| # Allow codesign to use the key non-interactively: | |
| security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k "$MAC_KEYCHAIN_PASSWORD" build.keychain | |
| rm -f dev.p12 | |
| env: | |
| MAC_CERT_P12: ${{ secrets.MAC_CERT_P12 }} | |
| MAC_CERT_P12_PASSWORD: ${{ secrets.MAC_CERT_P12_PASSWORD }} | |
| MAC_KEYCHAIN_PASSWORD: ${{ secrets.MAC_KEYCHAIN_PASSWORD }} | |
| - name: Write App Store Connect API key (macOS) | |
| if: startsWith(matrix.os, 'macos-') | |
| run: | | |
| set -euo pipefail | |
| mkdir -p $HOME/.private_keys | |
| echo "$AC_API_KEY_P8" | base64 -d > $HOME/.private_keys/AuthKey_${AC_API_KEY_ID}.p8 | |
| chmod 600 $HOME/.private_keys/AuthKey_${AC_API_KEY_ID}.p8 | |
| env: | |
| AC_API_KEY_P8: ${{ secrets.AC_API_KEY_P8 }} | |
| AC_API_KEY_ID: ${{ secrets.AC_API_KEY_ID }} | |
| # Configure | |
| - name: Configure (Linux) | |
| if: startsWith(matrix.os, 'ubuntu-') | |
| run: | | |
| cmake -S src -B build-Release -G Ninja \ | |
| -DCMAKE_BUILD_TYPE=Release | |
| - name: Configure (macOS) | |
| if: startsWith(matrix.os, 'macos-') | |
| run: | | |
| OMP_PREFIX="$(brew --prefix libomp)" | |
| cmake -S src -B build-Release -G Ninja \ | |
| -DCMAKE_BUILD_TYPE=Release \ | |
| -DOpenMP_INCLUDES="${OMP_PREFIX}/include" \ | |
| -DOpenMP_LIBRARY="${OMP_PREFIX}/lib/libomp.dylib" \ | |
| -DCODESIGN_ID="$CODESIGN_ID" | |
| env: | |
| CODESIGN_ID: ${{ secrets.CODESIGN_ID }} | |
| - name: Configure (Windows) | |
| if: startsWith(matrix.os, 'windows-') | |
| run: cmake -S src -B build-Release -G Ninja -DCMAKE_BUILD_TYPE=Release | |
| shell: pwsh | |
| # Build | |
| - name: Build (Unix) | |
| if: matrix.os != 'windows-latest' | |
| run: cmake --build build-Release --target package --parallel | |
| - name: Build (Windows) | |
| if: startsWith(matrix.os, 'windows-') | |
| run: cmake --build build-Release --target package --parallel | |
| shell: pwsh | |
| # Notarize | |
| - name: Notarize DMG with notarytool (macOS) | |
| if: startsWith(matrix.os, 'macos-') | |
| run: | | |
| set -euo pipefail | |
| DMG="$(/usr/bin/find build-Release -name '*.dmg' -print -quit)" | |
| echo "DMG: $DMG" | |
| JSON_OUT="$(mktemp)" | |
| xcrun notarytool submit "$DMG" \ | |
| --key "$HOME/.private_keys/AuthKey_${AC_API_KEY_ID}.p8" \ | |
| --key-id "$AC_API_KEY_ID" \ | |
| --issuer "$AC_API_ISSUER_ID" \ | |
| --wait --timeout 20m --output-format json > "$JSON_OUT" | |
| echo "Notarytool output:" | |
| cat "$JSON_OUT" | |
| # Extract submission id and status using plutil (built-in) | |
| SUBMISSION_ID=$(plutil -extract id raw -o - "$JSON_OUT") | |
| STATUS=$(plutil -extract status raw -o - "$JSON_OUT" 2>/dev/null || echo "") | |
| echo "Submission ID: $SUBMISSION_ID" | |
| echo "Status: $STATUS" | |
| # Always fetch and print the full log (super helpful when rejected) | |
| xcrun notarytool log "$SUBMISSION_ID" \ | |
| --key "$HOME/.private_keys/AuthKey_${AC_API_KEY_ID}.p8" \ | |
| --key-id "$AC_API_KEY_ID" \ | |
| --issuer "$AC_API_ISSUER_ID" || true | |
| # Hard fail unless Accepted | |
| if [[ "$STATUS" != "Accepted" ]]; then | |
| echo "Notarization did not succeed (status=$STATUS). Aborting before staple." | |
| exit 1 | |
| fi | |
| env: | |
| AC_API_KEY_ID: ${{ secrets.AC_API_KEY_ID }} | |
| AC_API_ISSUER_ID: ${{ secrets.AC_API_ISSUER_ID }} | |
| - name: macOS – staple | |
| if: startsWith(matrix.os, 'macos-') | |
| run: | | |
| set -euo pipefail | |
| DMG="$(/usr/bin/find build-Release -name '*.dmg' -print -quit)" | |
| xcrun stapler staple "$DMG" | |
| # Optional: also staple the app (useful if you ever upload the .app directly) | |
| APP_BUNDLE="$(/usr/bin/find build-Release -name '*.app' -maxdepth 2 -print -quit)" | |
| xcrun stapler staple "$APP_BUNDLE" || true | |
| # Artifacts | |
| - name: Upload packages | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: ${{ github.event.repository.name }}-${{ matrix.os }}-${{ matrix.arch }}-packages | |
| path: | | |
| build-Release/${{ github.event.repository.name }}-*.deb | |
| build-Release/${{ github.event.repository.name }}-*.rpm | |
| build-Release/${{ github.event.repository.name }}-*.sh | |
| build-Release/${{ github.event.repository.name }}-*.run | |
| build-Release/${{ github.event.repository.name }}-*.zip | |
| build-Release/${{ github.event.repository.name }}-*.tar.gz | |
| build-Release/${{ github.event.repository.name }}-*.dmg | |
| build-Release/${{ github.event.repository.name }}-*.exe | |
| if-no-files-found: error | |
| release: | |
| name: Publish GitHub Release | |
| if: github.event_name == 'release' || startsWith(github.ref, 'refs/tags/') | |
| needs: [build] | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Download build artifacts | |
| uses: actions/download-artifact@v4 | |
| with: | |
| pattern: ${{ github.event.repository.name }}-*packages | |
| merge-multiple: true | |
| path: artifacts | |
| - name: List files | |
| run: ls -lah artifacts | |
| - name: Create Release & upload assets | |
| uses: softprops/action-gh-release@v2 | |
| with: | |
| # Mark RC/Beta as prerelease automatically (optional) | |
| prerelease: ${{ contains(github.ref_name, '-rc') || contains(github.ref_name, '-beta') }} | |
| files: artifacts/* | |
| - name: Prepare Range Cloud client key and certificate | |
| run: | | |
| set -euo pipefail | |
| mkdir -p $HOME/.private_keys | |
| echo "$RANGE_CLOUD_KEY_PEM" | base64 -d > $HOME/.private_keys/range_cloud_key.pem | |
| chmod 600 $HOME/.private_keys/range_cloud_key.pem | |
| echo "$RANGE_CLOUD_CERT_PEM" | base64 -d > $HOME/.private_keys/range_cloud_cert.pem | |
| chmod 600 $HOME/.private_keys/range_cloud_cert.pem | |
| env: | |
| RANGE_CLOUD_KEY_PEM: ${{ secrets.RANGE_CLOUD_KEY_PEM }} | |
| RANGE_CLOUD_CERT_PEM: ${{ secrets.RANGE_CLOUD_CERT_PEM }} | |
| - name: Publish on Range Cloud | |
| run: | | |
| set -euo pipefail | |
| for f in artifacts/*; do | |
| [ -f "$f" ] || continue | |
| fileName="$(basename $f)" | |
| fileInfo=${fileName#$REPO_NAME} | |
| fileVersion=$(echo $fileInfo | cut -d'-' -f2) | |
| fileOs=$(echo $fileInfo | cut -d'-' -f3) | |
| fileArch=$(echo $fileInfo | cut -d'-' -f4 | cut -d'.' -f1) | |
| echo "Uploading: $fileName" | |
| curl -X PUT --upload-file $f -o $HOME/response.json --key $HOME/.private_keys/range_cloud_key.pem --key-type PEM --pass 12345678 --cert $HOME/.private_keys/range_cloud_cert.pem https://range-software.com:4012/file-replace/?resource-name=$fileName | |
| fileId=$(jq -r '.upload.id' $HOME/response.json) | |
| echo "Updating file access mode: $fileName : 644" | |
| curl -X POST -d "{\"user\":6,\"group\":4,\"other\":4}" --key $HOME/.private_keys/range_cloud_key.pem --key-type PEM --pass 12345678 --cert $HOME/.private_keys/range_cloud_cert.pem https://range-software.com:4012/file-update-access-mode/?resource-id=$fileId | |
| echo "Updating file version: $fileName : $fileVersion" | |
| curl -X POST -d "$fileVersion" --key $HOME/.private_keys/range_cloud_key.pem --key-type PEM --pass 12345678 --cert $HOME/.private_keys/range_cloud_cert.pem https://range-software.com:4012/file-update-version/?resource-id=$fileId | |
| echo "Updating file tags: $fileName : $REPO_NAME,$fileOs,$fileArch" | |
| curl -X POST -d "$REPO_NAME,$fileOs,$fileArch" --key $HOME/.private_keys/range_cloud_key.pem --key-type PEM --pass 12345678 --cert $HOME/.private_keys/range_cloud_cert.pem https://range-software.com:4012/file-update-tags/?resource-id=$fileId | |
| done | |
| env: | |
| RANGE_CLOUD_KEY_PASSWORD: ${{ secrets.RANGE_CLOUD_KEY_PASSWORD }} | |
| REPO_NAME: ${{ github.event.repository.name }} |