name: VCMI

on:
  push:
    branches:
      - features/*
      - beta
      - master
  pull_request:
  schedule:
    - cron: '0 2 * * *'
  workflow_dispatch:

env:
  # Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.)
  BUILD_TYPE: Release

jobs:
  check_last_build:
    if: github.event.schedule != ''
    runs-on: ubuntu-latest
    outputs:
      skip_build: ${{ steps.check_if_built.outputs.skip_build }}
    defaults:
      run:
        shell: bash
    steps:
      - name: Get repo name
        id: get_repo_name
        run: echo "::set-output name=value::${GITHUB_REPOSITORY#*/}"
      - name: Get last successful build for ${{ github.sha }}
        uses: octokit/request-action@v2.1.0
        id: get_last_scheduled_run
        with:
          route: GET /repos/{owner}/{repo}/actions/runs
          owner: ${{ github.repository_owner }}
          repo: ${{ steps.get_repo_name.outputs.value }}
          status: success
          per_page: 1
          head_sha: ${{ github.sha }}
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
      - name: Check if successful build of the current commit exists
        id: check_if_built
        run: |
          if [ ${{ fromJson(steps.get_last_scheduled_run.outputs.data).total_count }} -gt 0 ]; then
            echo '::set-output name=skip_build::1'
          else
            echo '::set-output name=skip_build::0'
          fi
      - name: Cancel current run
        if: steps.check_if_built.outputs.skip_build == 1
        uses: octokit/request-action@v2.1.0
        with:
          route: POST /repos/{owner}/{repo}/actions/runs/{run_id}/cancel
          owner: ${{ github.repository_owner }}
          repo: ${{ steps.get_repo_name.outputs.value }}
          run_id: ${{ github.run_id }}
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
      - name: Wait for the run to be cancelled
        if: steps.check_if_built.outputs.skip_build == 1
        run: sleep 60

  build:
    needs: check_last_build
    if: always() && needs.check_last_build.skip_build != 1
    strategy:
      matrix:
        include:
          - platform: linux-qt6
            os: ubuntu-22.04
            test: 0
            preset: linux-clang-test
          - platform: linux
            os: ubuntu-20.04
            test: 0
            preset: linux-gcc-test
          - platform: linux
            os: ubuntu-20.04
            test: 0
            preset: linux-gcc-debug
          - platform: mac-intel
            os: macos-12
            test: 0
            pack: 1
            extension: dmg
            preset: macos-conan-ninja-release
            conan_profile: macos-intel
            conan_options: --options with_apple_system_libs=True
            artifact_platform: intel
          - platform: mac-arm
            os: macos-12
            test: 0
            pack: 1
            extension: dmg
            preset: macos-arm-conan-ninja-release
            conan_profile: macos-arm
            conan_options: --options with_apple_system_libs=True
            artifact_platform: arm
          - platform: ios
            os: macos-12
            test: 0
            pack: 1
            extension: ipa
            preset: ios-release-conan
            conan_profile: ios-arm64
            conan_options: --options with_apple_system_libs=True
          - platform: msvc
            os: windows-latest
            test: 0
            pack: 1
            extension: exe
            preset: windows-msvc-release
          - platform: mingw-ubuntu
            os: ubuntu-22.04
            test: 0
            pack: 1
            extension: exe
            cpack_args: -D CPACK_NSIS_EXECUTABLE=`which makensis`
            cmake_args: -G Ninja
            preset: windows-mingw-conan-linux
            conan_profile: mingw64-linux.jinja
          - platform: android-32
            os: ubuntu-22.04
            extension: apk
            preset: android-conan-ninja-release
            conan_profile: android-32
            conan_options: --conf tools.android:ndk_path=$ANDROID_NDK_ROOT
            artifact_platform: armeabi-v7a
          - platform: android-64
            os: ubuntu-22.04
            extension: apk
            preset: android-conan-ninja-release
            conan_profile: android-64
            conan_options: --conf tools.android:ndk_path=$ANDROID_NDK_ROOT
            artifact_platform: arm64-v8a
    runs-on: ${{ matrix.os }}
    defaults:
      run:
        shell: bash

    steps:
    - uses: actions/checkout@v3
      with:
        submodules: recursive

    - name: Validate JSON
      # the Python yaml module doesn't seem to work on mac-arm
      # also, running it on multiple presets is redundant and slightly increases already long CI built times
      if: ${{ startsWith(matrix.preset, 'linux-clang-test') }}
      run: |
        pip3 install json5 jstyleson
        python3 .github/validate_json.py

    - name: Dependencies
      run: source '${{github.workspace}}/CI/${{matrix.platform}}/before_install.sh'
      env:
        VCMI_BUILD_PLATFORM: x64

    - name: ccache
      if: startsWith(matrix.preset, 'ios') != true
      uses: hendrikmuhs/ccache-action@v1.2
      with:
          key: ${{ matrix.preset }}
          # actual cache takes up less space, at most ~1 GB
          max-size: "5G"
          verbose: 2

    - uses: actions/setup-python@v4
      if: "${{ matrix.conan_profile != '' }}"
      with:
        python-version: '3.10'
    - name: Conan setup
      if: "${{ matrix.conan_profile != '' }}"
      run: |
        pip3 install 'conan<2.0'
        conan profile new default --detect
        conan install . \
          --install-folder=conan-generated \
          --no-imports \
          --build=never \
          --profile:build=default \
          --profile:host=CI/conan/${{ matrix.conan_profile }} \
          ${{ matrix.conan_options }}
      env:
        GENERATE_ONLY_BUILT_CONFIG: 1

    - name: Git branch name
      id: git-branch-name
      uses: EthanSK/git-branch-name-action@v1

    - name: Build Number
      run: |
        source '${{github.workspace}}/CI/get_package_name.sh'
        if [ '${{ matrix.artifact_platform }}' ]; then
          VCMI_PACKAGE_FILE_NAME+="-${{ matrix.artifact_platform }}"
        fi
        echo VCMI_PACKAGE_FILE_NAME="$VCMI_PACKAGE_FILE_NAME" >> $GITHUB_ENV
        echo VCMI_PACKAGE_NAME_SUFFIX="$VCMI_PACKAGE_NAME_SUFFIX" >> $GITHUB_ENV
        echo VCMI_PACKAGE_GITVERSION="$VCMI_PACKAGE_GITVERSION" >> $GITHUB_ENV
      env:
        PULL_REQUEST: ${{ github.event.pull_request.number }}

    - name: CMake Preset with ccache
      if: startsWith(matrix.preset, 'ios') != true
      run: |
        cmake -DCMAKE_CXX_COMPILER_LAUNCHER=ccache --preset ${{ matrix.preset }}

    - name: CMake Preset without ccache
      if: startsWith(matrix.preset, 'ios')
      run: |
        cmake --preset ${{ matrix.preset }}

    - name: Build Preset
      run: |
        cmake --build --preset ${{matrix.preset}}

    - name: Test
      if: ${{ matrix.test == 1 }}
      run: |
        ctest --preset ${{matrix.preset}}

    - name: Pack
      id: cpack
      if: ${{ matrix.pack == 1 }}
      run: |
        cd '${{github.workspace}}/out/build/${{matrix.preset}}'
        CPACK_PATH=`which -a cpack | grep -m1 -v -i chocolatey`
        "$CPACK_PATH" -C ${{env.BUILD_TYPE}} ${{ matrix.cpack_args }}
        test -f '${{github.workspace}}/CI/${{matrix.platform}}/post_pack.sh' \
          && '${{github.workspace}}/CI/${{matrix.platform}}/post_pack.sh' '${{github.workspace}}' "$(ls '${{ env.VCMI_PACKAGE_FILE_NAME }}'.*)"
        rm -rf _CPack_Packages

    - name: Create android package
      if: ${{ startsWith(matrix.platform, 'android') }}
      run: |
        cd android
        ./gradlew assembleDaily --info
        echo ANDROID_APK_PATH="$(ls ${{ github.workspace }}/android/vcmi-app/build/outputs/apk/daily/*.${{ matrix.extension }})" >> $GITHUB_ENV

    - name: Additional logs
      if: ${{ failure() && steps.cpack.outcome == 'failure' && matrix.platform == 'msvc' }}
      run: |
        cat '${{github.workspace}}/out/build/${{matrix.preset}}/_CPack_Packages/win32/NSIS/project.nsi'
        cat '${{github.workspace}}/out/build/${{matrix.preset}}/_CPack_Packages/win32/NSIS/NSISOutput.log'

    - name: Artifacts
      if: ${{ matrix.pack == 1 }}
      uses: actions/upload-artifact@v3
      with:
        name: ${{ env.VCMI_PACKAGE_FILE_NAME }} - ${{ matrix.platform }}
        path: |
          ${{github.workspace}}/out/build/${{matrix.preset}}/${{ env.VCMI_PACKAGE_FILE_NAME }}.${{ matrix.extension }}
          
    - name: Android artifacts
      if: ${{ startsWith(matrix.platform, 'android') }}
      uses: actions/upload-artifact@v3
      with:
        name: ${{ env.VCMI_PACKAGE_FILE_NAME }} - ${{ matrix.platform }}
        path: |
          ${{ env.ANDROID_APK_PATH }}

    - name: Android JNI ${{matrix.platform}}
      if: ${{ startsWith(matrix.platform, 'android') && github.ref == 'refs/heads/master' }}
      uses: actions/upload-artifact@v3
      with:
        name: Android JNI ${{matrix.platform}}
        path: |
          ${{ github.workspace }}/android/vcmi-app/src/main/jniLibs

    - name: Upload build
      if: ${{ (matrix.pack == 1 || startsWith(matrix.platform, 'android')) && (github.ref == 'refs/heads/develop' || github.ref == 'refs/heads/beta' || github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/heads/features/')) && matrix.platform != 'msvc' }}
      continue-on-error: true
      run: |
        if cd '${{github.workspace}}/android/vcmi-app/build/outputs/apk/daily' ; then
          mv '${{ env.ANDROID_APK_PATH }}' "$VCMI_PACKAGE_FILE_NAME.${{ matrix.extension }}"
        else
          cd '${{github.workspace}}/out/build/${{matrix.preset}}'
        fi
        source '${{github.workspace}}/CI/upload_package.sh'
      env:
        DEPLOY_RSA: ${{ secrets.DEPLOY_RSA }}
        PACKAGE_EXTENSION: ${{ matrix.extension }}

    - uses: act10ns/slack@v1
      with:
        status: ${{ job.status }}
        channel: '#notifications'
      env:
        SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
      if: always()
  
  # copy-pasted mostly
  bundle_release:
    
    needs: build
    if: always() && github.ref == 'refs/heads/master'
    strategy:
      matrix:
        include:
          - platform: android-32
            os: ubuntu-22.04
            extension: aab
            preset: android-conan-ninja-release
            conan_profile: android-32
            conan_options: --conf tools.android:ndk_path=$ANDROID_NDK_ROOT
            artifact_platform: aab
    runs-on: ${{ matrix.os }}
    defaults:
      run:
        shell: bash

    steps:
    - uses: actions/checkout@v3
      with:
        submodules: recursive

    - name: Dependencies
      run: source '${{github.workspace}}/CI/${{matrix.platform}}/before_install.sh'
      env:
        VCMI_BUILD_PLATFORM: x64

    - uses: actions/setup-python@v4
      if: "${{ matrix.conan_profile != '' }}"
      with:
        python-version: '3.10'
    - name: Conan setup
      if: "${{ matrix.conan_profile != '' }}"
      run: |
        pip3 install 'conan<2.0'
        conan profile new default --detect
        conan install . \
          --install-folder=conan-generated \
          --no-imports \
          --build=never \
          --profile:build=default \
          --profile:host=CI/conan/${{ matrix.conan_profile }} \
          ${{ matrix.conan_options }}
      env:
        GENERATE_ONLY_BUILT_CONFIG: 1

    - name: Git branch name
      id: git-branch-name
      uses: EthanSK/git-branch-name-action@v1

    - name: Build Number
      run: |
        source '${{github.workspace}}/CI/get_package_name.sh'
        if [ '${{ matrix.artifact_platform }}' ]; then
          VCMI_PACKAGE_FILE_NAME+="-${{ matrix.artifact_platform }}"
        fi
        echo VCMI_PACKAGE_FILE_NAME="$VCMI_PACKAGE_FILE_NAME" >> $GITHUB_ENV
        echo VCMI_PACKAGE_NAME_SUFFIX="$VCMI_PACKAGE_NAME_SUFFIX" >> $GITHUB_ENV
        echo VCMI_PACKAGE_GITVERSION="$VCMI_PACKAGE_GITVERSION" >> $GITHUB_ENV
      env:
        PULL_REQUEST: ${{ github.event.pull_request.number }}

    - name: CMake Preset
      run: |
        cmake --preset ${{ matrix.preset }}

    - name: Build Preset
      run: |
        cmake --build --preset ${{matrix.preset}}

    - name: Download libs x64
      uses: actions/download-artifact@v3
      with:
        name: Android JNI android-64
        path: ${{ github.workspace }}/android/vcmi-app/src/main/jniLibs/
 
    - name: Create android package
      run: |
        cd android
        ./gradlew bundleRelease --info
        echo ANDROID_APK_PATH="$(ls ${{ github.workspace }}/android/vcmi-app/build/outputs/bundle/release/*.aab)" >> $GITHUB_ENV
      env:
        ANDROID_STORE_PASSWORD: ${{ secrets.ANDROID_STORE_PASSWORD }}
        ANDROID_KEY_PASSWORD: ${{ secrets.ANDROID_KEY_PASSWORD }}

    - name: Android artifacts
      uses: actions/upload-artifact@v3
      with:
        name: ${{ env.VCMI_PACKAGE_FILE_NAME }}
        path: |
          ${{ env.ANDROID_APK_PATH }}

    - uses: act10ns/slack@v1
      with:
        status: ${{ job.status }}
        channel: '#notifications'
      env:
        SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
      if: always()
