name: 'DwarFS CI Build'

on:
  workflow_dispatch:
  push:
    branches:
      - main
      - 'mhx/**'
    tags:
      - v*

permissions:
  contents: read

jobs:
  windows:
    runs-on:
      - self-hosted
      - Windows

    strategy:
      matrix:
        arch:
          - X64
        build_mode:
          - Release
          - Debug

    steps:
      - name: Checkout
        uses: actions/checkout@v4
        with:
          submodules: 'true'
          fetch-depth: '0'
          ref: ${{ github.ref }}

      - name: Set MSVC Dev Environment
        uses: ilammy/msvc-dev-cmd@v1

      - name: Configure Build
        shell: cmd
        run: |
          cmake -B${{ runner.temp }}\build -S${{ runner.workspace }}\dwarfs -GNinja -DCMAKE_MAKE_PROGRAM=C:\bin\ninja.exe -DCMAKE_BUILD_TYPE=${{ matrix.build_mode }} -DWITH_TESTS=ON -DWITH_BENCHMARKS=ON -DCMAKE_TOOLCHAIN_FILE=C:\vcpkg\scripts\buildsystems\vcpkg.cmake -DVCPKG_TARGET_TRIPLET=x64-windows-static -DVCPKG_INSTALLED_DIR=${{ runner.workspace }}\vcpkg-install-dwarfs -DDWARFS_ARTIFACTS_DIR=Z:\artifacts\dwarfs -DUSE_PREFERRED_LIBS=ON -DWITH_PXATTR=ON

      - name: Run Build
        shell: cmd
        run: |
          cmake --build ${{ runner.temp }}\build

      - name: Run Test
        shell: cmd
        run: |
          copy "C:\Program Files (x86)\WinFsp\bin\winfsp-x64.dll" ${{ runner.temp }}\build
          ctest --test-dir ${{ runner.temp }}\build --output-on-failure -j8

      - name: Build Package
        shell: cmd
        run: |
          cmake --build ${{ runner.temp }}\build --target package
        if: matrix.build_mode == 'Release'

      - name: Compress Universal Binary
        shell: cmd
        run: |
          cmake --build ${{ runner.temp }}\build --target universal_upx
        if: matrix.build_mode == 'Release'

      - name: Copy Artifacts
        shell: cmd
        run: |
          cmake --build ${{ runner.temp }}\build --target copy_artifacts
        if: matrix.build_mode == 'Release'

      - name: Prepare Artifact Upload
        shell: cmd
        run: cat ${{ runner.temp }}\build\artifacts.env >> %GITHUB_ENV%
        if: matrix.build_mode == 'Release'

      - name: Upload Binary Tarball
        uses: actions/upload-artifact@v4
        with:
          name: ${{ env.binary_tarball }}
          path: ${{ runner.temp }}\build\${{ env.binary_tarball }}
          if-no-files-found: error
          compression-level: 0
        if: matrix.build_mode == 'Release'

      - name: Upload Universal Binary
        uses: actions/upload-artifact@v4
        with:
          name: ${{ env.universal_binary }}
          path: ${{ runner.temp }}\build\${{ env.universal_binary }}
          if-no-files-found: error
          compression-level: 0
        if: matrix.build_mode == 'Release'

  windows-hybrid:
    runs-on:
      - self-hosted
      - Windows

    strategy:
      matrix:
        arch:
          - X64
        build_mode:
          - Release

    steps:
      - name: Checkout
        uses: actions/checkout@v4
        with:
          submodules: 'true'
          fetch-depth: '0'
          ref: ${{ github.ref }}

      - name: Set MSVC Dev Environment
        uses: ilammy/msvc-dev-cmd@v1

      - name: Configure Rice++ Build
        shell: cmd
        run: |
          cmake -B${{ runner.temp }}\build-ricepp -S${{ runner.workspace }}\dwarfs\ricepp -GNinja -DCMAKE_MAKE_PROGRAM=C:\bin\ninja.exe -DCMAKE_BUILD_TYPE=${{ matrix.build_mode }} -DWITH_TESTS=ON -DWITH_BENCHMARKS=ON -DCMAKE_TOOLCHAIN_FILE=C:\vcpkg\scripts\buildsystems\vcpkg.cmake -DVCPKG_TARGET_TRIPLET=x64-windows-static -DVCPKG_INSTALLED_DIR=${{ runner.workspace }}\vcpkg-install-dwarfs -DCMAKE_C_COMPILER=clang-cl -DCMAKE_CXX_COMPILER=clang-cl

      - name: Run Build
        shell: cmd
        run: |
          cmake --build ${{ runner.temp }}\build-ricepp

      - name: Run Test
        shell: cmd
        run: |
          ctest --test-dir ${{ runner.temp }}\build-ricepp --output-on-failure -j8

      - name: Install Rice++ Library
        shell: cmd
        run: |
          cmake --install ${{ runner.temp }}\build-ricepp --prefix ${{ runner.temp }}\ricepp-install

      - name: Configure Build
        shell: cmd
        run: |
          cmake -B${{ runner.temp }}\build -S${{ runner.workspace }}\dwarfs -GNinja -DCMAKE_MAKE_PROGRAM=C:\bin\ninja.exe -DCMAKE_BUILD_TYPE=${{ matrix.build_mode }} -DWITH_TESTS=ON -DWITH_BENCHMARKS=ON -DCMAKE_TOOLCHAIN_FILE=C:\vcpkg\scripts\buildsystems\vcpkg.cmake -DVCPKG_TARGET_TRIPLET=x64-windows-static -DVCPKG_INSTALLED_DIR=${{ runner.workspace }}\vcpkg-install-dwarfs -DDWARFS_ARTIFACTS_DIR=Z:\artifacts\dwarfs -DCMAKE_PREFIX_PATH=${{ runner.temp }}\ricepp-install -DUSE_RICEPP_PACKAGE=ON -DUSE_PREFERRED_LIBS=ON

      - name: Run Build
        shell: cmd
        run: |
          cmake --build ${{ runner.temp }}\build

      - name: Run Test
        shell: cmd
        run: |
          copy "C:\Program Files (x86)\WinFsp\bin\winfsp-x64.dll" ${{ runner.temp }}\build
          ctest --test-dir ${{ runner.temp }}\build --output-on-failure -j8

      - name: Build Package
        shell: cmd
        run: |
          cmake --build ${{ runner.temp }}\build --target package
        if: matrix.build_mode == 'Release'

      - name: Compress Universal Binary
        shell: cmd
        run: |
          cmake --build ${{ runner.temp }}\build --target universal_upx
        if: matrix.build_mode == 'Release'

      - name: Copy Artifacts
        shell: cmd
        run: |
          cmake --build ${{ runner.temp }}\build --target copy_artifacts
        if: matrix.build_mode == 'Release'

      - name: Prepare Artifact Upload
        shell: cmd
        run: cat ${{ runner.temp }}\build\artifacts.env >> %GITHUB_ENV%
        if: matrix.build_mode == 'Release'

      - name: Upload Binary Tarball
        uses: actions/upload-artifact@v4
        with:
          name: ${{ env.binary_tarball }}
          path: ${{ runner.temp }}\build\${{ env.binary_tarball }}
          if-no-files-found: error
          compression-level: 0
        if: matrix.build_mode == 'Release'

      - name: Upload Universal Binary
        uses: actions/upload-artifact@v4
        with:
          name: ${{ env.universal_binary }}
          path: ${{ runner.temp }}\build\${{ env.universal_binary }}
          if-no-files-found: error
          compression-level: 0
        if: matrix.build_mode == 'Release'

  linux:
    strategy:
      matrix:
        arch:
          - amd64
          - arm64v8
        dist:
          - ubuntu
          - fedora
          - arch
        build_type:
          - gcc-debug-ninja
          - gcc-release-ninja
          - clang-release-ninja
        exclude:
          - arch: arm64v8
            dist: arch
            build_type: gcc-debug-ninja
          - arch: arm64v8
            dist: arch
            build_type: gcc-release-ninja
          - arch: arm64v8
            dist: arch
            build_type: clang-release-ninja
        include:
          - arch: amd64
            dist: ubuntu
            build_type: clang-asan-ninja
          - arch: amd64
            dist: ubuntu
            build_type: clang-tsan-ninja
          - arch: amd64
            dist: ubuntu
            build_type: clang-ubsan-ninja
          - arch: amd64
            dist: ubuntu
            build_type: clang-coverage-ninja
          - arch: amd64
            dist: ubuntu
            build_type: oldgcc-debug-make
          - arch: arm64v8
            dist: ubuntu
            build_type: gcc-debug-noperfmon-ninja
          - arch: arm64v8
            dist: ubuntu
            build_type: oldclang-debug-make
          - arch: amd64
            dist: ubuntu
            build_type: gcc-release-ninja-static
          - arch: arm64v8
            dist: ubuntu
            build_type: gcc-release-ninja-static
          - arch: amd64
            dist: ubuntu
            build_type: gcc-release-ninja-O2-static
          - arch: arm64v8
            dist: ubuntu
            build_type: gcc-release-ninja-O2-static
          - arch: amd64
            dist: ubuntu
            build_type: clang-release-ninja-static
          - arch: arm64v8
            dist: ubuntu
            build_type: clang-release-ninja-static
          - arch: amd64
            dist: ubuntu
            build_type: clang-release-ninja-O2-static
          - arch: arm64v8
            dist: ubuntu
            build_type: clang-release-ninja-O2-static
          - arch: amd64
            dist: ubuntu
            build_type: clang-reldbg-ninja-static
          - arch: arm64v8
            dist: ubuntu
            build_type: clang-reldbg-ninja-static
          - arch: amd64
            dist: ubuntu
            build_type: clang-debug-ninja-static
          - arch: arm64v8
            dist: ubuntu
            build_type: clang-debug-ninja-static
          - arch: arm64v8
            dist: ubuntu-2204
            build_type: gcc-release-ninja
          - arch: arm64v8
            dist: ubuntu-2204
            build_type: clang-release-ninja

    runs-on:
      - self-hosted
      - Linux
      - ${{ matrix.arch }}

    steps:
      - name: Checkout
        uses: actions/checkout@v4
        with:
          submodules: 'true'
          fetch-depth: '0'
          ref: ${{ github.ref }}

      - name: Build Docker Image
        run: |
          docker build \
            -f .docker/Dockerfile.${{ matrix.dist }} \
            -t dwarfs-linux-build-${{ matrix.dist }} \
            --build-arg ARCH=${{ matrix.arch }} \
            --build-arg SCRIPT=build-linux.sh \
            .docker

      - name: Run Build (${{ matrix.build_type }})
        run: |
          docker run --rm \
            --cap-add SYS_ADMIN --device /dev/fuse --privileged \
            --mount type=bind,source=${GITHUB_WORKSPACE},target=/workspace,readonly \
            --mount type=bind,source=${{ runner.temp }},target=/tmp-runner \
            --mount type=bind,source=/home/mhx/github-ccache,target=/ccache \
            --mount type=bind,source=/mnt/opensource/artifacts/dwarfs,target=/artifacts \
            --env BUILD_TYPE=${{ matrix.build_type }} \
            --env BUILD_ARCH=${{ matrix.arch }} \
            --env BUILD_DIST=${{ matrix.dist }} \
            --env GITHUB_REF_NAME \
            --env GITHUB_REF_TYPE \
            --env GITHUB_RUN_ID \
            --env GITHUB_RUN_NUMBER \
            --env GITHUB_RUN_ATTEMPT \
            dwarfs-linux-build-${{ matrix.dist }}

      - name: List Coverage Files
        id: coverage-files
        if: matrix.build_type == 'clang-coverage-ninja'
        run: |
          files=$(find ${{ runner.temp }}/coverage -type f | paste -d, -s)
          echo "list=$files" >> "$GITHUB_OUTPUT"

      - name: Upload Coverage Data
        if: matrix.build_type == 'clang-coverage-ninja'
        uses: codecov/codecov-action@v3
        with:
          token: ${{ secrets.CODECOV_TOKEN }}
          files: ${{ steps.coverage-files.outputs.list }}
          fail_ci_if_error: false

      - name: Prepare Artifact Upload
        run: cat ${{ runner.temp }}/artifacts.env >> $GITHUB_ENV
        if: ${{ endsWith(matrix.build_type, '-static') }}

      - name: Upload Binary Tarball
        uses: actions/upload-artifact@v4
        with:
          name: ${{ env.binary_tarball }}
          path: ${{ runner.temp }}/artifacts/${{ env.binary_tarball }}
          if-no-files-found: error
          compression-level: 0
        if: ${{ endsWith(matrix.build_type, '-static') }}

      - name: Upload Universal Binary
        uses: actions/upload-artifact@v4
        with:
          name: ${{ env.universal_binary }}
          path: ${{ runner.temp }}/artifacts/${{ env.universal_binary }}
          if-no-files-found: error
          compression-level: 0
        if: ${{ endsWith(matrix.build_type, '-static') }}
