#Calendar implementation for the HTWK Leipzig timetable. Evaluation and display of the individual dates in iCal format.
#Copyright (C) 2024 HTWKalender support@htwkalender.de

#This program is free software: you can redistribute it and/or modify
#it under the terms of the GNU Affero General Public License as published by
#the Free Software Foundation, either version 3 of the License, or
#(at your option) any later version.

#This program is distributed in the hope that it will be useful,
#but WITHOUT ANY WARRANTY; without even the implied warranty of
#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#GNU Affero General Public License for more details.

#You should have received a copy of the GNU Affero General Public License
#along with this program.  If not, see <https://www.gnu.org/licenses/>.

stages:
  - lint
  - build
  - test
  - sonarqube-check
  - oci-build
  - deploy
  - deploy-dev  # New stage for development deployment

lint-frontend:
  image: node:lts
  stage: lint
  rules:
    - changes:
        - frontend/**/*
  script:
    - cd frontend
    - npm i
    - npm run lint-no-fix

lint-data-manager:
  stage: lint
  image: golangci/golangci-lint:latest
  rules:
    - changes:
        - services/data-manager/**/*
  script:
    - cd services/data-manager
    - go mod download
    - golangci-lint --version
    - golangci-lint run -v --skip-dirs=migrations --timeout=5m

lint-ical:
  stage: lint
  image: golangci/golangci-lint:latest
  rules:
    - changes:
        - services/ical/**/*
  script:
    - cd services/ical
    - go mod download
    - golangci-lint --version
    - golangci-lint run -v --skip-dirs=migrations --timeout=5m


build-data-manager:
  image: golang:alpine
  stage: build
  rules:
    - changes:
      - services/data-manager/**/*
  script:
    - cd services/data-manager
    - go build -o htwkalender
  artifacts:
    paths:
      - data-manager/htwkalender
      - data-manager/go.sum
      - data-manager/go.mod

build-ical:
  image: golang:alpine
  stage: build
  rules:
    - changes:
        - services/ical/**/*
  script:
    - cd services/ical
    - go build -o htwkalender-ical
  artifacts:
    paths:
      - data-manager/htwkalender-ical
      - data-manager/go.sum
      - data-manager/go.mod

sonarqube-data-manager:
  stage: sonarqube-check
  image:
    name: sonarsource/sonar-scanner-cli:5.0
    entrypoint: [""]
  variables:
    SONAR_USER_HOME: "${CI_PROJECT_DIR}/.sonar"  # Defines the location of the analysis task cache
    GIT_DEPTH: "0"  # Tells git to fetch all the branches of the project, required by the analysis task
  cache:
    key: "${CI_JOB_NAME}"
    paths:
      - .sonar/cache
  script:
    - cd services/data-manager
    - sonar-scanner
  allow_failure: true
  only:
    - merge_requests
    - master
    - main
    - develop

build-frontend:
    image: node:lts
    stage: build
    rules:
        - changes:
            - frontend/**/*
    script:
        - cd frontend
        - npm i
        - npm run build
    artifacts:
        paths:
        - frontend/build

test-data-manager:
  image: golang:alpine
  stage: test
  rules:
    - changes:
      - services/data-manager/**/*
  script:
    - cd services/data-manager
    - go test -v ./...
  dependencies:
    - build-data-manager

test-ical:
  image: golang:alpine
  stage: test
  rules:
    - changes:
        - services/ical/**/*
  script:
    - cd services/ical
    - go test -v ./...
  dependencies:
    - build-ical

test-frontend:
  image: node:lts
  stage: test
  rules:
    - changes:
        - frontend/**/*
  script:
    - cd frontend
    - npm i
    - npm run test
  dependencies:
    - lint-frontend

build-data-manager-image:
  stage: oci-build
  image: docker:latest
  services:
    - docker:dind
  tags:
    - image
  variables:
    IMAGE_TAG: $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG-data-manager
    DOCKER_HOST: tcp://docker:2376
    DOCKER_TLS_CERTDIR: "/certs"
    DOCKER_TLS_VERIFY: 1
    DOCKER_CERT_PATH: "/certs/client"
  before_script:
    - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
  script:
    - docker build --pull -t $IMAGE_TAG -f ./services/data-manager/Dockerfile --target prod ./services
    - docker push $IMAGE_TAG
  rules:
    - if: $CI_COMMIT_BRANCH == "main" || $CI_COMMIT_BRANCH == "development"
      changes:
        - services/data-manager/**/*

build-ical-image:
  stage: oci-build
  image: docker:latest
  services:
    - docker:dind
  tags:
    - image
  variables:
    IMAGE_TAG: $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG-ical
    DOCKER_HOST: tcp://docker:2376
    DOCKER_TLS_CERTDIR: "/certs"
    DOCKER_TLS_VERIFY: 1
    DOCKER_CERT_PATH: "/certs/client"
  before_script:
    - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
  script:
    - docker build --pull -t $IMAGE_TAG -f ./services/ical/Dockerfile --target prod ./services
    - docker push $IMAGE_TAG
  rules:
    - if: $CI_COMMIT_BRANCH == "main" || $CI_COMMIT_BRANCH == "development"
      changes:
        - services/ical/**/*

build-frontend-image:
  stage: oci-build
  image: docker:latest
  services:
    - docker:dind
  tags:
    - image
  variables:
    IMAGE_TAG: $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG-frontend
    DOCKER_HOST: tcp://docker:2376
    DOCKER_TLS_CERTDIR: "/certs"
    DOCKER_TLS_VERIFY: 1
    DOCKER_CERT_PATH: "/certs/client"
  before_script:
    - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
    - cd ./frontend
  script:
    - docker build --pull -t $IMAGE_TAG -f ./Dockerfile --target prod .
    - docker push $IMAGE_TAG
  rules:
    - if: $CI_COMMIT_BRANCH == "main" || $CI_COMMIT_BRANCH == "development"
      changes:
        - frontend/**/*

# Development deployment job
deploy-dev:
  stage: deploy-dev  # New stage for development deployment
  image: alpine:latest
  before_script:
    - apk add --no-cache openssh-client sed # install dependencies
    - eval $(ssh-agent -s) # set some ssh variables
    - ssh-add <(echo "$CI_SSH_KEY" | tr -d '\r')
  script:
    # replace some placeholders
    - sed -i -e "s|DOCKER_REGISTRY_REPO|$CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG|" docker-compose.dev.yml  # Assuming you have a separate docker-compose file for development
    # upload necessary files to the dev server
    - >
      scp -P $CI_SSH_PORT -o StrictHostKeyChecking=no -o LogLevel=ERROR ./docker-compose.dev.yml ./reverseproxy.dev.conf
      $CI_SSH_USER@$CI_SSH_DEV_HOST:/home/$CI_SSH_USER/docker/htwkalender/
    # ssh to the dev server and start the service
    - >
      ssh -p $CI_SSH_PORT -o StrictHostKeyChecking=no -o LogLevel=ERROR $CI_SSH_USER@$CI_SSH_DEV_HOST
      "cd /home/$CI_SSH_USER/docker/htwkalender/ &&
      docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY &&
      docker compose -f ./docker-compose.dev.yml down && docker compose -f ./docker-compose.dev.yml up -d --remove-orphans && docker logout"
  rules:
    - if: $CI_COMMIT_BRANCH == "development"  # Only execute for the development branch


deploy-all:
  stage: deploy
  image: alpine:latest
  before_script:
    - apk add --no-cache openssh-client sed # install dependencies
    - eval $(ssh-agent -s) # set some ssh variables
    - ssh-add <(echo "$CI_SSH_KEY" | tr -d '\r')
  script:
    # replace some placeholders
    - sed -i -e "s|DOCKER_REGISTRY_REPO|$CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG|" docker-compose.prod.yml
    # upload necessary files to the server
    - >
      scp -P $CI_SSH_PORT -o StrictHostKeyChecking=no -o LogLevel=ERROR ./docker-compose.prod.yml ./reverseproxy.conf
      $CI_SSH_USER@$CI_SSH_HOST:/home/$CI_SSH_USER/docker/htwkalender/
    # ssh to the server and start the service
    - >
      ssh -p $CI_SSH_PORT -o StrictHostKeyChecking=no -o LogLevel=ERROR $CI_SSH_USER@$CI_SSH_HOST
      "cd /home/$CI_SSH_USER/docker/htwkalender/ &&
      docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY &&
      docker compose -f ./docker-compose.prod.yml down && docker compose -f ./docker-compose.prod.yml up -d --remove-orphans && docker logout &&
      docker exec --user root htwkalender-htwkalender-frontend-1 /bin/sh -c \"echo 'google-site-verification: $GOOGLE_VERIFICATION.html' > ./$GOOGLE_VERIFICATION.html\" "
  rules:
    - if: $CI_COMMIT_BRANCH == "main"
