# Types of CI pipelines:
# | pipeline name        | context   | description                                                 |
# |----------------------|-----------|-------------------------------------------------------------|
# | merge pipeline       | mesa/mesa | pipeline running for an MR; if it passes the MR gets merged |
# | pre-merge pipeline   | mesa/mesa | same as above, except its status doesn't affect the MR      |
# | post-merge pipeline  | mesa/mesa | pipeline immediately after merging                          |
# | fork pipeline        | fork      | pipeline running in a user fork                             |
# | scheduled pipeline   | mesa/mesa | nightly pipelines, running every morning at 4am UTC         |
# | direct-push pipeline | mesa/mesa | when commits are pushed directly to mesa/mesa, bypassing Marge and its gating pipeline |
#
# Note that the release branches maintained by the release manager fall under
# the "direct push" category.
#
# "context" indicates the permissions that the jobs get; notably, any
# container created in mesa/mesa gets pushed immediately for everyone to use
# as soon as the image tag change is merged.
#
# Merge pipelines contain all jobs that must pass before the MR can be merged.
# Pre-merge pipelines contain the exact same jobs as merge pipelines.
# Post-merge pipelines contain *only* the `pages` job that deploys the new
# version of the website.
# Fork pipelines contain everything.
# Scheduled pipelines only contain the container+build jobs, and some extra
# test jobs (typically "full" variants of pre-merge jobs that only run 1/X
# test cases), but not a repeat of the merge pipeline jobs.
# Direct-push pipelines contain the same jobs as merge pipelines.

workflow:
  rules:
    # do not duplicate pipelines on merge pipelines
    - if: $CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS && $CI_PIPELINE_SOURCE == "push"
      when: never
    # merge pipeline
    - if: &is-merge-attempt $GITLAB_USER_LOGIN == "marge-bot" && $CI_PIPELINE_SOURCE == "merge_request_event"
      variables:
        KERNEL_IMAGE_BASE: https://${S3_HOST}/mesa-lava/${KERNEL_REPO}/${KERNEL_TAG}
        MESA_CI_PERFORMANCE_ENABLED: 1
        VALVE_INFRA_VANGOGH_JOB_PRIORITY: ""  # Empty tags are ignored by gitlab
    # post-merge pipeline
    - if: &is-post-merge $GITLAB_USER_LOGIN == "marge-bot" && $CI_PIPELINE_SOURCE == "push"
    # nightly pipeline
    - if: &is-scheduled-pipeline $CI_PIPELINE_SOURCE == "schedule"
      variables:
        KERNEL_IMAGE_BASE: https://${S3_HOST}/mesa-lava/${KERNEL_REPO}/${KERNEL_TAG}
        JOB_PRIORITY: 50
        VALVE_INFRA_VANGOGH_JOB_PRIORITY: priority:low
    # pipeline for direct pushes that bypassed the CI
    - if: &is-direct-push $CI_PROJECT_NAMESPACE == "mesa" && $CI_PIPELINE_SOURCE == "push" && $GITLAB_USER_LOGIN != "marge-bot"
      variables:
        KERNEL_IMAGE_BASE: https://${S3_HOST}/mesa-lava/${KERNEL_REPO}/${KERNEL_TAG}
        JOB_PRIORITY: 40
        VALVE_INFRA_VANGOGH_JOB_PRIORITY: priority:low
    # pre-merge or fork pipeline
    - if: $FORCE_KERNEL_TAG != null
      variables:
        KERNEL_IMAGE_BASE: https://${S3_HOST}/mesa-lava/${KERNEL_REPO}/${FORCE_KERNEL_TAG}
        JOB_PRIORITY: 50
        VALVE_INFRA_VANGOGH_JOB_PRIORITY: priority:low
    - if: $FORCE_KERNEL_TAG == null
      variables:
        KERNEL_IMAGE_BASE: https://${S3_HOST}/mesa-lava/${KERNEL_REPO}/${KERNEL_TAG}
        JOB_PRIORITY: 50
        VALVE_INFRA_VANGOGH_JOB_PRIORITY: priority:low


variables:
  FDO_UPSTREAM_REPO: mesa/mesa
  MESA_TEMPLATES_COMMIT: &ci-templates-commit d5aa3941aa03c2f716595116354fb81eb8012acb
  CI_PRE_CLONE_SCRIPT: |-
          set -o xtrace
          wget -q -O download-git-cache.sh ${CI_PROJECT_URL}/-/raw/${CI_COMMIT_SHA}/.gitlab-ci/download-git-cache.sh
          bash download-git-cache.sh
          rm download-git-cache.sh
          set +o xtrace
  CI_JOB_JWT_FILE: /minio_jwt
  S3_HOST: s3.freedesktop.org
  # per-pipeline artifact storage on MinIO
  PIPELINE_ARTIFACTS_BASE: ${S3_HOST}/artifacts/${CI_PROJECT_PATH}/${CI_PIPELINE_ID}
  # per-job artifact storage on MinIO
  JOB_ARTIFACTS_BASE: ${PIPELINE_ARTIFACTS_BASE}/${CI_JOB_ID}
  # reference images stored for traces
  PIGLIT_REPLAY_REFERENCE_IMAGES_BASE: "${S3_HOST}/mesa-tracie-results/$FDO_UPSTREAM_REPO"
  # For individual CI farm status see .ci-farms folder
  # Disable farm with   `git mv .ci-farms{,-disabled}/$farm_name`
  # Re-enable farm with `git mv .ci-farms{-disabled,}/$farm_name`
  # NEVER MIX FARM MAINTENANCE WITH ANY OTHER CHANGE IN THE SAME MERGE REQUEST!
  ARTIFACTS_BASE_URL: https://${CI_PROJECT_ROOT_NAMESPACE}.${CI_PAGES_DOMAIN}/-/${CI_PROJECT_NAME}/-/jobs/${CI_JOB_ID}/artifacts
  # Python scripts for structured logger
  PYTHONPATH: "$PYTHONPATH:$CI_PROJECT_DIR/install"

default:
  before_script:
    - >
      export SCRIPTS_DIR=$(mktemp -d) &&
      curl -L -s --retry 4 -f --retry-all-errors --retry-delay 60 -O --output-dir "${SCRIPTS_DIR}" "${CI_PROJECT_URL}/-/raw/${CI_COMMIT_SHA}/.gitlab-ci/setup-test-env.sh" &&
      . ${SCRIPTS_DIR}/setup-test-env.sh &&
      echo -n "${CI_JOB_JWT}" > "${CI_JOB_JWT_FILE}" &&
      unset CI_JOB_JWT  # Unsetting vulnerable env variables

  after_script:
    # Work around https://gitlab.com/gitlab-org/gitlab/-/issues/20338
    - find -name '*.log' -exec mv {} {}.txt \;

    - >
      set +x

      test -e "${CI_JOB_JWT_FILE}" &&
      export CI_JOB_JWT="$(<${CI_JOB_JWT_FILE})" &&
      rm "${CI_JOB_JWT_FILE}"

  # Retry when job fails. Failed jobs can be found in the Mesa CI Daily Reports:
  # https://gitlab.freedesktop.org/mesa/mesa/-/issues/?sort=created_date&state=opened&label_name%5B%5D=CI%20daily
  retry:
    max: 1
    # Ignore runner_unsupported, stale_schedule, archived_failure, or
    # unmet_prerequisites
    when:
      - api_failure
      - runner_system_failure
      - script_failure
      - job_execution_timeout
      - scheduler_failure
      - data_integrity_failure
      - unknown_failure

stages:
  - sanity
  - container
  - git-archive
  - build-x86_64
  - build-misc
  - code-validation
  - amd
  - intel
  - nouveau
  - arm
  - broadcom
  - freedreno
  - etnaviv
  - software-renderer
  - layered-backends
  - deploy

include:
  - project: 'freedesktop/ci-templates'
    ref: 16bc29078de5e0a067ff84a1a199a3760d3b3811
    file:
      - '/templates/ci-fairy.yml'
  - project: 'freedesktop/ci-templates'
    ref: *ci-templates-commit
    file:
      - '/templates/alpine.yml'
      - '/templates/debian.yml'
      - '/templates/fedora.yml'
  - local: '.gitlab-ci/image-tags.yml'
  - local: '.gitlab-ci/lava/lava-gitlab-ci.yml'
  - local: '.gitlab-ci/container/gitlab-ci.yml'
  - local: '.gitlab-ci/build/gitlab-ci.yml'
  - local: '.gitlab-ci/test/gitlab-ci.yml'
  - local: '.gitlab-ci/farm-rules.yml'
  - local: '.gitlab-ci/test-source-dep.yml'
  - local: 'docs/gitlab-ci.yml'
  - local: 'src/amd/ci/gitlab-ci.yml'
  - local: 'src/broadcom/ci/gitlab-ci.yml'
  - local: 'src/etnaviv/ci/gitlab-ci.yml'
  - local: 'src/freedreno/ci/gitlab-ci.yml'
  - local: 'src/gallium/drivers/crocus/ci/gitlab-ci.yml'
  - local: 'src/gallium/drivers/d3d12/ci/gitlab-ci.yml'
  - local: 'src/gallium/drivers/i915/ci/gitlab-ci.yml'
  - local: 'src/gallium/drivers/r300/ci/gitlab-ci.yml'
  - local: 'src/gallium/drivers/lima/ci/gitlab-ci.yml'
  - local: 'src/gallium/drivers/llvmpipe/ci/gitlab-ci.yml'
  - local: 'src/gallium/drivers/nouveau/ci/gitlab-ci.yml'
  - local: 'src/gallium/drivers/softpipe/ci/gitlab-ci.yml'
  - local: 'src/gallium/drivers/virgl/ci/gitlab-ci.yml'
  - local: 'src/gallium/drivers/zink/ci/gitlab-ci.yml'
  - local: 'src/gallium/frontends/lavapipe/ci/gitlab-ci.yml'
  - local: 'src/intel/ci/gitlab-ci.yml'
  - local: 'src/microsoft/ci/gitlab-ci.yml'
  - local: 'src/panfrost/ci/gitlab-ci.yml'
  - local: 'src/virtio/ci/gitlab-ci.yml'


# YAML anchors for rule conditions
# --------------------------------
.rules-anchors:
  # Pre-merge pipeline
  - &is-pre-merge '$CI_PIPELINE_SOURCE == "merge_request_event"'


.never-post-merge-rules:
  rules:
    - if: *is-post-merge
      when: never


.container+build-rules:
  rules:
    # Run when re-enabling a disabled farm, but not when disabling it
    - !reference [.disable-farm-mr-rules, rules]
    # Never run immediately after merging, as we just ran everything
    - !reference [.never-post-merge-rules, rules]
    # Build everything in merge pipelines, if any files affecting the pipeline
    # were changed
    - if: *is-merge-attempt
      changes: &all_paths
        - VERSION
        - bin/git_sha1_gen.py
        - bin/install_megadrivers.py
        - bin/symbols-check.py
        # GitLab CI
        - .gitlab-ci.yml
        - .gitlab-ci/**/*
        - .ci-farms/*
        # Meson
        - meson*
        - build-support/**/*
        - subprojects/**/*
        # clang format
        - .clang-format
        - .clang-format-include
        - .clang-format-ignore
        # Source code
        - include/**/*
        - src/**/*
      when: on_success
    # Same as above, but for pre-merge pipelines
    - if: *is-pre-merge
      changes:
        *all_paths
      when: manual
    # Skip everything for pre-merge and merge pipelines which don't change
    # anything in the build
    - if: *is-merge-attempt
      when: never
    - if: *is-pre-merge
      when: never
    # Build everything after someone bypassed the CI
    - if: *is-direct-push
      when: on_success
    # Build everything in scheduled pipelines
    - if: *is-scheduled-pipeline
      when: on_success
    # Allow building everything in fork pipelines, but build nothing unless
    # manually triggered
    - when: manual


.ci-deqp-artifacts:
  artifacts:
    name: "mesa_${CI_JOB_NAME}"
    when: always
    untracked: false
    paths:
      # Watch out!  Artifacts are relative to the build dir.
      # https://gitlab.com/gitlab-org/gitlab-ce/commit/8788fb925706cad594adf6917a6c5f6587dd1521
      - artifacts
      - _build/meson-logs/*.txt
      - _build/meson-logs/strace

# Git archive

make git archive:
  extends:
    - .fdo.ci-fairy
  stage: git-archive
  rules:
    - !reference [.scheduled_pipeline-rules, rules]
  # ensure we are running on packet
  tags:
    - packet.net
  script:
    # Compactify the .git directory
    - git gc --aggressive
    # Download & cache the perfetto subproject as well.
    - rm -rf subprojects/perfetto ; mkdir -p subprojects/perfetto && curl https://android.googlesource.com/platform/external/perfetto/+archive/$(grep 'revision =' subprojects/perfetto.wrap | cut -d ' ' -f3).tar.gz | tar zxf - -C subprojects/perfetto
    # compress the current folder
    - tar -cvzf ../$CI_PROJECT_NAME.tar.gz .

    - ci-fairy s3cp --token-file "${CI_JOB_JWT_FILE}" ../$CI_PROJECT_NAME.tar.gz https://$S3_HOST/git-cache/$CI_PROJECT_NAMESPACE/$CI_PROJECT_NAME/$CI_PROJECT_NAME.tar.gz


# Sanity checks of MR settings and commit logs
sanity:
  extends:
    - .fdo.ci-fairy
  stage: sanity
  rules:
    - if: *is-pre-merge
      when: on_success
    - when: never
  variables:
    GIT_STRATEGY: none
  script:
    # ci-fairy check-commits --junit-xml=check-commits.xml
    - ci-fairy check-merge-request --require-allow-collaboration --junit-xml=check-merge-request.xml
  artifacts:
    when: on_failure
    reports:
      junit: check-*.xml
  tags:
    - placeholder-job


# Jobs that need to pass before spending hardware resources on further testing
.required-for-hardware-jobs:
  needs:
    - job: clang-format
      optional: true
    - job: rustfmt
      optional: true
