workflow:
  rules:
    - if: >-
        $CI_COMMIT_BRANCH == "staging" || $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
      when: always
    - when: never

variables:
  DOCKER_VERSION: '20.10.17'
  MONGO_VERSION: '4.4'
  K8S_NAMESPACE: 'todoapp-devops'
  GOOGLE_CLOUD_SDK_IMAGE_VERSION: '400.0.0'
  GCP_COMPUTE_REGION: 'europe-west4a'
  CONTAINER_TAG: '${CI_REGISTRY_IMAGE}:${CI_PIPELINE_IID}-${CI_COMMIT_SHORT_SHA}'

stages:
  - test
  - build
  - release
  - deploy

.gke-initialization:
    before_script:
    - echo $BASE64_GOOGLE_CREDENTIALS | base64 -d > ~/service_account.json
    - gcloud auth activate-service-account --key-file ~/service_account.json
    - gcloud config set project ${GCP_PROJECT_ID}
    - gcloud config set compute/zone ${GCP_COMPUTE_REGION}
    - gcloud container clusters get-credentials ${GCP_PROJECT_ID}-gke

run-tests:
  stage: test
  tags:
    - docker-privileged
    # - docker
  image: docker:${DOCKER_VERSION}
  # image:  node:16.17.0-alpine
  services:
    - name: docker:${DOCKER_VERSION}-dind
  script:
    - docker run -p 27017:27017 -d --name mongo-container --rm --add-host=host.docker.internal:host-gateway mongo:${MONGO_VERSION}
    - docker build
      --tag "${CONTAINER_TAG}-test"
      --target=test
      "./app"
    # - echo ‘http://dl-cdn.alpinelinux.org/alpine/v3.6/main’ >> /etc/apk/repositories
    # - echo ‘http://dl-cdn.alpinelinux.org/alpine/v3.6/community’ >> /etc/apk/repositories
    # - apk update
    # - apk add mongodb mongodb-tools
    # - mkdir -p /data/db/
    # - mongod --config "./app/server/dev.mongo.conf"
    # - cd "./app/client"
    # - npm ci --no-audit --no-fund
    # - npm run test
    # - cd "../server"
    # - npm ci --no-audit --no-fund
    # - MONGODB_URL=mongodb://localhost:27017/todo-app JWT_SECRET=a-big-secret npm run test
    # - jest --ci
  after_script:
    - docker stop mongo-container
    - docker images -a | grep "mongo" | awk '{print $3}' | xargs docker rmi --force
    - docker image rm --force "${CONTAINER_TAG}-test"

build-image:
  stage: build
  needs:
    - 'run-tests'
  tags:
    - docker-privileged
  image: docker:${DOCKER_VERSION}
  services:
    - name: docker:${DOCKER_VERSION}-dind
  before_script:
    - docker login -u ${CI_REGISTRY_USER} -p ${CI_REGISTRY_PASSWORD} ${CI_REGISTRY}
  script:
    - docker image build
      --tag "${CONTAINER_TAG}"
      "./app"
    # - docker image build
    #   --tag "${CONTAINER_TAG}-google-sdk"
    #   "./gcloud-image"
    - docker push "${CONTAINER_TAG}"
    # - docker push "${CONTAINER_TAG}-google-sdk"
  after_script:
    - docker image rm --force "${CONTAINER_TAG}"
    # - docker image rm --force "${CONTAINER_TAG}-google-sdk"

create-release_image:
  stage: release
  tags:
    - docker-privileged
  image: docker:${DOCKER_VERSION}
  services:
    - name: docker:${DOCKER_VERSION}-dind
  before_script:
    - docker login -u ${CI_REGISTRY_USER} -p ${CI_REGISTRY_PASSWORD} ${CI_REGISTRY}
    - docker pull "${CONTAINER_TAG}"
  script:
    - VERSION=$(cat ./app/client/package.json | docker run --interactive stedolan/jq --raw-output '.version')
    - docker tag "${CONTAINER_TAG}" "${CI_REGISTRY_IMAGE}:${VERSION}"
    - docker push "${CI_REGISTRY_IMAGE}:${VERSION}"
  after_script:
    - docker image rm --force
        $(docker images --format '{{.Repository}}{{.Tag}}' | grep '${CI_REGISTRY_IMAGE}')

# create-release_tag:
#   stage: release
#   needs:
#     - 'create-release_image'
#   rules:
#     - if: $CI_COMMIT_REF_NAME =~ /main/
#       when: 'always'
#   tags:
#     - docker-privileged
#   image: docker:${DOCKER_VERSION}-git
#   services:
#     - name: docker:${DOCKER_VERSION}-dind
#   script:
#     - VERSION=$(cat ./src/package.json | docker run --interactive stedolan/jq --raw-output '.version')
#     - echo ${VERSION}
#     #- git tag "v${VERSION}" && git push origin "v${VERSION}"


deploy-image:
  extends: .gke-initialization
  stage: deploy
  needs:
    - 'build-image'
  rules:
    - if: $CI_COMMIT_REF_NAME =~ /staging/
      when: 'always'
      variables:
        ENVIRONMENT_NAME: 'staging'
    - if: $CI_COMMIT_REF_NAME !~ /main/
      when: 'always'
      variables:
        ENVIRONMENT_NAME: 'production'
  tags:
    - docker
  image: google/cloud-sdk:${GOOGLE_CLOUD_SDK_IMAGE_VERSION}
  script:
    - VERSION="${CI_PIPELINE_IID}-${CI_COMMIT_SHORT_SHA}"
    - IMAGE="${CI_REGISTRY_IMAGE}:${VERSION}"
    - cd "app/k8s-manifests"
    - kubectl apply secrets.yaml --namespace "${ENVIRONMENT_NAME}-${K8S_NAMESPACE}"
    - kubectl apply gitlab-registry-credentials.yaml --namespace "${ENVIRONMENT_NAME}-${K8S_NAMESPACE}"
    - kubectl apply configmap.yaml --namespace "${ENVIRONMENT_NAME}-${K8S_NAMESPACE}"
    - kubectl apply deployment.yaml --namespace "${ENVIRONMENT_NAME}-${K8S_NAMESPACE}"
    - kubectl apply service.yaml --namespace "${ENVIRONMENT_NAME}-${K8S_NAMESPACE}"
    - kubectl apply ingress.yaml --namespace "${ENVIRONMENT_NAME}-${K8S_NAMESPACE}"