---
# yamllint disable rule:line-length
variables:
  PYTHON_CODE_DIRS: "./library/ ./module_utils/ha_cluster_lsr/ ./tests/unit/"
  WOKE_CONFIG: "https://raw.githubusercontent.com/linux-system-roles/tox-lsr/main/src/tox_lsr/config_files/woke.yml"
  YAMLLINT_CONFIG: "{extends: .yamllint.yml, ignore: [.github/, .markdownlint.yaml]}"
  PYENV_ROOT: /root/pyenvs/ansible

# Ansible 2.9 doesn't work with Python 3.12 shipped in RHEL 10
.all_images: &ALL_IMAGES
  - LsrRhel10NextAnsibleCurrent
  - LsrRhel10CurrentAnsibleCurrent
  - LsrRhel9NextAnsibleCurrent
  - LsrRhel9NextAnsible29
  - LsrRhel9CurrentAnsibleCurrent
  - LsrRhel9CurrentAnsible29
  - LsrRhel8NextAnsibleCurrent
  - LsrRhel8NextAnsible29
  - LsrRhel8OldestAnsibleCurrent
  - LsrRhel8OldestAnsible29

# Jobs running linters and test tools shipped with ansible. Old versions of
# ansible don't provide all required functionality.
.job_ansible_check:
  parallel:
    matrix:
      - BASE_IMAGE_NAME: *ALL_IMAGES
  rules:
    - if: ($BASE_IMAGE_NAME =~ /.*AnsibleCurrent$/) && ($BASE_IMAGE_NAME !~ /^LsrRhel8Oldest.*/)

# Do not run python unit tests and linters on RHEL8 as it doesn't ship a
# compatible version of pcs.
# Linters depending on pcs code (mypy, pylint) benefit from running on all
# capable combinations of pcs, python and ansible.
.job_python:
  parallel:
    matrix:
      - BASE_IMAGE_NAME: *ALL_IMAGES
  rules:
    - if: $BASE_IMAGE_NAME !~ /^LsrRhel8.*/

# Linting / code formatting that either works the same on all images or using
# the newest linter / formatter is desired
# Rhel9 can be dropped once Rhel10 is stable
.job_generic_linter:
  parallel:
    matrix:
      - BASE_IMAGE_NAME:
          - LsrRhel9NextAnsibleCurrent
          - LsrRhel10NextAnsibleCurrent

#  If we are running Python version other than what pcs was built for, Python
#  won't find installed pcs. To overcome this, symlink pcs to pyenv.
.symlink_pcs_to_pyenv: &symlink_pcs_to_pyenv
  - PYTHON_VER=$(python3 -c 'import sys; v=sys.version_info; print(f"{v.major}.{v.minor}")')
  - PYENV_PACKAGES="${PYENV_ROOT}/lib/python${PYTHON_VER}/site-packages"
  - PCS_DIR=$(rpm -ql pcs | grep 'site-packages/pcs$')
  - PCS_PYTHON_VER=$(echo "$PCS_DIR" | sed -e 's@.*/python\([0-9\.]\+\)/.*@\1@')
  - if [ "x$PYTHON_VER" != "x$PCS_PYTHON_VER" ]; then ln -s "${PCS_DIR}" "${PYENV_PACKAGES}/pcs"; fi
  - ls -l "$PYENV_PACKAGES"

.convert_role_to_collection: &convert_role_to_collection
  - MY_DIR="$(basename $(pwd))"
  - if [ "x$MY_DIR" != "xha_cluster" ]; then ln -s "$MY_DIR" ../ha_cluster; fi
  - LSR_INFO=true python /usr/local/lib/lsr-auto-maintenance/lsr_role2collection.py --dest-path ../ --src-path ../ --src-owner tomjelinek --role ha_cluster
  - coll_dir="../ansible_collections/fedora/linux_system_roles/"
  - ignore_dir="$coll_dir/tests/sanity"  # wokeignore:rule=sanity
  - mkdir -pv "$ignore_dir"
  - for file in .sanity-ansible-ignore-*.txt; do if [ -f "$file" ]; then cp "$file" "$ignore_dir/${file//*.sanity-ansible-}"; fi; done  # wokeignore:rule=sanity
  - cd "$coll_dir"
  - rm -f .pandoc_template-ha_cluster.html5  # remove irrelevant files

default:
  before_script:
    - source "${PYENV_ROOT}/bin/activate"
    - python --version

stages:
  - tier0
  - tier1

# tier0 - non-python
ansible_lint:
  extends: .job_ansible_check
  stage: tier0
  script:
    - ansible-lint --version
    - ansible-lint -v --exclude=tests/roles --exclude=.github --skip-list role-name,fqcn --config-file .ansible-lint

ansible_test:
  extends: .job_ansible_check
  stage: tier0
  script:
    - *convert_role_to_collection
    - ansible-test --version
    - ansible-test sanity -v --color=yes --truncate=0 --no-redact --coverage --docker  # wokeignore:rule=sanity

# TODO enable shellcheck for RHEL 10 once it is available there
shellcheck:
  extends: .job_generic_linter
  stage: tier0
  script:
    - shellcheck --version
    - shellcheck files/*.sh
  rules:
    - if: $BASE_IMAGE_NAME !~ /^LsrRhel10.*/

markdownlint:
  extends: .job_generic_linter
  stage: tier0
  script:
    - chcon -R -t container_ro_file_t "../$(basename $(pwd))"
    - podman run --rm --volume "$(pwd):/ha_cluster:ro" docker://avtodev/markdown-lint:master --config /ha_cluster/.markdownlint.yaml --ignore /ha_cluster/CHANGELOG.md /ha_cluster/**/*.md  # wokeignore:rule=master

woke:
  extends: .job_generic_linter
  stage: tier0
  script:
    - woke --version
    - woke -c "${WOKE_CONFIG}" --exit-1-on-failure --debug

yaml_lint:
  extends: .job_generic_linter
  stage: tier0
  script:
    - yamllint --version
    - yamllint --config-data "${YAMLLINT_CONFIG}" ./

# tier0 - python
black:
  extends: .job_generic_linter
  stage: tier0
  script:
    - black --version
    - black --config pyproject.toml --check ${PYTHON_CODE_DIRS}

isort:
  extends: .job_generic_linter
  stage: tier0
  script:
    - isort --version
    - isort --check-only ${PYTHON_CODE_DIRS}

mypy:
  extends: .job_python
  stage: tier0
  script:
    - dnf install -y pcs
    - touch "$(rpm -ql pcs | grep 'site-packages/pcs$')/py.typed"
    - *symlink_pcs_to_pyenv
    - pcs --version
    - mypy --version
    - mypy --config-file mypy.ini ${PYTHON_CODE_DIRS}

pylint:
  extends: .job_python
  stage: tier0
  script:
    - pylint --rcfile pylintrc --persistent=n --reports=y --score=y --disable similarities ${PYTHON_CODE_DIRS}

unit_tests:
  extends: .job_python
  stage: tier0
  script:
    - dnf install -y pcs
    - *symlink_pcs_to_pyenv
    - pcs --version
    - PYTHONPATH="./library:./module_utils:$PYTHONPATH" python -m unittest --verbose tests/unit/*.py

unit_tests_rhel8:
  parallel:
    matrix:
      - BASE_IMAGE_NAME: *ALL_IMAGES
  rules:
    - if: $BASE_IMAGE_NAME =~ /^LsrRhel8.*/
  stage: tier0
  script:
    - dnf install -y pcs
    - *symlink_pcs_to_pyenv
    - pcs --version
    - PYTHONPATH="./library:./module_utils:$PYTHONPATH" python -m unittest --verbose tests/unit/test_ha_cluster_info.py

# tier 1
build_tier1_ci_yml:
  variables:
    BASE_IMAGE_NAME: LsrRhel9CurrentAnsibleCurrent
  stage: tier0
  script:
    - cd tests
    - export TESTS=$(ls -1 tests_*.yml | sed -e 's/^tests_\(.*\)\.yml$/\1/')
    - cd ..
    - python -c 'import os; from jinja2 import Template; print(Template(open(".gitlab-ci-tier1.yml.j2").read()).render(tests=os.environ["TESTS"].split()));' > .gitlab-ci-tier1.yml
  artifacts:
    paths:
      - .gitlab-ci-tier1.yml
    expire_in: 1 day

trigger_tier1:
  stage: tier1
  trigger:
    include:
      - artifact: .gitlab-ci-tier1.yml
        job: build_tier1_ci_yml
    strategy: depend
  parallel:
    matrix:
      - BASE_IMAGE_NAME: *ALL_IMAGES
