name: CI-MacOS

on:
  push:
    branches: [ master ]
  pull_request:
    branches: [ master ]

  # Allows you to run this workflow manually from the Actions tab.
  workflow_dispatch:
    inputs:
      debug_enabled:
        type: boolean
        description: 'Run the build with tmate debugging enabled'
        required: false
        default: false

env:
    VNOTE_VER: 3.19.2
    CMAKE_VER: 3.24.3

jobs:
  build:
    environment: Mac-code-sign
    name: Build On MacOS
    timeout-minutes: 120

    strategy:
      fail-fast: false
      matrix:
        config:
          - name: "Build on Arm64"
            os: macos-latest
            arch: universal
            qt: 6.8.3

    runs-on: ${{matrix.config.os}}

    steps:
      # Checks-out your repository under $GITHUB_WORKSPACE.
      - uses: actions/checkout@v2
        with:
          fetch-depth: 1

      - name: Init Submodules
        run: |
          auth_header="$(git config --local --get http.https://github.com/.extraheader)"
          git submodule sync --recursive
          git -c "http.extraheader=$auth_header" -c protocol.version=2 submodule update --init --force --recursive --depth=1

      - name: Install Dependencies
        run: |
          brew install tree libiodbc libpq

      - name: Fix SQL
        run: |
          sudo mkdir -p /usr/local/opt/libiodbc/lib
          sudo ln -s /opt/homebrew/opt/libiodbc/lib/libiodbc.2.dylib /usr/local/opt/libiodbc/lib/libiodbc.2.dylib
          sudo mkdir -p /Applications/Postgres.app/Contents/Versions/14/lib
          sudo ln -s /opt/homebrew/Cellar/libpq/16.3/lib/libpq.5.dylib /Applications/Postgres.app/Contents/Versions/14/lib/libpq.5.dylib

      - name: Install a fresh CMake
        run: |
          wget --no-verbose https://github.com/Kitware/CMake/releases/download/v${CMAKE_VER}/cmake-${CMAKE_VER}-macos-universal.tar.gz
          tar xzf cmake-${CMAKE_VER}-macos-universal.tar.gz
          sudo rm -f /usr/local/bin/cmake /usr/local/bin/cpack
          sudo ln -s ${{runner.workspace}}/cmake-${CMAKE_VER}-macos-universal/CMake.app/Contents/bin/cmake /usr/local/bin/cmake
          sudo ln -s ${{runner.workspace}}/cmake-${CMAKE_VER}-macos-universal/CMake.app/Contents/bin/cpack /usr/local/bin/cpack
        working-directory: ${{runner.workspace}}

      - name: Install macdeployqtfix
        run: |
          git clone https://github.com/tamlok/macdeployqtfix.git macdeployqtfix --depth=1
        working-directory: ${{runner.workspace}}

      - name: Install optool
        run: |
          wget --no-verbose https://github.com/alexzielenski/optool/releases/download/0.1/optool.zip
          unzip ./optool.zip
          sudo ln -s ./optool /usr/local/bin/optool
        working-directory: ${{runner.workspace}}

      - name: Cache Qt
        id: cache-qt
        uses: actions/cache@v4
        with:
          path: ${{runner.workspace}}/Qt
          key: ${{ runner.os }}-QtCache-6.8

      - name: Install Qt
        uses: jurplel/install-qt-action@v3
        with:
          version: ${{matrix.config.qt}}
          target: desktop
          modules: 'qtwebengine qtwebchannel qtpositioning qtpdf qtimageformats qt5compat qtserialport'
          cache: 'true'

      - name: Create Build Dir
        run: mkdir build
        working-directory: ${{runner.workspace}}

      - name: Configure Project
        run: |
          qmake -v
          cmake --version
          cmake -DMACDEPLOYQTFIX_EXECUTABLE=${{runner.workspace}}/macdeployqtfix/macdeployqtfix.py -DCMAKE_OSX_ARCHITECTURES="x86_64;arm64"  ${GITHUB_WORKSPACE}
        working-directory: ${{runner.workspace}}/build

      - name: Build Project
        run: |
          # Keep only required SQL drivers
          rm ${{env.Qt6_DIR}}/plugins/sqldrivers/libqsqlmimer.dylib
          rm ${{env.Qt6_DIR}}/plugins/sqldrivers/libqsqlodbc.dylib
          rm ${{env.Qt6_DIR}}/plugins/sqldrivers/libqsqlpsql.dylib

          # Build the project
          cmake --build . --target pack

          # Fix Qt frameworks
          python3 ${{runner.workspace}}/macdeployqtfix/macdeployqtfix.py ./src/VNote.app/Contents/MacOS/VNote ${{env.Qt6_DIR}}/../..

          # Only delete rpaths that exist to avoid errors
          for rpath in $(otool -l ./src/VNote.app/Contents/MacOS/VNote | awk '/LC_RPATH/ {getline; getline; print $2}' | grep 'vnote'); do
            echo "Checking rpath: $rpath"
            if otool -l ./src/VNote.app/Contents/MacOS/VNote | grep -q "$rpath"; then
              echo "Deleting rpath: $rpath"
              install_name_tool -delete_rpath "$rpath" ./src/VNote.app/Contents/MacOS/VNote
            else
              echo "Rpath not found: $rpath"
            fi
          done
          for rpath in $(otool -l ./src/VNote.app/Contents/Frameworks/libVTextEdit.dylib | awk '/LC_RPATH/ {getline; getline; print $2}' | grep 'vnote'); do
            echo "Checking rpath: $rpath"
            if otool -l ./src/VNote.app/Contents/Frameworks/libVTextEdit.dylib | grep -q "$rpath"; then
              echo "Deleting rpath: $rpath"
              install_name_tool -delete_rpath "$rpath" ./src/VNote.app/Contents/Frameworks/libVTextEdit.dylib
            else
              echo "Rpath not found: $rpath"
            fi
          done

          # Run macdeployqtfix again to ensure all dependencies are properly fixed
          python3 ${{runner.workspace}}/macdeployqtfix/macdeployqtfix.py ./src/VNote.app/Contents/MacOS/VNote ${{env.Qt6_DIR}}/../..
        working-directory: ${{runner.workspace}}/build

      - name: Codesign Bundle
        # Extract the secrets we defined earlier as environment variables
        env:
          MACOS_CERTIFICATE: ${{ secrets.CLI_MACOS_CERTIFICATE }}
          MACOS_CERTIFICATE_PWD: ${{ secrets.CLI_MACOS_CERTIFICATE_PWD }}
          MACOS_CERTIFICATE_NAME: ${{ secrets.CLI_MACOS_CERTIFICATE_NAME }}
          MACOS_CI_KEYCHAIN_PWD: ${{ secrets.CLI_MACOS_CERTIFICATE }}
        run: |
          # Turn our base64-encoded certificate back to a regular .p12 file
          echo $MACOS_CERTIFICATE | base64 --decode > certificate.p12

          # We need to create a new keychain, otherwise using the certificate will prompt
          # with a UI dialog asking for the certificate password, which we can't
          # use in a headless CI environment
          security create-keychain -p "$MACOS_CI_KEYCHAIN_PWD" build.keychain
          security default-keychain -s build.keychain
          security unlock-keychain -p "$MACOS_CI_KEYCHAIN_PWD" build.keychain
          security import certificate.p12 -k build.keychain -P "$MACOS_CERTIFICATE_PWD" -T /usr/bin/codesign
          security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k "$MACOS_CI_KEYCHAIN_PWD" build.keychain

          echo "Codesigning main app bundle"
          codesign --force --deep -s "$MACOS_CERTIFICATE_NAME" --entitlements ${{github.workspace}}/package/entitlements.xml --options runtime ./src/VNote.app
          codesign -v -vvv ./src/VNote.app

          hdiutil create -volname "VNote" -srcfolder ./src/VNote.app -ov -format UDZO VNote-${{env.VNOTE_VER}}-mac-${{matrix.config.arch}}.dmg
          codesign --force --deep -s "$MACOS_CERTIFICATE_NAME" --entitlements ${{github.workspace}}/package/entitlements.xml --options runtime ./VNote-${{env.VNOTE_VER}}-mac-${{matrix.config.arch}}.dmg
          codesign -v -vvv ./VNote-${{env.VNOTE_VER}}-mac-${{matrix.config.arch}}.dmg

        working-directory: ${{runner.workspace}}/build

      - name: "Notarize Bundle"
        # Extract the secrets we defined earlier as environment variables
        env:
          PROD_MACOS_NOTARIZATION_APPLE_ID: ${{ secrets.CLI_MACOS_NOTARY_USER }}
          PROD_MACOS_NOTARIZATION_TEAM_ID: ${{ secrets.CLI_MACOS_TEAM_ID }}
          PROD_MACOS_NOTARIZATION_PWD: ${{ secrets.CLI_MACOS_NOTARY_PWD }}
        run: |
          # Store the notarization credentials so that we can prevent a UI password dialog
          # from blocking the CI
          echo "Create keychain profile"
          xcrun notarytool store-credentials "notarytool-profile" --apple-id "$PROD_MACOS_NOTARIZATION_APPLE_ID" --team-id "$PROD_MACOS_NOTARIZATION_TEAM_ID" --password "$PROD_MACOS_NOTARIZATION_PWD"

          # Here we send the notarization request to the Apple's Notarization service, waiting for the result.
          # This typically takes a few seconds inside a CI environment, but it might take more depending on the App
          # characteristics. Visit the Notarization docs for more information and strategies on how to optimize it if
          # you're curious
          echo "Notarize app"
          xcrun notarytool submit "${{runner.workspace}}/build/VNote-${{env.VNOTE_VER}}-mac-${{matrix.config.arch}}.dmg" --keychain-profile "notarytool-profile" --wait

          # Finally, we need to "attach the staple" to our executable, which will allow our app to be
          # validated by macOS even when an internet connection is not available.
          echo "Attach staple"
          xcrun stapler staple "${{runner.workspace}}/build/VNote-${{env.VNOTE_VER}}-mac-${{matrix.config.arch}}.dmg"

      # Enable tmate debugging of manually-triggered workflows if the input option was provided
      - name: Setup tmate session
        uses: mxschmitt/action-tmate@v3
        if: ${{ github.event_name == 'workflow_dispatch' && inputs.debug_enabled }}

      - name: Archive DMG
        uses: actions/upload-artifact@v4
        with:
          name: VNote-${{env.VNOTE_VER}}-mac-${{matrix.config.arch}}
          path: ${{runner.workspace}}/build/VNote-${{env.VNOTE_VER}}-mac-${{matrix.config.arch}}.dmg

      - name: Update Tag
        if: github.ref == 'refs/heads/master'
        run: |
          git tag --force continuous-build ${GITHUB_SHA}
          git push --force --tags

      - name: Update Continuous Build Release
        if: github.ref == 'refs/heads/master'
        uses: johnwbyrd/update-release@v1.0.0
        with:
          token: ${{ secrets.GITHUB_TOKEN }}
          files: ${{runner.workspace}}/build/VNote-${{env.VNOTE_VER}}-mac-${{matrix.config.arch}}.dmg
          release: Continuous Build
          tag: continuous-build

      - name: Release
        if: github.ref == 'refs/heads/master' && startsWith(github.event.head_commit.message, '[Release]')
        uses: ncipollo/release-action@v1.11.0
        with:
          token: ${{ secrets.GITHUB_TOKEN }}
          artifacts: ${{runner.workspace}}/build/VNote-${{env.VNOTE_VER}}-mac-${{matrix.config.arch}}.dmg
          commit: master
          tag: v${{env.VNOTE_VER}}
          allowUpdates: true
          draft: true
