image: ${CI_DEPENDENCY_PROXY_DIRECT_GROUP_IMAGE_PREFIX}/python:3.12-slim

variables:
  FF_NETWORK_PER_BUILD: 1
  PIP_CACHE_DIR: "$CI_PROJECT_DIR/.cache/pip"
  PYTHONPATH: "$CI_PROJECT_DIR"
  CLOWM_UI_URI: "http://localhost"
  CLOWM_S3__URI: "http://localhost"
  CLOWM_S3__ACCESS_KEY: "nonempty"
  CLOWM_S3__SECRET_KEY: "nonempty"
  CLOWM_LIFESCIENCE_OIDC__CLIENT_SECRET: "nonempty"
  CLOWM_LIFESCIENCE_OIDC__CLIENT_ID: "nonempty"
  CLOWM_CLUSTER__SLURM__TOKEN: "nonempty"
  CLOWM_CLUSTER__SLURM__URI: "http://localhost"
  CLOWM_DEV_SYSTEM: true
  CLOWM_CLUSTER__JOB_MONITORING: "LINEAR"
  CLOWM_CLUSTER__ACTIVE_WORKFLOW_EXECUTION_LIMIT: 3
  CLOWM_CLUSTER__TOWER_SECRET: "nonempty"

cache:
  paths:
    - .cache/pip
    - venv/

default:
  tags:
    - docker
  before_script:
    - python --version  # For debugging
    - pip install --disable-pip-version-check virtualenv
    - virtualenv venv
    - source venv/bin/activate
    - python -m pip install --disable-pip-version-check --upgrade -r requirements.txt -r requirements-dev.txt

stages: # List of stages for jobs, and their order of execution
  - lint
  - test
  - deploy-docker-images

lint-test-job: # Runs linters checks on code
  stage: lint
  before_script:
    - python --version  # For debugging
    - pip install --disable-pip-version-check virtualenv
    - virtualenv venv
    - source venv/bin/activate
    - python -m pip install --disable-pip-version-check --upgrade -r requirements.txt -r requirements-dev.txt --upgrade-strategy=eager
  script:
    - ./scripts/lint.sh


integration-test-job: # Runs integration tests with the database
  stage: test
  variables:
    CLOWM_DB__PASSWORD: "$TEST_DB_PASSWORD"
    CLOWM_DB__USER: "test_api_user"
    CLOWM_DB__NAME: "integration-test-db"
    CLOWM_DB__HOST: "integration-test-db"
    CLOWM_S3__URI: "http://integration-test-mock-s3:8000"
  services:
    - name: ${CI_DEPENDENCY_PROXY_DIRECT_GROUP_IMAGE_PREFIX}/mysql:8
      alias: integration-test-db
      variables:
        MYSQL_RANDOM_ROOT_PASSWORD: "yes"
        MYSQL_DATABASE: "$CLOWM_DB__NAME"
        MYSQL_USER: "$CLOWM_DB__USER"
        MYSQL_PASSWORD: "$CLOWM_DB__PASSWORD"
    - name: ${CI_DEPENDENCY_PROXY_DIRECT_GROUP_IMAGE_PREFIX}/motoserver/moto:latest
      alias: integration-test-mock-s3
      variables:
        MOTO_PORT: 8000
        HEALTHCHECK_TCP_PORT: 8000
  script:
    - python clowm/check_ceph_connection.py
    - python clowm/check_database_connection.py
    - pytest --junitxml=integration-report.xml --cov=clowm --cov-report=term-missing clowm/tests/crud
    - mkdir coverage-integration
    - mv .coverage coverage-integration
  artifacts:
    paths:
      - $CI_PROJECT_DIR/coverage-integration/.coverage
    reports:
      junit: $CI_PROJECT_DIR/integration-report.xml

e2e-test-job: # Runs e2e tests on the API endpoints
  stage: test
  variables:
    CLOWM_DB__PASSWORD: "$TEST_DB_PASSWORD"
    CLOWM_DB__USER: "test_api_user"
    CLOWM_DB__NAME: "e2e-test-db"
    CLOWM_DB__HOST: "e2e-test-db"
    CLOWM_S3__URI: "http://e2e-test-mock-s3:8000"
  services:
    - name: ${CI_DEPENDENCY_PROXY_DIRECT_GROUP_IMAGE_PREFIX}/mysql:8
      alias: e2e-test-db
      variables:
        MYSQL_RANDOM_ROOT_PASSWORD: "yes"
        MYSQL_DATABASE: "$CLOWM_DB__NAME"
        MYSQL_USER: "$CLOWM_DB__USER"
        MYSQL_PASSWORD: "$CLOWM_DB__PASSWORD"
    - name: ${CI_DEPENDENCY_PROXY_DIRECT_GROUP_IMAGE_PREFIX}/motoserver/moto:latest
      alias: e2e-test-mock-s3
      variables:
        MOTO_PORT: 8000
        HEALTHCHECK_TCP_PORT: 8000
  script:
    - python clowm/check_ceph_connection.py
    - python clowm/check_database_connection.py
    - pytest --junitxml=e2e-report.xml --cov=clowm --cov-report=term-missing clowm/tests/api
    - mkdir coverage-e2e
    - mv .coverage coverage-e2e
  artifacts:
    paths:
      - $CI_PROJECT_DIR/coverage-e2e/.coverage
    reports:
      junit: $CI_PROJECT_DIR/e2e-report.xml

unit-test-job: # Runs unit tests
  stage: test
  variables:
    CLOWM_DB__PASSWORD: "nonempty"
    CLOWM_DB__USER: "nonempty"
    CLOWM_DB__NAME: "nonempty"
    CLOWM_DB__HOST: "nonempty"
  script:
    - pytest --junitxml=unit-report.xml --cov=clowm --cov-report=term-missing clowm/tests/unit
    - mkdir coverage-unit
    - mv .coverage coverage-unit
  artifacts:
    paths:
      - $CI_PROJECT_DIR/coverage-unit/.coverage
    reports:
      junit: $CI_PROJECT_DIR/unit-report.xml

combine-test-coverage-job: # Combine coverage reports from different test jobs
  stage: test
  needs:
    - job: "e2e-test-job"
      artifacts: true
    - job: "integration-test-job"
      artifacts: true
    - job: "unit-test-job"
      artifacts: true
  script:
    - coverage combine coverage-e2e/.coverage coverage-integration/.coverage coverage-unit/.coverage
    - coverage report
    - coverage xml --data-file=$CI_PROJECT_DIR/.coverage -o coverage.xml
  coverage: '/(?i)total.*? (100(?:\.0+)?\%|[1-9]?\d(?:\.\d+)?\%)$/'
  artifacts:
    reports:
      coverage_report:
        coverage_format: cobertura
        path: $CI_PROJECT_DIR/coverage.xml

.publish-docker-container:
  stage: deploy-docker-images
  image:
    name: gcr.io/kaniko-project/executor:v1.23.0-debug
    entrypoint: [ "" ]
  dependencies: [ ]
  cache: [ ]
  before_script:
    - echo "{\"auths\":{\"${CI_REGISTRY}\":{\"auth\":\"$(printf "%s:%s" "${CI_REGISTRY_USER}" "${CI_REGISTRY_PASSWORD}" | base64 | tr -d '\n')\"},\"$CI_DEPENDENCY_PROXY_SERVER\":{\"auth\":\"$(printf "%s:%s" ${CI_DEPENDENCY_PROXY_USER} "${CI_DEPENDENCY_PROXY_PASSWORD}" | base64 | tr -d '\n')\"}}}" > /kaniko/.docker/config.json

.publish-main-docker-container:
  extends: .publish-docker-container
  only:
    refs:
      - main

publish-main-gunicorn-docker-container-job:
  extends: .publish-main-docker-container
  script:
    - /kaniko/executor
      --context "${CI_PROJECT_DIR}"
      --build-arg "GIT_COMMIT_HASH=${CI_COMMIT_SHA}"
      --dockerfile "${CI_PROJECT_DIR}/Dockerfile-Gunicorn"
      --destination "${CI_REGISTRY_IMAGE}:main-gunicorn-${CI_COMMIT_SHA}"
      --destination "${CI_REGISTRY_IMAGE}:main-gunicorn-latest"

publish-main-uvicorn-docker-container-job:
  extends: .publish-version-docker-container
  script:
    - /kaniko/executor
      --context "${CI_PROJECT_DIR}"
      --build-arg "GIT_COMMIT_HASH=${CI_COMMIT_SHA}"
      --dockerfile "${CI_PROJECT_DIR}/Dockerfile"
      --destination "${CI_REGISTRY_IMAGE}:main-${CI_COMMIT_SHA}"
      --destination "${CI_REGISTRY_IMAGE}:main-latest"

.publish-version-docker-container:
  extends: .publish-docker-container
  only:
    - tags

publish-uvicorn-docker-container-job:
  extends: .publish-version-docker-container
  script:
    - /kaniko/executor
      --context "${CI_PROJECT_DIR}"
      --build-arg "GIT_COMMIT_HASH=${CI_COMMIT_SHA}"
      --dockerfile "${CI_PROJECT_DIR}/Dockerfile"
      --destination "${CI_REGISTRY_IMAGE}:${CI_COMMIT_TAG}"
      --destination "${CI_REGISTRY_IMAGE}:$(echo ${CI_COMMIT_TAG} | cut -d'.' -f1-2)"
      --destination "${CI_REGISTRY_IMAGE}:$(echo ${CI_COMMIT_TAG} | cut -d'.' -f1)"
      --destination "${CI_REGISTRY_IMAGE}:latest"


publish-gunicorn-docker-container-job:
  extends: .publish-version-docker-container
  script:
    - /kaniko/executor
      --context "${CI_PROJECT_DIR}"
      --build-arg "GIT_COMMIT_HASH=${CI_COMMIT_SHA}"
      --dockerfile "${CI_PROJECT_DIR}/Dockerfile-Gunicorn"
      --destination "${CI_REGISTRY_IMAGE}:gunicorn-${CI_COMMIT_TAG}"
      --destination "${CI_REGISTRY_IMAGE}:gunicorn-$(echo ${CI_COMMIT_TAG} | cut -d'.' -f1-2)"
      --destination "${CI_REGISTRY_IMAGE}:gunicorn-$(echo ${CI_COMMIT_TAG} | cut -d'.' -f1)"
      --destination "${CI_REGISTRY_IMAGE}:gunicorn-latest"