name: Build Artifacts (MinGW)
on:
  workflow_dispatch:
    inputs:
      logLevel:
        description: 'Log level'
        required: true
        default: 'warning'
        type: choice
        options:
        - info
        - warning
        - debug
      tags:
        description: 'Test scenario tags'
        required: false
        type: boolean
  pull_request:
    branches: [master, develop]
    paths-ignore:
    - '**/*.md'
    - '.circleci/**'
    - '.cirrus.yml'
  push:
    branches: [master, develop, mingw]
    paths-ignore:
    - '**/*.md'
    - '.circleci/**'
    - '.cirrus.yml'
  release:
    types: [published]
  schedule:
    - cron: '0 16 * * *'
concurrency:
  group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.run_id }}
  cancel-in-progress: ${{ startsWith(github.event_name, 'pull') }}
env:
  CACHE_EPOCH: 148-2
  GOPROXY: direct
jobs:
  mingw64-release:
    runs-on: ubuntu-24.04
    permissions:
      contents: write
    strategy:
      fail-fast: false
      matrix:
        include:
          - arch: i686
            build_type: Release
            variant: ucrt
            suffix: -winxp
            build_options: -mingw-allow-xp -use-allocator=tcmalloc
            mingw_version: 20250709
          - arch: x86_64
            build_type: Release
            variant: ucrt
            suffix: -winxp
            build_options: -mingw-allow-xp -use-allocator=tcmalloc
            mingw_version: 20250709
          - arch: aarch64
            build_type: Release
            variant: ucrt
            suffix:
            build_options:
            mingw_version: 20250709
    env:
      BUILD_TYPE: ${{ matrix.build_type }}
    steps:
      - uses: actions/checkout@v5
      - name: Checkout with shallow submodules
        run: |
          # unshallow must come first otherwise submodule may be get unshallowed
          git fetch --tags --unshallow
          git submodule update --init --depth 1
      - name: Cache toolchain
        id: toolchain-cache
        uses: actions/cache@v5
        with:
          path: |
            third_party/llvm-build/Release+Asserts
          key: ${{ runner.os }}-toolchain-${{ hashFiles('CLANG_REVISION') }}-v${{ env.CACHE_EPOCH }}
      - name: Cache mingw64 llvm sysroot
        id: sysroot-cache
        uses: actions/cache@v5
        with:
          path: |
            third_party/llvm-mingw-${{ matrix.mingw_version }}-${{ matrix.variant }}-ubuntu-22.04-x86_64
          key: ${{ runner.os }}-mingw64-sysroot-third_party-llvm-${{ matrix.mingw_version }}-${{ matrix.variant }}-v1
      - uses: actions/setup-go@v6
        with:
          go-version: '>=1.20.0'
          cache-dependency-path: |
            tools/go.sum
            third_party/boringssl/src/go.sum
      - name: Build build tool
        run: |
          cd tools
          go build
      - name: "Install dependency: prebuilt clang and clang-tidy binaries"
        if: ${{ steps.toolchain-cache.outputs.cache-hit != 'true' }}
        run: |
          ./scripts/download-clang-prebuilt-binaries.py
          rm -f third_party/llvm-build/Release+Asserts/*.tgz
      - name: "Install dependency: llvm-mingw sysroot"
        if: ${{ steps.sysroot-cache.outputs.cache-hit != 'true' }}
        run: |
          pushd third_party
          curl -L -O https://github.com/mstorsjo/llvm-mingw/releases/download/${{ matrix.mingw_version }}/llvm-mingw-${{ matrix.mingw_version }}-${{ matrix.variant }}-ubuntu-22.04-x86_64.tar.xz
          tar -xf llvm-mingw-${{ matrix.mingw_version }}-${{ matrix.variant }}-ubuntu-22.04-x86_64.tar.xz
          rm -vf llvm-mingw-*.xz
          popd
      - name: Change ubuntu mirror
        run: |
          sudo sed -i 's/azure.archive.ubuntu.com/azure.archive.ubuntu.com/g' /etc/apt/sources.list
          sudo apt-get update -qq
      - name: Populate depedencies
        run: |
          sudo apt-get update -qq
          sudo apt-get install -y nasm zip nsis locales-all
      - name: Populate depedencies (for objcopy)
        if: ${{ matrix.arch == 'i686' || matrix.arch == 'x86_64' }}
        run: |
          sudo apt-get install -y binutils-mingw-w64
      - name: Patch libcxx for windows xp
        if: ${{ matrix.arch == 'i686' || matrix.arch == 'x86_64' }}
        run: |
          pushd third_party/libc++/trunk
          patch -p1 < ../winxp.patch
          popd
          pushd third_party/libc++abi/trunk
          patch -p1 < ../winxp.patch
          popd
      - name: Build Binary (CLI)
        run: |
          ./tools/build --variant cli --arch ${{ matrix.arch }} --system mingw \
            -mingw-dir $PWD/third_party/llvm-mingw-${{ matrix.mingw_version }}-${{ matrix.variant }}-ubuntu-22.04-x86_64 -nc \
            -build-test -build-benchmark \
            ${{ matrix.build_options }}
      - name: Build Binary (GUI)
        run: |
          # fix cpack error on C.UTF-8 locale
          # see https://github.com/lightspark/lightspark/discussions/604#discussioncomment-1034262
          export LC_ALL=en_US.UTF-8
          ./tools/build --variant gui --arch ${{ matrix.arch }} --system mingw \
            -mingw-dir $PWD/third_party/llvm-mingw-${{ matrix.mingw_version }}-${{ matrix.variant }}-ubuntu-22.04-x86_64 -nc \
            ${{ matrix.build_options }}
      - name: Build Binary (DYLIB)
        run: |
          ./tools/build --variant dylib --arch ${{ matrix.arch }} --system mingw \
            -mingw-dir $PWD/third_party/llvm-mingw-${{ matrix.mingw_version }}-${{ matrix.variant }}-ubuntu-22.04-x86_64 -nc \
            ${{ matrix.build_options }}
      - uses: actions/upload-artifact@v6
        with:
          name: mingw64${{ matrix.suffix }}-release-${{ matrix.build_type }}-${{ matrix.variant }}-${{ matrix.arch }}-${{ github.run_id }}-gui
          path: |
            build-mingw${{ matrix.suffix }}-${{ matrix.arch }}/yass.exe
            build-mingw${{ matrix.suffix }}-${{ matrix.arch }}/*.dll
            build-mingw${{ matrix.suffix }}-${{ matrix.arch }}/LICENSE
            !build-mingw${{ matrix.suffix }}-${{ matrix.arch }}/YASS-C.dll
      - uses: actions/upload-artifact@v6
        with:
          name: mingw64${{ matrix.suffix }}-release-${{ matrix.build_type }}-${{ matrix.variant }}-${{ matrix.arch }}-${{ github.run_id }}-nsis-installer
          path: |
            *.exe
          compression-level: 0 # no compression
      - uses: actions/upload-artifact@v6
        with:
          name: mingw64${{ matrix.suffix }}-release-${{ matrix.build_type }}-${{ matrix.variant }}-${{ matrix.arch }}-${{ github.run_id }}-cli
          path: |
            build-mingw${{ matrix.suffix }}-${{ matrix.arch }}/yass_cli.exe
            build-mingw${{ matrix.suffix }}-${{ matrix.arch }}/*.dll
            build-mingw${{ matrix.suffix }}-${{ matrix.arch }}/LICENSE
            !build-mingw${{ matrix.suffix }}-${{ matrix.arch }}/YASS-C.dll
      - uses: actions/upload-artifact@v6
        with:
          name: mingw64${{ matrix.suffix }}-release-${{ matrix.build_type }}-${{ matrix.variant }}-${{ matrix.arch }}-${{ github.run_id }}-dylib
          path: |
            build-mingw${{ matrix.suffix }}-${{ matrix.arch }}/devel
            build-mingw${{ matrix.suffix }}-${{ matrix.arch }}/yass.py
            build-mingw${{ matrix.suffix }}-${{ matrix.arch }}/*.dll
            build-mingw${{ matrix.suffix }}-${{ matrix.arch }}/LICENSE
      - uses: actions/upload-artifact@v6
        with:
          name: mingw64${{ matrix.suffix }}-release-${{ matrix.build_type }}-${{ matrix.variant }}-${{ matrix.arch }}-${{ github.run_id }}-test
          path: |
            build-mingw${{ matrix.suffix }}-${{ matrix.arch }}/yass_test.exe
            build-mingw${{ matrix.suffix }}-${{ matrix.arch }}/*.dll
            !build-mingw${{ matrix.suffix }}-${{ matrix.arch }}/YASS-C.dll
      - uses: actions/upload-artifact@v6
        with:
          name: mingw64${{ matrix.suffix }}-release-${{ matrix.build_type }}-${{ matrix.variant }}-${{ matrix.arch }}-${{ github.run_id }}-benchmark
          path: |
            build-mingw${{ matrix.suffix }}-${{ matrix.arch }}/yass_benchmark.exe
            build-mingw${{ matrix.suffix }}-${{ matrix.arch }}/*.dll
            !build-mingw${{ matrix.suffix }}-${{ matrix.arch }}/YASS-C.dll
      - uses: actions/upload-artifact@v6
        with:
          name: mingw64${{ matrix.suffix }}-release-${{ matrix.build_type }}-${{ matrix.variant }}-${{ matrix.arch }}-${{ github.run_id }}-dbg
          path: |
            build-mingw${{ matrix.suffix }}-${{ matrix.arch }}/*.dbg
          compression-level: 9 # maximum compression
      - name: Upload dist tarball
        if: ${{ github.event_name == 'release' && matrix.build_type == 'Release' }}
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        run: |
          gh release upload ${{ github.event.release.tag_name }} *.zip *.exe
  mingw64-release-build-msi:
    runs-on: windows-2022
    needs: mingw64-release
    permissions:
      contents: write
    strategy:
      fail-fast: false
      matrix:
        include:
          - arch: i686
            build_type: Release
            variant: ucrt
            suffix: -winxp
            build_options: -mingw-allow-xp
          - arch: x86_64
            build_type: Release
            variant: ucrt
            suffix: -winxp
            build_options: -mingw-allow-xp
          - arch: aarch64
            build_type: Release
            variant: ucrt
            suffix:
            build_options:
    defaults:
      run:
        shell: cmd
    env:
      BUILD_TYPE: ${{ matrix.build_type }}
    steps:
      - uses: actions/checkout@v5
      - name: Checkout with unshallow history
        run: |
          # unshallow must come first otherwise submodule may be get unshallowed
          git fetch --tags --unshallow
      - uses: actions/setup-go@v6
        with:
          go-version: '>=1.20.0'
          cache-dependency-path: |
            tools/go.sum
            third_party/boringssl/src/go.sum
      - name: Build build tool
        run: |
          cd tools
          go build
      - name: Download built executables
        uses: actions/download-artifact@v7
        with:
          name: mingw64${{ matrix.suffix }}-release-${{ matrix.build_type }}-${{ matrix.variant }}-${{ matrix.arch }}-${{ github.run_id }}-gui
          path: build-mingw${{ matrix.suffix }}-${{ matrix.arch }}
      - name: Build Binary (MSI)
        run: |
          tools\build --variant gui --arch ${{ matrix.arch }} --system mingw ${{ matrix.build_options }} -mingw-only-build-msi -nc
      - uses: actions/upload-artifact@v6
        with:
          name: mingw64${{ matrix.suffix }}-release-${{ matrix.build_type }}-${{ matrix.variant }}-${{ matrix.arch }}-${{ github.run_id }}-msi-installer
          path: |
            *.msi
          compression-level: 0 # no compression
      - name: Upload dist tarball
        if: ${{ github.event_name == 'release' && matrix.build_type == 'Release' }}
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        run: |
          gh release upload ${{ github.event.release.tag_name }} *.msi
  mingw64-release-wine-test:
    runs-on: ubuntu-22.04
    needs: mingw64-release
    strategy:
      fail-fast: false
      matrix:
        include:
          - arch: i686
            build_type: Release
            variant: ucrt
            suffix: -winxp
          - arch: x86_64
            build_type: Release
            variant: ucrt
            suffix: -winxp
    steps:
      - name: Populate depedencies (i686)
        if: ${{ matrix.arch == 'i686' }}
        run: |
          sudo dpkg --add-architecture i386
          sudo apt-get update -qq
          sudo apt-get install -y wine wine32
      - name: Populate depedencies (x86_64)
        if: ${{ matrix.arch == 'x86_64' }}
        run: |
          sudo apt-get update -qq
          sudo apt-get install -y wine wine64
      - name: Download built executables
        uses: actions/download-artifact@v7
        with:
          name: mingw64${{ matrix.suffix }}-release-${{ matrix.build_type }}-${{ matrix.variant }}-${{ matrix.arch }}-${{ github.run_id }}-cli
      - name: Download built executables
        uses: actions/download-artifact@v7
        with:
          name: mingw64${{ matrix.suffix }}-release-${{ matrix.build_type }}-${{ matrix.variant }}-${{ matrix.arch }}-${{ github.run_id }}-test
      - name: Download built executables
        uses: actions/download-artifact@v7
        with:
          name: mingw64${{ matrix.suffix }}-release-${{ matrix.build_type }}-${{ matrix.variant }}-${{ matrix.arch }}-${{ github.run_id }}-benchmark
      - name: Run tests
        if: ${{ matrix.arch == 'i686' || matrix.arch == 'x86_64' }}
        run: |
          wine yass_cli.exe --version
          wine yass_test.exe
      - name: Run benchmarks
        if: ${{ matrix.arch == 'i686' || matrix.arch == 'x86_64' }}
        run: |
          wine yass_benchmark.exe
  mingw64-release-native-test:
    runs-on: windows-2022
    needs: mingw64-release
    strategy:
      fail-fast: false
      matrix:
        include:
          - arch: i686
            build_type: Release
            variant: ucrt
            suffix: -winxp
            gtest_repeat_times: 10
          - arch: x86_64
            build_type: Release
            variant: ucrt
            suffix: -winxp
            gtest_repeat_times: 10
    defaults:
      run:
        shell: cmd
    steps:
      - name: Download built executables
        uses: actions/download-artifact@v7
        with:
          name: mingw64${{ matrix.suffix }}-release-${{ matrix.build_type }}-${{ matrix.variant }}-${{ matrix.arch }}-${{ github.run_id }}-test
      - name: Run tests
        if: ${{ matrix.arch == 'i686' || matrix.arch == 'x86_64' }}
        run: |
          yass_test --gtest_shuffle --gtest_repeat=${{ matrix.gtest_repeat_times }} --gtest_throw_on_failure --proxy_type http || exit /b
          yass_test --gtest_shuffle --gtest_repeat=${{ matrix.gtest_repeat_times }} --gtest_throw_on_failure --proxy_type http --ipv6_mode || exit /b
  mingw64-release-native-benchmark:
    runs-on: windows-2022
    needs: mingw64-release
    strategy:
      fail-fast: false
      matrix:
        include:
          - arch: i686
            build_type: Release
            variant: ucrt
            suffix: -winxp
          - arch: x86_64
            build_type: Release
            variant: ucrt
            suffix: -winxp
    defaults:
      run:
        shell: cmd
    steps:
      - name: Download built executables
        uses: actions/download-artifact@v7
        with:
          name: mingw64${{ matrix.suffix }}-release-${{ matrix.build_type }}-${{ matrix.variant }}-${{ matrix.arch }}-${{ github.run_id }}-benchmark
      - name: Run benchmarks
        if: ${{ matrix.arch == 'i686' || matrix.arch == 'x86_64' }}
        shell: cmd
        run: |
          yass_benchmark || exit /b
