image: docker:latest

variables:
  IMAGE_BASE: "$CI_REGISTRY/$CI_PROJECT_NAMESPACE/$CI_PROJECT_NAME"
  DOCKER_BUILDKIT: 1

stages:
  - prep
  - build
  - test
  - deliver
  - deploy

preparation:
  stage: prep
  tags:
    - dev
  script:
    - export BUILD_ID=$(date +%Y%m%d%H%M)
    - echo "BUILD_ID=${BUILD_ID}" > context.env

    - echo "FLIGHTS_INFO_PROD_IMAGE_NAME=${IMAGE_BASE}/flights-information:prod-${BUILD_ID}"       >> context.env
    - echo "FLIGHTS_INFO_TEST_IMAGE_NAME=${IMAGE_BASE}/flights-information:test-${BUILD_ID}"       >> context.env

    - echo "GATEWAY_PROD_IMAGE_NAME=${IMAGE_BASE}/gateway:prod-${BUILD_ID}"       >> context.env
    - echo "GATEWAY_TEST_IMAGE_NAME=${IMAGE_BASE}/gateway:test-${BUILD_ID}"       >> context.env

    - echo "USER_MANAGER_PROD_IMAGE_NAME=${IMAGE_BASE}/user-manager:prod-${BUILD_ID}"       >> context.env
    - echo "USER_MANAGER_TEST_IMAGE_NAME=${IMAGE_BASE}/user-manager:test-${BUILD_ID}"       >> context.env

    - echo "SCREEN_CLIENT_PROD_IMAGE_NAME=${IMAGE_BASE}/screens-client:prod-${BUILD_ID}" >> context.env
    - echo "SCREEN_CLIENT_TEST_IMAGE_NAME=${IMAGE_BASE}/screens-client:test-${BUILD_ID}" >> context.env

    - echo "BROWSER_CLIENT_PROD_IMAGE_NAME=${IMAGE_BASE}/browser-client:prod-${BUILD_ID}" >> context.env
    - echo "BROWSER_CLIENT_TEST_IMAGE_NAME=${IMAGE_BASE}/browser-client:test-${BUILD_ID}" >> context.env

    - echo "DOCKER_HUB_SCREEN_CLIENT_IMAGE=$DOCKER_HUB_USER/screens-client:${BUILD_ID}"         >> context.env
    - echo "DOCKER_HUB_BROWSER_CLIENT_IMAGE=$DOCKER_HUB_USER/browser-client:${BUILD_ID}"         >> context.env
    - echo "DOCKER_HUB_USER_MANAGER_IMAGE=$DOCKER_HUB_USER/user-manager:${BUILD_ID}"         >> context.env
    - echo "DOCKER_HUB_FLIGHT_INFO_IMAGE=$DOCKER_HUB_USER/flights-information:${BUILD_ID}"         >> context.env

    - echo "ENV_DEV_FILE=$(echo $ENV_DEV)"     >> context.env
    - echo "ENV_PROD_FILE=$(echo $ENV_PROD)"   >> context.env
  artifacts: 
    paths: 
      - context.env

build-auth-api:
  stage: build
  tags:
    - dev
  script:
    - export $(cat context.env | xargs)

    - export USER_MANAGER=auth-domain/user-manager
    - docker build $USER_MANAGER -f $USER_MANAGER/Dockerfile.prod -t ${USER_MANAGER_PROD_IMAGE_NAME}
    - docker build $USER_MANAGER -f $USER_MANAGER/Dockerfile.test --build-arg "BASE_IMAGE=$USER_MANAGER_PROD_IMAGE_NAME" -t ${USER_MANAGER_TEST_IMAGE_NAME}

    - docker login -u $CI_REGISTRY_USER --password $CI_JOB_TOKEN $CI_REGISTRY

    - docker push ${USER_MANAGER_PROD_IMAGE_NAME}
    - docker push ${USER_MANAGER_TEST_IMAGE_NAME}
  needs:
    - job: preparation
      artifacts: true

build-flights-api:
  stage: build
  tags:
    - dev
  script:
    - export $(cat context.env | xargs)

    - export FLIGHTS_INFORMATION=flights-domain/flights-information
    - docker build $FLIGHTS_INFORMATION -f $FLIGHTS_INFORMATION/Dockerfile.prod -t ${FLIGHTS_INFO_PROD_IMAGE_NAME}
    - docker build $FLIGHTS_INFORMATION -f $FLIGHTS_INFORMATION/Dockerfile.test --build-arg "BASE_IMAGE=$FLIGHTS_INFO_PROD_IMAGE_NAME" -t ${FLIGHTS_INFO_TEST_IMAGE_NAME}

    - docker login -u $CI_REGISTRY_USER --password $CI_JOB_TOKEN $CI_REGISTRY

    - docker push ${FLIGHTS_INFO_PROD_IMAGE_NAME}
    - docker push ${FLIGHTS_INFO_TEST_IMAGE_NAME}
  needs:
    - job: preparation
      artifacts: true

build-browser-client:
  stage: build
  tags:
    - dev
  script:
    - export $(cat context.env | xargs)

    - docker build browser-domain -f browser-domain/Dockerfile.prod -t ${BROWSER_CLIENT_PROD_IMAGE_NAME}
    - docker build browser-domain -f browser-domain/Dockerfile.test -t ${BROWSER_CLIENT_TEST_IMAGE_NAME}

    - docker login -u $CI_REGISTRY_USER --password $CI_JOB_TOKEN $CI_REGISTRY

    - docker push ${BROWSER_CLIENT_PROD_IMAGE_NAME}
    - docker push ${BROWSER_CLIENT_TEST_IMAGE_NAME}
  needs:
    - job: preparation
      artifacts: true

build-screen-client:
  stage: build
  tags:
    - dev
  script:
    - export $(cat context.env | xargs)

    - docker build screen-domain -f screen-domain/Dockerfile.prod -t ${SCREEN_CLIENT_PROD_IMAGE_NAME}
    - docker build screen-domain -f screen-domain/Dockerfile.test -t ${SCREEN_CLIENT_TEST_IMAGE_NAME}

    - docker login -u $CI_REGISTRY_USER --password $CI_JOB_TOKEN $CI_REGISTRY

    - docker push ${SCREEN_CLIENT_PROD_IMAGE_NAME}
    - docker push ${SCREEN_CLIENT_TEST_IMAGE_NAME}
  needs:
    - job: preparation
      artifacts: true

build-gateway:
  stage: build
  tags:
    - dev
  script:
    - export $(cat context.env | xargs)

    - docker build gateway -f gateway/Dockerfile.prod -t ${GATEWAY_PROD_IMAGE_NAME}
    - docker build gateway -f gateway/Dockerfile.test --build-arg "BASE_IMAGE=$GATEWAY_PROD_IMAGE_NAME" -t ${GATEWAY_TEST_IMAGE_NAME}

    - docker login -u $CI_REGISTRY_USER --password $CI_JOB_TOKEN $CI_REGISTRY

    - docker push ${GATEWAY_PROD_IMAGE_NAME}
    - docker push ${GATEWAY_TEST_IMAGE_NAME}
  needs:
    - job: preparation
      artifacts: true

test-auth-api:
  stage: test
  tags:
    - dev
  script:
    - export $(cat context.env | xargs)

    - export API_IMAGE=$USER_MANAGER_TEST_IMAGE_NAME
    - export CLIENT_IMAGE=dummy-image

    - docker login -u $CI_REGISTRY_USER --password $CI_JOB_TOKEN $CI_REGISTRY

    - docker compose -f auth-domain/docker-compose.yml --env-file $ENV_DEV_FILE down
    - docker compose -f auth-domain/docker-compose.yml --env-file $ENV_DEV_FILE pull
    - docker compose -f auth-domain/docker-compose.yml --env-file $ENV_DEV_FILE up --abort-on-container-exit --renew-anon-volumes
    - docker cp fids_usermanager_api:/usr/src/app/coverage.xml .
    - docker cp fids_usermanager_api:/usr/src/app/report.xml .
  artifacts:
    when: always
    paths:
      - coverage.xml
      - report.xml
    reports:
      junit: report.xml
  needs:
    - job: preparation
    - job: build-auth-api
      artifacts: true

test-flights-api:
  stage: test
  tags:
    - dev
  script:
    - export $(cat context.env | xargs)

    - export API_IMAGE=$FLIGHTS_INFO_TEST_IMAGE_NAME
    - export CLIENT_IMAGE=dummy-image

    - docker login -u $CI_REGISTRY_USER --password $CI_JOB_TOKEN $CI_REGISTRY

    - docker compose -f flights-domain/docker-compose.yml --env-file $ENV_DEV_FILE down
    - docker compose -f flights-domain/docker-compose.yml --env-file $ENV_DEV_FILE pull
    - docker compose -f flights-domain/docker-compose.yml --env-file $ENV_DEV_FILE up --abort-on-container-exit --renew-anon-volumes
    - docker cp fids_flights_api:/usr/src/app/coverage.xml .
    - docker cp fids_flights_api:/usr/src/app/report.xml .
  artifacts:
    when: always
    paths:
      - coverage.xml
      - report.xml
    reports:
      junit: report.xml
  needs:
    - job: preparation
    - job: build-flights-api
      artifacts: true

test-gateway:
  stage: test
  tags:
    - dev
  script:
    - export $(cat context.env | xargs)

    - export API_IMAGE=$GATEWAY_TEST_IMAGE_NAME

    - docker login -u $CI_REGISTRY_USER --password $CI_JOB_TOKEN $CI_REGISTRY

    - docker compose -f gateway/docker-compose.yml --env-file $ENV_DEV_FILE down
    - docker compose -f gateway/docker-compose.yml --env-file $ENV_DEV_FILE pull
    - docker compose -f gateway/docker-compose.yml --env-file $ENV_DEV_FILE up --abort-on-container-exit --renew-anon-volumes
    - docker cp fids_api_gateway:/usr/src/app/coverage.xml .
    - docker cp fids_api_gateway:/usr/src/app/report.xml .
  artifacts:
    when: always
    paths:
      - coverage.xml
      - report.xml
    reports:
      junit: report.xml
  needs:
    - job: preparation
    - job: build-gateway
      artifacts: true

test-integration:
  stage: test
  tags:
    - dev
  script:
    - export $(cat context.env | xargs)
    - docker login -u $CI_REGISTRY_USER --password $CI_JOB_TOKEN $CI_REGISTRY

    - export API_IMAGE=$FLIGHTS_INFO_TEST_IMAGE_NAME
    - export TEST_TARGET=INTEGRATION 
    - docker compose -f flights-domain/docker-compose.yml --env-file $ENV_DEV_FILE down
    - docker compose -f flights-domain/docker-compose.yml --env-file $ENV_DEV_FILE pull
    - docker compose -f flights-domain/docker-compose.yml --env-file $ENV_DEV_FILE up -d

    - export API_IMAGE=$GATEWAY_TEST_IMAGE_NAME
    - export TEST_TARGET=INTEGRATION 
    - docker compose -f gateway/docker-compose.yml --env-file $ENV_DEV_FILE down
    - docker compose -f gateway/docker-compose.yml --env-file $ENV_DEV_FILE pull
    - docker compose -f gateway/docker-compose.yml --env-file $ENV_DEV_FILE up -d

    - export API_IMAGE=$USER_MANAGER_TEST_IMAGE_NAME
    - export TEST_TARGET=INTEGRATION 
    - docker compose -f auth-domain/docker-compose.yml --env-file $ENV_DEV_FILE down
    - docker compose -f auth-domain/docker-compose.yml --env-file $ENV_DEV_FILE pull
    - docker compose -f auth-domain/docker-compose.yml --env-file $ENV_DEV_FILE up -d
  needs:
    - job: test-flights-api
    - job: test-auth-api
    - job: preparation
      artifacts: true

test-browser-integration:
  stage: test
  tags:
    - dev
  script:
    - export $(cat context.env | xargs)
    - docker login -u $CI_REGISTRY_USER --password $CI_JOB_TOKEN $CI_REGISTRY

    - export CLIENT_IMAGE=$BROWSER_CLIENT_TEST_IMAGE_NAME
    - docker compose -f browser-domain/docker-compose.yml --env-file $ENV_DEV_FILE down
    - docker compose -f browser-domain/docker-compose.yml --env-file $ENV_DEV_FILE pull
    - docker compose -f browser-domain/docker-compose.yml --env-file $ENV_DEV_FILE up --abort-on-container-exit
  needs:
    - job: test-integration
    - job: build-browser-client
    - job: preparation
      artifacts: true

test-screen-integration:
  stage: test
  tags:
    - dev
  script:
    - export $(cat context.env | xargs)
    - docker login -u $CI_REGISTRY_USER --password $CI_JOB_TOKEN $CI_REGISTRY

    - export CLIENT_IMAGE=$SCREEN_CLIENT_TEST_IMAGE_NAME
    - docker compose -f screen-domain/docker-compose.yml --env-file $ENV_DEV_FILE down
    - docker compose -f screen-domain/docker-compose.yml --env-file $ENV_DEV_FILE pull
    - docker compose -f screen-domain/docker-compose.yml --env-file $ENV_DEV_FILE up --abort-on-container-exit
  needs:
    - job: test-integration
    - job: build-screen-client
    - job: preparation
      artifacts: true

deliver-dockerhub:
  stage: deliver
  tags:
    - dev
  script:
    - export $(cat context.env | xargs)

    - docker login -u $CI_REGISTRY_USER --password $CI_JOB_TOKEN $CI_REGISTRY
    - docker login -u $DOCKER_HUB_USER --password $DOCKER_HUB_PASS

    - export API_IMAGE=$FLIGHTS_INFO_TEST_IMAGE_NAME
    - docker compose -f flights-domain/docker-compose.yml --env-file $ENV_DEV_FILE down
    - export API_IMAGE=$USER_MANAGER_TEST_IMAGE_NAME
    - docker compose -f auth-domain/docker-compose.yml --env-file $ENV_DEV_FILE down
    - export API_IMAGE=$GATEWAY_TEST_IMAGE_NAME
    - docker compose -f gateway/docker-compose.yml --env-file $ENV_DEV_FILE down

    - docker tag $FLIGHTS_INFO_PROD_IMAGE_NAME $DOCKER_HUB_FLIGHT_INFO_IMAGE
    - docker tag $USER_MANAGER_PROD_IMAGE_NAME $DOCKER_HUB_USER_MANAGER_IMAGE
    - docker tag $GATEWAY_PROD_IMAGE_NAME $DOCKER_HUB_GATEWAY_IMAGE
    - docker tag $BROWSER_CLIENT_PROD_IMAGE_NAME $DOCKER_HUB_BROWSER_CLIENT_IMAGE
    - docker tag $SCREEN_CLIENT_PROD_IMAGE_NAME $DOCKER_HUB_SCREEN_CLIENT_IMAGE

    - docker push $DOCKER_HUB_FLIGHT_INFO_IMAGE
    - docker push $DOCKER_HUB_USER_MANAGER_IMAGE
    - docker push $DOCKER_HUB_GATEWAY_IMAGE
    - docker push $DOCKER_HUB_BROWSER_CLIENT_IMAGE
    - docker push $DOCKER_HUB_SCREEN_CLIENT_IMAGE
  needs:
    - job: test-screen-integration
    - job: test-browser-integration
    - job: preparation
      artifacts: true  

deploy-prod:
  stage: deploy
  tags: 
    - prod
  rules:
    - if: $CI_COMMIT_REF_NAME == "master"
      when: on_success
  script:
    - export $(cat context.env | xargs)

    - docker login -u $DOCKER_HUB_USER --password $DOCKER_HUB_PASS

    - export API_IMAGE=$DOCKER_HUB_FLIGHT_INFO_IMAGE
    - docker compose -f flights-domain/docker-compose.yml --env-file $ENV_PROD_FILE stop
    - docker compose -f flights-domain/docker-compose.yml --env-file $ENV_PROD_FILE rm -f
    - docker compose -f flights-domain/docker-compose.yml --env-file $ENV_PROD_FILE pull
    - docker compose -f flights-domain/docker-compose.yml --env-file $ENV_PROD_FILE up -d

    - export API_IMAGE=$DOCKER_HUB_USER_MANAGER_IMAGE
    - docker compose -f auth-domain/docker-compose.yml --env-file $ENV_PROD_FILE stop
    - docker compose -f auth-domain/docker-compose.yml --env-file $ENV_PROD_FILE rm -f
    - docker compose -f auth-domain/docker-compose.yml --env-file $ENV_PROD_FILE pull
    - docker compose -f auth-domain/docker-compose.yml --env-file $ENV_PROD_FILE up -d
    - docker compose -f auth-domain/docker-compose.yml --env-file $ENV_PROD_FILE exec usermanager-api python manage.py recreate_db
    - docker compose -f auth-domain/docker-compose.yml --env-file $ENV_PROD_FILE exec usermanager-api python manage.py seed_db

    - export API_IMAGE=$DOCKER_HUB_GATEWAY_IMAGE
    - docker compose -f gateway/docker-compose.yml --env-file $ENV_PROD_FILE stop
    - docker compose -f gateway/docker-compose.yml --env-file $ENV_PROD_FILE rm -f
    - docker compose -f gateway/docker-compose.yml --env-file $ENV_PROD_FILE pull
    - docker compose -f gateway/docker-compose.yml --env-file $ENV_PROD_FILE up -d

    - export CLIENT_IMAGE=$DOCKER_HUB_SCREEN_CLIENT_IMAGE
    - docker compose -f screen-domain/docker-compose.yml stop
    - docker compose -f screen-domain/docker-compose.yml rm -f
    - docker compose -f screen-domain/docker-compose.yml pull
    - docker compose -f screen-domain/docker-compose.yml up -d
    - export CLIENT_IMAGE=$DOCKER_HUB_BROWSER_CLIENT_IMAGE
    - docker compose -f browser-domain/docker-compose.yml stop
    - docker compose -f browser-domain/docker-compose.yml rm -f
    - docker compose -f browser-domain/docker-compose.yml pull
    - docker compose -f browser-domain/docker-compose.yml up -d
  needs:
    - job: deliver-dockerhub
    - job: preparation
      artifacts: true