stages:
  - test
  - release
  - build

services:
  - name: ghcr.io/griefed/gitlab-ci-cd:2.2.11
    alias: docker
    command: ["--experimental"]

image: ghcr.io/griefed/gitlab-ci-cd:2.2.11

variables:
  project_name: $CI_PROJECT_NAME
  SEMANTIC_RELEASE_PACKAGE: $CI_PROJECT_NAME
  FOCAL_RELEASE_DATE: "current"
  OVERLAY_VERSION: "v2.2.0.3"

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

test docker:
  stage: test
  before_script:
    - docker login -u "$DOCKERHUB_USER" -p "$DOCKERHUB_TOKEN" docker.io
    - docker login -u "$DOCKERHUB_USER" -p "$GITHUB_TOKEN" ghcr.io
  script:
    - echo "**** Build amd64 ****"
    - docker build
      --no-cache
      --tag "index.docker.io/$DOCKERHUB_USER/$DOCKERHUB_REPO:amd64-develop"
      --tag "ghcr.io/$DOCKERHUB_USER/$DOCKERHUB_REPO:amd64-develop"
      --build-arg FOCAL_ARCH=amd64
      --build-arg FOCAL_RELEASE_DATE="$FOCAL_RELEASE_DATE"
      --build-arg BUILD_DATE="$CI_PIPELINE_CREATED_AT"
      --build-arg VERSION="$CI_COMMIT_SHORT_SHA"
      --build-arg OVERLAY_VERSION="$OVERLAY_VERSION"
      --build-arg OVERLAY_ARCH=amd64 .
    - docker push "index.docker.io/$DOCKERHUB_USER/$DOCKERHUB_REPO:amd64-develop"
    - docker push "ghcr.io/$DOCKERHUB_USER/$DOCKERHUB_REPO:amd64-develop"
    - echo "**** Build armhf ****"
    - docker build
      --no-cache
      --tag "index.docker.io/$DOCKERHUB_USER/$DOCKERHUB_REPO:armhf-develop"
      --tag "ghcr.io/$DOCKERHUB_USER/$DOCKERHUB_REPO:armhf-develop"
      --build-arg FOCAL_ARCH=armhf
      --build-arg FOCAL_RELEASE_DATE="$FOCAL_RELEASE_DATE"
      --build-arg BUILD_DATE="$CI_PIPELINE_CREATED_AT"
      --build-arg VERSION="$CI_COMMIT_SHORT_SHA"
      --build-arg OVERLAY_VERSION="$OVERLAY_VERSION"
      --build-arg OVERLAY_ARCH=arm .
    - docker push "index.docker.io/$DOCKERHUB_USER/$DOCKERHUB_REPO:armhf-develop"
    - docker push "ghcr.io/$DOCKERHUB_USER/$DOCKERHUB_REPO:armhf-develop"
    - echo "**** Build arm64 ****"
    - docker build
      --no-cache
      --tag "index.docker.io/$DOCKERHUB_USER/$DOCKERHUB_REPO:arm64-develop"
      --tag "ghcr.io/$DOCKERHUB_USER/$DOCKERHUB_REPO:arm64-develop"
      --build-arg FOCAL_ARCH=arm64
      --build-arg FOCAL_RELEASE_DATE="$FOCAL_RELEASE_DATE"
      --build-arg BUILD_DATE="$CI_PIPELINE_CREATED_AT"
      --build-arg VERSION="$CI_COMMIT_SHORT_SHA"
      --build-arg OVERLAY_VERSION="$OVERLAY_VERSION"
      --build-arg OVERLAY_ARCH=aarch64 .
    - docker push "index.docker.io/$DOCKERHUB_USER/$DOCKERHUB_REPO:arm64-develop"
    - docker push "ghcr.io/$DOCKERHUB_USER/$DOCKERHUB_REPO:arm64-develop"
    - echo "**** Create DockerHub manifest ****"
    - docker manifest create "index.docker.io/$DOCKERHUB_USER/$DOCKERHUB_REPO:develop" "index.docker.io/$DOCKERHUB_USER/$DOCKERHUB_REPO:amd64-develop" "index.docker.io/$DOCKERHUB_USER/$DOCKERHUB_REPO:armhf-develop" "index.docker.io/$DOCKERHUB_USER/$DOCKERHUB_REPO:arm64-develop"
    - docker manifest annotate "index.docker.io/$DOCKERHUB_USER/$DOCKERHUB_REPO:develop" "index.docker.io/$DOCKERHUB_USER/$DOCKERHUB_REPO:armhf-develop" --os linux --arch arm
    - docker manifest annotate "index.docker.io/$DOCKERHUB_USER/$DOCKERHUB_REPO:develop" "index.docker.io/$DOCKERHUB_USER/$DOCKERHUB_REPO:arm64-develop" --os linux --arch arm64 --variant v8
    - docker manifest push --purge "index.docker.io/$DOCKERHUB_USER/$DOCKERHUB_REPO:develop"
    - echo "**** Create GitHub manifest ****"
    - docker manifest create "ghcr.io/$DOCKERHUB_USER/$DOCKERHUB_REPO:develop" "ghcr.io/$DOCKERHUB_USER/$DOCKERHUB_REPO:amd64-develop" "ghcr.io/$DOCKERHUB_USER/$DOCKERHUB_REPO:armhf-develop" "ghcr.io/$DOCKERHUB_USER/$DOCKERHUB_REPO:arm64-develop"
    - docker manifest annotate "ghcr.io/$DOCKERHUB_USER/$DOCKERHUB_REPO:develop" "ghcr.io/$DOCKERHUB_USER/$DOCKERHUB_REPO:armhf-develop" --os linux --arch arm
    - docker manifest annotate "ghcr.io/$DOCKERHUB_USER/$DOCKERHUB_REPO:develop" "ghcr.io/$DOCKERHUB_USER/$DOCKERHUB_REPO:arm64-develop" --os linux --arch arm64 --variant v8
    - docker manifest push --purge "ghcr.io/$DOCKERHUB_USER/$DOCKERHUB_REPO:develop"
  except:
    refs:
      - tags
    variables:
      - '$CI_COMMIT_TITLE =~ /^RELEASE:.+$/ || $CI_PIPELINE_SOURCE == "schedule"'

release:
  needs: ['test docker']
  stage: release
  script:
    - npx semantic-release
  only:
    - master
  except:
    refs:
      - tags
    variables:
      - '$CI_COMMIT_TITLE =~ /^RELEASE:.+$/ || $CI_PIPELINE_SOURCE == "schedule"'

build:
  stage: build
  before_script:
    - docker login -u "$DOCKERHUB_USER" -p "$DOCKERHUB_TOKEN" docker.io
    - docker login -u "$DOCKERHUB_USER" -p "$GITHUB_TOKEN" ghcr.io
  script:
    - echo "**** Build amd64 ****"
    - docker build
      --no-cache
      --tag "index.docker.io/$DOCKERHUB_USER/$DOCKERHUB_REPO:amd64-latest"
      --tag "index.docker.io/$DOCKERHUB_USER/$DOCKERHUB_REPO:amd64-$CI_COMMIT_TAG"
      --tag "ghcr.io/$DOCKERHUB_USER/$DOCKERHUB_REPO:amd64-latest"
      --tag "ghcr.io/$DOCKERHUB_USER/$DOCKERHUB_REPO:amd64-$CI_COMMIT_TAG"
      --build-arg FOCAL_ARCH=amd64
      --build-arg FOCAL_RELEASE_DATE="$FOCAL_RELEASE_DATE"
      --build-arg BUILD_DATE="$CI_PIPELINE_CREATED_AT"
      --build-arg VERSION="$CI_COMMIT_TAG"
      --build-arg OVERLAY_VERSION="$OVERLAY_VERSION"
      --build-arg OVERLAY_ARCH=amd64 .
    - docker push "index.docker.io/$DOCKERHUB_USER/$DOCKERHUB_REPO:amd64-latest"
    - docker push "index.docker.io/$DOCKERHUB_USER/$DOCKERHUB_REPO:amd64-$CI_COMMIT_TAG"
    - docker push "ghcr.io/$DOCKERHUB_USER/$DOCKERHUB_REPO:amd64-latest"
    - docker push "ghcr.io/$DOCKERHUB_USER/$DOCKERHUB_REPO:amd64-$CI_COMMIT_TAG"
    - echo "**** Build armhf ****"
    - docker build
      --no-cache
      --tag "index.docker.io/$DOCKERHUB_USER/$DOCKERHUB_REPO:armhf-latest"
      --tag "index.docker.io/$DOCKERHUB_USER/$DOCKERHUB_REPO:armhf-$CI_COMMIT_TAG"
      --tag "ghcr.io/$DOCKERHUB_USER/$DOCKERHUB_REPO:armhf-latest"
      --tag "ghcr.io/$DOCKERHUB_USER/$DOCKERHUB_REPO:armhf-$CI_COMMIT_TAG"
      --build-arg FOCAL_ARCH=armhf
      --build-arg FOCAL_RELEASE_DATE="$FOCAL_RELEASE_DATE"
      --build-arg BUILD_DATE="$CI_PIPELINE_CREATED_AT"
      --build-arg VERSION="$CI_COMMIT_TAG"
      --build-arg OVERLAY_VERSION="$OVERLAY_VERSION"
      --build-arg OVERLAY_ARCH=arm .
    - docker push "index.docker.io/$DOCKERHUB_USER/$DOCKERHUB_REPO:armhf-latest"
    - docker push "index.docker.io/$DOCKERHUB_USER/$DOCKERHUB_REPO:armhf-$CI_COMMIT_TAG"
    - docker push "ghcr.io/$DOCKERHUB_USER/$DOCKERHUB_REPO:armhf-latest"
    - docker push "ghcr.io/$DOCKERHUB_USER/$DOCKERHUB_REPO:armhf-$CI_COMMIT_TAG"
    - echo "**** Build arm64 ****"
    - docker build
      --no-cache
      --tag "index.docker.io/$DOCKERHUB_USER/$DOCKERHUB_REPO:arm64-latest"
      --tag "index.docker.io/$DOCKERHUB_USER/$DOCKERHUB_REPO:arm64-$CI_COMMIT_TAG"
      --tag "ghcr.io/$DOCKERHUB_USER/$DOCKERHUB_REPO:arm64-latest"
      --tag "ghcr.io/$DOCKERHUB_USER/$DOCKERHUB_REPO:arm64-$CI_COMMIT_TAG"
      --build-arg FOCAL_ARCH=arm64
      --build-arg FOCAL_RELEASE_DATE="$FOCAL_RELEASE_DATE"
      --build-arg BUILD_DATE="$CI_PIPELINE_CREATED_AT"
      --build-arg VERSION="$CI_COMMIT_TAG"
      --build-arg OVERLAY_VERSION="$OVERLAY_VERSION"
      --build-arg OVERLAY_ARCH="aarch64" .
    - docker push "index.docker.io/$DOCKERHUB_USER/$DOCKERHUB_REPO:arm64-latest"
    - docker push "index.docker.io/$DOCKERHUB_USER/$DOCKERHUB_REPO:arm64-$CI_COMMIT_TAG"
    - docker push "ghcr.io/$DOCKERHUB_USER/$DOCKERHUB_REPO:arm64-latest"
    - docker push "ghcr.io/$DOCKERHUB_USER/$DOCKERHUB_REPO:arm64-$CI_COMMIT_TAG"
    - echo "**** Create DockerHub manifest ****"
    - docker manifest create "index.docker.io/$DOCKERHUB_USER/$DOCKERHUB_REPO:latest" "index.docker.io/$DOCKERHUB_USER/$DOCKERHUB_REPO:amd64-latest" "index.docker.io/$DOCKERHUB_USER/$DOCKERHUB_REPO:armhf-latest" "index.docker.io/$DOCKERHUB_USER/$DOCKERHUB_REPO:arm64-latest"
    - docker manifest annotate "index.docker.io/$DOCKERHUB_USER/$DOCKERHUB_REPO:latest" "index.docker.io/$DOCKERHUB_USER/$DOCKERHUB_REPO:armhf-latest" --os linux --arch arm
    - docker manifest annotate "index.docker.io/$DOCKERHUB_USER/$DOCKERHUB_REPO:latest" "index.docker.io/$DOCKERHUB_USER/$DOCKERHUB_REPO:arm64-latest" --os linux --arch arm64 --variant v8
    - docker manifest push --purge "index.docker.io/$DOCKERHUB_USER/$DOCKERHUB_REPO:latest"
    - docker manifest create "index.docker.io/$DOCKERHUB_USER/$DOCKERHUB_REPO:$CI_COMMIT_TAG" "index.docker.io/$DOCKERHUB_USER/$DOCKERHUB_REPO:amd64-$CI_COMMIT_TAG" "index.docker.io/$DOCKERHUB_USER/$DOCKERHUB_REPO:armhf-$CI_COMMIT_TAG" "index.docker.io/$DOCKERHUB_USER/$DOCKERHUB_REPO:arm64-$CI_COMMIT_TAG"
    - docker manifest annotate "index.docker.io/$DOCKERHUB_USER/$DOCKERHUB_REPO:$CI_COMMIT_TAG" "index.docker.io/$DOCKERHUB_USER/$DOCKERHUB_REPO:armhf-$CI_COMMIT_TAG" --os linux --arch arm
    - docker manifest annotate "index.docker.io/$DOCKERHUB_USER/$DOCKERHUB_REPO:$CI_COMMIT_TAG" "index.docker.io/$DOCKERHUB_USER/$DOCKERHUB_REPO:arm64-$CI_COMMIT_TAG" --os linux --arch arm64 --variant v8
    - docker manifest push --purge "index.docker.io/$DOCKERHUB_USER/$DOCKERHUB_REPO:$CI_COMMIT_TAG"
    - echo "**** Create GitHub manifest ****"
    - docker manifest create "ghcr.io/$DOCKERHUB_USER/$DOCKERHUB_REPO:latest" "ghcr.io/$DOCKERHUB_USER/$DOCKERHUB_REPO:amd64-latest" "ghcr.io/$DOCKERHUB_USER/$DOCKERHUB_REPO:armhf-latest" "ghcr.io/$DOCKERHUB_USER/$DOCKERHUB_REPO:arm64-latest"
    - docker manifest annotate "ghcr.io/$DOCKERHUB_USER/$DOCKERHUB_REPO:latest" "ghcr.io/$DOCKERHUB_USER/$DOCKERHUB_REPO:armhf-latest" --os linux --arch arm
    - docker manifest annotate "ghcr.io/$DOCKERHUB_USER/$DOCKERHUB_REPO:latest" "ghcr.io/$DOCKERHUB_USER/$DOCKERHUB_REPO:arm64-latest" --os linux --arch arm64 --variant v8
    - docker manifest push --purge "ghcr.io/$DOCKERHUB_USER/$DOCKERHUB_REPO:latest"
    - docker manifest create "ghcr.io/$DOCKERHUB_USER/$DOCKERHUB_REPO:$CI_COMMIT_TAG" "ghcr.io/$DOCKERHUB_USER/$DOCKERHUB_REPO:amd64-$CI_COMMIT_TAG" "ghcr.io/$DOCKERHUB_USER/$DOCKERHUB_REPO:armhf-$CI_COMMIT_TAG" "ghcr.io/$DOCKERHUB_USER/$DOCKERHUB_REPO:arm64-$CI_COMMIT_TAG"
    - docker manifest annotate "ghcr.io/$DOCKERHUB_USER/$DOCKERHUB_REPO:$CI_COMMIT_TAG" "ghcr.io/$DOCKERHUB_USER/$DOCKERHUB_REPO:armhf-$CI_COMMIT_TAG" --os linux --arch arm
    - docker manifest annotate "ghcr.io/$DOCKERHUB_USER/$DOCKERHUB_REPO:$CI_COMMIT_TAG" "ghcr.io/$DOCKERHUB_USER/$DOCKERHUB_REPO:arm64-$CI_COMMIT_TAG" --os linux --arch arm64 --variant v8
    - docker manifest push --purge "ghcr.io/$DOCKERHUB_USER/$DOCKERHUB_REPO:$CI_COMMIT_TAG"
  only:
    - tags

Check Packages:on-schedule:
  only:
    - schedules
  before_script:
    - |-
      echo "Preparing package versions comparison."
      # Check and, if necessary, update git user and mail
      if [[ "$(git config --list | grep user.name)" != "user.name=$GIT_USER" ]];then
        git config --global user.name $GIT_USER
      fi
      if [[ "$(git config --list | grep user.email)" != "user.email=$GIT_MAIL" ]];then
        git config --global user.email $GIT_MAIL
      fi

      # Clean system of potentially interrupting images
      docker image rm -f $DOCKERHUB_USER/$DOCKERHUB_REPO:latest
      docker image rm -f $DOCKERHUB_REPO
      rm -rf /tmp/$CI_PROJECT_PATH
      mkdir -p /tmp/$CI_PROJECT_PATH
      echo "Preparations complete."
  script:
    - |-
      echo "Comparing package versions."
      # Clone the repository
      git clone $CI_PROJECT_URL.git /tmp/$CI_PROJECT_PATH && \
      cd /tmp/$CI_PROJECT_PATH && \

      if [ ! -s "package_versions.txt" ];then
        echo "No package_versions.txt present. Creating..."

        # Gather package information from latest build
        docker run --rm --entrypoint /bin/sh -v /tmp/$CI_PROJECT_PATH:/tmp $DOCKERHUB_USER/$DOCKERHUB_REPO:latest -c '\
          apt list -qq --installed > /tmp/package_versions.txt && \
          sort -o /tmp/package_versions.txt  /tmp/package_versions.txt && \
          chmod 777 /tmp/package_versions.txt' && \

        # Checkout our branch
        git checkout -f $CI_DEFAULT_BRANCH && \

        wait && \

        # Add and commit new file to repository
        git add package_versions.txt && \
        git commit -m 'chore: Add list of package versions.' && \

        # Push the changes to the remote
        echo "https://***:***@$CI_SERVER_HOST/$CI_PROJECT_PATH.git"
        git push "https://$GIT_USER:$GITLAB_TOKEN@$CI_SERVER_HOST/$CI_PROJECT_PATH".git --all && \

        # Nice
        echo "package_versions.txt added."

      elif [ -s "package_versions.txt" ];then
        echo "package_versions.txt present. Comapring..."

        # Build local image for new package versions list
        docker build --no-cache --tag $DOCKERHUB_REPO . && \

        # Get packages from newly build local image
        docker run --rm --entrypoint /bin/sh -v /tmp/$CI_PROJECT_PATH:/tmp $DOCKERHUB_REPO -c '\
          apt list -qq --installed > /tmp/package_versions_new.txt && \
          sort -o /tmp/package_versions_new.txt  /tmp/package_versions_new.txt && \
          chmod 777 /tmp/package_versions_new.txt' && \

        # Get checksum of old packages
        OLD_CHECKSUM=$(md5sum package_versions.txt | cut -f1 -d" ") && \

        # Get checksum of new packages
        NEW_CHECKSUM=$(md5sum package_versions_new.txt | cut -f1 -d" ") && \

        # If new checksum is not the same as old checksum, we have new versions
        if [ "${OLD_CHECKSUM}" != "${NEW_CHECKSUM}" ]; then

          # Checkout our branch
          git checkout -f $CI_DEFAULT_BRANCH && \

          # Copy the new package versions list to repository
          mv -f package_versions_new.txt package_versions.txt && \

          wait && \

          # Add and commit new file to repository
          git add package_versions.txt && \
          git commit -m 'build: Update installed packages in Docker container.' && \

          # Push the changes to the remote
          git push "https://$GIT_USER:$GITLAB_TOKEN@$CI_SERVER_HOST/$CI_PROJECT_PATH.git" --all && \

          # Nice
          echo "Packages updated."
        else
          echo "No package updates available."
        fi

      fi
      echo "Comparison complete."
  after_script:
    - |-
      echo "Cleaning up."
      docker image rm -f $DOCKERHUB_USER/$DOCKERHUB_REPO:latest
      docker image rm -f $DOCKERHUB_REPO
      rm -rf /tmp/$CI_PROJECT_PATH
      echo "Done."