String GITHUB_REPOSITORY = "crm-order-api"
String ECR_ACCOUNT_ID = '703740486246'
String ECR_REPO = 'crm-ecommerce/order'
List<String> AWS_REGIONS = ['us-east-1']
String INTEGRATION_TEST_ROLE = "dev-ecommerce-integration-tests-role"
String DEPLOYMENT_ROLE = "prod-jenkins-pipeline-deploy-role"
String ACCOUNT_ID = '703740486246'
String SESSION_NAME = "crm-jenkins"
String CLUSTER_NAME = 'ecommerce-clu'
String SERVICE_NAME = 'ecommerce-order'
String SLACK_NOTIFICATIONS_CHANNEL = '#crm-cicd-alerts'

List<String> VULNERABILITIES_TO_IGNORE = [
  "IN-DISCONTINUED-001",
  "CVE-2023-20883",
  "CVE-2023-30535",
  "CVE-2024-38819",
  "CVE-2021-45046",
  "CVE-2016-1000027",
  "CVE-2019-17531",
  "CVE-2023-26464",
  "CVE-2018-11307",
  "CVE-2020-8840",
  "CVE-2023-44487",
  "CVE-2021-25329",
  "CVE-2017-3523",
  "CVE-2021-22118",
  "CVE-2016-1000343",
  "CVE-2020-36184",
  "CVE-2021-46877",
  "CVE-2020-24750",
  "CVE-2020-35490",
  "CVE-2024-22243",
  "CVE-2019-10202",
  "CVE-2025-48734",
  "CVE-2022-42252",
  "CVE-2018-5968",
  "CVE-2018-12022",
  "CVE-2017-7525",
  "CVE-2018-14719",
  "CVE-2020-36182",
  "CVE-2024-38816",
  "CVE-2022-22968",
  "CVE-2022-23307",
  "CVE-2020-36187",
  "CVE-2017-7957",
  "CVE-2019-14439",
  "CVE-2023-20860",
  "CVE-2014-0114",
  "CVE-2018-14718",
  "CVE-2022-21724",
  "CVE-2018-3258",
  "CVE-2025-49125",
  "CVE-2020-11620",
  "CVE-2019-12086",
  "CVE-2023-1436",
  "CVE-2020-11111",
  "CVE-2018-19361",
  "CVE-2022-23181",
  "CVE-2025-24813",
  "CVE-2020-24616",
  "CVE-2022-25857",
  "CVE-2022-31197",
  "CVE-2022-1471",
  "CVE-2019-14893",
  "CVE-2020-10673",
  "CVE-2019-17571",
  "CVE-2020-26217",
  "CVE-2024-22259",
  "CVE-2020-25638",
  "CVE-2018-1336",
  "CVE-2016-1000340",
  "CVE-2018-14720",
  "CVE-2020-36188",
  "CVE-2020-36518",
  "CVE-2024-50379",
  "CVE-2024-21634",
  "CVE-2020-36181",
  "CVE-2021-45105",
  "CVE-2020-35491",
  "CVE-2016-1000338",
  "CVE-2020-36189",
  "CVE-2022-26520",
  "CVE-2019-14379",
  "CVE-2022-42003",
  "CVE-2020-9484",
  "CVE-2018-8014",
  "CVE-2024-1597",
  "CVE-2020-36180",
  "CVE-2020-36185",
  "CVE-2020-14060",
  "CVE-2023-20873",
  "CVE-2019-10086",
  "CVE-2022-23221",
  "CVE-2024-34750",
  "CVE-2020-14062",
  "CVE-2020-9547",
  "CVE-2018-7489",
  "CVE-2022-22970",
  "CVE-2016-1000352",
  "CVE-2021-44228",
  "CVE-2022-42004",
  "CVE-2020-9546",
  "CVE-2021-27568",
  "CVE-2022-40150",
  "CVE-2019-16942",
  "CVE-2018-19360",
  "CVE-2023-5072",
  "CVE-2025-22235",
  "CVE-2023-6378",
  "CVE-2020-28491",
  "CVE-2023-2976",
  "CVE-2017-15095",
  "CVE-2024-22262",
  "CVE-2024-56337",
  "CVE-2021-25122",
  "CVE-2023-24998",
  "CVE-2018-19362",
  "CVE-2020-13692",
  "CVE-2022-45693",
  "CVE-2020-10969",
  "CVE-2020-11112",
  "CVE-2022-22965",
  "CVE-2019-16335",
  "CVE-2019-10172",
  "CVE-2024-29857",
  "CVE-2023-6481",
  "CVE-2024-24549",
  "CVE-2021-4104",
  "CVE-2020-9548",
  "CVE-2022-40149",
  "CVE-2020-14195",
  "CVE-2017-17485",
  "CVE-2016-5388",
  "CVE-2024-38286",
  "CVE-2018-12023",
  "CVE-2022-23302",
  "CVE-2018-14721",
  "CVE-2020-36179",
  "CVE-2022-45688",
  "CVE-2020-36186",
  "CVE-2024-47554",
  "CVE-2025-48988",
  "CVE-2020-1938",
  "CVE-2016-1000342",
  "CVE-2023-46589",
  "CVE-2017-5929",
  "CVE-2025-24789",
  "CVE-2025-48989",
  "CVE-2025-46701",
  "CVE-2020-10968",
  "CVE-2020-11619",
  "CVE-2020-36183",
  "CVE-2021-31684",
  "CVE-2020-10650",
  "CVE-2023-22102",
  "CVE-2023-20863",
  "CVE-2019-17267",
  "CVE-2022-23305",
  "CVE-2018-8088",
  "CVE-2020-11113",
  "CVE-2020-35728",
  "CVE-2023-31582",
  "CVE-2021-42392",
  "CVE-2022-45685",
  "CVE-2021-41079",
  "CVE-2018-10936",
  "CVE-2020-5421",
  "CVE-2024-52316",
  "CVE-2021-20190",
  "CVE-2020-17527",
  "CVE-2020-25649",
  "CVE-2019-20330",
  "CVE-2023-1370",
  "CVE-2019-14540",
  "CVE-2018-8034",
  "CVE-2025-52999",
  "CVE-2016-1000344",
  "CVE-2020-14061",
  "CVE-2019-16943",
  "CVE-2020-13936",
  "CVE-2020-10672",
  "CVE-2019-14892",
  "CVE-2018-1000180",
  "CVE-2025-55752",
  "CVE-2025-49124",
  "CVE-2024-12798",
  "CVE-2025-41249",
  "CVE-2025-12183",
  "CVE-2025-66566",
  "CVE-2014-0107",
  "CVE-2022-34169",
  "CVE-2024-29371",
  "CVE-2025-7962",
  "CVE-2026-24400",
  "CVE-2026-0603",
]

pipeline {
  agent any

  options {
    ansiColor('xterm')
    disableConcurrentBuilds()
    timestamps()
  }

  parameters {
    booleanParam(name: 'DEPLOY_TO_PROD', defaultValue: true, description: 'Whether or not to deploy to prod.')
    booleanParam(name: 'DEPLOY_DEV_FROM_PR', defaultValue: false, description: 'Deploy dev environment from the PR')
    booleanParam(name: 'SKIP_CI_REPORTS', defaultValue: false, description: 'Skip checkstyle, pmd and findbugs reports')
    string(name: 'SHARED_LIBRARIES_VERSION', defaultValue: 'master', description: 'The version of the Jenkins shared libraries to use. Can be a branch, tag or Git revision.')
  }

  triggers {
    issueCommentTrigger('.*retest this please.*')
  }

  stages {
    stage('Load Shared Libraries') {
      steps {
        library "jenkins-global-libraries@${params.SHARED_LIBRARIES_VERSION}"
      }
    }
    stage('Validate Software Catalog Definition') {
      steps {
        datadogSoftwareCatalogValidate()
      }
    }
    stage("Tests and checkstyle") {
      agent {
        docker {
          image "maven:3.9.13-eclipse-temurin-17"
          // The following args are aimed to workaround some issues with using Docker container as a Jenkins agent:
          // 1. Disable image entrypoint to let Jenkins verify container was started correctly using custom commands.
          // 2. Explicitly tell SBT locations for configs and local cache because Jenkins runs container using a
          //    custom user (with `-u 1000:1000`) and SBT cannot resolve these paths automatically.
          // 3. Set MaxMetaspaceSize to 1G due to OOM
          //args '--entrypoint "" -e JAVA_OPTS="-Dsbt.color=false -Dsbt.global.base=.sbt -Dsbt.boot.directory=.sbt -Dsbt.ivy.home=.ivy2"'
          reuseNode true
        }
      }
      stages {
        stage("Dependencies") {
          steps {
              sh 'mvn dependency:go-offline -B --settings .custom-mvn-settings.xml'
          }
        }
        stage("Test") {
          steps {
            withAWS(role: INTEGRATION_TEST_ROLE,
                    roleAccount: ACCOUNT_ID,
                    roleSessionName: SESSION_NAME,
                    useNode: true) {
              sh 'mvn test -q --settings .custom-mvn-settings.xml'
            }
          }
        }
        stage("Checkstyle/pmd") {
          when {
            not {
              expression {return params.SKIP_CI_REPORTS}
            }
          }
          steps {
              sh 'mvn checkstyle:checkstyle pmd:pmd pmd:cpd -q --settings .custom-mvn-settings.xml'
          }
        }
      }
      post {
        always {
          junit testResults: '**/target/surefire-reports/TEST-*.xml'
          recordIssues enabledForFailure: false, tools: [mavenConsole(), java(), javaDoc()]
          recordIssues enabledForFailure: true, tool: checkStyle()
          recordIssues enabledForFailure: true, tool: cpd(pattern: '**/target/cpd.xml')
          recordIssues enabledForFailure: true, tool: pmdParser(pattern: '**/target/pmd.xml')
        }
      }
    }

    stage('Compliance Checks') {
      steps {
        complianceChecks()
      }
    }
   /* Disabled by request from DevOps team
    stage('Static Application Security Tests') {
      steps {
        sastTests()
      }
    }
    */
    /* Java project are not yet supported by our library
    stage('Sonar Scan and Analysis') {
      when {
        branch 'master'
      }
      steps {
        sonarScan project: GITHUB_REPOSITORY, language: 'java'
      }
    } */
    stage('Create a Release') {
      when {
        anyOf {
          branch 'master'
          expression { env.GITHUB_COMMENT =~ 'build docker' }
          expression { return params.DEPLOY_DEV_FROM_PR }
        }
      }
      steps {
          dockerToEcr awsRegions: AWS_REGIONS, ecrAccountId: ECR_ACCOUNT_ID, imageName: ECR_REPO, imageTag: env.GIT_COMMIT,
              dockerBuildTarget: 'deploy'
      }
    }
    stage('Deploy to dev') {
      when {
        anyOf{
          branch 'master'
          expression { return params.DEPLOY_DEV_FROM_PR }
        }
      }
      environment {
        ENV = "dev"
      }
      steps {
        withAWS(
          role: DEPLOYMENT_ROLE,
          roleAccount: ACCOUNT_ID,
          roleSessionName: SESSION_NAME,
          useNode: true
        ) {
          retagEcrImage awsRegions: AWS_REGIONS,
            ecrAccountId: ECR_ACCOUNT_ID,
            imageName: ECR_REPO,
            imageTag: env.GIT_COMMIT,
            newTag: 'develop'
          sh """
            set -eu
            aws ecs update-service --service ${env.ENV}-${SERVICE_NAME} --cluster ${env.ENV}-${CLUSTER_NAME} --force-new-deployment
            aws ecs wait services-stable --service ${env.ENV}-${SERVICE_NAME} --cluster ${env.ENV}-${CLUSTER_NAME}
          """
        }
      }
    }
    stage('Scan Docker Image') {
      when {
        anyOf {
          branch 'master'
          expression { env.GITHUB_COMMENT =~ 'build docker' }
          expression { return params.DEPLOY_DEV_FROM_PR }
        }
      }
      steps {
          dockerScan awsRegion: AWS_REGIONS[0], ecrAccountId: ECR_ACCOUNT_ID, imageName: ECR_REPO,
              imageTag: env.GIT_COMMIT, vulnerabilitiesToIgnore: VULNERABILITIES_TO_IGNORE
      }
    }
    stage('Deploy to Prod') {
      when {
        allOf{
          branch 'master'
          expression { return params.DEPLOY_TO_PROD }
        }
      }
      environment {
        ENV = "prod"
      }
      steps {
        withAWS(
          role: DEPLOYMENT_ROLE,
          roleAccount: ACCOUNT_ID,
          roleSessionName: SESSION_NAME,
          useNode: true
        ) {
          retagEcrImage awsRegions: AWS_REGIONS,
            ecrAccountId: ECR_ACCOUNT_ID,
            imageName: ECR_REPO,
            imageTag: env.GIT_COMMIT,
            newTag: 'production'
          sh """
            set -eu
            aws ecs update-service --service ${env.ENV}-${SERVICE_NAME} --cluster ${env.ENV}-${CLUSTER_NAME} --force-new-deployment
            aws ecs wait services-stable --service ${env.ENV}-${SERVICE_NAME} --cluster ${env.ENV}-${CLUSTER_NAME}
          """
        }
      }
    }
    stage('Publish Software Catalog Definition') {
      when {
        allOf {
          branch 'master'
          expression { params.DEPLOY_TO_PROD }
        }
      }
      steps {
        datadogSoftwareCatalogPublish()
      }
    }
  }
  post {
    regression {
      script {
        if (env.BRANCH_NAME == 'master') {
          slackNotify channel: SLACK_NOTIFICATIONS_CHANNEL
        }
      }
    }
    fixed {
      script {
        if (env.BRANCH_NAME == 'master') {
          slackNotify channel: SLACK_NOTIFICATIONS_CHANNEL
        }
      }
    }
    cleanup {
      cleanWs()
    }
  }
}
