# ns-3 CI/CD script with the code-linting stage
#
# Contains jobs to check the ns-3 coding style and perform lint checking.

# Common settings
.code-linting-base:
  stage: .pre
  timeout: 1h
  interruptible: true

# Clang-format
.check-style-clang-format:
  extends: .code-linting-base
  image: ubuntu:rolling
  before_script:
    - apt update
    - DEBIAN_FRONTEND=noninteractive apt install -y
      python3
      clang-format-$CLANG_FORMAT_VERSION
  script:
    - python3 utils/check-style-clang-format.py --verbose .

check-style-clang-format-20:
  extends: .check-style-clang-format
  variables:
    CLANG_FORMAT_VERSION: 20

# check-style-clang-format-21:
#   extends: .check-style-clang-format
#   variables:
#     CLANG_FORMAT_VERSION: 21

# Clang-tidy
clang-tidy-21:
  extends: .code-linting-base
  stage: code-linting
  image: ubuntu:rolling
  variables:
    MPI_CI: 1
    CLANG_TIDY_OUTPUT: clang-tidy-output.log
    FILES_CHANGED: git-diff-name-only.log
  before_script:
    - apt update
    - DEBIAN_FRONTEND=noninteractive apt install -y
      clang cmake
      clang-tidy clang-tidy-21
      libboost-all-dev libeigen3-dev libgtk-3-dev libopenmpi-dev libsqlite3-dev
      gsl-bin libgsl-dev libgsl28
      git ssh
    - ./ns3 configure -d debug
      --enable-clang-tidy
      --enable-examples --enable-tests --enable-asserts
      --enable-mpi
  script:
    - if (git remote | grep -qw upstream) ; then
      git remote remove upstream ;
      fi
    - git remote add -t $CI_DEFAULT_BRANCH --no-tags -f upstream https://gitlab.com/nsnam/ns-3-dev.git
    - git diff --name-only upstream/$CI_DEFAULT_BRANCH > $FILES_CHANGED

    # Run clang-tidy on all files in the following cases: 1) default branch, 2) ".clang-tidy" file changed
    # Otherwise, run clang-tidy on changed files only.
    # File paths generated by git diff are relative to the working tree. Therefore, iregex should only contain paths relative to the working tree.
    - |
      if [[ $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH ]] ||
         (grep -q ".clang-tidy" $FILES_CHANGED) ||
         (grep -q "gitlab-ci-code-linting.yml" $FILES_CHANGED) ;
      then
        FILES_TO_CHECK="";
        echo "Running clang-tidy on all files";
      else
        FILES_TO_CHECK=$(cat $FILES_CHANGED);
        echo "Running clang-tidy on the following changed files:";
        echo $FILES_TO_CHECK;
      fi
    - run-clang-tidy-21 -p cmake-cache/ -quiet $FILES_TO_CHECK
      1> $CLANG_TIDY_OUTPUT
      2> /dev/null

    # Trim empty lines from output file
    - sed -i '/^$/d' $CLANG_TIDY_OUTPUT

    # Check job results
    - (! egrep -v "file not found \[clang-diagnostic-error\]" $CLANG_TIDY_OUTPUT | egrep -A3 "error:|warning:|note:")
    - echo "No clang-tidy errors found"
  dependencies: []
  artifacts:
    paths:
      - $CLANG_TIDY_OUTPUT
    when: on_failure
  timeout: 3h

# Spell checking
spell-check:
  extends: .code-linting-base
  image: python:latest
  before_script:
    - pip install codespell
  script:
    # Get commit messages
    - if (git remote | grep -qw upstream) ; then
      git remote remove upstream ;
      fi
    - git remote add -t $CI_DEFAULT_BRANCH --no-tags -f upstream https://gitlab.com/nsnam/ns-3-dev.git

    - git log --pretty=%B HEAD...upstream/$CI_DEFAULT_BRANCH ^upstream/$CI_DEFAULT_BRANCH > git_messages.txt
    # Check source code and commit messages
    - codespell -f -C0 ./

# Check cmake format
cmake-format:
  extends: .code-linting-base
  image: python:3.12
  before_script:
    - pip install pyyaml cmake cmake-format ninja
  script:
    - ./ns3 configure --enable-modules=core
    - |
      if (! ./ns3 build cmake-format-check) ; then
        echo "Bad formatting detected in CMake files.";
        echo "To fix the formatting issues, run the following command:";
        echo "   $ ./ns3 build cmake-format";
        echo "Note that it requires having cmake-format installed in your system.";
        echo "You might need to run \"./ns3 configure\" after installing it.";
        exit 1;
      fi

# Check Python format
python-format-latest:
  extends: .code-linting-base
  image: python:latest
  before_script:
    - pip install black isort
  script:
    - black --check .
    - isort --check .

# Markdown lint
markdown-lint:
  extends: .code-linting-base
  image: node:slim
  before_script:
    - npm install -g markdownlint-cli
  script:
    - markdownlint .
