---
# SPDX-License-Identifier: GPL-2.0-or-later
#
# This file is part of nvme.
# Copyright (c) 2026 SUSE LLC
#
# Authors: Daniel Wagner <dwagner@suse.de>

name: Build

on:
  push:
    branches: [master]
  pull_request:
    branches: [master]

  workflow_dispatch:

jobs:
  nvme-cli:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        distro: [debian, fedora, tumbleweed]
        compiler: [gcc, clang]
        buildtype: [debug, release]
    container:
      image: ghcr.io/linux-nvme/${{ matrix.distro }}:latest
    steps:
      - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
      - name: Mark repo as safe for git
        run: git config --global --add safe.directory "$GITHUB_WORKSPACE"
      - name: build
        run: |
          if [ "${{ matrix.compiler }}" = "gcc" ]; then
            if [ "${{ matrix.buildtype }}" = "release" ]; then
              if [ "${{ matrix.distro }}" = "tumbleweed" ]; then
                export CFLAGS="-O2 -Wall -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=3 \
                  -fstack-protector-strong -funwind-tables -fasynchronous-unwind-tables \
                  -fstack-clash-protection -Werror=return-type -flto=auto -g"
                export CXXFLAGS="$CFLAGS"
                export LDFLAGS="-flto=auto"
              # TODO: The RH build depends on environment varibles/settings which prevent
              # the compiler from working.
              #
              # elif [ "${{ matrix.distro }}" = "fedora" ]; then
              #   export CFLAGS="-O2 -flto=auto -ffat-lto-objects -fexceptions -g \
              #     -grecord-gcc-switches -pipe -Wall -Werror=format-security \
              #     -Wp,-U_FORTIFY_SOURCE,-D_FORTIFY_SOURCE=3 -Wp,-D_GLIBCXX_ASSERTIONS \
              #     -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -fstack-protector-strong \
              #     -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -m32 -march=i686 -mtune=generic \
              #     -msse2 -mfpmath=sse -mstackrealign -fasynchronous-unwind-tables \
              #     -fstack-clash-protection"
              #   export CXXFLAGS="$CFLAGS"
              #   export LDFLAGS='-Wl,-z,relro -Wl,--as-needed -Wl,-z,pack-relative-relocs \
              #     -Wl,-z,now -specs=/usr/lib/rpm/redhat/redhat-hardened-ld \
              #     -specs=/usr/lib/rpm/redhat/redhat-hardened-ld-errors \
              #     -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 \
              #     -Wl,--build-id=sha1 -specs=/usr/lib/rpm/redhat/redhat-package-notes'
              fi
            fi
          fi

          scripts/build.sh -b ${{ matrix.buildtype }} -c ${{ matrix.compiler }} -x
      - uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
        name: upload logs
        if: failure()
        with:
          name: logs files
          path: |
            .build-ci/meson-logs/*.txt

  # Second test pass: the build matrix above runs the suite under valgrind,
  # which skips the fork-based tests (e.g. the python multiprocessing registry
  # test is skipIf(_under_valgrind)).  Run the suite once more WITHOUT valgrind
  # so those tests actually execute.  fedora:latest tracks the newest Python,
  # where interpreter-default changes (e.g. the 3.14 forkserver default that
  # broke a fork-based test) surface before the other CI distros.
  nvme-cli-no-valgrind:
    name: nvme-cli unit tests without valgrind
    runs-on: ubuntu-latest
    container:
      image: ghcr.io/linux-nvme/fedora:latest
    steps:
      - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
      - name: Mark repo as safe for git
        run: git config --global --add safe.directory "$GITHUB_WORKSPACE"
      - name: Report interpreter/toolchain versions
        run: |
          grep -E '^(NAME|VERSION)=' /etc/os-release
          python3 --version
          gcc --version | head -1
          meson --version
      - name: build
        # No -x: scripts/build.sh runs plain "meson test" (default setup, no
        # valgrind), so the fork-based tests valgrind skips actually run.
        run: |
          scripts/build.sh -b release -c gcc
      - uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
        name: upload logs
        if: failure()
        with:
          name: no-valgrind logs files
          path: |
            .build-ci/meson-logs/*.txt

  libnvme:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        distro: [debian]
        compiler: [gcc]
        buildtype: [release]
    container:
      image: ghcr.io/linux-nvme/${{ matrix.distro }}:latest
    steps:
      - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
      - name: Mark repo as safe for git
        run: git config --global --add safe.directory "$GITHUB_WORKSPACE"
      - name: build
        run: |
          scripts/build.sh -b ${{ matrix.buildtype }} -c ${{ matrix.compiler }} -x libnvme
      - uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
        name: upload logs
        if: failure()
        with:
          name: libnvme logs files
          path: |
            .build-ci/meson-logs/*.txt

  cross:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        include:
          - arch: armhf
          - arch: s390x
          - arch: ppc64le
    steps:
      - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
      - name: enable foreign arch
        uses: docker/setup-qemu-action@96fe6ef7f33517b61c61be40b68a1882f3264fb8 # v4.2.0
      - name: Login to GitHub Container Registry
        uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4.6.0
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}
      - name: compile and run unit tests
        run: |
          docker run --rm \
            --platform linux/amd64 \
            -v "${{ github.workspace }}:/build" \
            -w /build \
            ghcr.io/linux-nvme/ubuntu-cross-${{ matrix.arch }}:latest \
            sh -c "git config --global --add safe.directory /build && scripts/build.sh -b release -c gcc -t ${{ matrix.arch }} cross"
      - uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
        name: upload logs
        if: failure()
        with:
          name: log files
          path: |
            .build-ci/meson-logs/*.txt

  fallback-shared-libraries:
    name: fallback shared libraries
    runs-on: ubuntu-latest
    container:
      image: ghcr.io/linux-nvme/debian:latest
    if: github.ref == 'refs/heads/master'
    steps:
      - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
      - name: Mark repo as safe for git
        run: git config --global --add safe.directory "$GITHUB_WORKSPACE"
      - name: build
        run: |
          scripts/build.sh -b release -c gcc fallback
      - uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
        if: failure()
        with:
          name: log files
          path: |
            .build-ci/meson-logs/*.txt

  build-muon:
    name: muon minimal static
    runs-on: ubuntu-latest
    container:
      image: ghcr.io/linux-nvme/debian:latest
    steps:
      - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
      - name: Mark repo as safe for git
        run: git config --global --add safe.directory "$GITHUB_WORKSPACE"
      - name: build
        run: |
          scripts/build.sh -m muon

  build-make-static:
    name: make static
    runs-on: ubuntu-latest
    container:
      image: ghcr.io/linux-nvme/debian:latest
    steps:
      - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
      - name: Mark repo as safe for git
        run: git config --global --add safe.directory "$GITHUB_WORKSPACE"
      - name: build
        run: |
          make static

  build-musl:
    name: musl libc build on Debian
    runs-on: ubuntu-latest
    container:
      image: ghcr.io/linux-nvme/debian:latest
    steps:
      - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
      - name: Mark repo as safe for git
        run: git config --global --add safe.directory "$GITHUB_WORKSPACE"
      - name: build
        run: |
          CC=musl-gcc scripts/build.sh musl

  build-musl-minimal-static:
    name: musl libc minimal static build on Debian
    runs-on: ubuntu-latest
    container:
      image: ghcr.io/linux-nvme/debian:latest
    steps:
      - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
      - name: Mark repo as safe for git
        run: git config --global --add safe.directory "$GITHUB_WORKSPACE"
      - name: build
        run: |
          scripts/build.sh minimal_static

  build-nofabrics:
    name: no-fabrics build with unit tests
    runs-on: ubuntu-latest
    container:
      image: ghcr.io/linux-nvme/debian:latest
    steps:
      - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
      - name: Mark repo as safe for git
        run: git config --global --add safe.directory "$GITHUB_WORKSPACE"
      - name: build
        run: |
          scripts/build.sh nofabrics
      - uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
        name: upload logs
        if: failure()
        with:
          name: no-fabrics log files
          path: |
            .build-ci/meson-logs/*.txt

  build-alpine:
    name: musl libc build on Alpine
    runs-on: ubuntu-latest
    container:
      image: ghcr.io/linux-nvme/alpine:latest
    steps:
      - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
      - name: Mark repo as safe for git
        run: git config --global --add safe.directory "$GITHUB_WORKSPACE"
      - name: build
        run: |
          scripts/build.sh musl

  build-distro:
    name: build libnvme and nvme-cli separately
    runs-on: ubuntu-latest
    container:
      image: ghcr.io/linux-nvme/debian:latest
    steps:
      - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
      - name: Mark repo as safe for git
        run: git config --global --add safe.directory "$GITHUB_WORKSPACE"
      - name: build
        run: |
          scripts/build.sh distro

  build-liburing:
    name: build with liburing support enabled
    runs-on: ubuntu-latest
    container:
      image: ghcr.io/linux-nvme/debian:latest
    steps:
      - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
      - name: Mark repo as safe for git
        run: git config --global --add safe.directory "$GITHUB_WORKSPACE"
      - name: build
        run: |
          scripts/build.sh liburing

  windows-msys2-ucrt64:
    runs-on: windows-latest
    timeout-minutes: 60
    steps:
      - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
      - uses: msys2/setup-msys2@66cd2cce69caa17b53920067426061ca1de3a884 # v2.32.0
        with:
          msystem: UCRT64
          update: true
          install: >-
            git
            mingw-w64-ucrt-x86_64-gcc
            mingw-w64-ucrt-x86_64-pkgconf
            mingw-w64-ucrt-x86_64-meson
            mingw-w64-ucrt-x86_64-ninja
            mingw-w64-ucrt-x86_64-ccache
            mingw-w64-ucrt-x86_64-json-c
            mingw-w64-ucrt-x86_64-python-jsonschema

      - name: Build nvme-cli
        shell: msys2 {0}
        run: |
          set -euxo pipefail
          which bash
          bash --version
          which git
          git --version
          git config --global --add safe.directory "$GITHUB_WORKSPACE"
          scripts/build.sh -b release -c /ucrt64/bin/gcc

      - uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
        if: failure()
        with:
          name: windows-msys2-ucrt64-logs
          path: |
            .build-ci/meson-logs/*.txt

  # This job uses clang rather than gcc because MSYS2 has no gcc toolchain for
  # native Windows-on-ARM64: CLANGARM64 is its only aarch64 environment, and
  # gcc's aarch64-w64-mingw32 target exists only as an experimental
  # cross-compiler (mingw-w64-cross-mingwarm64-gcc, still versioned 15.0.1dev).
  # Note that "pacman -S mingw-w64-clang-aarch64-gcc" does resolve, but it is a
  # virtual package satisfied by mingw-w64-clang-aarch64-gcc-compat, which only
  # installs gcc-named aliases for clang -- not a second compiler.
  windows-msys2-clangarm64:
    runs-on: windows-11-arm
    timeout-minutes: 60
    steps:
      - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
      - uses: msys2/setup-msys2@66cd2cce69caa17b53920067426061ca1de3a884 # v2.32.0
        with:
          msystem: CLANGARM64
          update: true
          install: >-
            git
            mingw-w64-clang-aarch64-clang
            mingw-w64-clang-aarch64-pkgconf
            mingw-w64-clang-aarch64-meson
            mingw-w64-clang-aarch64-ninja
            mingw-w64-clang-aarch64-ccache
            mingw-w64-clang-aarch64-json-c
            mingw-w64-clang-aarch64-python-jsonschema

      - name: Build nvme-cli
        shell: msys2 {0}
        run: |
          set -euxo pipefail
          which bash
          bash --version
          which git
          git --version
          clang --version
          git config --global --add safe.directory "$GITHUB_WORKSPACE"
          scripts/build.sh -b release -c /clangarm64/bin/clang

      - uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
        if: failure()
        with:
          name: windows-msys2-clangarm64-logs
          path: |
            .build-ci/meson-logs/*.txt
