variables:
  DOCKER_TLS_CERTDIR: "" # HACK: see https://gitlab.com/gitlab-org/gitlab-runner/issues/4501

stages:
  - setup
  - check
  - build
  - deploy

# TODO: maybe stup some notifications as a last stage?

#==[ JOB TEMPLATES ]============================================================

.node-job: &node-job
  image: node:16-alpine
  tags:
    - shared
  only:
    - pushes

.fe-node-job:
  <<: *node-job
  cache:
    key:
      files:
        - frontend/package-lock.json
    paths:
      - frontend/.npm/
  before_script:
    - cd frontend
    - npm ci --cache .npm --prefer-offline

.be-node-job:
  <<: *node-job
  cache:
    key:
      files:
        - backend/package-lock.json
    paths:
      - backend/.npm/
  before_script:
    - cd backend
    - npm ci --cache .npm --prefer-offline

#==[ SETUP STAGE ]==============================================================

#--[ Frontend ]-----------------------------------------------------------------

cache-fe-node-job:
  extends: .fe-node-job
  stage: setup
  script:
    - echo "Done!"

#--[ Backend ]------------------------------------------------------------------

cache-be-node-job:
  extends: .be-node-job
  stage: setup
  script:
    - echo "Done!"

#==[ CHECK STAGE ]==============================================================

#--[ Frontend ]-----------------------------------------------------------------

.check-fe-node-job: &check-fe-node-job
  extends: .fe-node-job
  stage: check
  needs:
    - cache-fe-node-job
  allow_failure: true # TODO: disallow!

format-fe-node-job:
  <<: *check-fe-node-job
  script:
    - npm run format:check

lint-fe-node-job:
  <<: *check-fe-node-job
  script:
    - npm run lint:check

test-fe-node-job:
  <<: *check-fe-node-job
  script:
    - npm run test

#--[ Backend ]------------------------------------------------------------------

.check-be-node-job: &check-be-node-job
  extends: .be-node-job
  stage: check
  needs:
    - cache-be-node-job
  allow_failure: true # TODO: disallow!

format-be-node-job:
  <<: *check-be-node-job
  script:
    - npm run format:check

lint-be-node-job:
  <<: *check-be-node-job
  script:
    - npm run lint:check

test-be-node-job:
  <<: *check-be-node-job
  script:
    - npm run test

#==[ BUILD STAGE ]==============================================================

#--[ Frontend ]-----------------------------------------------------------------

prd-build-fe-node-job:
  extends: .fe-node-job
  stage: build
  variables:
    NODE_ENV: production
    APP_VERSION: ${CI_COMMIT_TAG}
  script:
    - npm run build -- --out-dir dist/prd
  artifacts:
    paths:
      - frontend/dist/prd
    expire_in: 1 week
  only:
    - tags

stg-build-fe-node-job:
  extends: .fe-node-job
  stage: build
  variables:
    NODE_ENV: staging
    APP_VERSION: ${CI_COMMIT_SHORT_SHA}
  script:
    - npm run build -- --out-dir dist/stg
  artifacts:
    paths:
      - frontend/dist/stg
    expire_in: 1 week
  only:
    - development

#--[ Backend ]------------------------------------------------------------------

# TODO: cache docker layers
build-be-job:
  image: docker:20.10.12
  stage: build
  tags:
    - commul # NOTE: we need commul (not shared) because of credentials in environment
  services:
    - docker:dind
  variables:
    IMAGE_NAME: $CI_REGISTRY_IMAGE/backend
  before_script:
    - docker login -u $CI_REGISTRY_USER -p $CI_JOB_TOKEN https://$CI_REGISTRY
  script:
    - >
      docker build
      --rm --no-cache
      --target production
      --tag=$IMAGE_NAME:${CI_COMMIT_SHA}
      --tag=$IMAGE_NAME:${CI_COMMIT_REF_NAME}
      --tag=$IMAGE_NAME:${CI_COMMIT_TAG:-latest}
      --build-arg APP_VERSION=${CI_COMMIT_TAG:-$CI_COMMIT_SHORT_SHA}
      backend
    - docker image push --all-tags $IMAGE_NAME
  only:
    - tags
    - development

#==[ DEPLOY STAGE ]=============================================================

#--[ Frontend ]-----------------------------------------------------------------

.fe-deploy-job:
  image: alpine:latest
  stage: deploy
  tags:
    - commul # NOTE: we can't use shared because extended seccomp policies are needed
  before_script:
    - ./ci/install-butler-on-alpine.sh
  script:
    - >
      butler push
      $DIST_PATH
      eurac/$GAME_NAME:html5
      --userversion ${CI_COMMIT_TAG:-$CI_COMMIT_SHORT_SHA}

prd-fe-deploy-job:
  extends: .fe-deploy-job
  needs:
    - job: prd-build-fe-node-job
      artifacts: true
  environment:
    name: production/frontend
    deployment_tier: production
    url: https://eurac.itch.io/oetzi
  variables:
    GAME_NAME: oetzi
    DIST_PATH: frontend/dist/prd
  only:
    - tags

stg-fe-deploy-job:
  extends: .fe-deploy-job
  needs:
    - job: stg-build-fe-node-job
      artifacts: true
  environment:
    name: staging/frontend
    deployment_tier: staging
    url: https://eurac.itch.io/oetzi-staging
  variables:
    GAME_NAME: oetzi-staging
    DIST_PATH: frontend/dist/stg
  only:
    - development

#--[ Backend ]------------------------------------------------------------------

.be-deploy-job:
  image: alpine:latest
  stage: deploy
  needs:
    - job: build-be-job
      artifacts: false
  tags:
    - shared
  variables:
    IMAGE_NAME: $CI_REGISTRY_IMAGE/backend
  before_script:
    - ./ci/install-kubectl-on-alpine.sh
  script:
    - kubectl set image deployment/${K8S_DEPLOYMENT} oetzi=${IMAGE_NAME}:${CI_COMMIT_SHA} --namespace=${K8S_NAMESPACE}

prd-be-deploy-job:
  extends: .be-deploy-job
  environment:
    name: production/backend
    deployment_tier: production
    url: https://kommul.eurac.edu/oetzi
  variables:
    K8S_NAMESPACE: kommul
    K8S_DEPLOYMENT: oetzi-webserver-deployment
  only:
    - tags

stg-be-deploy-job:
  extends: .be-deploy-job
  environment:
    name: staging/backend
    deployment_tier: staging
    url: https://kommul-dev.eurac.edu/oetzi
  variables:
    K8S_NAMESPACE: kommul-dev
    K8S_DEPLOYMENT: oetzi-webserver-deployment
  only:
    - development
