# polkadot-sdk | CI definitions (via GitLab CI)
#
# FYI: Pipelines can be triggered manually through the web UI (if you have enough permissions)
#
# Currently, entire CI instructions are split into different subfiles. Each CI stage has a corresponding
# file which can be found here: .gitlab/pipeline/<stage_name>.yml

stages:
  - check
  - test
  - build
  - publish
  - short-benchmarks
  - zombienet
  - deploy
  - notify

workflow:
  rules:
    - if: $CI_COMMIT_TAG
    - if: $CI_COMMIT_BRANCH

variables:
  CI_IMAGE: "paritytech/ci-unified:bullseye-1.70.0-2023-05-23-v20230706"
  # BUILDAH_IMAGE is defined in group variables
  BUILDAH_COMMAND: "buildah --storage-driver overlay2"
  RELENG_SCRIPTS_BRANCH: "master"
  RUSTY_CACHIER_SINGLE_BRANCH: master
  RUSTY_CACHIER_DONT_OPERATE_ON_MAIN_BRANCH: "true"
  RUSTY_CACHIER_COMPRESSION_METHOD: zstd
  NEXTEST_FAILURE_OUTPUT: immediate-final
  NEXTEST_SUCCESS_OUTPUT: final
  ZOMBIENET_IMAGE: "docker.io/paritytech/zombienet:v1.3.65"
  DOCKER_IMAGES_VERSION: "${CI_COMMIT_REF_NAME}-${CI_COMMIT_SHORT_SHA}"

default:
  retry:
    max: 2
    when:
      - runner_system_failure
      - unknown_failure
      - api_failure
  cache: {}
  interruptible: true

.collect-artifacts:
  artifacts:
    name: "${CI_JOB_NAME}_${CI_COMMIT_REF_NAME}"
    when: on_success
    expire_in: 1 days
    paths:
      - artifacts/

.collect-artifacts-short:
  artifacts:
    name: "${CI_JOB_NAME}_${CI_COMMIT_REF_NAME}"
    when: on_failure
    expire_in: 3 hours
    paths:
      - artifacts/

.prepare-env:
  before_script:
    # $WASM_BUILD_WORKSPACE_HINT enables wasm-builder to find the Cargo.lock from within generated
    # packages
    - export WASM_BUILD_WORKSPACE_HINT="$PWD"
    # ensure that RUSTFLAGS are set correctly
    - echo $RUSTFLAGS

.common-before-script:
  before_script:
    - !reference [.job-switcher, before_script]
    - !reference [.timestamp, before_script]
    - !reference [.pipeline-stopper-vars, script]

.job-switcher:
  before_script:
    - if echo "$CI_DISABLED_JOBS" | grep -xF "$CI_JOB_NAME"; then echo "The job has been cancelled in CI settings"; exit 0; fi

.kubernetes-env:
  image: "${CI_IMAGE}"
  before_script:
    - !reference [.common-before-script, before_script]
    - !reference [.prepare-env, before_script]
  tags:
    - kubernetes-parity-build

.rust-info-script:
  script:
    - rustup show
    - cargo --version
    - rustup +nightly show
    - cargo +nightly --version

# collecting vars for pipeline stopper
# they will be used if the job fails
.pipeline-stopper-vars:
  script:
    - echo "Collecting env variables for the cancel-pipeline job"
    - echo "FAILED_JOB_URL=${CI_JOB_URL}" > pipeline-stopper.env
    - echo "FAILED_JOB_NAME=${CI_JOB_NAME}" >> pipeline-stopper.env
    - echo "PR_NUM=${CI_COMMIT_REF_NAME}" >> pipeline-stopper.env

.pipeline-stopper-artifacts:
  artifacts:
    reports:
      dotenv: pipeline-stopper.env

.docker-env:
  image: "${CI_IMAGE}"
  before_script:
    - !reference [.common-before-script, before_script]
    - !reference [.prepare-env, before_script]
    - !reference [.rust-info-script, script]
    - !reference [.rusty-cachier, before_script]
  tags:
    - linux-docker-vm-c2

# rusty-cachier's hidden job. Parts of this job are used to instrument the pipeline's other real jobs with rusty-cachier
# rusty-cachier's commands are described here: https://gitlab.parity.io/parity/infrastructure/ci_cd/rusty-cachier/client#description
.rusty-cachier:
  before_script:
    # - curl -s https://gitlab-ci-token:${CI_JOB_TOKEN}@gitlab.parity.io/parity/infrastructure/ci_cd/rusty-cachier/client/-/raw/release/util/install.sh | bash
    # - mkdir -p cargo_home cargo_target_dir
    # - export CARGO_HOME=$CI_PROJECT_DIR/cargo_home
    # - export CARGO_TARGET_DIR=$CI_PROJECT_DIR/cargo_target_dir
    # - find . \( -path ./cargo_target_dir -o -path ./cargo_home \) -prune -o -type f -exec touch -t 202005260100 {} +
    # - git restore-mtime
    # - rusty-cachier --version
    # - rusty-cachier project touch-changed
    - echo tbd

.common-refs:
  rules:
    - if: $CI_PIPELINE_SOURCE == "web"
    - if: $CI_PIPELINE_SOURCE == "schedule"
    - if: $CI_COMMIT_REF_NAME == "master"
    - if: $CI_COMMIT_REF_NAME =~ /^[0-9]+$/ # PRs
    - if: $CI_COMMIT_REF_NAME =~ /^v[0-9]+\.[0-9]+.*$/ # i.e. v1.0, v2.1rc1

.test-pr-refs:
  rules:
    - if: $CI_COMMIT_REF_NAME =~ /^[0-9]+$/ # PRs

# handle the specific case where benches could store incorrect bench data because of the downstream staging runs
# exclude cargo-check-benches from such runs
.test-refs-check-benches:
  rules:
    - if: $CI_COMMIT_REF_NAME == "master" && $CI_PIPELINE_SOURCE == "pipeline"  && $CI_IMAGE =~ /staging$/
      when: never
    - if: $CI_PIPELINE_SOURCE == "web"
    - if: $CI_PIPELINE_SOURCE == "schedule"
    - if: $CI_COMMIT_REF_NAME == "master"
    - if: $CI_COMMIT_REF_NAME =~ /^[0-9]+$/ # PRs
    - if: $CI_COMMIT_REF_NAME =~ /^v[0-9]+\.[0-9]+.*$/ # i.e. v1.0, v2.1rc1

.test-refs-no-trigger:
  rules:
    - if: $CI_PIPELINE_SOURCE == "pipeline"
      when: never
    - if: $CI_PIPELINE_SOURCE == "web"
    - if: $CI_PIPELINE_SOURCE == "schedule"
    - if: $CI_COMMIT_REF_NAME == "master"
    - if: $CI_COMMIT_REF_NAME =~ /^[0-9]+$/ # PRs
    - if: $CI_COMMIT_REF_NAME =~ /^v[0-9]+\.[0-9]+.*$/ # i.e. v1.0, v2.1rc1
    - if: $CI_COMMIT_REF_NAME =~ /^ci-release-.*$/

.test-refs-no-trigger-prs-only:
  rules:
    - if: $CI_PIPELINE_SOURCE == "pipeline"
      when: never
    - if: $CI_PIPELINE_SOURCE == "web"
    - if: $CI_PIPELINE_SOURCE == "schedule"
    - if: $CI_COMMIT_REF_NAME =~ /^[0-9]+$/ # PRs

.publish-refs:
  rules:
    - if: $CI_PIPELINE_SOURCE == "pipeline"
      when: never
    - if: $CI_PIPELINE_SOURCE == "web"
    - if: $CI_PIPELINE_SOURCE == "schedule"
    - if: $CI_COMMIT_REF_NAME == "master"
    - if: $CI_COMMIT_REF_NAME =~ /^v[0-9]+\.[0-9]+.*$/ # i.e. v1.0, v2.1rc1

.build-refs:
  # publish-refs + PRs
  rules:
    - if: $CI_PIPELINE_SOURCE == "pipeline"
      when: never
    - if: $CI_PIPELINE_SOURCE == "web"
    - if: $CI_PIPELINE_SOURCE == "schedule"
    - if: $CI_COMMIT_REF_NAME == "master"
    - if: $CI_COMMIT_REF_NAME =~ /^v[0-9]+\.[0-9]+.*$/ # i.e. v1.0, v2.1rc1
    - if: $CI_COMMIT_REF_NAME =~ /^[0-9]+$/ # PRs

.zombienet-refs:
  extends: .build-refs

include:
  # weights jobs
  # - gitlab/pipeline/weights.yml
  # check jobs
  - .gitlab/pipeline/check.yml
  # test jobs
  - .gitlab/pipeline/test.yml
  # build jobs
  - .gitlab/pipeline/build.yml
  # short-benchmarks jobs
  - .gitlab/pipeline/short-benchmarks.yml
  # publish jobs
  - .gitlab/pipeline/publish.yml
  # zombienet jobs
  - .gitlab/pipeline/zombienet.yml
  # # timestamp handler
  - project: parity/infrastructure/ci_cd/shared
    ref: v0.2
    file: /common/timestamp.yml

# This job cancels the whole pipeline if any of provided jobs fail.
# In a DAG, every jobs chain is executed independently of others. The `fail_fast` principle suggests
# to fail the pipeline as soon as possible to shorten the feedback loop.
.cancel-pipeline-template:
  stage: .post
  rules:
    - if: $CI_COMMIT_REF_NAME =~ /^[0-9]+$/ # PRs
      when: on_failure
  variables:
    PROJECT_ID: "${CI_PROJECT_ID}"
    PROJECT_NAME: "${CI_PROJECT_NAME}"
    PIPELINE_ID: "${CI_PIPELINE_ID}"
    FAILED_JOB_URL: "${FAILED_JOB_URL}"
    FAILED_JOB_NAME: "${FAILED_JOB_NAME}"
    PR_NUM: "${PR_NUM}"
  trigger:
    project: "parity/infrastructure/ci_cd/pipeline-stopper"

remove-cancel-pipeline-message:
  stage: .post
  rules:
    - if: $CI_COMMIT_REF_NAME =~ /^[0-9]+$/ # PRs
  variables:
    PROJECT_ID: "${CI_PROJECT_ID}"
    PROJECT_NAME: "${CI_PROJECT_NAME}"
    PIPELINE_ID: "${CI_PIPELINE_ID}"
    FAILED_JOB_URL: "https://gitlab.com"
    FAILED_JOB_NAME: "nope"
    PR_NUM: "${CI_COMMIT_REF_NAME}"
  trigger:
    project: "parity/infrastructure/ci_cd/pipeline-stopper"
# need to copy jobs this way because otherwise gitlab will wait
# for all 3 jobs to finish instead of cancelling if one fails
cancel-pipeline-test-linux-stable1:
  extends: .cancel-pipeline-template
  needs:
    - job: "test-linux-stable 1/3"

cancel-pipeline-test-linux-stable2:
  extends: .cancel-pipeline-template
  needs:
    - job: "test-linux-stable 2/3"

cancel-pipeline-test-linux-stable3:
  extends: .cancel-pipeline-template
  needs:
    - job: "test-linux-stable 3/3"

cancel-pipeline-test-linux-stable-additional-tests:
  extends: .cancel-pipeline-template
  needs:
    - job: "test-linux-stable-additional-tests"

cancel-pipeline-test-linux-stable-slow:
  extends: .cancel-pipeline-template
  needs:
    - job: "test-linux-stable-slow"

cancel-pipeline-cargo-check-benches1:
  extends: .cancel-pipeline-template
  needs:
    - job: "cargo-check-benches 1/2"

cancel-pipeline-cargo-check-benches2:
  extends: .cancel-pipeline-template
  needs:
    - job: "cargo-check-benches 2/2"

cancel-pipeline-test-linux-stable-int:
  extends: .cancel-pipeline-template
  needs:
    - job: test-linux-stable-int

cancel-pipeline-cargo-check-each-crate-1:
  extends: .cancel-pipeline-template
  needs:
    - job: "cargo-check-each-crate 1/6"

cancel-pipeline-cargo-check-each-crate-2:
  extends: .cancel-pipeline-template
  needs:
    - job: "cargo-check-each-crate 2/6"

cancel-pipeline-cargo-check-each-crate-3:
  extends: .cancel-pipeline-template
  needs:
    - job: "cargo-check-each-crate 3/6"

cancel-pipeline-cargo-check-each-crate-4:
  extends: .cancel-pipeline-template
  needs:
    - job: "cargo-check-each-crate 4/6"

cancel-pipeline-cargo-check-each-crate-5:
  extends: .cancel-pipeline-template
  needs:
    - job: "cargo-check-each-crate 5/6"

cancel-pipeline-cargo-check-each-crate-6:
  extends: .cancel-pipeline-template
  needs:
    - job: "cargo-check-each-crate 6/6"

cancel-pipeline-cargo-check-each-crate-macos:
  extends: .cancel-pipeline-template
  needs:
    - job: cargo-check-each-crate-macos

cancel-pipeline-check-tracing:
  extends: .cancel-pipeline-template
  needs:
    - job: check-tracing

cancel-pipeline-cargo-clippy:
  extends: .cancel-pipeline-template
  needs:
    - job: cargo-clippy
