# =========================================================================================
# Copyright (C) 2021 Orange & contributors
#
# This program is free software; you can redistribute it and/or modify it under the terms 
# of the GNU Lesser 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 Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License along with this 
# program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth 
# Floor, Boston, MA  02110-1301, USA.
# =========================================================================================
variables:
  # Maven image (can be overridden)
  MAVEN_IMAGE: "maven:latest"

  # default production ref name (pattern)
  PROD_REF: '/^(master|main)$/'
  # default integration ref name (pattern)
  INTEG_REF: '/^develop$/'

  # default configuration directory
  MAVEN_CFG_DIR: ".m2"

  # This will suppress any download for dependencies and plugins or upload messages which would clutter the console log.
  # `showDateTime` will show the passed time in milliseconds. You need to specify `--batch-mode` to make this work.
  MAVEN_OPTS: >-
    -Dhttps.protocols=TLSv1.2
    -Dmaven.repo.local=${MAVEN_CFG_DIR}/repository
    -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=WARN
    -Dorg.slf4j.simpleLogger.showDateTime=true
    -Djava.awt.headless=true

  # As of Maven 3.3.0 instead of this you may define these options in `.mvn/maven.config` so the same config is used
  # when running from the command line.
  # `installAtEnd` and `deployAtEnd` are only effective with recent version of the corresponding plugins.
  MAVEN_CLI_OPTS: >-
    --batch-mode
    --errors
    --fail-at-end
    --show-version
    -DinstallAtEnd=true
    -DdeployAtEnd=true

  # Maven build arguments
  MAVEN_BUILD_ARGS: "org.jacoco:jacoco-maven-plugin:prepare-agent verify org.jacoco:jacoco-maven-plugin:report"

  # Sonar base analysis default args
  # see: https://docs.sonarqube.org/latest/analysis/analysis-parameters/
  # default uses branch analysis: https://docs.sonarqube.org/latest/branches/overview/
  SONAR_BASE_ARGS: >-
    sonar:sonar
    -Dsonar.host.url=${SONAR_URL}
    -Dsonar.links.homepage=${CI_PROJECT_URL}
    -Dsonar.links.ci=${CI_PROJECT_URL}/-/pipelines
    -Dsonar.links.issue=${CI_PROJECT_URL}/-/issues

  # Sonar GitLab plugin args
  # see: https://github.com/gabrie-allaigre/sonar-gitlab-plugin/#plugins-properties
  # -> enabled if $SONAR_GITLAB_TOKEN is set
  SONAR_GITLAB_ARGS: >-
    -Dsonar.gitlab.url=${CI_SERVER_URL}
    -Dsonar.gitlab.user_token=${SONAR_GITLAB_TOKEN}
    -Dsonar.gitlab.project_id=${CI_PROJECT_ID}
    -Dsonar.gitlab.commit_sha=${CI_COMMIT_SHA}
    -Dsonar.gitlab.ref_name=${CI_COMMIT_REF_NAME}

  # Dependency Check arguments
  MAVEN_DEPENDENCY_CHECK_ARGS: >-
    org.owasp:dependency-check-maven:check
    -DretireJsAnalyzerEnabled=false
    -DassemblyAnalyzerEnabled=false
    -Dformats=HTML,JSON,XML
  
  # Maven deploy arguments
  MAVEN_DEPLOY_ARGS: "deploy -Dmaven.test.skip=true"

  # Maven release arguments
  MAVEN_RELEASE_ARGS: "release:prepare release:perform -Darguments=-Dmaven.test.skip=true"
  MAVEN_RELEASE_SCM_COMMENT_PREFIX: "[ci skip][maven-release-plugin]"

stages:
  - build
  - test
  - publish

.mvn-scripts: &mvn-scripts |
  # BEGSCRIPT
  set -e

  function log_info() {
      echo -e "[\\e[1;94mINFO\\e[0m] $*"
  }

  function log_warn() {
      echo -e "[\\e[1;93mWARN\\e[0m] $*"
  }

  function log_error() {
      echo -e "[\\e[1;91mERROR\\e[0m] $*"
  }

  function output_coverage() {
    jacoco_reports=$(find . -name "${JACOCO_CSV_REPORT:-jacoco.csv}")

    if [[ -n "$jacoco_reports" ]]
    then
      log_info "--- \\e[32mJaCoCo report(s) found\\e[0m (\\e[33;1m${jacoco_reports}\\e[0m): output"
      # shellcheck disable=SC2046,SC2086
      awk -F',' '{ instructions += $4 + $5; covered += $5 } END { print covered"/"instructions " instructions covered"; print 100*covered/instructions "% covered" }' $(find . -name "${JACOCO_CSV_REPORT:-jacoco.csv}")
    else
      log_info "--- \\e[32mJaCoCo report(s) not found: skip"
    fi
  }

  function sonar_http_auth_args() {
    if [[ -n "$SONAR_AUTH_TOKEN" ]]
    then
      echo "$SONAR_AUTH_TOKEN:"
    elif [[ -n "$SONAR_LOGIN" ]] && [[ -n "$SONAR_PASSWORD" ]]
    then
      echo "$SONAR_LOGIN:$SONAR_PASSWORD"
    else
     echo ""
    fi
  }
  
  function sonar_autodetect_mr() {
    if [[ "$SONAR_BRANCH_ANALYSIS_DISABLED" == "true" ]]
    then
      log_info "Branch Analysis and Merge Request Analysis are disabled"
      return
    fi
    if [[ "$CI_MERGE_REQUEST_ID" ]]
    then
      # we are in an MR pipeline: no need to pass arguments as the SonarScanner for Maven will
      log_info "Merge Request pipeline detected: let Maven plugin handle..."
      return
    fi
    if [[ -n "$SONAR_GITLAB_TOKEN" ]]
    then 
      curl -sS --header "PRIVATE-TOKEN: $SONAR_GITLAB_TOKEN" "$CI_API_V4_URL/projects/${CI_PROJECT_ID}/merge_requests?state=opened&source_branch=${CI_COMMIT_REF_NAME}" -o mr.json
      if [ "$(cat mr.json)" != "[]" ]
      then
        mr_title=$(sed -E 's/\[\{[^{]*"title":"([^"]*)".*/\1/g' < mr.json)
        mr_target=$(sed -E 's/\[\{[^{]*"target_branch":"([^"]*)".*/\1/g' < mr.json)
        mr_id=$(sed -E 's/\[\{[^{]*"iid":([0-9]+).*/\1/g' < mr.json)
        log_info "Merge Request \\e[33;1m$mr_title\\e[0m detected associated to this branch: trigger MR analysis..."
        export sonar_mr_args="-Dsonar.pullrequest.key=$mr_id -Dsonar.pullrequest.branch=${CI_COMMIT_REF_NAME} -Dsonar.pullrequest.base=$mr_target"
      else 
        log_info "No Merge Request associated to this branch: trigger branch analysis..."
        export sonar_mr_args="-Dsonar.branch.name=${CI_COMMIT_REF_NAME}"
      fi
    else 
      log_info "\$SONAR_GITLAB_TOKEN unset: trigger branch analysis..."
      export sonar_mr_args="-Dsonar.branch.name=${CI_COMMIT_REF_NAME}"
    fi
  }

  function sonar_quality_gate_check() {
    log_info "--- Waiting for Sonar analysis end..."
    taskId=$(grep ceTaskId target/sonar/report-task.txt | cut -c10-)
    curl -sS -k --user "$(sonar_http_auth_args)" "$SONAR_URL/api/ce/task?id=$taskId" -o analysis.json
    analysisStatus=$(grep --only-matching --extended-regexp "\"status\":\"[A-Z_-]+\"" analysis.json | awk -F: '{print $2}' | tr -d '"')
    while [ "$analysisStatus" == "IN_PROGRESS" ] || [ "$analysisStatus" == "PENDING" ]; do
      sleep 5s
      curl -sS -k --user "$(sonar_http_auth_args)" "$SONAR_URL/api/ce/task?id=$taskId" -o analysis.json
      analysisStatus=$(grep --only-matching --extended-regexp "\"status\":\"[A-Z_-]+\"" analysis.json | awk -F: '{print $2}' | tr -d '"')
    done

    # Check quality gate
    if [ "$analysisStatus" == "SUCCESS" ]; then
      analysisId=$(grep --only-matching --extended-regexp "\"analysisId\":\"[a-zA-Z0-9_-]+\"" analysis.json | awk -F: '{print $2}' | tr -d '"')
      qualityGateStatus=$(curl -sS -k --user "$(sonar_http_auth_args)" "$SONAR_URL/api/qualitygates/project_status?analysisId=$analysisId" | grep --only-matching --extended-regexp "{\"projectStatus\":{\"status\":\"[A-Z_]+\"" | awk -F: '{print $3}' | tr -d '"')
      if [ "$qualityGateStatus" == "ERROR" ]; then
        log_error "... quality gate FAILED"
        exit 1
      else
        log_info "... quality gate SUCCEEDED"
        exit 0
      fi
    else
        log_error "... Sonar analysis FAILED"
      exit 1
    fi
  }

  function maybe_set_version_from_git() {
    if [[ -n "$MAVEN_RELEASE_VERSION_FROM_GIT" ]]; then
      # compute version as timestamp of latest commit
      cur_version="$(date -d "$(git log -n 1 --pretty=format:%ci)" "+%Y.%m.%d.%H%M%S")"

      log_info "--- setting project version from latest git commit: \\e[33;1m${cur_version}\\e[0m"

      # change version in pom
      # shellcheck disable=SC2086
      mvn versions:set $MAVEN_CLI_OPTS $mvn_settings_opt $java_proxy_args -DgenerateBackupPoms=false -DnewVersion="$cur_version-SNAPSHOT"

      # git commit change
      git commit -am "[ci skip] Prepare release with $cur_version version"
    fi
  }

  function configure_scm_auth() {
    # shellcheck disable=SC2086
    scm_url=$(mvn $MAVEN_CLI_OPTS $mvn_settings_opt $java_proxy_args org.apache.maven.plugins:maven-help-plugin:3.2.0:evaluate -Dexpression=project.scm.developerConnection -q -DforceStdout | tail -n 1)
    if [[ $scm_url == "scm:git:https"* ]]; then
      if [[ -n "${GIT_USERNAME}" ]] && [[ -n "${GIT_PASSWORD}" ]]; then
        log_info "--- using SCM credentials from env (\$GIT_USERNAME and \$GIT_PASSWORD)..."
        export scm_auth_args="-Dusername=${GIT_USERNAME} -Dpassword=${GIT_PASSWORD}"
      else
        log_error "--- project scm.developerConnection is using HTTPS protocol but no Git credentials are configured."
        log_error "--- Please specify the \$GIT_USERNAME and \$GIT_PASSWORD variables or change to SSH protocol with a SSH key."
      fi
    else
      # assume project is using SSH protocol
      if [[ -n "${GIT_PRIVATE_KEY}" ]]; then
        log_info "--- using Git SSH key from env (\$GIT_PRIVATE_KEY)..."
        mkdir -m 700 "${HOME}/.ssh"
        ssh-keyscan -H "${CI_SERVER_HOST}" >> ~/.ssh/known_hosts
        eval "$(ssh-agent -s)"
        # Handle file variable
        if [[ -f "${GIT_PRIVATE_KEY}" ]]; then
          tr -d '\r' < "${GIT_PRIVATE_KEY}" | ssh-add -
        else
          echo "${GIT_PRIVATE_KEY}" | tr -d '\r' | ssh-add -
        fi
        git config --global user.email "${GITLAB_USER_EMAIL}"
        git config --global user.name "${GITLAB_USER_LOGIN}"
      else
        log_error "--- project scm.developerConnection is using SSH protocol but no SSH key configured."
        log_error "--- Please either specify the \$GIT_PRIVATE_KEY variable or change to https protocol with username/password credentials."
      fi
    fi
  }

  function install_ca_certs() {
    certs=$1
    if [[ -z "$certs" ]]
    then
      return
    fi

    # import in system
    if echo "$certs" >> /etc/ssl/certs/ca-certificates.crt
    then
      log_info "CA certificates imported in \\e[33;1m/etc/ssl/certs/ca-certificates.crt\\e[0m"
    fi
    if echo "$certs" >> /etc/ssl/cert.pem
    then
      log_info "CA certificates imported in \\e[33;1m/etc/ssl/cert.pem\\e[0m"
    fi

    # import in Java keystore (if keytool command found)
    if command -v keytool > /dev/null
    then
      # shellcheck disable=SC2046
      javahome=${JAVA_HOME:-$(dirname $(readlink -f $(command -v java)))/..}
      # shellcheck disable=SC2086
      keystore=${JAVA_KEYSTORE_PATH:-$(ls -1 $javahome/jre/lib/security/cacerts 2>/dev/null || ls -1 $javahome/lib/security/cacerts 2>/dev/null || echo "")}
      if [[ -f "$keystore" ]]
      then
        storepass=${JAVA_KEYSTORE_PASSWORD:-changeit}
        nb_certs=$(echo "$certs" | grep -c 'END CERTIFICATE')
        log_info "importing $nb_certs certificates in Java keystore \\e[33;1m$keystore\\e[0m..."
        for idx in $(seq 0 $((nb_certs - 1)))
        do
          # TODO: use keytool option -trustcacerts ?
          if echo "$certs" | awk "n==$idx { print }; /END CERTIFICATE/ { n++ }" | keytool -noprompt -import -alias "imported CA Cert $idx" -keystore "$keystore" -storepass "$storepass"
          then
            log_info "... CA certificate [$idx] successfully imported"
          else
            log_warn "... Failed importing CA certificate [$idx]: abort"
            return
          fi
        done
      else
        log_warn "Java keystore \\e[33;1m$keystore\\e[0m not found: could not import CA certificates"
      fi
    fi
  }

  function unscope_variables() {
    _scoped_vars=$(env | awk -F '=' "/^scoped__[a-zA-Z0-9_]+=/ {print \$1}" | sort)
    if [[ -z "$_scoped_vars" ]]; then return; fi
    log_info "Processing scoped variables..."
    for _scoped_var in $_scoped_vars
    do
      _fields=${_scoped_var//__/:}
      _condition=$(echo "$_fields" | cut -d: -f3)
      case "$_condition" in
      if) _not="";;
      ifnot) _not=1;;
      *)
        log_warn "... unrecognized condition \\e[1;91m$_condition\\e[0m in \\e[33;1m${_scoped_var}\\e[0m"
        continue
      ;;
      esac
      _target_var=$(echo "$_fields" | cut -d: -f2)
      _cond_var=$(echo "$_fields" | cut -d: -f4)
      _cond_val=$(eval echo "\$${_cond_var}")
      _test_op=$(echo "$_fields" | cut -d: -f5)
      case "$_test_op" in
      defined)
        if [[ -z "$_not" ]] && [[ -z "$_cond_val" ]]; then continue; 
        elif [[ "$_not" ]] && [[ "$_cond_val" ]]; then continue; 
        fi
        ;;
      equals|startswith|endswith|contains|in|equals_ic|startswith_ic|endswith_ic|contains_ic|in_ic)
        # comparison operator
        # sluggify actual value
        _cond_val=$(echo "$_cond_val" | tr '[:punct:]' '_')
        # retrieve comparison value
        _cmp_val_prefix="scoped__${_target_var}__${_condition}__${_cond_var}__${_test_op}__"
        _cmp_val=${_scoped_var#"$_cmp_val_prefix"}
        # manage 'ignore case'
        if [[ "$_test_op" == *_ic ]]
        then
          # lowercase everything
          _cond_val=$(echo "$_cond_val" | tr '[:upper:]' '[:lower:]')
          _cmp_val=$(echo "$_cmp_val" | tr '[:upper:]' '[:lower:]')
        fi
        case "$_test_op" in
        equals*)
          if [[ -z "$_not" ]] && [[ "$_cond_val" != "$_cmp_val" ]]; then continue; 
          elif [[ "$_not" ]] && [[ "$_cond_val" == "$_cmp_val" ]]; then continue; 
          fi
          ;;
        startswith*)
          if [[ -z "$_not" ]] && [[ "$_cond_val" != "$_cmp_val"* ]]; then continue; 
          elif [[ "$_not" ]] && [[ "$_cond_val" == "$_cmp_val"* ]]; then continue; 
          fi
          ;;
        endswith*)
          if [[ -z "$_not" ]] && [[ "$_cond_val" != *"$_cmp_val" ]]; then continue; 
          elif [[ "$_not" ]] && [[ "$_cond_val" == *"$_cmp_val" ]]; then continue; 
          fi
          ;;
        contains*)
          if [[ -z "$_not" ]] && [[ "$_cond_val" != *"$_cmp_val"* ]]; then continue; 
          elif [[ "$_not" ]] && [[ "$_cond_val" == *"$_cmp_val"* ]]; then continue; 
          fi
          ;;
        in*)
          if [[ -z "$_not" ]] && [[ "__${_cmp_val}__" != *"__${_cond_val}__"* ]]; then continue; 
          elif [[ "$_not" ]] && [[ "__${_cmp_val}__" == *"__${_cond_val}__"* ]]; then continue; 
          fi
          ;;
        esac
        ;;
      *)
        log_warn "... unrecognized test operator \\e[1;91m${_test_op}\\e[0m in \\e[33;1m${_scoped_var}\\e[0m"
        continue
        ;;
      esac
      # matches
      _val=$(eval echo "\$${_target_var}")
      log_info "... apply \\e[32m${_target_var}\\e[0m from \\e[32m\$${_scoped_var}\\e[0m${_val:+ (\\e[33;1moverwrite\\e[0m)}"
      _val=$(eval echo "\$${_scoped_var}")
      export "${_target_var}"="${_val}"
    done
    log_info "... done"
  }

  # builds the Java proxy options from Linux env (http_proxy, https_proxy, ftp_proxy and no_proxy)
  function eval_java_proxy_args() {
    # transform no_proxy into Java stype nonProxyHosts
    nph=$(echo "${no_proxy:-$NO_PROXY}" | sed -e 's/\s*//g' -e 's/^\./*./' -e 's/,\./,*./g' -e 's/,/|/g')
    java_proxy_args="$(java_proto_proxy_args http "${http_proxy:-$HTTP_PROXY}" "$nph") $(java_proto_proxy_args https "${https_proxy:-$HTTPS_PROXY}" "$nph") $(java_proto_proxy_args ftp "${ftp_proxy:-$FTP_PROXY}" "$nph")"
    export java_proxy_args
    if [[ "$java_proxy_args" ]]
    then
      log_info "Using Java proxy options (from env):  \\e[33;1m$java_proxy_args\\e[0m"
    fi
  }

  function java_proto_proxy_args() {
    proto=$1
    proxy=$2
    non_proxy_hosts=$3
    if [[ "$proxy" ]]
    then
      host_port=$(echo "$proxy" | cut -d'/' -f3)
      host=$(echo "$host_port" | cut -d':' -f1)
      port=$(echo "$host_port" | cut -s -d':' -f2)
      proto_proxy_args="-D$proto.proxyHost=$host -D$proto.proxyPort=${port:-80}"
      if [[ "$non_proxy_hosts" ]]; then proto_proxy_args="$proto_proxy_args -D$proto.nonProxyHosts=\"$non_proxy_hosts\""; fi
      echo "$proto_proxy_args"
    fi
  }

  # autodetects any Maven settings file in $MAVEN_CFG_DIR and builds the Java CLI option accordingly
  function eval_mvn_settings_opt() {
    if [[ -f "$MAVEN_CFG_DIR/settings.xml" ]]
    then
      log_info "Maven settings file found: \\e[33;1m$MAVEN_CFG_DIR/settings.xml\\e[0m"
      mvn_settings_opt="-s $MAVEN_CFG_DIR/settings.xml"
    fi
  }

  function get_latest_template_version() {
    tag_json=$(curl -s --connect-timeout 5 "$CI_API_V4_URL/projects/to-be-continuous%2F$1/repository/tags?per_page=1" 2> /dev/null || echo "")
    echo "$tag_json" | sed -rn 's/^.*"name":"([^"]*)".*$/\1/p'
  }

  function check_for_update() {
    template="$1"
    actual="$2"
    latest=$(get_latest_template_version "$template")
    if [[ -n "$latest" ]] && [[ "$latest" != "$actual" ]]
    then
      log_warn "\\e[1;93m=======================================================================================================\\e[0m"
      log_warn "\\e[93mThe template \\e[32m$template\\e[93m:\\e[33m$actual\\e[93m you're using is not up-to-date: consider upgrading to version \\e[32m$latest\\e[0m"
      log_warn "\\e[93m(set \$TEMPLATE_CHECK_UPDATE_DISABLED to disable this message)\\e[0m"
      log_warn "\\e[1;93m=======================================================================================================\\e[0m"
    fi
  }

  function perform_snapshot() {
    # shellcheck disable=SC2086
    pom_version=$(mvn $MAVEN_CLI_OPTS $mvn_settings_opt $java_proxy_args org.apache.maven.plugins:maven-help-plugin:3.2.0:evaluate -Dexpression=project.version -q -DforceStdout | tail -n 1)
    case $pom_version in
        *-SNAPSHOT)
            log_info "Snapshot version for pom (\\e[33;1m${pom_version}\\e[0m): deploy"
            # shellcheck disable=SC2086
            mvn $MAVEN_CLI_OPTS $mvn_settings_opt $java_proxy_args $MAVEN_DEPLOY_ARGS
            ;;
        *)
            log_info "Not snapshot version for pom (\\e[33;1m${pom_version}\\e[0m): skip"
            ;;
    esac
  }

  if [[ "$TEMPLATE_CHECK_UPDATE_DISABLED" != "true" ]]; then check_for_update maven "2.1.4"; fi
  unscope_variables

  # ENDSCRIPT

# Generic maven job
.mvn-base:
  image: $MAVEN_IMAGE
  services:
    - name: "$CI_REGISTRY/to-be-continuous/tools/tracking:master"
      command: ["--service", "maven", "2.1.4" ]
  before_script:
    - *mvn-scripts
    - install_ca_certs "${CUSTOM_CA_CERTS:-$DEFAULT_CA_CERTS}"
    - eval_java_proxy_args
    - eval_mvn_settings_opt
  # Cache downloaded dependencies and plugins between builds.
  # To keep cache across branches add 'key: "$CI_JOB_NAME"'
  cache:
    key: "$CI_COMMIT_REF_SLUG-maven"
    paths:
      - ${MAVEN_CFG_DIR}/repository

mvn-build:
  extends: .mvn-base
  stage: build
  script:
    - mvn ${TRACE+-X} $MAVEN_CLI_OPTS $mvn_settings_opt $java_proxy_args $MAVEN_BUILD_ARGS
    - output_coverage
  # code coverage RegEx
  coverage: '/^(\d+\.?\d*\%) covered$/'
  # keep build artifacts and JUnit reports
  artifacts:
    name: "$CI_JOB_NAME artifacts from $CI_PROJECT_NAME on $CI_COMMIT_REF_SLUG"
    expire_in: 1 day
    when: always
    reports:
      junit:
        - "**/target/*-reports/TEST-*.xml"
    paths:
      - "**/target"
  rules:
    # exclude merge requests
    - if: '$CI_MERGE_REQUEST_ID == null'

# Sonar job
mvn-sonar:
  stage: test
  extends: .mvn-base
  variables:
    # Tells git to fetch all the branches of the project, required by the analysis task
    # see: https://docs.sonarqube.org/8.5/analysis/gitlab-cicd/#header-2
    GIT_DEPTH: 0
  script:
    - sonar_autodetect_mr
    - if [[ "$SONAR_GITLAB_TOKEN" ]]; then sonar_extra_args="$SONAR_GITLAB_ARGS"; fi
    - mvn ${TRACE+-Dsonar.verbose=true} $MAVEN_CLI_OPTS $mvn_settings_opt $java_proxy_args ${SONAR_AUTH_TOKEN+-Dsonar.login=$SONAR_AUTH_TOKEN} ${SONAR_LOGIN+-Dsonar.login=$SONAR_LOGIN} ${SONAR_PASSWORD+-Dsonar.password=$SONAR_PASSWORD} $SONAR_BASE_ARGS $sonar_extra_args $sonar_mr_args
    - if [[ "$SONAR_QUALITY_GATE_ENABLED" == "true" ]]; then sonar_quality_gate_check; fi
  rules:
    # exclude merge requests
    - if: $CI_MERGE_REQUEST_ID
      when: never
    # exclude if $SONAR_URL not set
    - if: '$SONAR_URL == null || $SONAR_URL == ""'
      when: never
    # on tags: auto
    - if: $CI_COMMIT_TAG
    # on production or integration: auto
    - if: '$CI_COMMIT_REF_NAME =~ $PROD_REF || $CI_COMMIT_REF_NAME =~ $INTEG_REF'
    # else (non-production, non-integration branches): manual if $SONAR_AUTO_ON_DEV_DISABLED
    - if: '$SONAR_AUTO_ON_DEV_DISABLED == "true"'
      when: manual
      allow_failure: true
    # else: auto & allow failure
    - allow_failure: true

mvn-dependency-check:
  extends: .mvn-base
  stage: test
  # force no dependency
  dependencies: []
  script:
    - mvn ${TRACE+-X} $MAVEN_CLI_OPTS $mvn_settings_opt $java_proxy_args $MAVEN_DEPENDENCY_CHECK_ARGS
  rules:
    # exclude merge requests
    - if: $CI_MERGE_REQUEST_ID
      when: never
    # on schedule: auto
    - if: '$CI_PIPELINE_SOURCE == "schedule"'
      allow_failure: true
      when: always
    # all other cases: manual & non-blocking
    - when: manual
      allow_failure: true
  artifacts:
    name: "$CI_JOB_NAME artifacts from $CI_PROJECT_NAME on $CI_COMMIT_REF_SLUG"
    expire_in: 1 day
    when: always
    paths:
      - "**/target/dependency-check-report.*"

mvn-forbid-snapshot-dependencies:
  extends: .mvn-base
  stage: test
  script:
    - mvn ${TRACE+-X} $MAVEN_CLI_OPTS $mvn_settings_opt $java_proxy_args org.apache.maven.plugins:maven-enforcer-plugin:3.0.0:enforce -Drules=requireReleaseDeps
  rules:
    # exclude merge requests
    - if: $CI_MERGE_REQUEST_ID
      when: never
    # exclude if disabled
    - if: '$MVN_FORBID_SNAPSHOT_DEPENDENCIES_DISABLED == "true"'
      when: never
    # on production or integration branches: auto
    - if: '$CI_COMMIT_REF_NAME =~ $PROD_REF || $CI_COMMIT_REF_NAME =~ $INTEG_REF'
    # else (feature branches): auto & non-blocking
    - allow_failure: true

mvn-snapshot:
  extends: .mvn-base
  stage: publish
  script:
    - perform_snapshot
  rules:
    # exclude merge requests
    - if: $CI_MERGE_REQUEST_ID
      when: never
    # on tags: never
    - if: $CI_COMMIT_TAG
      when: never
    # exclude unprotected ref if specified
    - if: '$MAVEN_DEPLOY_FROM_UNPROTECTED_DISABLED == "true" && $CI_COMMIT_REF_PROTECTED != "true"'
      when: never
    # else: if $MAVEN_DEPLOY_ENABLED is set
    - if: '$MAVEN_DEPLOY_ENABLED == "true"'

mvn-release:
  extends: .mvn-base
  stage: publish
  before_script:
    - !reference [ .mvn-base, before_script ]
    - log_info "Preparing Git repository for release..."
    - git config --global user.name $GITLAB_USER_ID
    - git config --global user.email $GITLAB_USER_EMAIL
    - git checkout -B "$CI_BUILD_REF_NAME"
  script:
    - configure_scm_auth
    - maybe_set_version_from_git
    - |
      if [ "${SEMREL_INFO_ON}" ] && [ "${MVN_SEMREL_RELEASE_DISABLED}" != "true" ]
      then
        if [ -z "${SEMREL_INFO_NEXT_VERSION}" ]
        then
          log_info "no new version to release"
          exit 0
        else
          log_info "semantic-release info is activated, using computed next version for release \\e[1;94m${SEMREL_INFO_NEXT_VERSION}\\e[0m"
          semrel_args="-DreleaseVersion=${SEMREL_INFO_NEXT_VERSION}"
        fi
      fi
    - mvn ${TRACE+-X} $MAVEN_CLI_OPTS $mvn_settings_opt $java_proxy_args $scm_auth_args ${MAVEN_RELEASE_ARGS} ${semrel_args} -DscmCommentPrefix="$MAVEN_RELEASE_SCM_COMMENT_PREFIX"
  rules:
    # exclude merge requests
    - if: $CI_MERGE_REQUEST_ID
      when: never
    # on production branch(es): manual & non-blocking if $MAVEN_DEPLOY_ENABLED is set
    - if: '$MAVEN_DEPLOY_ENABLED == "true" && $CI_COMMIT_REF_NAME =~ $PROD_REF'
      when: manual
      allow_failure: true
    # on integration branch(es): manual & non-blocking if $MAVEN_DEPLOY_ENABLED is set
    - if: '$MAVEN_DEPLOY_ENABLED == "true" && $CI_COMMIT_REF_NAME =~ $INTEG_REF'
      when: manual
      allow_failure: true
