--- # ASE Gitlab CI configuration

variables:
  OMP_NUM_THREADS: "1"
  PIP_CACHE_DIR: "$CI_PROJECT_DIR/pip-cache"
  PYTEST_ADDOPTS: "--color=yes --durations=20 -r s"

stages:
  - test
  - paperwork
  - deploy

# This will ensure that only pipelines in master get to update the cache,
# see https://docs.gitlab.com/ci/caching/
# conditional-policy:
#  rules:
#    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
#      variables:
#        POLICY: pull-push
#    - if: $CI_COMMIT_BRANCH != $CI_DEFAULT_BRANCH
#      variables:
#        POLICY: pull

# Check oldest supported Python with oldest supported libraries.
# Does not install any optional libraries except matplotlib.
oldlibs:
  image: registry.gitlab.com/ase/ase:ase-oldlibs
  before_script:
    - pwd
    - whoami
    - >
      pip install
      numpy==1.19.5 scipy==1.6.0 matplotlib==3.3.4
      pytest==7.0.0 attrs==20.3.0 pluggy==1.0.0 py==1.11.0 six==1.15.0
      pytest-xdist==2.1.0 execnet==1.8.1 pytest-forked==1.4.0
    - pip install --no-deps .
  script:
    - ase test
  cache:
    key: oldlibs
    paths:
     - $PIP_CACHE_DIR


# For testing newest versions of libraries against standard images
# on dockerhub.
pipinstall:
  image: python:3.11
  before_script:
    - python --version
    - pip install .[test]
  script:
    - ase test
  when: manual

# This is the main test job using new versions of libraries.
# The intention is to enable as many features and libraries as possible.
#
# We execute it inside the project dir with --editable in order for
# the coverage script to correctly resolve the OMIT paths (a bit hacky).
# It would be better to install it for real, and for things to just work.
main:
  image: registry.gitlab.com/ase/ase:ase-main
  before_script:
    - python --version
    - pip install --no-deps --editable .
    - ase info --calculators
    - cd $CI_PROJECT_DIR
  script:
    - >
      ase test
      --calculators asap,ff,lj,morse,tip3p,tip4p
      --coverage --pytest
      --junit-xml=report.xml
  after_script:
    - coverage xml --data-file ase/test/.coverage
    - mv ase/test/coverage-html coverage-main
    - mv ase/test/.coverage coverage-main/coverage.dat
  artifacts:
    paths:
      - coverage-main/
    reports:
      coverage_report:
        coverage_format: cobertura
        path: coverage.xml
      junit: ase/test/report.xml
    expire_in: 1 week
  cache:
    key: main
    paths:
     - $PIP_CACHE_DIR

# Calculator integration tests which always run.
# Encompasses those tests marked as @pytest.mark.calculator_lite.
# Please make sure these tests are cheap.
calculators-lite:
  image: registry.gitlab.com/ase/ase:ase-full-monty
  before_script:
    - pip install --no-deps --editable .
    - export ASE_CONFIG_PATH=/home/ase/aseconfig.ini
    - sed 's/binary = /command = /' -i /home/ase/aseconfig.ini
  script:
    - >
      ase test calculator --calculators=auto --coverage
      --pytest -m calculator_lite
      --junit-xml=report.xml
  after_script:
    - coverage xml --data-file ase/test/.coverage
    - mv ase/test/coverage-html coverage-calculators-lite
    - mv ase/test/.coverage coverage-calculators-lite/coverage.dat
  artifacts:
    paths:
      - coverage-calculators-lite/
    reports:
      coverage_report:
        coverage_format: cobertura
        path: coverage.xml
      junit: ase/test/report.xml
    expire_in: 1 week
  cache:
    key: calculators
    paths:
     - $PIP_CACHE_DIR

# Plan: Test as many calculators as possible as well as possible.
# Obviously this is kind of expensive so the job is manually activated.
# Also, the docker serves as a knowledgebase for how to set up those
# calculators with ASE.
#
# It would be great if someone could enable more calculators with this.
calculators:
  image: registry.gitlab.com/ase/ase:ase-full-monty
  before_script:
    - pip install --no-deps --editable .
    - export ASE_CONFIG_PATH=/home/ase/aseconfig.ini
    - sed 's/binary = /command = /' -i /home/ase/aseconfig.ini
    - ase info --calculators
  script:
    - >
      ase test calculator --calculators abinit,asap,cp2k,dftb,espresso,gpaw,kim,lammpslib,lammpsrun,mopac,nwchem,octopus,siesta
      --coverage --pytest --junit-xml=report.xml
  after_script:
    - coverage xml --data-file ase/test/.coverage
    - mv ase/test/coverage-html coverage-calculators
    - mv ase/test/.coverage coverage-calculators/coverage.dat
  rules:
    - if: $CI_PIPELINE_SOURCE == "push"
      when: manual
      allow_failure: true
    - if: $CI_PIPELINE_SOURCE == "schedule"
  artifacts:
    paths:
      - coverage-calculators/
    reports:
      coverage_report:
        coverage_format: cobertura
        path: coverage.xml
      junit: ase/test/report.xml
    expire_in: 1 week
  cache:
    key: calculators
    policy: pull
    paths:
     - $PIP_CACHE_DIR

bleeding-edge:
  image: python:3-alpine
  variables:
    PIP_CACHE_DIR: "$CI_PROJECT_DIR/pip-cache"
  before_script:
    - pip install --upgrade numpy scipy matplotlib
    - pip install --editable .[test]
    - pip freeze
  script:
    - ase test --pytest --ignore gui/ --ignore test_imports.py
  cache:
    paths:
      - $PIP_CACHE_DIR
    key: bleeding-edge


doc:
  image: registry.gitlab.com/ase/ase:ase-main
  variables:
    PIP_CACHE_DIR: "$CI_PROJECT_DIR/pip-cache-doc"
  before_script:
    - pip install scriv sphinx_book_theme
    - pip install --no-deps .[docs]
    - ase info
    - which sphinx-build
  script:
    - scriv collect --keep || echo Not compiling changelog then  # Avoid error
    - python -m ase.utils.sphinx run # test scripts
    - sphinx-build -W doc doc/build
    - mv doc/build web-html
  cache:
    paths:
      - $PIP_CACHE_DIR
    key: doc
  artifacts:
    paths:
      - web-html
    expire_in: 1 week

distribution-package:
  image: registry.gitlab.com/ase/ase:ase-main
  before_script:
    - mkdir dist
    - pip install setuptools build
  script:
    - python -m build
    - ls dist/*
    - pip install dist/ase-*.tar.gz
    - ase test
    - pip uninstall --yes ase
    - pip install dist/ase-*-py3-none-any.whl
    - ase test
  artifacts:
    paths:
      - dist
    expire_in: 1 week
  rules:
    - if: $CI_COMMIT_TAG
    - if: $CI_PIPELINE_SOURCE == "schedule"
    - if: $CI_PIPELINE_SOURCE == "push"
      when: manual


# Publish code coverage data on web.
#  * The deploy stage is specially recognized by gitlab
#  * The jobname pages is specially recognized by gitlab
#  * The public/ directory is specially recognized by gitlab
# https://about.gitlab.com/blog/2016/11/03/publish-code-coverage-report-with-gitlab-pages/
pages:
  stage: deploy
  dependencies:
    - coverage-combine
    - doc
  script:
    - mkdir public
    - mv coverage-html public/
    - pwd
    - ls
    - mv web-html/* public/
  artifacts:
    paths:
      - public
    expire_in: 2 weeks
  only:
    - master

lint:
  image: python:3.12.4-alpine
  before_script:
    - pip install .[lint]
    - pip freeze
  script:
    - mypy --version
    - mypy --color-output -p ase
    - python -We:invalid -m compileall -f -q ase/
    - ruff check
    - ruff format --check
  variables:
    PIP_CACHE_DIR: "$CI_PROJECT_DIR/pip-cache"
  cache:
    paths:
      - $PIP_CACHE_DIR
    key: lint

coverage-combine:
  image: registry.gitlab.com/ase/ase:ase-paperwork
  stage: paperwork
  dependencies:
    - main
    - calculators-lite
  script:
    - cd ase/test # Next to .coveragerc and friends
    - coverage combine ../../coverage-main/coverage.dat ../../coverage-calculators-lite/coverage.dat
    - coverage report
    - coverage html
    - cd ../..
    - mv ase/test/coverage-html .
  coverage: '/TOTAL.+ ([0-9]+\.[0-9]+%)/'
  artifacts:
    paths:
      - coverage-html
    expire_in: 1 week

.windows_test:
  tags:
    - saas-windows-medium-amd64
  stage: test
  before_script:
    # https://stackoverflow.com/questions/61791108/gitlab-ci-shared-windows-runner-for-python
    # https://gitlab.com/gitlab-org/ci-cd/shared-runners/images/gcp/windows-containers/-/issues/13
    - Import-Module "$env:ChocolateyInstall\helpers\chocolateyProfile.psm1"
    - choco install python --version=3.9 -y -f
    - refreshenv
    - python --version
    - python -m pip install --upgrade pip
    - python -m pip install pytest
    - python -m pip install .
  script:
    - >
      ase test
      --calculators eam,ff,lj,morse,tip3p,tip4p
      --pytest
      -W "ignore:The --rsyncdir command line argument"
      -W "ignore:NumPy will stop allowing conversion of out-of-bound Python integers"
  rules:
    - if: $CI_PIPELINE_SOURCE == "push"
      when: manual
      allow_failure: true
    - if: $CI_PIPELINE_SOURCE == "schedule"
