String GITHUB_REPOSITORY = 'docker-database-images'
String ECR_ACCOUNT_ID = '086679231553'
String SLACK_NOTIFICATIONS_CHANNEL = '#devops-internal-alerts'
List<String> AWS_REGIONS = ['us-east-1']

@groovy.transform.Field
String ARTIFACTS_DIR = 'artifacts'

@groovy.transform.Field
String AWS_SHARED_ACCOUNT_ID = '086679231553'

@groovy.transform.Field
String AWS_COPY_ROLE = 'shared-s3-rds-backup-artifacts-read'

@groovy.transform.Field
List<String> databases = null

pipeline {
    agent any

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

    parameters {
        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).'
        )
        string(
            name: 'DATABASE',
            defaultValue: '',
            description: 'Build single database, default all.'
        )
    }

    triggers {
        issueCommentTrigger('.*retest this please.*')
        parameterizedCron(env.BRANCH_NAME == 'master' ? '0 9 * * *' : '')
    }

    stages {
        stage('Load Shared Libraries') {
            steps {
                library "jenkins-global-libraries@${params.SHARED_LIBRARIES_VERSION}"
            }
        }
        stage('Compliance Checks') {
            steps {
                complianceChecks()
            }
        }
        stage('Build') {
            steps {
                script {
                    parallel(getDatabases().collectEntries { database ->
                        return [(database):{
                            def engineData = readJSON(file: "${ARTIFACTS_DIR}/${database}/engine.json")
                            def dbType = engineData.engine
                            def dbVersion = engineData.version
                            def imageTag = env.BRANCH_NAME == 'master' ? database : "${database}-${env.BRANCH_NAME}"
                            echo "Building ${database}:${dbType}:${dbVersion}"
                            dockerToEcr(
                                awsRegions: AWS_REGIONS,
                                ecrAccountId: ECR_ACCOUNT_ID,
                                imageName: GITHUB_REPOSITORY,
                                imageTag: imageTag,
                                dockerBuildContext: "${dbType}/",
                                dockerBuildFile: "${dbType}/Dockerfile",
                                dockerBuildArgs: [
                                    'VERSION': dbVersion
                                ],
                                additionalContexts: [
                                    'artifacts': "../../${ARTIFACTS_DIR}/${database}"
                                ],
                                pushLatest: false
                            )
                        }]
                    })
                }
            }
        }
        stage('Test') {
            steps {
                script {
                    parallel(getDatabases().collectEntries { database ->
                        return [(database):{
                            def engineData = readJSON(file: "${ARTIFACTS_DIR}/${database}/engine.json")
                            def dbType = engineData.engine
                            def imageTag = env.BRANCH_NAME == 'master' ? database : "${database}-${env.BRANCH_NAME}"
                            withEcr {
                                dir(dbType) {
                                    sh("./test.sh ${ECR_ACCOUNT_ID} ${AWS_REGIONS[0]} ${imageTag}")
                                }
                            }
                        }]
                    })
                }
            }
        }
    }
    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()
        }
    }
}

def getDatabases() {
    if (this.@databases != null) {
        return this.@databases
    }
    withAWS(role: AWS_COPY_ROLE, roleAccount: AWS_SHARED_ACCOUNT_ID, useNode: true) {
        sh("aws s3 cp s3://shared-rds-backup-artifacts/ ./ --recursive")
    }
    this.@databases = []
    if (params.DATABASE != '') {
        this.@databases << params.DATABASE
    }
    else {
        dir(ARTIFACTS_DIR) {
            findFiles().each { file ->
                echo "Found file: ${file.name} ${file.directory}"
                if (file.directory && file.name != ARTIFACTS_DIR) {
                    def engineData = readJSON(file: "${file.name}/engine.json")
                    def dbType = engineData.engine
                    if (dbType == 'postgresql') {
                        echo "Skipping Postgres due to known issues"
                    }
                    else {
                        this.@databases << file.name
                    }
                }
            }
        }
    }
    assert this.@databases.size() > 0, "No databases found to build"
    return this.@databases
}
