workflow:
  rules:
  - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
    when: never
  - when: always

# Functions that should be executed before the build script is run

variables:
  HELM_VERSION: "3.13.3"
  IMAGE_NAME: "df-wiki"
  # dev
  HOST_DEV: 'defense-finder.dev.pasteur.cloud'
  MEILI_HOST_DEV: 'defense-finder-meilisearch.dev.pasteur.cloud'
  # prod
  HOST_PROD: "https://defense-finder.pasteur.cloud"
  MEILI_HOST_PROD: 'defense-finder-meilisearch.pasteur.cloud'
  PIP_CACHE_DIR: "$CI_PROJECT_DIR/.cache/pip"



cache:
  paths:
    - node_modules/
    - .output/public
    

stages:
  - build-df-cli
  - deploy-meilisearch
  - zotero
  - get-meili-key
  - build
  # - build-wiki
  - delete-release
  - lint
  - update-meilisearch-indexes
  - deploy
  - post-deploy

.docker-login: &docker-login
  - i=0; while [ "$i" -lt 12 ]; do docker info && break; sleep 5; i=$(( i + 1 )) ; done
  - docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY



# Build df-wiki-cli package


.df-wiki-cli-run:
  image: python:3.11-bullseye
  cache:                      # Pip's cache doesn't store the python packages
    paths:                    # https://pip.pypa.io/en/stable/topics/caching/
      - .cache/pip
  before_script:
    - pip install df-wiki-cli --index-url https://gitlab-ci-token:${CI_JOB_TOKEN}@gitlab.pasteur.fr/api/v4/projects/5222/packages/pypi/simple

build:df-wiki-cli:
  image: python:3.11-bullseye
  stage: build-df-cli
  before_script:
    - cd packages/df-wiki-cli/
    - pip install poetry
    - poetry install
    - source `poetry env info --path`/bin/activate

  script:
    - echo "This is the build stage"
    - poetry config repositories.gitlab "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/pypi"
    - poetry config http-basic.gitlab gitlab-ci-token "$CI_JOB_TOKEN"
    - echo "Repository gitlab configured ..."
    - poetry build
    - echo "Build done ..."
    - poetry publish --repository gitlab --skip-existing
    - echo "Publishing done!"
  when: manual
  allow_failure: true
################ DEPLOY MEILISEARCH #################

.deploy:meilisearch:
  stage: deploy-meilisearch
  image: harbor.pasteur.fr/kube-system/helm-kubectl:$HELM_VERSION
  variables:
    CI_DEBUG_TRACE: "false"
    ENV: development
  before_script:
    - helm dependency update deploy/meilisearch/ 
  script: 
    - >
      helm upgrade --install 
      ${CI_PROJECT_NAME}-${CI_ENVIRONMENT_NAME}-meilisearch 
      ./deploy/meilisearch 
      --namespace=${KUBE_NAMESPACE}
      --set meilisearch.ingress.hosts[0]=${PUBLIC_URL}
      --set meilisearch.environment.MEILI_MASTER_KEY=${MEILI_MASTER_KEY}
      --set meilisearch.environment.MEILI_ENV=${ENV:-development}
      --set env=${ENV:-development}
      --values deploy/meilisearch/values.yaml
      --values deploy/meilisearch/values.${ENV:-development}.yaml
    # wait for it to start
    # - MEILI_POD=$(kubectl -n=${KUBE_NAMESPACE} get po -l app.kubernetes.io\/instance=${CI_PROJECT_NAME}-${CI_ENVIRONMENT_NAME}-meilisearch,app.kubernetes.io\/name=meilisearch --output jsonpath='{.items[0].metadata.name}')
    # - |
    #   until kubectl -n=${KUBE_NAMESPACE} wait --for=condition=ready pod ${MEILI_POD} --timeout=1s
    #   do
    #     date
    #     sleep 1
    #     kubectl -n=${KUBE_NAMESPACE} get po
    #   done
  when: manual


deploy:meilisearch:dev:
  extends: .deploy:meilisearch
  rules:
    - if: $CI_COMMIT_BRANCH != "main"
  variables:
    CI_DEBUG_TRACE: "true"
    ENV: "development"
    PUBLIC_URL: "$MEILI_HOST_DEV"
    KUBE_NAMESPACE: "defense-finder-dev"

  environment:
      name: k8sdev-01
      url: "https://${MEILI_HOST_DEV}"


deploy:meilisearch:prod:
  extends: .deploy:meilisearch
  rules:
    - if: $CI_COMMIT_BRANCH == "main"
  variables:
    CI_DEBUG_TRACE: "false"
    ENV: "production"
    PUBLIC_URL: $MEILI_HOST_PROD
    KUBE_NAMESPACE: "defense-finder-prod"
  environment:
      name: k8sprod-02
      url: "https://${MEILI_HOST_PROD}"


############### DELETE RELEASE

delete-meili-helm-release:
  rules:
    - if: $CI_COMMIT_BRANCH != "main"
  stage: delete-release
  when: manual
  image: harbor.pasteur.fr/kube-system/helm-kubectl:$HELM_VERSION
  variables:
    GIT_STRATEGY: none # important to not checkout source when branch is deleted
    NAMESPACE: "defense-finder-dev"
  environment:
    name: "k8sdev-01"
    action: stop
  script:
    - echo "Removing $CI_PROJECT_NAME-$CI_ENVIRONMENT_NAME-meilisearch"
    - helm delete -n ${NAMESPACE} ${CI_PROJECT_NAME}-${CI_ENVIRONMENT_NAME}-meilisearch 


delete-meili-helm-release:prod:
  rules:
    - if: $CI_COMMIT_BRANCH == "main"
  stage: delete-release
  when: manual
  image: harbor.pasteur.fr/kube-system/helm-kubectl:$HELM_VERSION
  variables:
    GIT_STRATEGY: none # important to not checkout source when branch is deleted
    NAMESPACE: "defense-finder-prod"
  environment:
    name: "k8sprod-02"
    action: stop
  script:
    - echo "Removing $CI_PROJECT_NAME-$CI_ENVIRONMENT_NAME-meilisearch"
    - helm delete -n ${NAMESPACE} ${CI_PROJECT_NAME}-${CI_ENVIRONMENT_NAME}-meilisearch 


# lint

lint:
  extends: .df-wiki-cli-run
  stage: lint
  script:
    - cd content/3.defense-systems
    - find . -name '*.md' ! -name '0.index.md' | sort | xargs -I {} df-wiki-cli content lint --file {}
  when: manual

# Update Meili search indexes + generate some file that goes to meilisearch
.update-meilisearch-index:
  extends: .df-wiki-cli-run
  stage: update-meilisearch-indexes
  variables:
    MEILI_HOST: "http://localhost:7700"
  script:
    # - rm data/list-systems.json
    ###### REFSEQ
    # delete all document refseq
    - >
      df-wiki-cli
      meilisearch 
      --host ${MEILI_HOST} 
      --key ${MEILI_MASTER_KEY}
      delete-all-documents refseq
    # update refseq index
    - >
      df-wiki-cli meilisearch 
      --host ${MEILI_HOST} 
      --key ${MEILI_MASTER_KEY}
      index-update refseq sys_id
    - >
      df-wiki-cli
      meilisearch 
      --host ${MEILI_HOST} 
      --key ${MEILI_MASTER_KEY}
      update
      --file data/refseq_res.csv
      --document refseq 
    # REF SEQ TAXO #
    - >
      df-wiki-cli 
      content 
      refseq-group-per-assembly
      --input data/refseq_res.csv
      --output data/refseqtaxo.csv
    - >
      df-wiki-cli
      meilisearch 
      --host ${MEILI_HOST} 
      --key ${MEILI_MASTER_KEY}
      delete-all-documents refseqtaxo
    - >
      df-wiki-cli meilisearch 
      --host ${MEILI_HOST} 
      --key ${MEILI_MASTER_KEY}
      index-update refseqtaxo Assembly
    - >
      df-wiki-cli
      meilisearch 
      --host ${MEILI_HOST} 
      --key ${MEILI_MASTER_KEY}
      update
      --file data/refseqtaxo.csv
      --document refseqtaxo
    # REFSEQ TAXO TYPE #
    - >
      df-wiki-cli 
      content 
      refseq-group-per-assembly-and-type      
      --input data/refseq_res.csv
      --output data/refseqtaxotype.csv
    - >
      df-wiki-cli
      meilisearch 
      --host ${MEILI_HOST} 
      --key ${MEILI_MASTER_KEY}
      delete-all-documents refseqtaxotype
    - >
      df-wiki-cli meilisearch 
      --host ${MEILI_HOST} 
      --key ${MEILI_MASTER_KEY}
      index-update refseqtaxotype index
    - >
      df-wiki-cli
      meilisearch 
      --host ${MEILI_HOST} 
      --key ${MEILI_MASTER_KEY}
      update
      --file data/refseqtaxotype.csv
      --document refseqtaxotype
    # SANITIZED REFSEQ
    - >
      df-wiki-cli 
      content 
      refseq-sanitized-hits
      --input data/refseq_res.csv
      --output data/refseq-sanitized.csv
    - >
      df-wiki-cli
      meilisearch 
      --host ${MEILI_HOST} 
      --key ${MEILI_MASTER_KEY}
      delete-all-documents refseqsanitized
    - >
      df-wiki-cli meilisearch 
      --host ${MEILI_HOST} 
      --key ${MEILI_MASTER_KEY}
      index-update refseqsanitized index
    - >
      df-wiki-cli
      meilisearch 
      --host ${MEILI_HOST} 
      --key ${MEILI_MASTER_KEY}
      update
      --file data/refseq-sanitized.csv
      --document refseqsanitized 
    # SYSTEMS
    - >
      df-wiki-cli 
      content systems 
      --dir content/3.defense-systems/ 
      --pfam public/pfam-a-hmm.csv 
      --output data/list-systems.json
    - >
      df-wiki-cli
      meilisearch 
      --host ${MEILI_HOST} 
      --key ${MEILI_MASTER_KEY}
      update
      --file data/list-systems.json
      --document systems
    # STRUCTURE
    - >
      df-wiki-cli
      meilisearch 
      --host ${MEILI_HOST} 
      --key ${MEILI_MASTER_KEY}
      update
      --file data/all_predictions_statistics_clean.csv
      --document structure
    # ARTICLES
    - > 
      df-wiki-cli
      meilisearch 
      --host ${MEILI_HOST} 
      --key ${MEILI_MASTER_KEY}
      delete-all-documents article
    - >
      df-wiki-cli
      meilisearch 
      --host ${MEILI_HOST} 
      --key ${MEILI_MASTER_KEY}
      update
      --file zot-articles.json
      --document article



  allow_failure: false
  when: manual


update-meilisearch-index:dev:
  rules:
    - if: $CI_COMMIT_BRANCH != "main"
  extends: .update-meilisearch-index
  variables:
    MEILI_HOST: "https://${MEILI_HOST_DEV}"


update-meilisearch-index:prod:
  rules:
    - if: $CI_COMMIT_BRANCH == "main"
  extends: .update-meilisearch-index
  variables:
    MEILI_HOST: "https://${MEILI_HOST_PROD}"

############# get-meili-key ###############

.set-meili-env:
  extends: .df-wiki-cli-run
  stage: get-meili-key
  variables:
    MEILI_HOST: "http://localhost:7700"
    MEILI_HOST_NO_PROTOCOLE: "localhost:7700"
  script:
    - > 
      df-wiki-cli 
      meilisearch 
      --key "${MEILI_MASTER_KEY}" 
      --host ${MEILI_HOST_NO_PROTOCOLE} 
      get-env-var
      --output build.env
  artifacts:
      reports:
        dotenv: build.env
  allow_failure: false


set-meili-env:dev:
  extends: .set-meili-env
  variables:
    MEILI_HOST: "https://${MEILI_HOST_DEV}"
    MEILI_HOST_NO_PROTOCOLE: ${MEILI_HOST_DEV}
  rules:
    - if: $CI_COMMIT_BRANCH != "main"  

set-meili-env:prod:
  extends: .set-meili-env
  variables:
    MEILI_HOST: "https://${MEILI_HOST_PROD}"
    MEILI_HOST_NO_PROTOCOLE: ${MEILI_HOST_PROD}

  rules:
    - if: $CI_COMMIT_BRANCH == "main"  

##############################
sync-zotero:
  extends: .df-wiki-cli-run
  stage: zotero
  script:
    - df-wiki-cli articles missing-doi --dir ./content/ --key ${ZOTERO_API_KEY}
    - df-wiki-cli articles fetch-from-zotero --key ${ZOTERO_API_KEY} --output zot-articles.json
  artifacts:
    paths:
      - zot-articles.json
  rules:
    - if: $CI_COMMIT_BRANCH == "main" || $CI_COMMIT_BRANCH == "dev"


################ BUILD ##########################

.build:
  stage: build
  image: docker:24
  variables:
    CONTEXT: "."
    DOCKERFILE: "Dockerfile"
    BASE_URL: /
    MEILI_HOST: "http://localhost:7700"
  before_script:
    - *docker-login
  script:
    - echo $MEILI_HOST
    - echo $MEILI_API_KEY
    - >
      docker buildx build --pull -t "$CI_REGISTRY_IMAGE/$IMAGE_NAME:$CI_COMMIT_SHORT_SHA" 
      --build-arg "BASE_URL=$BASE_URL" 
      --build-arg "MEILI_HOST=$MEILI_HOST" 
      --build-arg "MEILI_API_KEY=$MEILI_API_KEY"
      -f $DOCKERFILE $CONTEXT
    - docker push "$CI_REGISTRY_IMAGE/$IMAGE_NAME:$CI_COMMIT_SHORT_SHA"



build:dev:wiki:
  extends: .build
  needs:
    - set-meili-env:dev
    # - get-pfam
  variables:
    BASE_URL: /wiki/
    HOST_URL: https://${HOST_DEV}
  before_script:
    - *docker-login
    # - "sed -i 's/MEILISEARCH_API_KEY/${$MEILI_API_KEY}/g' nuxt.config.ts"
  rules:
    - if: $CI_COMMIT_BRANCH != "main"  


build:prod:wiki:
  extends: .build
  needs:
    - set-meili-env:prod
    - sync-zotero
    # - get-pfam
  variables:
    BASE_URL: /wiki/
    HOST_URL: https://${HOST_PROD}

  rules:
    - if: $CI_COMMIT_BRANCH == "main"  




################ DEPLOY ##########################
.deploy:
  stage: deploy
  image: harbor.pasteur.fr/kube-system/helm-kubectl:$HELM_VERSION
  variables:
    CI_DEBUG_TRACE: "false"
    TEAM_ID: "df"
  script:
    - >
      helm upgrade --install $CI_PROJECT_NAME-$CI_ENVIRONMENT_NAME ./deploy/df-wiki --namespace=${KUBE_NAMESPACE}
      --set registry.image=${CI_REGISTRY_IMAGE}
      --set registry.username=${DEPLOY_USER}
      --set registry.password=${DEPLOY_TOKEN}
      --set registry.host=${CI_REGISTRY}
      --set ingress.hosts[0].host="${PUBLIC_URL}"
      --set imagePullSecrets[0].name="registry-pull-secret-${CI_COMMIT_REF_SLUG}"
      --set image.repository="$CI_REGISTRY_IMAGE/$IMAGE_NAME"
      --set image.tag="$CI_COMMIT_SHORT_SHA"
      --set env="${ENV:-development}"
      --values deploy/df-wiki/values.yaml
      --values deploy/df-wiki/values.${ENV:-development}.yaml
  after_script:
    - sleep 30
    - kubectl --namespace ${KUBE_NAMESPACE} wait pod -l "app.kubernetes.io/name=df-wiki" --for condition=Ready --timeout=600s 
    - echo "Wiki pod is ready"
    - WIKI_POD=$(kubectl --namespace ${KUBE_NAMESPACE} get pods -l "app.kubernetes.io/name=df-wiki" --output jsonpath='{.items[0].metadata.name}')
    - echo ${WIKI_POD}
    - kubectl --namespace ${KUBE_NAMESPACE} exec ${WIKI_POD} -- rsync -avz /public-website/ /usr/share/nginx/html/
    
    

deploy:dev:
  extends: .deploy
  rules:
    - if: $CI_COMMIT_BRANCH == "dev" || $CI_COMMIT_BRANCH == "distri-system-section"
  needs:
    - "build:dev:wiki"
  when: manual
  variables:
    NODE_ENV: "development"
    KUBE_NAMESPACE: "defense-finder-dev"
    PUBLIC_URL: "${HOST_DEV}"
    CI_DEBUG_TRACE: "true"
    ENV: "development"
  environment:
    name: k8sdev-01
    url: "https://${HOST_DEV}"


deploy:prod:
  extends: .deploy
  rules:
    - if: $CI_COMMIT_BRANCH == "main"
  needs:
    - "build:prod:wiki"
  when: manual
  variables:
    NODE_ENV: "production"
    KUBE_NAMESPACE: "defense-finder-prod"
    PUBLIC_URL: "${HOST_PROD}"
    CI_DEBUG_TRACE: "false"
    ENV: "production"
  environment:
    name: k8sprod-02
    url: "https://${HOST_PROD}"

delete-helm-release:dev:
  rules:
    - if: $CI_COMMIT_BRANCH != "main"
  stage: delete-release
  when: manual
  image: harbor.pasteur.fr/kube-system/helm-kubectl:$HELM_VERSION
  variables:
    GIT_STRATEGY: none # important to not checkout source when branch is deleted
    NAMESPACE: "defense-finder-dev"
  environment:
    name: "k8sdev-01"
    action: stop
  script:
    - echo "Removing $CI_PROJECT_NAME-$CI_ENVIRONMENT_NAME"
    - helm delete -n ${NAMESPACE} $CI_PROJECT_NAME-$CI_ENVIRONMENT_NAME

delete-helm-release:prod:
  rules:
    - if: $CI_COMMIT_BRANCH == "main"
  stage: delete-release
  when: manual
  image: harbor.pasteur.fr/kube-system/helm-kubectl:$HELM_VERSION
  variables:
    GIT_STRATEGY: none # important to not checkout source when branch is deleted
    NAMESPACE: "defense-finder-prod"
  environment:
    name: "k8sprod-02"
    action: stop
  script:
    - echo "Removing $CI_PROJECT_NAME-$CI_ENVIRONMENT_NAME"
    - helm delete -n ${NAMESPACE} $CI_PROJECT_NAME-$CI_ENVIRONMENT_NAME



.create-structures-archives:
  stage: post-deploy
  image: harbor.pasteur.fr/kube-system/helm-kubectl:$HELM_VERSION
  when: manual
  variables:
    CI_DEBUG_TRACE: "false"
    TEAM_ID: "df"
  script:
    - kubectl --namespace ${KUBE_NAMESPACE} wait pod -l "app.kubernetes.io/name=df-wiki" --for condition=Ready --timeout=600s 
    - echo "Wiki pod is ready"
    - WIKI_POD=$(kubectl --namespace ${KUBE_NAMESPACE} get pods -l "app.kubernetes.io/name=df-wiki" --output jsonpath='{.items[0].metadata.name}')
    - echo ${WIKI_POD}
    # - kubectl --namespace ${KUBE_NAMESPACE} exec ${WIKI_POD} -- rsync -avz /public-website/ /usr/share/nginx/html/
    - kubectl --namespace ${KUBE_NAMESPACE} exec ${WIKI_POD} -- bash -c "cd /usr/share/nginx/html/ && find ./ -name '*.pdb' -exec tar -czvf /usr/share/nginx/html/df-all-pdbs.tar.gz {} +"
    - kubectl --namespace ${KUBE_NAMESPACE} exec ${WIKI_POD} -- bash -c "cd /usr/share/nginx/html/ && find ./ -name '*.cif' -exec tar -czvf /usr/share/nginx/html/df-all-cifs.tar.gz {} +"


create-structures-archives:dev:
  extends: .create-structures-archives
  rules:
    - if: $CI_COMMIT_BRANCH != "main"  
  needs:
    - "deploy:dev"
  variables:
    NODE_ENV: "development"
    KUBE_NAMESPACE: "defense-finder-dev"
    PUBLIC_URL: "${HOST_DEV}"
    CI_DEBUG_TRACE: "true"
    ENV: "development"
  environment:
    name: k8sdev-01
    url: "https://${HOST_DEV}"


create-structures-archives:prod:
  extends: .create-structures-archives
  rules:
    - if: $CI_COMMIT_BRANCH == "main"  
  needs:
    - "deploy:prod"
  variables:
    NODE_ENV: "production"
    KUBE_NAMESPACE: "defense-finder-prod"
    PUBLIC_URL: "${HOST_PROD}"
    CI_DEBUG_TRACE: "false"
    ENV: "production"
  environment:
    name: k8sprod-02
    url: "https://${HOST_PROD}"
