############
# Settings #
############
image: docker:28.0.0
services:
  - docker:28.0.0-dind
stages:
  - readme
  - revert
  - build
  - test
  - manifest
variables:
  BASE_TAG: "{{ BASE_TAG }}"
  USE_PRIVATE_IMAGES: {{ USE_PRIVATE_IMAGES }}
  KASM_RELEASE: "{{ KASM_RELEASE }}"
  DOCKER_HOST: tcp://docker:2375
  DOCKER_TLS_CERTDIR: ""
  TEST_INSTALLER: "{{ TEST_INSTALLER }}"
  MIRROR_ORG_NAME: "{{ MIRROR_ORG_NAME }}"
default:
  retry: 2
before_script:
  - docker login --username $DOCKER_HUB_USERNAME --password $DOCKER_HUB_PASSWORD
  - if [ "$CI_COMMIT_REF_PROTECTED" == "true" ]; then docker login --username $QUAY_USERNAME --password $QUAY_PASSWORD quay.io; fi 
  - if [ "$CI_COMMIT_REF_PROTECTED" == "true" ]; then docker login --username $GHCR_USERNAME --password $GHCR_PASSWORD ghcr.io; fi 
  - export SANITIZED_BRANCH="$(echo $CI_COMMIT_REF_NAME | sed -r 's#^release/##' | sed 's/\//_/g')"

.run_rules:
  rules:
    - if: >
        $README_USERNAME || 
        $README_PASSWORD || 
        $QUAY_API_KEY || 
        $DOCKERHUB_REVERT || 
        $REVERT_IS_ROLLING
      when: never

###############################################
# Build Containers and push to cache endpoint #
###############################################
{% for IMAGE in multiImages %}
build_{{ IMAGE.name }}:
  stage: build
  extends: .run_rules
  rules:
    - !reference [.run_rules, rules]
    - if: $PARENT_PIPELINE_SOURCE == "schedule" && $RUN_SET != "{{ IMAGE.runset }}"
      when: never
    - if: $CI_COMMIT_REF_NAME == "develop" || $CI_COMMIT_REF_NAME =~ /^release\/.*$/
      when: always
    - if: $PARENT_PIPELINE_SOURCE == "merge_request_event"
      when: always
    {% if FILE_LIMITS %}- changes:
      {% for FILE in files %}- {{ FILE }}
      {% endfor %}{% for FILE in IMAGE.changeFiles %}- {{ FILE }}
      {% endfor %}{% endif %}
    - when: never
  script:
    - apk add bash
    - bash ci-scripts/build.sh "{{ IMAGE.name }}" "{{ IMAGE.base }}" "{{ IMAGE.dockerfile }}"
  tags:
    - ${TAG}
  retry: 1
  parallel:
    matrix:
      - TAG: [ oci-amd-scheduled, oci-arm-scheduled ]
{% endfor %}

{% for IMAGE in singleImages %}
build_{{ IMAGE.name }}:
  stage: build
  extends: .run_rules
  rules:
    - !reference [.run_rules, rules]
    - if: $PARENT_PIPELINE_SOURCE == "schedule" && $RUN_SET != "{{ IMAGE.runset }}"
      when: never
    - if: $CI_COMMIT_REF_NAME == "develop" || $CI_COMMIT_REF_NAME =~ /^release\/.*$/
      when: always
    - if: $PARENT_PIPELINE_SOURCE == "merge_request_event"
      when: always
    {% if FILE_LIMITS %}- changes:
      {% for FILE in files %}- {{ FILE }}
      {% endfor %}{% for FILE in IMAGE.changeFiles %}- {{ FILE }}
      {% endfor %}{% endif %}
    - when: never
  script:
    - apk add bash
    - bash ci-scripts/build.sh "{{ IMAGE.name }}" "{{ IMAGE.base }}" "{{ IMAGE.dockerfile }}"
  tags:
    - oci-amd-scheduled
  retry: 1
{% endfor %}

######################################
# Test containers and upload results #
######################################
{% for IMAGE in multiImages %}
test_{{ IMAGE.name }}:
  stage: test
  extends: .run_rules
  rules:
    - !reference [.run_rules, rules]
    - if: $PARENT_PIPELINE_SOURCE == "schedule" && $RUN_SET != "{{ IMAGE.runset }}"
      when: never
    - if: $CI_COMMIT_REF_NAME == "develop" || $CI_COMMIT_REF_NAME =~ /^release\/.*$/
      when: always
    - if: $PARENT_PIPELINE_SOURCE == "merge_request_event"
      when: always
    {% if FILE_LIMITS %}- changes:
      {% for FILE in files %}- {{ FILE }}
      {% endfor %}{% for FILE in IMAGE.changeFiles %}- {{ FILE }}
      {% endfor %}{% endif %}
  script:
    - apk add bash
    - bash ci-scripts/test.sh "{{ IMAGE.name }}" "{{ IMAGE.base }}" "{{ IMAGE.dockerfile }}" "${ARCH}" "${EC2_LAUNCHER_ID}" "${EC2_LAUNCHER_SECRET}"
  needs:
    - build_{{ IMAGE.name }}
  tags:
    - oci-amd-scheduled
  retry: 1
  parallel:
    matrix:
      - ARCH: [ "x86_64", "aarch64" ]
{% endfor %}

{% for IMAGE in singleImages %}
test_{{ IMAGE.name }}:
  stage: test
  extends: .run_rules
  rules:
    - !reference [.run_rules, rules]
    - if: $PARENT_PIPELINE_SOURCE == "schedule" && $RUN_SET != "{{ IMAGE.runset }}"
      when: never
    - if: $CI_COMMIT_REF_NAME == "develop" || $CI_COMMIT_REF_NAME =~ /^release\/.*$/
      when: always
    - if: $PARENT_PIPELINE_SOURCE == "merge_request_event"
      when: always
    {% if FILE_LIMITS %}- changes:
      {% for FILE in files %}- {{ FILE }}
      {% endfor %}{% for FILE in IMAGE.changeFiles %}- {{ FILE }}
      {% endfor %}{% endif %}
  script:
    - apk add bash
    - bash ci-scripts/test.sh "{{ IMAGE.name }}" "{{ IMAGE.base }}" "{{ IMAGE.dockerfile }}" "x86_64" "${EC2_LAUNCHER_ID}" "${EC2_LAUNCHER_SECRET}"
  needs:
    - build_{{ IMAGE.name }}
  tags:
    - oci-amd-scheduled
  retry: 1
{% endfor %}

############################################
# Manifest Containers if their test passed #
############################################
{% for IMAGE in multiImages %}
manifest_{{ IMAGE.name }}:
  stage: manifest
  extends: .run_rules
  rules:
    - !reference [.run_rules, rules]
    - if: $PARENT_PIPELINE_SOURCE == "schedule" && $RUN_SET != "{{ IMAGE.runset }}"
      when: never
    - if: $CI_COMMIT_REF_NAME == "develop" || $CI_COMMIT_REF_NAME =~ /^release\/.*$/
      when: always
    - if: $PARENT_PIPELINE_SOURCE == "merge_request_event"
      when: always
    {% if FILE_LIMITS %}- changes:
      {% for FILE in files %}- {{ FILE }}
      {% endfor %}{% for FILE in IMAGE.changeFiles %}- {{ FILE }}
      {% endfor %}{% endif %}
  variables:
    SCHEDULED: "{{ SCHEDULED }}"
    SCHEDULE_NAME: "{{ SCHEDULE_NAME }}"
  script:
    - apk add bash tar
    - bash ci-scripts/manifest.sh "{{ IMAGE.name }}" "multi"
    # Disabling app layer build due to feature not being used
    #{% if IMAGE.singleapp %}
    #- bash ci-scripts/app-layer.sh "{{ IMAGE.name }}" "multi" "{{ IMAGE.base }}"{% endif %}
  needs:
    - test_{{ IMAGE.name }}
  retry: 1
  tags:
    - oci-amd-scheduled
{% endfor %}

{% for IMAGE in singleImages %}
manifest_{{ IMAGE.name }}:
  stage: manifest
  extends: .run_rules
  rules:
    - !reference [.run_rules, rules]
    - if: $PARENT_PIPELINE_SOURCE == "schedule" && $RUN_SET != "{{ IMAGE.runset }}"
      when: never
    - if: $CI_COMMIT_REF_NAME == "develop" || $CI_COMMIT_REF_NAME =~ /^release\/.*$/
      when: always
    - if: $PARENT_PIPELINE_SOURCE == "merge_request_event"
      when: always
    {% if FILE_LIMITS %}- changes:
      {% for FILE in files %}- {{ FILE }}
      {% endfor %}{% for FILE in IMAGE.changeFiles %}- {{ FILE }}
      {% endfor %}{% endif %}
  variables:
    SCHEDULED: "{{ SCHEDULED }}"
    SCHEDULE_NAME: "{{ SCHEDULE_NAME }}"
  script:
    - apk add bash tar
    - bash ci-scripts/manifest.sh "{{ IMAGE.name }}" "single"
    # Disabling app layer build due to feature not being used
    #{% if IMAGE.singleapp %}
    #- bash ci-scripts/app-layer.sh "{{ IMAGE.name }}" "single" "{{ IMAGE.base }}"{% endif %}
  needs:
    - test_{{ IMAGE.name }}
  retry: 1
  tags:
    - oci-amd-scheduled
{% endfor %}

#############################
# Manifest for Weekly Build #
#############################

{% for IMAGE in multiImages %}
weekly_manifest_{{ IMAGE.name }}:
  stage: manifest
  extends: .run_rules
  rules:
    - !reference [.run_rules, rules]
    - if: $PARENT_PIPELINE_SOURCE == "schedule" && $RUN_SET == "schedule"
      when: always
    - when: never
  script:
    - apk add bash tar
    - bash ci-scripts/weekly-manifest.sh "{{ IMAGE.name }}" "multi"
  retry: 1
  tags:
    - oci-amd-scheduled
{% endfor %}

{% for IMAGE in singleImages %}
weekly_manifest_{{ IMAGE.name }}:
  stage: manifest
  extends: .run_rules
  rules:
    - !reference [.run_rules, rules]
    - if: $PARENT_PIPELINE_SOURCE == "schedule" && $RUN_SET == "schedule"
      when: always
    - when: never
  script:
    - apk add bash tar
    - bash ci-scripts/weekly-manifest.sh "{{ IMAGE.name }}" "single"
  retry: 1
  tags:
    - oci-amd-scheduled
{% endfor %}

####################
# Helper Functions #
####################

## Update Readmes ##
{% for IMAGE in multiImages %}
update_readmes_{{ IMAGE.name }}:
  stage: readme
  rules:
    - if: >
        $README_USERNAME && 
        $README_PASSWORD
      when: always
  script:
    - apk add bash
    - bash ci-scripts/readme.sh "{{ IMAGE.name }}"
  tags:
    - oci-amd-scheduled
{% endfor %}

{% for IMAGE in singleImages %}
update_readmes_{{ IMAGE.name }}:
  stage: readme
  rules:
    - if: >
        $README_USERNAME && 
        $README_PASSWORD
      when: always
  script:
    - apk add bash
    - bash ci-scripts/readme.sh "{{ IMAGE.name }}"
  tags:
    - oci-amd-scheduled
{% endfor %}

## Update Quay Readmes ##
{% for IMAGE in multiImages %}
update_quay_readmes_{{ IMAGE.name }}:
  stage: readme
  rules:
    - if: $QUAY_API_KEY
      when: always
  script:
    - apk add bash
    - bash ci-scripts/quay_readme.sh "{{ IMAGE.name }}"
  tags:
    - oci-amd-scheduled
{% endfor %}

{% for IMAGE in singleImages %}
update_quay_readmes_{{ IMAGE.name }}:
  stage: readme
  rules:
    - if: $QUAY_API_KEY
      when: always
  script:
    - apk add bash
    - bash ci-scripts/quay_readme.sh "{{ IMAGE.name }}"
  tags:
    - oci-amd-scheduled
{% endfor %}

## Revert Images to specific build id ##
{% for IMAGE in multiImages %}
dockerhub_revert_{{ IMAGE.name }}:
  stage: revert
  rules:
    - if: >
        $DOCKERHUB_REVERT && 
        $REVERT_IS_ROLLING
      when: always
  script:
    - /bin/bash ci-scripts/manifest.sh "{{ IMAGE.name }}" "multi" "${DOCKERHUB_REVERT}" "${REVERT_IS_ROLLING}"
  tags:
    - oci-amd-scheduled
{% endfor %}

{% for IMAGE in singleImages %}
dockerhub_revert_{{ IMAGE.name }}:
  stage: revert
  rules:
    - if: >
        $DOCKERHUB_REVERT && 
        $REVERT_IS_ROLLING
      when: always
  script:
    - /bin/bash ci-scripts/manifest.sh "{{ IMAGE.name }}" "single" "${DOCKERHUB_REVERT}" "${REVERT_IS_ROLLING}"
  tags:
    - oci-amd-scheduled
{% endfor %}
