name: build

on:
  push:
    branches:
      - master
      - stable
      - users
    tags:
      - "v*"
      - "!*-fdroid"
      - "!*-armv7a"
  pull_request:

jobs:
  prepare-release:
    if: startsWith(github.ref, 'refs/tags/v')
    runs-on: ubuntu-latest
    steps:
      - name: Clone project
        uses: actions/checkout@v3

      - name: Build changelog
        id: build_changelog
        uses: mikepenz/release-changelog-builder-action@v4
        with:
          configuration: .github/changelog_conf.json
          failOnError: true
          ignorePreReleases: true
          commitMode: true
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

      - name: Create release
        uses: softprops/action-gh-release@v1
        with:
          body: ${{ steps.build_changelog.outputs.changelog }}
          prerelease: true
          files: |
            LICENSE
          fail_on_unmatched_files: true
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

  build:
    name: build-${{ matrix.os }}-${{ matrix.ghc }}
    if: always()
    needs: prepare-release
    runs-on: ${{ matrix.os }}
    strategy:
      fail-fast: false
      matrix:
        include:
          - os: ubuntu-20.04
            ghc: "8.10.7"
            cache_path: ~/.cabal/store
          - os: ubuntu-20.04
            ghc: "9.6.3"
            cache_path: ~/.cabal/store
            asset_name: simplex-chat-ubuntu-20_04-x86-64
            desktop_asset_name: simplex-desktop-ubuntu-20_04-x86_64.deb
          - os: ubuntu-22.04
            ghc: "9.6.3"
            cache_path: ~/.cabal/store
            asset_name: simplex-chat-ubuntu-22_04-x86-64
            desktop_asset_name: simplex-desktop-ubuntu-22_04-x86_64.deb
          - os: macos-latest
            ghc: "9.6.3"
            cache_path: ~/.cabal/store
            asset_name: simplex-chat-macos-aarch64
            desktop_asset_name: simplex-desktop-macos-aarch64.dmg
          - os: macos-13
            ghc: "9.6.3"
            cache_path: ~/.cabal/store
            asset_name: simplex-chat-macos-x86-64
            desktop_asset_name: simplex-desktop-macos-x86_64.dmg
          - os: windows-latest
            ghc: "9.6.3"
            cache_path: C:/cabal
            asset_name: simplex-chat-windows-x86-64
            desktop_asset_name: simplex-desktop-windows-x86_64.msi
    steps:
      - name: Configure pagefile (Windows)
        if: matrix.os == 'windows-latest'
        uses: al-cheb/configure-pagefile-action@v1.3
        with:
          minimum-size: 16GB
          maximum-size: 16GB
          disk-root: "C:"

      - name: Clone project
        uses: actions/checkout@v3

      - name: Setup Haskell
        uses: haskell-actions/setup@v2
        with:
          ghc-version: ${{ matrix.ghc }}
          cabal-version: "3.10.1.0"

      - name: Restore cached build
        id: restore_cache
        uses: actions/cache/restore@v3
        with:
          path: |
            ${{ matrix.cache_path }}
            dist-newstyle
          key: ${{ matrix.os }}-ghc${{ matrix.ghc }}-${{ hashFiles('cabal.project', 'simplex-chat.cabal') }}

      # / Unix

      - name: Unix prepare cabal.project.local for Mac
        if: matrix.os == 'macos-latest'
        shell: bash
        run: |
          echo "ignore-project: False"                                         >> cabal.project.local
          echo "package simplexmq"                                             >> cabal.project.local
          echo "    extra-include-dirs: /opt/homebrew/opt/openssl@1.1/include" >> cabal.project.local
          echo "    extra-lib-dirs: /opt/homebrew/opt/openssl@1.1/lib"         >> cabal.project.local
          echo ""                                                              >> cabal.project.local
          echo "package direct-sqlcipher"                                      >> cabal.project.local
          echo "    extra-include-dirs: /opt/homebrew/opt/openssl@1.1/include" >> cabal.project.local
          echo "    extra-lib-dirs: /opt/homebrew/opt/openssl@1.1/lib"         >> cabal.project.local
          echo "    flags: +openssl"                                           >> cabal.project.local

      - name: Unix prepare cabal.project.local for Mac
        if: matrix.os == 'macos-13'
        shell: bash
        run: |
          echo "ignore-project: False"                                         >> cabal.project.local
          echo "package simplexmq"                                             >> cabal.project.local
          echo "    extra-include-dirs: /usr/local/opt/openssl@1.1/include"    >> cabal.project.local
          echo "    extra-lib-dirs: /usr/local/opt/openssl@1.1/lib"            >> cabal.project.local
          echo ""                                                              >> cabal.project.local
          echo "package direct-sqlcipher"                                      >> cabal.project.local
          echo "    extra-include-dirs: /usr/local/opt/openssl@1.1/include"    >> cabal.project.local
          echo "    extra-lib-dirs: /usr/local/opt/openssl@1.1/lib"            >> cabal.project.local
          echo "    flags: +openssl"                                           >> cabal.project.local

      - name: Install AppImage dependencies
        if: startsWith(github.ref, 'refs/tags/v') && matrix.asset_name && matrix.os == 'ubuntu-20.04'
        run: sudo apt install -y desktop-file-utils

      - name: Install pkg-config for Mac
        if: matrix.os == 'macos-latest' || matrix.os == 'macos-13'
        run: brew install pkg-config

      - name: Unix prepare cabal.project.local for Ubuntu
        if: matrix.os == 'ubuntu-20.04' || matrix.os == 'ubuntu-22.04'
        shell: bash
        run: |
          echo "ignore-project: False"    >> cabal.project.local
          echo "package direct-sqlcipher" >> cabal.project.local
          echo "    flags: +openssl"      >> cabal.project.local

      - name: Unix build CLI
        id: unix_cli_build
        if: matrix.os != 'windows-latest'
        shell: bash
        run: |
          cabal build --enable-tests
          path=$(cabal list-bin simplex-chat)
          echo "bin_path=$path" >> $GITHUB_OUTPUT
          echo "bin_hash=$(echo SHA2-512\(${{ matrix.asset_name }}\)= $(openssl sha512 $path | cut -d' ' -f 2))" >> $GITHUB_OUTPUT

      - name: Unix upload CLI binary to release
        if: startsWith(github.ref, 'refs/tags/v') && matrix.asset_name && matrix.os != 'windows-latest'
        uses: svenstaro/upload-release-action@v2
        with:
          repo_token: ${{ secrets.GITHUB_TOKEN }}
          file: ${{ steps.unix_cli_build.outputs.bin_path }}
          asset_name: ${{ matrix.asset_name }}
          tag: ${{ github.ref }}

      - name: Unix update CLI binary hash
        if: startsWith(github.ref, 'refs/tags/v') && matrix.asset_name && matrix.os != 'windows-latest'
        uses: softprops/action-gh-release@v1
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          append_body: true
          body: |
            ${{ steps.unix_cli_build.outputs.bin_hash }}

      - name: Setup Java
        if: startsWith(github.ref, 'refs/tags/v') && matrix.asset_name
        uses: actions/setup-java@v3
        with:
          distribution: 'corretto'
          java-version: '17'
          cache: 'gradle'

      - name: Linux build desktop
        id: linux_desktop_build
        if: startsWith(github.ref, 'refs/tags/v') && matrix.asset_name && (matrix.os == 'ubuntu-20.04' || matrix.os == 'ubuntu-22.04')
        shell: bash
        run: |
          scripts/desktop/build-lib-linux.sh
          cd apps/multiplatform
          ./gradlew packageDeb
          path=$(echo $PWD/release/main/deb/simplex_*_amd64.deb)
          echo "package_path=$path" >> $GITHUB_OUTPUT
          echo "package_hash=$(echo SHA2-512\(${{ matrix.desktop_asset_name }}\)= $(openssl sha512 $path | cut -d' ' -f 2))" >> $GITHUB_OUTPUT

      - name: Linux make AppImage
        id: linux_appimage_build
        if: startsWith(github.ref, 'refs/tags/v') && matrix.asset_name && matrix.os == 'ubuntu-20.04'
        shell: bash
        run: |
          scripts/desktop/make-appimage-linux.sh
          path=$(echo $PWD/apps/multiplatform/release/main/*imple*.AppImage)
          echo "appimage_path=$path" >> $GITHUB_OUTPUT
          echo "appimage_hash=$(echo SHA2-512\(simplex-desktop-x86_64.AppImage\)= $(openssl sha512 $path | cut -d' ' -f 2))" >> $GITHUB_OUTPUT

      - name: Mac build desktop
        id: mac_desktop_build
        if: startsWith(github.ref, 'refs/tags/v') && (matrix.os == 'macos-latest' || matrix.os == 'macos-13')
        shell: bash
        env:
          APPLE_SIMPLEX_SIGNING_KEYCHAIN: ${{ secrets.APPLE_SIMPLEX_SIGNING_KEYCHAIN }}
          APPLE_SIMPLEX_NOTARIZATION_APPLE_ID: ${{ secrets.APPLE_SIMPLEX_NOTARIZATION_APPLE_ID }}
          APPLE_SIMPLEX_NOTARIZATION_PASSWORD: ${{ secrets.APPLE_SIMPLEX_NOTARIZATION_PASSWORD }}
        run: |
          scripts/ci/build-desktop-mac.sh
          path=$(echo $PWD/apps/multiplatform/release/main/dmg/SimpleX-*.dmg)
          echo "package_path=$path" >> $GITHUB_OUTPUT
          echo "package_hash=$(echo SHA2-512\(${{ matrix.desktop_asset_name }}\)= $(openssl sha512 $path | cut -d' ' -f 2))" >> $GITHUB_OUTPUT

      - name: Linux upload desktop package to release
        if: startsWith(github.ref, 'refs/tags/v') && matrix.asset_name && (matrix.os == 'ubuntu-20.04' || matrix.os == 'ubuntu-22.04')
        uses: svenstaro/upload-release-action@v2
        with:
          repo_token: ${{ secrets.GITHUB_TOKEN }}
          file: ${{ steps.linux_desktop_build.outputs.package_path }}
          asset_name: ${{ matrix.desktop_asset_name }}
          tag: ${{ github.ref }}

      - name: Linux update desktop package hash
        if: startsWith(github.ref, 'refs/tags/v') && matrix.asset_name && (matrix.os == 'ubuntu-20.04' || matrix.os == 'ubuntu-22.04')
        uses: softprops/action-gh-release@v1
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          append_body: true
          body: |
            ${{ steps.linux_desktop_build.outputs.package_hash }}

      - name: Linux upload AppImage to release
        if: startsWith(github.ref, 'refs/tags/v') && matrix.asset_name && matrix.os == 'ubuntu-20.04'
        uses: svenstaro/upload-release-action@v2
        with:
          repo_token: ${{ secrets.GITHUB_TOKEN }}
          file: ${{ steps.linux_appimage_build.outputs.appimage_path }}
          asset_name: simplex-desktop-x86_64.AppImage
          tag: ${{ github.ref }}

      - name: Linux update AppImage hash
        if: startsWith(github.ref, 'refs/tags/v') && matrix.asset_name && matrix.os == 'ubuntu-20.04'
        uses: softprops/action-gh-release@v1
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          append_body: true
          body: |
            ${{ steps.linux_appimage_build.outputs.appimage_hash }}

      - name: Mac upload desktop package to release
        if: startsWith(github.ref, 'refs/tags/v') && (matrix.os == 'macos-latest' || matrix.os == 'macos-13')
        uses: svenstaro/upload-release-action@v2
        with:
          repo_token: ${{ secrets.GITHUB_TOKEN }}
          file: ${{ steps.mac_desktop_build.outputs.package_path }}
          asset_name: ${{ matrix.desktop_asset_name }}
          tag: ${{ github.ref }}

      - name: Mac update desktop package hash
        if: startsWith(github.ref, 'refs/tags/v') && (matrix.os == 'macos-latest' || matrix.os == 'macos-13')
        uses: softprops/action-gh-release@v1
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          append_body: true
          body: |
            ${{ steps.mac_desktop_build.outputs.package_hash }}

      - name: Cache unix build
        uses: actions/cache/save@v3
        if: matrix.os != 'windows-latest'
        with:
          path: |
            ${{ matrix.cache_path }}
            dist-newstyle
          key: ${{ steps.restore_cache.outputs.cache-primary-key }}

      - name: Unix test
        if: matrix.os != 'windows-latest'
        timeout-minutes: 40
        shell: bash
        run: cabal test --test-show-details=direct

      # Unix /

      # / Windows
      # rm -rf dist-newstyle/src/direct-sq* is here because of the bug in cabal's dependency which prevents second build from finishing

      - name: 'Setup MSYS2'
        if: matrix.os == 'windows-latest'
        uses: msys2/setup-msys2@v2
        with:
          msystem: ucrt64
          update: true
          install: >-
            git
            perl
            make
          pacboy: >-
            toolchain:p
            cmake:p


      - name: Windows build
        id: windows_build
        if: matrix.os == 'windows-latest'
        shell: msys2 {0}
        run: |
          export PATH=$PATH:/c/ghcup/bin:$(echo /c/tools/ghc-*/bin || echo)
          scripts/desktop/prepare-openssl-windows.sh
          openssl_windows_style_path=$(echo `pwd`/dist-newstyle/openssl-1.1.1w | sed 's#/\([a-zA-Z]\)#\1:#' | sed 's#/#\\#g')
          rm cabal.project.local 2>/dev/null || true
          echo "ignore-project: False" >> cabal.project.local
          echo "package direct-sqlcipher" >> cabal.project.local
          echo "    flags: +openssl" >> cabal.project.local
          echo "    extra-include-dirs: $openssl_windows_style_path\include" >> cabal.project.local
          echo "    extra-lib-dirs: $openssl_windows_style_path" >> cabal.project.local

          rm -rf dist-newstyle/src/direct-sq*
          sed -i "s/, unix /--, unix /" simplex-chat.cabal
          cabal build --enable-tests
          rm -rf dist-newstyle/src/direct-sq*
          path=$(cabal list-bin simplex-chat | tail -n 1)
          echo "bin_path=$path" >> $GITHUB_OUTPUT
          echo "bin_hash=$(echo SHA2-512\(${{ matrix.asset_name }}\)= $(openssl sha512 $path | cut -d' ' -f 2))" >> $GITHUB_OUTPUT

      - name: Windows upload CLI binary to release
        if: startsWith(github.ref, 'refs/tags/v') && matrix.os == 'windows-latest'
        uses: svenstaro/upload-release-action@v2
        with:
          repo_token: ${{ secrets.GITHUB_TOKEN }}
          file: ${{ steps.windows_build.outputs.bin_path }}
          asset_name: ${{ matrix.asset_name }}
          tag: ${{ github.ref }}

      - name: Windows update CLI binary hash
        if: startsWith(github.ref, 'refs/tags/v') && matrix.os == 'windows-latest'
        uses: softprops/action-gh-release@v1
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          append_body: true
          body: |
            ${{ steps.windows_build.outputs.bin_hash }}

      - name: Windows build desktop
        id: windows_desktop_build
        if: startsWith(github.ref, 'refs/tags/v') && matrix.os == 'windows-latest'
        shell: msys2 {0}
        run: |
          export PATH=$PATH:/c/ghcup/bin:$(echo /c/tools/ghc-*/bin || echo)
          scripts/desktop/build-lib-windows.sh
          cd apps/multiplatform
          ./gradlew packageMsi
          path=$(echo $PWD/release/main/msi/*imple*.msi | sed 's#/\([a-z]\)#\1:#' | sed 's#/#\\#g')
          echo "package_path=$path" >> $GITHUB_OUTPUT
          echo "package_hash=$(echo SHA2-512\(${{ matrix.desktop_asset_name }}\)= $(openssl sha512 $path | cut -d' ' -f 2))" >> $GITHUB_OUTPUT

      - name: Windows upload desktop package to release
        if: startsWith(github.ref, 'refs/tags/v') && matrix.os == 'windows-latest'
        uses: svenstaro/upload-release-action@v2
        with:
          repo_token: ${{ secrets.GITHUB_TOKEN }}
          file: ${{ steps.windows_desktop_build.outputs.package_path }}
          asset_name: ${{ matrix.desktop_asset_name }}
          tag: ${{ github.ref }}

      - name: Windows update desktop package hash
        if: startsWith(github.ref, 'refs/tags/v') && matrix.os == 'windows-latest'
        uses: softprops/action-gh-release@v1
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          append_body: true
          body: |
            ${{ steps.windows_desktop_build.outputs.package_hash }}

      - name: Cache windows build
        uses: actions/cache/save@v3
        if: matrix.os == 'windows-latest'
        with:
          path: |
            ${{ matrix.cache_path }}
            dist-newstyle
          key: ${{ steps.restore_cache.outputs.cache-primary-key }}

      # Windows /
