name: libyang CI
on:
  push:
    branches:
      - master
      - devel
  pull_request:
    branches:
      - master
      - devel

jobs:
  build-unix:
    name: ${{ matrix.config.name }}
    runs-on: ${{ matrix.config.os }}
    strategy:
      fail-fast: false
      matrix:
        config:
          - {
            name: "Release, gcc",
            os: "ubuntu-22.04",
            build-type: "Release",
            cc: "gcc",
            options: "-DENABLE_TESTS=ON",
            packager: "sudo apt-get",
            # no expect because stdout seems to be redirected
            packages: "libcmocka-dev libxxhash-dev",
            snaps: "",
            build-cmd: "make"
          }
          - {
            name: "Release, clang",
            os: "ubuntu-22.04",
            build-type: "Release",
            cc: "clang",
            options: "-DENABLE_TESTS=ON",
            packager: "sudo apt-get",
            packages: "libcmocka-dev libxxhash-dev",
            snaps: "",
            build-cmd: "make"
          }
          - {
            name: "Debug, gcc",
            os: "ubuntu-22.04",
            build-type: "Debug",
            cc: "gcc",
            options: "",
            packager: "sudo apt-get",
            packages: "libcmocka-dev libxxhash-dev valgrind",
            snaps: "",
            build-cmd: "make"
          }
          - {
            name: "Debug, clang",
            os: "ubuntu-22.04",
            build-type: "Debug",
            cc: "clang",
            options: "",
            packager: "sudo apt-get",
            # no valgrind because it does not support DWARF5 yet generated by clang 14
            packages: "libcmocka-dev libxxhash-dev",
            snaps: "",
            build-cmd: "make"
          }
          - {
            name: "Release, macOS 14, clang",
            os: "macos-14",
            build-type: "Release",
            cc: "clang",
            options: "-DENABLE_TESTS=ON -DPATH_EXPECT=",
            packager: "brew",
            packages: "cmocka xxhash tcl-tk",
            snaps: "",
            build-cmd: "make"
          }
          - {
            name: "ASAN and UBSAN",
            os: "ubuntu-22.04",
            build-type: "Debug",
            cc: "clang",
            options: "-DCMAKE_C_FLAGS=-fsanitize=address,undefined -DENABLE_TESTS=ON -DENABLE_VALGRIND_TESTS=OFF",
            packager: "sudo apt-get",
            packages: "libcmocka-dev libxxhash-dev",
            snaps: "",
            build-cmd: "make"
          }
          - {
            name: "DEB Package",
            os: "ubuntu-22.04",
            build-type: "Release",
            cc: "gcc",
            options: "",
            packager: "sudo apt-get",
            packages: "cmake debhelper libcmocka-dev libxxhash-dev python3-pip",
            snaps: "",
            build-cmd: ""
          }

    steps:
      - uses: actions/checkout@main
        with:
          fetch-depth: 100

      - name: Deps-packages
        shell: bash
        run: |
          ${{ matrix.config.packager }} update
          if ${{ matrix.config.packages != '' }}
            then ${{ matrix.config.packager }} install ${{ matrix.config.packages }}
          fi
          if ${{ matrix.config.snaps != '' }}
            then sudo snap install ${{ matrix.config.snaps }}
          fi

      - name: Deps-uncrustify
        shell: bash
        working-directory: ${{ github.workspace }}
        run: |
          git clone --branch uncrustify-0.77.1 https://github.com/uncrustify/uncrustify
          cd uncrustify
          mkdir build
          cd build
          CC=${{ matrix.config.cc }} cmake -DCMAKE_POLICY_VERSION_MINIMUM=3.5 ..
          make
          sudo make install
        if: ${{ matrix.config.name == 'Debug, gcc' }}

      - name: Build-and-install-package
        shell: bash
        working-directory: ${{ github.workspace }}
        run: |
          pip install apkg
          apkg system-setup
          apkg build
          apkg install
        if: ${{ matrix.config.name == 'DEB Package' }}

      - name: Configure
        shell: bash
        working-directory: ${{ github.workspace }}
        run: |
          mkdir build
          cd build
          CC=${{ matrix.config.cc }} cmake -DCMAKE_BUILD_TYPE=${{ matrix.config.build-type }} ${{ matrix.config.options }} ..
        if: ${{ matrix.config.name != 'DEB Package' }}

      - name: Build
        shell: bash
        working-directory: ${{ github.workspace }}/build
        run: |
          export LC_ALL=C.UTF-8
          export PATH=/snap/bin:${{ github.workspace }}/coverity-tools/bin:$PATH
          ${{ matrix.config.build-cmd }}
        if: ${{ matrix.config.name != 'DEB Package' }}

      - name: Test
        shell: bash
        working-directory: ${{ github.workspace }}/build
        run: ctest --output-on-failure
        if: ${{ matrix.config.name != 'DEB Package' }}

  build-windows:
    name: ${{ matrix.name }}
    runs-on: ${{ matrix.os }}
    strategy:
      fail-fast: false
      matrix:
        include:
          - name: "Windows 2022 MSVC 16 LF"
            os: windows-2022
            triplet: x64-windows
            build_type: Release
            generators: "Visual Studio 17 2022"
            autocrlf: input
            eol: lf

          - name: "Windows 2022 MSVC 16 no autoCRLF"
            os: windows-2022
            triplet: x64-windows
            build_type: Release
            generators: "Visual Studio 17 2022"

    steps:
      - name: Unix line endings in git
        if: matrix.autocrlf
        run: |
          git config --global core.autocrlf ${{ matrix.autocrlf }}

      - name: Unix line endings in git
        if: matrix.eol
        run: |
          git config --global core.eol ${{ matrix.eol }}

      - uses: actions/checkout@main

      - name: Get number of CPU cores
        id: cpu-cores
        uses: SimenB/github-actions-cpu-cores@v1

      - name: pin CMake to the latest 3.x series
        uses: jwlawson/actions-setup-cmake@09fd9b0fb3b239b4b68d9256cd65adf8d6b91da0
        with:
          cmake-version: '3.31.6'

      - name: Install Windows dependencies
        run: vcpkg install --triplet=${{ matrix.triplet }} pcre2 pthreads dirent dlfcn-win32 cmocka getopt xxhash

      - name: Configure
        shell: bash
        run: |
          cmake \
            -S '${{ github.workspace }}/' \
            -B '${{ github.workspace }}/'../build \
            -G '${{ matrix.generators }}' \
            -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} \
            -DVCPKG_TARGET_TRIPLET=${{ matrix.triplet }} \
            -DCMAKE_TOOLCHAIN_FILE=${VCPKG_INSTALLATION_ROOT//\\//}/scripts/buildsystems/vcpkg.cmake \
            -DENABLE_TESTS=ON \
            '-DCMAKE_INSTALL_PREFIX:PATH=${{ github.workspace }}'/../target

      - name: Build
        working-directory: '${{ github.workspace }}/../build'
        run: cmake --build . -j${{ steps.cpu-cores.outputs.count }} --config ${{ matrix.build_type }}

      - name: Test
        working-directory: '${{ github.workspace }}/../build'
        run: ctest --output-on-failure -j${{ steps.cpu-cores.outputs.count }} --build-config ${{ matrix.build_type }}

      - name: Install
        working-directory: '${{ github.workspace }}/../build'
        run: cmake --install . --strip

  build-solaris:
    name: Release, Solaris, gcc
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@main

      - name: Build and test
        uses: vmactions/solaris-vm@main
        with:
          release: '11.4-gcc'
          usesh: true

          prepare: |
            echo "Installing dependencies..."
            export PATH=/opt/csw/bin:$PATH

            pkgutil -y -i git cmake libpcre2_dev

            # build cmocka from source
            git clone --depth 1 https://github.com/clibs/cmocka.git
            cd cmocka
            mkdir build-cmocka
            cd build-cmocka
            cmake -DCMAKE_BUILD_TYPE=Release ..
            gmake
            gmake install
            cd ../..

          run: |
            set -e
            echo "Starting build..."
            mkdir build
            cd build
            cmake -DCMAKE_BUILD_TYPE=Release -DENABLE_TESTS=ON ..
            gmake
            ctest --output-on-failure

  build-freebsd:
    name: Release, FreeBSD, clang
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@main

      - name: Release, FreeBSD, clang
        uses: vmactions/freebsd-vm@main
        with:
          usesh: true

          prepare: |
            echo "Installing dependencies..."
            pkg update -f
            pkg install -y cmake cmocka xxhash bash git pcre2

          run: |
            set -e
            echo "Starting build..."
            mkdir build
            cd build

            cmake -DCMAKE_BUILD_TYPE=Release -DENABLE_TESTS=ON ..
            make
            ctest --output-on-failure

  build-linux-32bit:
    name: Release, Linux 32-bit, gcc
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@main

      - name: Build in 32-bit container
        run: |
          docker run --rm \
            -v ${{ github.workspace }}:${{ github.workspace }} \
            -w ${{ github.workspace }} \
            i386/ubuntu \
            /bin/bash -c " \
              apt-get update -q && \
              apt-get install -y -q git cmake gcc libcmocka-dev libxxhash-dev libpcre2-dev && \
              mkdir build && cd build && \
              cmake -DCMAKE_BUILD_TYPE=Release -DENABLE_TESTS=ON .. && \
              make && \
              ctest --output-on-failure \
            "

  build-big-endian:
    name: Release, Big-endian, s390x
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@main

      - name: Build and test
        # use QEMU user-static emulation to run non-x86 Linux
        uses: uraimo/run-on-arch-action@master
        with:
          arch: s390x
          distro: ubuntu22.04

          # speeds up build by caching Docker images in GitHub Packages
          githubToken: ${{ github.token }}

          # map the build directory to the container
          dockerRunArgs: |
            --volume "${PWD}:/workspace"

          # install dependencies inside the emulated container
          install: |
            apt-get update -q -y
            apt-get install -q -y git cmake gcc libcmocka-dev libxxhash-dev libpcre2-dev

          # run the build
          run: |
            set -e
            mkdir build
            cd build
            cmake -DCMAKE_BUILD_TYPE=Release -DENABLE_TESTS=ON ..
            make
            ctest --output-on-failure
