name: Build


on:
  push:
    paths-ignore:
      - 'docs/**'
      - 'mirai-console/docs/**'
      - '**/*.md'
  pull_request:
    paths-ignore:
      - 'docs/**'
      - 'mirai-console/docs/**'
      - '**/*.md'

jobs:
  build-mirai-jvm:
    name: "JVM (${{ matrix.os }})"
    runs-on: ${{ matrix.os }}
    strategy:
      fail-fast: false
      matrix:
        os: # You must use macos-12
          #          - windows-2022
          - macos-12
    env:
      gradleArgs: --scan "-Dmirai.target=jvm;android;!other" "-Pkotlin.compiler.execution.strategy=in-process" "-Dorg.gradle.jvmargs=-Xmx6000m" "-Dfile.encoding=UTF-8"
      isMac: ${{ startsWith(matrix.os, 'macos') }}
      isWindows: ${{ startsWith(matrix.os, 'windows') }}
      isUbuntu: ${{ startsWith(matrix.os, 'ubuntu') }}
      isUnix: ${{ startsWith(matrix.os, 'macos') || startsWith(matrix.os, 'ubuntu') }}
    steps:
      - uses: actions/checkout@v2
        with:
          submodules: 'recursive'

      - uses: actions/setup-java@v2
        with:
          distribution: 'temurin'
          java-version: '17'

      - name: Setup Gradle
        uses: gradle/gradle-build-action@v2

      - if: ${{ env.isUnix == 'true' }}
        run: chmod -R 777 *

      - if: ${{ env.isWindows == 'true' }}
        name: Setup Memory Environment on Windows
        run: >
          wmic pagefileset where name="D:\\pagefile.sys" set InitialSize=1024,MaximumSize=18432 &
          net stop mongodb
        shell: cmd
        continue-on-error: true

      - name: Clean and download dependencies
        run: ./gradlew clean ${{ env.gradleArgs }}

      - run: >
          ./gradlew updateSnapshotVersion ${{ env.gradleArgs }}
        if: github.event.pusher
        env:
          MIRAI_IS_SNAPSHOTS_PUBLISHING: true
          SNAPSHOTS_PUBLISHING_USER: ${{ secrets.SNAPSHOTS_PUBLISHING_USER }}
          SNAPSHOTS_PUBLISHING_KEY: ${{ secrets.SNAPSHOTS_PUBLISHING_KEY }}
          SNAPSHOTS_PUBLISHING_URL: ${{ secrets.SNAPSHOTS_PUBLISHING_URL }}
          CURRENT_BRANCH_NAME: dev # always use -dev for now

      - name: "Assemble"
        run: ./gradlew assemble ${{ env.gradleArgs }}

      - name: Publish Local Artifacts
        if: ${{ env.enableLocalPublishingTest == 'true' }}
        run: ./gradlew :mirai-deps-test:publishMiraiArtifactsToMavenLocal ${{ env.gradleArgs }} "-Dmirai.build.project.version=2.99.0-deps-test"

      - name: "Check"
        run: ./gradlew check ${{ env.gradleArgs }}

      # Upload

      - name: Upload mirai-core-utils
        uses: actions/upload-artifact@v3
        with:
          name: mirai-core-utils
          path: mirai-core-utils/build/libs

      - name: Upload mirai-core-api
        uses: actions/upload-artifact@v3
        with:
          name: mirai-core-api
          path: mirai-core-api/build/libs

      - name: Upload mirai-core
        uses: actions/upload-artifact@v3
        with:
          name: mirai-core
          path: mirai-core/build/libs

      - name: Upload mirai-core-all
        uses: actions/upload-artifact@v3
        with:
          name: mirai-core-all
          path: mirai-core-all/build/libs

      - name: Upload mirai-console
        uses: actions/upload-artifact@v3
        with:
          name: mirai-console
          path: mirai-console/backend/mirai-console/build/libs

      - name: Upload mirai-console-terminal
        uses: actions/upload-artifact@v3
        with:
          name: mirai-console-terminal
          path: mirai-console/frontend/mirai-console-terminal/build/libs

      - name: Upload mirai-console-compiler-annotations
        uses: actions/upload-artifact@v3
        with:
          name: mirai-console-compiler-annotations
          path: mirai-console/tools/mirai-console-compiler-annotations/build/libs

      - name: Upload mirai-console-compiler-common
        uses: actions/upload-artifact@v3
        with:
          name: mirai-console-compiler-common
          path: mirai-console/tools/mirai-console-compiler-common/build/libs

      - name: Upload mirai-console-intellij
        uses: actions/upload-artifact@v3
        with:
          name: mirai-console-intellij
          path: mirai-console/tools/intelli-plugin/build/distribution

      - name: Upload mirai-logging-log4j2
        uses: actions/upload-artifact@v3
        with:
          name: mirai-logging-log4j2
          path: logging/mirai-logging-log4j2/build/libs

      - name: Upload mirai-logging-slf4j
        uses: actions/upload-artifact@v3
        with:
          name: mirai-logging-slf4j
          path: logging/mirai-logging-slf4j/build/libs

      - name: Upload mirai-logging-slf4j-logback
        uses: actions/upload-artifact@v3
        with:
          name: mirai-logging-slf4j-logback
          path: logging/mirai-logging-slf4j-logback/build/libs

      - name: Upload mirai-logging-slf4j-simple
        uses: actions/upload-artifact@v3
        with:
          name: mirai-logging-slf4j-simple
          path: logging/mirai-logging-slf4j-simple/build/libs

  build-mirai-all:
    name: "Everything (${{ matrix.os }})"
    runs-on: ${{ matrix.os }}
    strategy:
      fail-fast: false
      matrix:
        os:
          - macos-12
    env:
      enableLocalPublishingTest: 'false'
      gradleArgs: --scan
      isMac: ${{ startsWith(matrix.os, 'macos') }}
      isWindows: ${{ startsWith(matrix.os, 'windows') }}
      isUbuntu: ${{ startsWith(matrix.os, 'ubuntu') }}
      isUnix: ${{ startsWith(matrix.os, 'macos') || startsWith(matrix.os, 'ubuntu') }}
    steps:
      - uses: actions/checkout@v2
        with:
          submodules: 'recursive'

      - uses: actions/setup-java@v2
        with:
          distribution: 'temurin'
          java-version: '17'

      - name: Setup Gradle
        uses: gradle/gradle-build-action@v2

      - name: Cache konan
        uses: pat-s/always-upload-cache@v3
        with:
          path: ~/.konan
          key: ${{ runner.os }}-gradle-${{ hashFiles('*.gradle.kts') }}
          restore-keys: |
            ${{ runner.os }}-gradle-

      - if: ${{ env.isUnix == 'true' }}
        run: chmod -R 777 *

      # Prepare environment for linking for macOS

      - if: ${{ env.isMac == 'true' }}
        name: Install OpenSSL
        run: >
          git clone https://github.com/openssl/openssl.git --recursive &&
          cd openssl &&
          git checkout tags/openssl-3.0.3 &&
          ./Configure --prefix=/opt/openssl --openssldir=/usr/local/ssl &&
          make &&
          sudo make install

      - name: Clean and download dependencies
        run: ./gradlew clean ${{ env.gradleArgs }}

      - run: >
          ./gradlew updateSnapshotVersion ${{ env.gradleArgs }}
        if: github.event.pusher
        env:
          MIRAI_IS_SNAPSHOTS_PUBLISHING: true
          SNAPSHOTS_PUBLISHING_USER: ${{ secrets.SNAPSHOTS_PUBLISHING_USER }}
          SNAPSHOTS_PUBLISHING_KEY: ${{ secrets.SNAPSHOTS_PUBLISHING_KEY }}
          SNAPSHOTS_PUBLISHING_URL: ${{ secrets.SNAPSHOTS_PUBLISHING_URL }}
          CURRENT_BRANCH_NAME: dev # always use -dev for now

      - name: "Assemble"
        run: ./gradlew assemble ${{ env.gradleArgs }}

      - name: Publish Local Artifacts
        if: ${{ env.enableLocalPublishingTest == 'true' }}
        run: ./gradlew :mirai-deps-test:publishMiraiArtifactsToMavenLocal ${{ env.gradleArgs }} "-Dmirai.build.project.version=2.99.0-deps-test"

      - name: "Check"
        run: ./gradlew check ${{ env.gradleArgs }}

      - if: ${{ env.isMac == 'true' }}
        name: Ensure KDoc valid
        run: ./gradlew dokkaHtmlMultiModule ${{ env.gradleArgs }}

      - name: Publish Snapshots
        if: ${{ github.event.pusher && env.isMac == 'true' }}
        run: ./gradlew publishAllPublicationsToMiraiRepoRepository ${{ env.gradleArgs }}
        env:
          MIRAI_IS_SNAPSHOTS_PUBLISHING: true
          SNAPSHOTS_PUBLISHING_USER: ${{ secrets.SNAPSHOTS_PUBLISHING_USER }}
          SNAPSHOTS_PUBLISHING_KEY: ${{ secrets.SNAPSHOTS_PUBLISHING_KEY }}
          SNAPSHOTS_PUBLISHING_URL: ${{ secrets.SNAPSHOTS_PUBLISHING_URL }}
          CURRENT_BRANCH_NAME: dev

  build-mirai-core-native:
    name: "Native (${{ matrix.os }})"
    runs-on: ${{ matrix.os }}
    strategy:
      fail-fast: false
      matrix:
        os:
          - windows-2022
          - ubuntu-20.04
          - ubuntu-18.04
          # - macos-12
          - macos-11
        include:
          - os: windows-2022
            targetName: mingwX64
          - os: ubuntu-20.04
            targetName: linuxX64
          - os: ubuntu-18.04
            targetName: linuxX64
          # - os: macos-12
          #   targetName: macosX64
          - os: macos-11
            targetName: macosX64
    env:
      # FIXME there must be two or more targets, or we'll get error on `@OptionalExpectation`
      # > Declaration annotated with '@OptionalExpectation' can only be used in common module sources
      enableLocalPublishingTest: 'false'
      gradleArgs: --scan  "-Dmirai.target=jvm;${{ matrix.targetName }};!other" "-Pkotlin.compiler.execution.strategy=in-process" "-Dorg.gradle.jvmargs=-Xmx4096m -Dfile.encoding=UTF-8"
      isMac: ${{ startsWith(matrix.os, 'macos') }}
      isWindows: ${{ startsWith(matrix.os, 'windows') }}
      isUbuntu: ${{ startsWith(matrix.os, 'ubuntu') }}
      isUnix: ${{ startsWith(matrix.os, 'macos') || startsWith(matrix.os, 'ubuntu') }}
      VCPKG_DEFAULT_BINARY_CACHE: ${{ startsWith(matrix.os, 'windows') && 'C:\vcpkg\binary_cache' || '/usr/local/share/vcpkg/binary_cache' }}
    steps:
      - uses: actions/checkout@v2
        with:
          submodules: 'recursive'

      - uses: actions/setup-java@v2
        with:
          distribution: 'adopt-openj9'
          java-version: '17'

      - name: Setup Gradle
        uses: gradle/gradle-build-action@v2

      - name: Cache konan
        uses: pat-s/always-upload-cache@v3
        with:
          path: ~/.konan
          key: ${{ runner.os }}-gradle-${{ hashFiles('*.gradle.kts') }}
          restore-keys: |
            ${{ runner.os }}-gradle-

      - name: Prepare to cache vcpkg
        if: ${{ env.isWindows == 'true' }}
        run: mkdir -p ${{ env.VCPKG_DEFAULT_BINARY_CACHE }}

      - name: Cache vcpkg
        if: ${{ env.isWindows == 'true' }}
        uses: pat-s/always-upload-cache@v3
        with:
          path: ${{ env.VCPKG_DEFAULT_BINARY_CACHE }}
          key: ${{ runner.os }}-vcpkg-binary-cache-${{ github.job }}
          restore-keys: |
            ${{ runner.os }}-vcpkg-binary-cache-

      - if: ${{ env.isUnix == 'true' }}
        run: chmod -R 777 *

      # Prepare environment for linking on macOS
      - if: ${{ env.isMac == 'true' }}
        name: Install OpenSSL on Mac OS
        run: >
          git clone https://github.com/openssl/openssl.git --recursive &&
          cd openssl &&
          git checkout tags/openssl-3.0.3 &&
          ./Configure --prefix=/opt/openssl --openssldir=/usr/local/ssl &&
          make &&
          sudo make install

      # Prepare environment for linking on Ubuntu
      - if: ${{ env.isUbuntu == 'true' }}
        name: Install OpenSSL on Ubuntu
        run: sudo apt install libssl-dev -y

      # Prepare environment for linking on Windows
      - if: ${{ env.isWindows == 'true' }}
        name: Setup Memory Environment on Windows
        run: >
          wmic pagefileset where name="D:\\pagefile.sys" set InitialSize=1024,MaximumSize=9216 &
          net stop mongodb
        shell: cmd
        continue-on-error: true

      - if: ${{ env.isWindows == 'true' }}
        name: Install OpenSSL & cURL on Windows
        run: |
          echo "set(VCPKG_BUILD_TYPE release)" | Out-File -FilePath "$env:VCPKG_INSTALLATION_ROOT\triplets\x64-windows.cmake" -Encoding utf8 -Append
          vcpkg install openssl:x64-windows curl[core,ssl]:x64-windows
          New-Item -Path $env:VCPKG_INSTALLATION_ROOT\installed\x64-windows\lib\crypto.lib -ItemType SymbolicLink -Value $env:VCPKG_INSTALLATION_ROOT\installed\x64-windows\lib\libcrypto.lib
          New-Item -Path $env:VCPKG_INSTALLATION_ROOT\installed\x64-windows\lib\ssl.lib -ItemType SymbolicLink -Value $env:VCPKG_INSTALLATION_ROOT\installed\x64-windows\lib\libssl.lib
          New-Item -Path $env:VCPKG_INSTALLATION_ROOT\installed\x64-windows\lib\curl.lib -ItemType SymbolicLink -Value $env:VCPKG_INSTALLATION_ROOT\installed\x64-windows\lib\libcurl.lib
          echo "$env:VCPKG_INSTALLATION_ROOT\installed\x64-windows\bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append

      - name: Clean and download dependencies
        run: ./gradlew clean ${{ env.gradleArgs }}

      - run: >
          ./gradlew updateSnapshotVersion ${{ env.gradleArgs }}
        if: github.event.pusher
        env:
          MIRAI_IS_SNAPSHOTS_PUBLISHING: true
          SNAPSHOTS_PUBLISHING_USER: ${{ secrets.SNAPSHOTS_PUBLISHING_USER }}
          SNAPSHOTS_PUBLISHING_KEY: ${{ secrets.SNAPSHOTS_PUBLISHING_KEY }}
          SNAPSHOTS_PUBLISHING_URL: ${{ secrets.SNAPSHOTS_PUBLISHING_URL }}
          CURRENT_BRANCH_NAME: dev # always use -dev for now

      - name: "Test mirai-core-utils for ${{ matrix.os }}"
        run: ./gradlew :mirai-core-utils:${{ matrix.targetName }}Test ${{ env.gradleArgs }}

      - name: "Test mirai-core-api for ${{ matrix.os }}"
        run: ./gradlew :mirai-core-api:${{ matrix.targetName }}Test ${{ env.gradleArgs }}

      - name: "Test mirai-core for ${{ matrix.os }}"
        run: ./gradlew :mirai-core:${{ matrix.targetName }}Test ${{ env.gradleArgs }}

      - name: Publish Local Artifacts
        if: ${{ env.enableLocalPublishingTest == 'true' }}
        run: ./gradlew :mirai-deps-test:publishMiraiArtifactsToMavenLocal ${{ env.gradleArgs }} "-Dmirai.build.project.version=2.99.0-deps-test"

      - name: Check Publication
        if: ${{ env.enableLocalPublishingTest == 'true' }}
        run: ./gradlew :mirai-deps-test:check ${{ env.gradleArgs }}

      # Publish native snapshots. Other artifacts are published in build-mirai-all

      - name: Publish MingwX64 Snapshots
        if: ${{ github.event.pusher && env.isWindows == 'true' }}
        run: ./gradlew publishMingwX64PublicationToMiraiRepoRepository ${{ env.gradleArgs }}
        env:
          MIRAI_IS_SNAPSHOTS_PUBLISHING: true
          SNAPSHOTS_PUBLISHING_USER: ${{ secrets.SNAPSHOTS_PUBLISHING_USER }}
          SNAPSHOTS_PUBLISHING_KEY: ${{ secrets.SNAPSHOTS_PUBLISHING_KEY }}
          SNAPSHOTS_PUBLISHING_URL: ${{ secrets.SNAPSHOTS_PUBLISHING_URL }}
          CURRENT_BRANCH_NAME: dev

      - name: Publish LinuxX64 Snapshots
        if: ${{ github.event.pusher && env.isUbuntu == 'true' }}
        run: ./gradlew publishLinuxX64PublicationToMiraiRepoRepository ${{ env.gradleArgs }}
        env:
          MIRAI_IS_SNAPSHOTS_PUBLISHING: true
          SNAPSHOTS_PUBLISHING_USER: ${{ secrets.SNAPSHOTS_PUBLISHING_USER }}
          SNAPSHOTS_PUBLISHING_KEY: ${{ secrets.SNAPSHOTS_PUBLISHING_KEY }}
          SNAPSHOTS_PUBLISHING_URL: ${{ secrets.SNAPSHOTS_PUBLISHING_URL }}
          CURRENT_BRANCH_NAME: dev

      - name: Publish macOSX64 Snapshots
        if: ${{ github.event.pusher && env.isMac == 'true' }}
        run: ./gradlew publishMacosX64PublicationToMiraiRepoRepository ${{ env.gradleArgs }}
        env:
          MIRAI_IS_SNAPSHOTS_PUBLISHING: true
          SNAPSHOTS_PUBLISHING_USER: ${{ secrets.SNAPSHOTS_PUBLISHING_USER }}
          SNAPSHOTS_PUBLISHING_KEY: ${{ secrets.SNAPSHOTS_PUBLISHING_KEY }}
          SNAPSHOTS_PUBLISHING_URL: ${{ secrets.SNAPSHOTS_PUBLISHING_URL }}
          CURRENT_BRANCH_NAME: dev