String GITHUB_REPOSITORY = 'ows-royalties-workflows'
String SLACK_NOTIFICATIONS_CHANNEL = 'abacus-devs'

def deploymentTargets = [
    'qa': [
        accountId: '437795906767',
        deploymentRole: 'qa-abacus-managed-airflow-s3-policy-jenkins-invoke-role'
    ],
    'prod': [
        accountId: '437795906767',
        deploymentRole: 'prod-abacus-managed-airflow-s3-policy-jenkins-invoke-role'
    ],
    'uat': [
        accountId: '989790945997',
        deploymentRole: 'uat-abacus-airflow-s3-policy-jenkins-invoke-role'
    ]
]

pipeline {
    agent any

    environment {
        AWS_REGION = 'us-east-1'
        BUCKET_NAME = 'abacus-airflow'
        CLUSTER_ID = 'abacus-airflow'
        QA_ENVIRONMENT_NAME = 'qa'
        PROD_ENVIRONMENT_NAME = 'prod'
        UAT_ENVIRONMENT_NAME = 'uat'
        AWS_ASSUME_PROFILE = 'orcd-prod'
        QA_KMS_KEY_ID = 'cdbef157-21cf-4e9b-b91a-8a063b0d9c02'
        PROD_KMS_KEY_ID = 'f8a7ea1e-4d1e-4715-b4ab-6af8de4a1685'
        UAT_KMS_KEY_ID = '110dfd71-7dc5-45b0-8bc7-c6d4c9db43f0'
    }

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

    parameters {
        booleanParam(name: 'DEPLOY_TO_PROD', defaultValue: true, description: 'Whether or not to deploy to prod.')
        booleanParam(name: 'DEPLOY_TO_UAT', defaultValue: true, description: 'Whether or not to deploy to UAT Accounting.')
        string(name: 'SHARED_LIBRARIES_VERSION', defaultValue: 'master', description: 'The version of the Jenkins shared libraries to use. Can be a branch, tag, Git revision or PR ref (e.g. pull/PR_NUMBER/merge).')
    }

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

    stages {
        stage('Load Shared Libraries') {
            steps {
                library "jenkins-global-libraries@${params.SHARED_LIBRARIES_VERSION}"
            }
        }
        stage('Compliance Checks') {
            steps {
                complianceChecks()
            }
        }
        stage('Unit Tests and Style Checks') {
            steps {
                withEcr {
                    sh '''
                        export AWS_DEFAULT_REGION=${AWS_REGION}
                        export AWS_ROLE_ARN="arn:aws:iam::437795906767:role/prod-jenkins-aws-pipeline-agent"
                        export AWS_CREDS_JSON="$(aws sts assume-role --output json --role-arn ${AWS_ROLE_ARN} --duration-seconds 3600 --role-session-name session-${AWS_ASSUME_PROFILE})"
                        export AWS_SESSION_TOKEN="$(echo ${AWS_CREDS_JSON} | jq -r .Credentials.SessionToken)"
                        export AWS_ACCESS_KEY_ID="$(echo ${AWS_CREDS_JSON} | jq -r .Credentials.AccessKeyId)"
                        export AWS_SECRET_ACCESS_KEY="$(echo ${AWS_CREDS_JSON} | jq -r .Credentials.SecretAccessKey)"
                        export AIRFLOW_HOME=$WORKSPACE
                        make ci_unit_lint
                    '''
                }
            }
            post {
                always {
                    xunit tools: [JUnit(pattern: 'build/pyunit.xml', deleteOutputFiles: true, failIfNotNew: true, stopProcessingIfError: true)]
                    recordCoverage(tools: [[parser: 'COBERTURA', pattern: 'build/coverage.xml']], enabledForFailure: true, failOnError: true, sourceDirectories: [[path: "dags"]])
                }
                cleanup {
                    sh 'make ci_unit_lint_clean'
                }
            }
        }
        stage('Sonar Scan and Analysis') {
            when {
                branch 'master'
            }
            steps {
                sonarScan project: GITHUB_REPOSITORY, language: 'py'
            }
        }
        stage('Deploy Airflow to QA') {
            when {
                branch 'master'
            }
            steps {
                airflowDeploy(
                    bucket: "${QA_ENVIRONMENT_NAME}-${BUCKET_NAME}",
                    environment: QA_ENVIRONMENT_NAME,
                    gitCommit: env.GIT_COMMIT,
                    kmsKeyId: QA_KMS_KEY_ID,
                    serviceName: CLUSTER_ID,
                    awsDeploymentRoleName: deploymentTargets['qa'].deploymentRole,
                    awsDeploymentTargetAccountId: deploymentTargets['qa'].accountId
                )
            }
        }
        stage('Deploy Airflow to UAT Accounting') {
            when {
                allOf {
                    branch 'master'
                    expression { params.DEPLOY_TO_UAT == true }
                }
            }
            steps {
                airflowDeploy(
                    bucket: "${UAT_ENVIRONMENT_NAME}-${BUCKET_NAME}",
                    environment: UAT_ENVIRONMENT_NAME,
                    gitCommit: env.GIT_COMMIT,
                    kmsKeyId: UAT_KMS_KEY_ID,
                    serviceName: CLUSTER_ID,
                    awsDeploymentRoleName: deploymentTargets['uat'].deploymentRole,
                    awsDeploymentTargetAccountId: deploymentTargets['uat'].accountId
                )
            }
        }
        stage('Deploy Airflow to PROD') {
            when {
                allOf {
                    branch 'master'
                    expression { params.DEPLOY_TO_PROD == true }
                }
            }
            steps {
                airflowDeploy(
                    bucket: "${PROD_ENVIRONMENT_NAME}-${BUCKET_NAME}",
                    environment: PROD_ENVIRONMENT_NAME,
                    gitCommit: env.GIT_COMMIT,
                    kmsKeyId: PROD_KMS_KEY_ID,
                    serviceName: CLUSTER_ID,
                    awsDeploymentRoleName: deploymentTargets['prod'].deploymentRole,
                    awsDeploymentTargetAccountId: deploymentTargets['prod'].accountId
                )
            }
        }
    }

    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()
        }
    }
}
