Skip to content
Snippets Groups Projects
gitlab-ci-maven.yml 23.4 KiB
Newer Older
Pierre Smeyers's avatar
Pierre Smeyers committed
# =========================================================================================
Pierre Smeyers's avatar
Pierre Smeyers committed
# Copyright (C) 2021 Orange & contributors
Pierre Smeyers's avatar
Pierre Smeyers committed
#
# 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.
# =========================================================================================
Pierre Smeyers's avatar
Pierre Smeyers committed
# default workflow rules: Merge Request pipelines
workflow:
  rules:
Pierre Smeyers's avatar
Pierre Smeyers committed
    # prevent branch pipeline when an MR is open (prefer MR pipeline)
    - if: '$CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS'
      when: never
    - if: '$CI_COMMIT_MESSAGE =~ "/\[(ci skip|skip ci) on ([^],]*,)*tag(,[^],]*)*\]/" && $CI_COMMIT_TAG'
      when: never
    - if: '$CI_COMMIT_MESSAGE =~ "/\[(ci skip|skip ci) on ([^],]*,)*branch(,[^],]*)*\]/" && $CI_COMMIT_BRANCH'
      when: never
    - if: '$CI_COMMIT_MESSAGE =~ "/\[(ci skip|skip ci) on ([^],]*,)*mr(,[^],]*)*\]/" && $CI_MERGE_REQUEST_ID'
      when: never
    - if: '$CI_COMMIT_MESSAGE =~ "/\[(ci skip|skip ci) on ([^],]*,)*default(,[^],]*)*\]/" && $CI_COMMIT_REF_NAME =~ $CI_DEFAULT_BRANCH'
      when: never
    - if: '$CI_COMMIT_MESSAGE =~ "/\[(ci skip|skip ci) on ([^],]*,)*prod(,[^],]*)*\]/" && $CI_COMMIT_REF_NAME =~ $PROD_REF'
      when: never
    - if: '$CI_COMMIT_MESSAGE =~ "/\[(ci skip|skip ci) on ([^],]*,)*integ(,[^],]*)*\]/" && $CI_COMMIT_REF_NAME =~ $INTEG_REF'
      when: never
    - if: '$CI_COMMIT_MESSAGE =~ "/\[(ci skip|skip ci) on ([^],]*,)*dev(,[^],]*)*\]/" && $CI_COMMIT_REF_NAME !~ $PROD_REF && $CI_COMMIT_REF_NAME !~ $INTEG_REF'
      when: never
    - when: always

Pierre Smeyers's avatar
Pierre Smeyers committed
# test job prototype: implement adaptive pipeline rules
.test-policy:
  rules:
    # on tag: auto & failing
    - if: $CI_COMMIT_TAG
    # on ADAPTIVE_PIPELINE_DISABLED: auto & failing
    - if: '$ADAPTIVE_PIPELINE_DISABLED == "true"'
    # on production or integration branch(es): auto & failing
    - if: '$CI_COMMIT_REF_NAME =~ $PROD_REF || $CI_COMMIT_REF_NAME =~ $INTEG_REF'
    # early stage (dev branch, no MR): manual & non-failing
    - if: '$CI_MERGE_REQUEST_ID == null && $CI_OPEN_MERGE_REQUESTS == null'
      when: manual
      allow_failure: true
    # Draft MR: auto & non-failing
    - if: '$CI_MERGE_REQUEST_TITLE =~ /^Draft:.*/'
      allow_failure: true
    # else (Ready MR): auto & failing
    - when: on_success

Pierre Smeyers's avatar
Pierre Smeyers committed
variables:
  # variabilized tracking image
  TBC_TRACKING_IMAGE: "$CI_REGISTRY/to-be-continuous/tools/tracking:master"

  # Default Maven project root directory
  MAVEN_PROJECT_DIR: .

Pierre Smeyers's avatar
Pierre Smeyers committed
  # Maven image (can be overridden)
  MAVEN_IMAGE: "registry.hub.docker.com/library/maven:latest"
Pierre Smeyers's avatar
Pierre Smeyers committed

  # default production ref name (pattern)
  PROD_REF: '/^(master|main)$/'
Pierre Smeyers's avatar
Pierre Smeyers committed
  # default integration ref name (pattern)
  INTEG_REF: '/^develop$/'
  # default release tag name (pattern)
  RELEASE_REF: '/^v?[0-9]+\.[0-9]+\.[0-9]+$/'
Pierre Smeyers's avatar
Pierre Smeyers committed

  # default configuration directory
  MAVEN_CFG_DIR: ".m2"
  # default settings.xml file path
  MAVEN_SETTINGS_FILE: "$MAVEN_CFG_DIR/settings.xml"
Pierre Smeyers's avatar
Pierre Smeyers committed

  # `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.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: >-
    --no-transfer-progress
Pierre Smeyers's avatar
Pierre Smeyers committed
    --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.links.homepage=${CI_PROJECT_URL}
    -Dsonar.links.ci=${CI_PROJECT_URL}/-/pipelines
    -Dsonar.links.issue=${CI_PROJECT_URL}/-/issues

  # Dependency Check arguments
  MAVEN_DEPENDENCY_CHECK_ARGS: >-
    org.owasp:dependency-check-maven:aggregate
Pierre Smeyers's avatar
Pierre Smeyers committed
    -DretireJsAnalyzerEnabled=false
    -DassemblyAnalyzerEnabled=false
    -Dformats=HTML,JSON,XML
  
  # SBOM genenration arguments
  MAVEN_SBOM_GEN_ARGS: org.cyclonedx:cyclonedx-maven-plugin:makeAggregateBom

Pierre Smeyers's avatar
Pierre Smeyers committed
  # Maven deploy arguments
  MAVEN_DEPLOY_ARGS: "deploy -Dmaven.test.skip=true"
Pierre Smeyers's avatar
Pierre Smeyers committed

  # Maven release arguments
  MAVEN_RELEASE_ARGS: "release:prepare -DtagNameFormat=@{project.version} -Darguments=-Dmaven.test.skip=true"
  MAVEN_RELEASE_SCM_COMMENT_PREFIX: "chore(maven-release): "
Pierre Smeyers's avatar
Pierre Smeyers committed

stages:
  - build
  - test
  - package-build
  - package-test
  - infra
  - deploy
  - acceptance
Pierre Smeyers's avatar
Pierre Smeyers committed
  - publish
  - infra-prod
  - production
Pierre Smeyers's avatar
Pierre Smeyers committed

.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\\e[0m: skip"
Pierre Smeyers's avatar
Pierre Smeyers committed
    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"
Pierre Smeyers's avatar
Pierre Smeyers committed

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

  function configure_scm_auth() {
    log_info "Preparing Git repository for release..."
    # set user info
    git config --global user.email "${GITLAB_USER_EMAIL}"
    git config --global user.name "${GITLAB_USER_NAME}"
Pierre Smeyers's avatar
Pierre Smeyers committed
    # shellcheck disable=SC2086
    scm_url=$(mvn $MAVEN_CLI_OPTS $mvn_settings_opt $java_proxy_args help:evaluate -Dexpression=project.scm.developerConnection -q -DforceStdout | tail -n 1)
Pierre Smeyers's avatar
Pierre Smeyers committed
    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
      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}__"
Cédric OLIVIER's avatar
Cédric OLIVIER committed
        _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"
  }

Pierre Smeyers's avatar
Pierre Smeyers committed
  # 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
Pierre Smeyers's avatar
Pierre Smeyers committed
      echo "$proto_proxy_args"
    fi
  }

  # autodetects any Maven settings file in and builds the Java CLI option accordingly
  function eval_mvn_settings_opt() {
    if [[ -f "$MAVEN_SETTINGS_FILE" ]]
      log_info "Maven settings file found: \\e[33;1m$MAVEN_SETTINGS_FILE\\e[0m"
      mvn_settings_opt="-s $MAVEN_SETTINGS_FILE"
  function mvn_deploy() {
Pierre Smeyers's avatar
Pierre Smeyers committed
    # shellcheck disable=SC2086
    pom_version=$(mvn $MAVEN_CLI_OPTS $mvn_settings_opt $java_proxy_args help:evaluate -Dexpression=project.version -q -DforceStdout | tail -n 1)
    if [[ "$CI_COMMIT_TAG" ]] && [[ "$pom_version" =~ -SNAPSHOT$ ]]
    then
      log_warn "Can't publish SNAPSHOT version \\e[33;1m${pom_version}\\e[0m from tag: skip"
    elif [[ -z "$CI_COMMIT_TAG" ]] && [[ ! "$pom_version" =~ -SNAPSHOT$ ]]
    then
      log_warn "Can't publish non-SNAPSHOT version \\e[33;1m${pom_version}\\e[0m from branch: skip"
    else
      log_info "Publish version \\e[33;1m${pom_version}\\e[0m..."
      # shellcheck disable=SC2086
      mvn ${TRACE+-X} $MAVEN_CLI_OPTS $mvn_settings_opt $java_proxy_args $MAVEN_DEPLOY_ARGS
    fi
  # only on a branch commit, with deploy and "SNAPSHOT with slug" enabled
  function maybe_inject_slug_in_version() {
    if [[ "$CI_COMMIT_BRANCH" ]] && [[ "$MAVEN_DEPLOY_ENABLED" == "true" ]] && [[ "$MAVEN_DEPLOY_SNAPSHOT_WITH_SLUG_ENABLED" == "true" ]]
    then
      # check if on non-prod branch
      prod_ref_expr=${PROD_REF#/}
      prod_ref_expr=${prod_ref_expr%/}
      if [[ ! "$CI_COMMIT_BRANCH" =~ $prod_ref_expr ]]
      then
        # shellcheck disable=SC2086
        pom_version=$(mvn $MAVEN_CLI_OPTS $mvn_settings_opt $java_proxy_args help:evaluate -Dexpression=project.version -q -DforceStdout | tail -n 1)
        altered_pom_version="${pom_version%-SNAPSHOT}-${CI_COMMIT_REF_SLUG}-SNAPSHOT"
        log_info "Inject branch slug into SNAPSHOT version: \\e[33;1m${altered_pom_version}\\e[0m..."
        # shellcheck disable=SC2086
        mvn $MAVEN_CLI_OPTS $mvn_settings_opt $java_proxy_args versions:set -DgenerateBackupPoms=false -DnewVersion="${altered_pom_version}"
      fi
    fi
  }

  unscope_variables
Pierre Smeyers's avatar
Pierre Smeyers committed

  # ENDSCRIPT

# Generic maven job
.mvn-base:
  image: $MAVEN_IMAGE
  services:
    - name: "$TBC_TRACKING_IMAGE"
      command: ["--service", "maven", "3.7.0" ]
Pierre Smeyers's avatar
Pierre Smeyers committed
  before_script:
    - *mvn-scripts
    - install_ca_certs "${CUSTOM_CA_CERTS:-$DEFAULT_CA_CERTS}"
    - eval_java_proxy_args
    - eval_mvn_settings_opt
    - cd ${MAVEN_PROJECT_DIR}
Pierre Smeyers's avatar
Pierre Smeyers committed
  # 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_PROJECT_DIR}/${MAVEN_CFG_DIR}/repository"
Pierre Smeyers's avatar
Pierre Smeyers committed

mvn-build:
  extends: .mvn-base
  stage: build
  script:
    - maybe_inject_slug_in_version
    - mvn ${TRACE+-X} $MAVEN_CLI_OPTS $mvn_settings_opt $java_proxy_args $MAVEN_BUILD_ARGS
Pierre Smeyers's avatar
Pierre Smeyers committed
    - 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
Pierre Smeyers's avatar
Pierre Smeyers committed
    reports:
      junit:
        - "${MAVEN_PROJECT_DIR}/**/target/*-reports/TEST-*.xml"
Pierre Smeyers's avatar
Pierre Smeyers committed
    paths:
      # version may have been altered
      - pom.xml
      - "${MAVEN_PROJECT_DIR}/**/target"
Pierre Smeyers's avatar
Pierre Smeyers committed

# Sonar job
mvn-sonar:
  stage: test
  extends: .mvn-base
    # see: https://docs.sonarqube.org/latest/analysis/gitlab-integration/#header-4
    SONAR_USER_HOME: "${CI_PROJECT_DIR}/${MAVEN_PROJECT_DIR}/.sonar" # Defines the location of the analysis task cache
    GIT_DEPTH: 0 # Tells git to fetch all the branches of the project, required by the analysis task
  cache:
    key: "$CI_COMMIT_REF_SLUG-maven-sonar"
    paths:
      - "${MAVEN_PROJECT_DIR}/${MAVEN_CFG_DIR}/repository"
      - "${MAVEN_PROJECT_DIR}/.sonar/cache"
Pierre Smeyers's avatar
Pierre Smeyers committed
  script:
    - |
      if [[ "$SONAR_URL" ]] && [[ -z "$SONAR_HOST_URL" ]]
      then 
        log_warn '$SONAR_URL variable defined: use $SONAR_HOST_URL instead (see doc)'
        export SONAR_HOST_URL="$SONAR_URL"
      fi
    - |
      if [[ "$SONAR_AUTH_TOKEN" ]] && [[ -z "$SONAR_TOKEN" ]]
      then 
        log_warn '$SONAR_AUTH_TOKEN variable defined: use $SONAR_TOKEN instead (see doc)'
        export SONAR_TOKEN="$SONAR_AUTH_TOKEN"
      fi
    - >-
      mvn ${TRACE+-Dsonar.verbose=true} $MAVEN_CLI_OPTS $mvn_settings_opt $java_proxy_args
      ${SONAR_LOGIN+-Dsonar.login=$SONAR_LOGIN}
      ${SONAR_PASSWORD+-Dsonar.password=$SONAR_PASSWORD}
      ${SONAR_QUALITY_GATE_ENABLED+-Dsonar.qualitygate.wait=$SONAR_QUALITY_GATE_ENABLED}
Pierre Smeyers's avatar
Pierre Smeyers committed
  rules:
    # exclude if $SONAR_URL and $SONAR_HOST_URL not set
    - if: '($SONAR_HOST_URL == null || $SONAR_HOST_URL == "") && ($SONAR_URL == null || $SONAR_URL == "")'
Pierre Smeyers's avatar
Pierre Smeyers committed
      when: never
Pierre Smeyers's avatar
Pierre Smeyers committed
    - !reference [.test-policy, rules]
Pierre Smeyers's avatar
Pierre Smeyers committed

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
Pierre Smeyers's avatar
Pierre Smeyers committed
  artifacts:
    name: "$CI_JOB_NAME artifacts from $CI_PROJECT_NAME on $CI_COMMIT_REF_SLUG"
    expire_in: 1 day
    when: always
    paths:
      - "${MAVEN_PROJECT_DIR}/**/target/dependency-check-report.*"
Pierre Smeyers's avatar
Pierre Smeyers committed
  rules:
    # exclude if disable
    - if: '$MAVEN_DEPENDENCY_CHECK_DISABLED == "true"'
      when: never
Pierre Smeyers's avatar
Pierre Smeyers committed
    # on schedule: auto
    - if: '$CI_PIPELINE_SOURCE == "schedule"'
      allow_failure: true
      when: always
    # all other cases: manual & non-blocking
    - when: manual
      allow_failure: true

  extends: .mvn-base
  stage: test
    - mvn ${TRACE+-X} $MAVEN_CLI_OPTS $mvn_settings_opt $java_proxy_args enforcer:enforce -Drules=requireReleaseDeps
  rules:
    # exclude if disabled
    - if: '$MVN_FORBID_SNAPSHOT_DEPENDENCIES_DISABLED == "true"'
Pierre Smeyers's avatar
Pierre Smeyers committed
    - !reference [.test-policy, rules]
mvn-sbom:
  extends: .mvn-base
  stage: test
  # force no dependency
  dependencies: []
  script:
    - mvn ${TRACE+-X} $MAVEN_CLI_OPTS $mvn_settings_opt $java_proxy_args $MAVEN_SBOM_GEN_ARGS -DoutputName=mvn-sbom.cyclonedx -DoutputFormat=json
    - chmod a+r target/mvn-sbom.cyclonedx.json
  artifacts:
    name: "SBOM for Maven from $CI_PROJECT_NAME on $CI_COMMIT_REF_SLUG"
    expire_in: 1 week
    when: always
    paths:
      - "${MAVEN_PROJECT_DIR}/target/mvn-sbom.cyclonedx.json"
    reports:
      cyclonedx: 
        - "${MAVEN_PROJECT_DIR}/target/mvn-sbom.cyclonedx.json"
  rules:
    # exclude if disabled
    - if: '$MAVEN_SBOM_DISABLED == "true"'
      when: never
    - !reference [.test-policy, rules]

mvn-deploy-snapshot:
Pierre Smeyers's avatar
Pierre Smeyers committed
  extends: .mvn-base
  stage: publish
  script:
Pierre Smeyers's avatar
Pierre Smeyers committed
  rules:
    # exclude if $MAVEN_DEPLOY_ENABLED not set
    - if: '$MAVEN_DEPLOY_ENABLED != "true"'
      when: never
Pierre Smeyers's avatar
Pierre Smeyers committed
    # on tags: never
    - if: $CI_COMMIT_TAG
      when: never
    # exclude unprotected ref if disabled
    - if: '$MAVEN_DEPLOY_FROM_UNPROTECTED_DISABLED != "true" || $CI_COMMIT_REF_PROTECTED == "true"'

mvn-deploy-release:
  extends: .mvn-base
  stage: publish
  script:
    - mvn_deploy
  rules:
    # exclude if $MAVEN_DEPLOY_ENABLED not set
    - if: '$MAVEN_DEPLOY_ENABLED != "true"'
Pierre Smeyers's avatar
Pierre Smeyers committed
      when: never
    # on tag with release pattern: auto
    - if: '$CI_COMMIT_TAG =~ $RELEASE_REF'
Pierre Smeyers's avatar
Pierre Smeyers committed

mvn-release:
  extends: .mvn-base
  stage: publish
  before_script:
    - !reference [ .mvn-base, before_script ]
    - git checkout -B "$CI_COMMIT_REF_NAME"
Pierre Smeyers's avatar
Pierre Smeyers committed
  script:
    - configure_scm_auth
    - maybe_set_version_from_git
      if [ "${SEMREL_INFO_ON}" ] && [ "${MVN_SEMREL_RELEASE_DISABLED}" != "true" ]
        if [ -z "${SEMREL_INFO_NEXT_VERSION}" ]
        then
          log_info "No next release version determined by semantic-release info: skip"
          log_info "Use next release version determined by semantic-release info: \\e[1;94m${SEMREL_INFO_NEXT_VERSION}\\e[0m"
          semrel_args="-DreleaseVersion=${SEMREL_INFO_NEXT_VERSION}"
        fi
    - >-
      mvn ${TRACE+-X} $MAVEN_CLI_OPTS $mvn_settings_opt $java_proxy_args
      ${scm_auth_args} ${semrel_args}
      ${MAVEN_RELEASE_VERSION+-DreleaseVersion="$MAVEN_RELEASE_VERSION"}
      ${MAVEN_RELEASE_SCM_COMMENT_PREFIX+-DscmCommentPrefix="$MAVEN_RELEASE_SCM_COMMENT_PREFIX"}
      ${MAVEN_RELEASE_SCM_RELEASE_COMMENT+-DscmReleaseCommitComment="$MAVEN_RELEASE_SCM_RELEASE_COMMENT"}
      ${MAVEN_RELEASE_SCM_DEV_COMMENT+-DscmDevelopmentCommitComment="$MAVEN_RELEASE_SCM_DEV_COMMENT"}
      ${MAVEN_RELEASE_ARGS}
Pierre Smeyers's avatar
Pierre Smeyers committed
  rules:
    # exclude if $MAVEN_DEPLOY_ENABLED not set
    - if: '$MAVEN_DEPLOY_ENABLED != "true"'
      when: never
    # on production or integration branch: manual, non blocking
    - if: '$CI_COMMIT_REF_NAME =~ $PROD_REF || $CI_COMMIT_REF_NAME =~ $INTEG_REF'
Pierre Smeyers's avatar
Pierre Smeyers committed
      when: manual
      allow_failure: true