import groovy.json.JsonOutput

STAGING_BRANCH = "master"
STAGING_ACCOUNT = "twitch-eventbus-dev"
STAGING_ACCOUNT_ID = 297385687169
PRODUCTION_ACCOUNT = "twitch-eventbus-prod"
PRODUCTION_ACCOUNT_ID = 859517684765
AWS_REGION = "us-west-2"

def make(cmd) {
  sh "make ${cmd}"
}

def ecrEndpoint(accountID) {
  return "${accountID}.dkr.ecr.us-west-2.amazonaws.com"
}

def gitShortCommitSha() {
    return sh(script: "git rev-parse --short HEAD", returnStdout: true).trim()
}

def gitShortCommitMsg() {
    return sh(script: "git log --pretty=oneline --abbrev-commit -1 --no-decorate", returnStdout: true).trim()
}

def commitLink() {
  sha = gitShortCommitSha()
  msg = gitShortCommitMsg()
  return "<https://git.xarth.tv/eventbus/controlplane/commit/${sha}|*\"${msg}\"*>"
}

// see https://api.slack.com/tools/block-kit-builder
def postSlackBlocks(blocks) {
    d = [icon_emoji: ":jenkins:", blocks: blocks]
    json = JsonOutput.toJson(d)
    withCredentials([string(credentialsId: 'eventbus_deploys_webhook', variable: 'EVENTBUS_DEPLOYS_WEBHOOK')]) {
      sh "curl -X POST $eventbus_deploys_webhook -d '${json}' "
    }
}

pipeline {
    agent any
    options {
        disableConcurrentBuilds()
        timeout(time: 1, unit: 'HOURS')
        ansiColor('xterm')
        timestamps()
    }
    stages {
        stage('Clean') {
            steps {
                make("clean")
            }
        }
        stage('Build') {
            steps {
                make("build")
            }
        }
        stage('Lint & Test') {
            steps {
                echo "Build environment"
                sh "env"
                echo "Start with fresh data volumes"
                make("clean")
                echo "Running linter with `make lint`"
                make("lint")
                echo "Running tests with `make test`"
                make("test")
                echo "cleanup data volumes"
                make("clean")
            }
        }
        stage('End to End Tests') {
            steps {
                echo "End-to-end testing"
                make("e2e")
            }
        }
        stage('Push Image Staging') {
            when {
                branch STAGING_BRANCH
            }
            steps {
                withAWS(credentials: STAGING_ACCOUNT, region: AWS_REGION) {
		    sh """
		      scripts/push_image.sh controlplane-httpserver ${GIT_COMMIT} docker/httpserver/Dockerfile ${ecrEndpoint(STAGING_ACCOUNT_ID)}
		      scripts/push_image.sh controlplane-converger ${GIT_COMMIT} docker/converger/Dockerfile ${ecrEndpoint(STAGING_ACCOUNT_ID)}
		      scripts/push_image.sh controlplane-validator ${GIT_COMMIT} docker/validator/Dockerfile ${ecrEndpoint(STAGING_ACCOUNT_ID)}
		    """
                }
            }
	}
        stage('Deploy Staging') {
            when {
                branch STAGING_BRANCH
            }
            steps {
                withAWS(credentials: STAGING_ACCOUNT, region: AWS_REGION) {
		    sh """
		      scripts/ecs-deploy.sh --verbose --timeout 300 \
		        --cluster eventbus-staging --service-name controlplane-httpserver-staging \
		        --image ${ecrEndpoint(STAGING_ACCOUNT_ID)}/controlplane-httpserver:${GIT_COMMIT}

		      scripts/ecs-deploy.sh --verbose --timeout 300 \
		        --cluster eventbus-staging --service-name controlplane-converger-staging \
		        --image ${ecrEndpoint(STAGING_ACCOUNT_ID)}/controlplane-converger:${GIT_COMMIT}

            scripts/ecs-deploy.sh --verbose --timeout 300 \
		        --cluster eventbus-staging --service-name controlplane-validator-staging \
		        --image ${ecrEndpoint(STAGING_ACCOUNT_ID)}/controlplane-validator:${GIT_COMMIT}
		    """
                }
            }
            post {
                success {
                    script {
                        text = "Deployed to controlplane staging successfully ✔ \nSuccessfully deployed commit ${commitLink()}"
                        prodJenkinsLink = "https://jenkins-og.xarth.tv/job/eventbus/job/controlplane/job/master"
                        blocks = [
                          [type: "section",text: [type: "mrkdwn",text: "${text}"]],
                          [type: "actions",
                           "elements": [
                             [type: "button",text: [type: "plain_text",text: "Deploy to *Production* 🚀"],url: "${prodJenkinsLink}"]
                           ]
                          ]
                        ]
                        postSlackBlocks( blocks )
                    }
                }
                failure {
                    script {
                        text = "Failed to deploy to controlplane staging ❌\nFailed to deploy commit ${commitLink()}"
                        blocks = [
                          [type: "section",text: [type: "mrkdwn",text: "${text}"]],
                          [type: "actions",
                           "elements": [
                             [type: "button",text: [type: "plain_text",text: "Build logs"],url: "${env.BUILD_URL}console"]
                           ]
                          ]
                        ]
                        postSlackBlocks( blocks )
                    }
                }
            }
        }
        stage('Push Image Production') {
            when {
                branch 'master'
            }
            steps {
                withAWS(credentials: PRODUCTION_ACCOUNT, region: AWS_REGION) {
		    sh """
		      scripts/push_image.sh controlplane-httpserver ${GIT_COMMIT} docker/httpserver/Dockerfile ${ecrEndpoint(PRODUCTION_ACCOUNT_ID)}
		      scripts/push_image.sh controlplane-converger ${GIT_COMMIT} docker/converger/Dockerfile ${ecrEndpoint(PRODUCTION_ACCOUNT_ID)}
		      scripts/push_image.sh controlplane-validator ${GIT_COMMIT} docker/validator/Dockerfile ${ecrEndpoint(PRODUCTION_ACCOUNT_ID)}
		    """
                }
            }
	}
        stage('Deploy Production') {
            when {
                branch 'master'
            }
            steps {
                input(message: "Deploy to production?", ok: 'Yes')
                withAWS(credentials: PRODUCTION_ACCOUNT, region: AWS_REGION) {
		    sh """
		      scripts/ecs-deploy.sh --verbose --timeout 300 \
		        --cluster eventbus-prod --service-name controlplane-httpserver-prod \
		        --image ${ecrEndpoint(PRODUCTION_ACCOUNT_ID)}/controlplane-httpserver:${GIT_COMMIT}

		      scripts/ecs-deploy.sh --verbose --timeout 300 \
		        --cluster eventbus-prod --service-name controlplane-converger-prod \
		        --image ${ecrEndpoint(PRODUCTION_ACCOUNT_ID)}/controlplane-converger:${GIT_COMMIT}

            scripts/ecs-deploy.sh --verbose --timeout 300 \
		        --cluster eventbus-prod --service-name controlplane-validator-prod \
		        --image ${ecrEndpoint(PRODUCTION_ACCOUNT_ID)}/controlplane-validator:${GIT_COMMIT}
		    """
                }
            }
            post {
                success {
                    script {
                        text = "Deployed controlplane to production successfully ✔ \nSuccessfully deployed commit ${commitLink()}"
                        blocks = [
                          [type: "section",text: [type: "mrkdwn",text: "${text}"]],
                        ]
                        postSlackBlocks( blocks )
                    }
                }
                failure {
                    script {
                        text = "Failed to deploy controlplane to production ❌\nFailed to deploy commit ${commitLink()}"
                        blocks = [
                          [type: "section",text: [type: "mrkdwn",text: "${text}"]],
                          [type: "actions",
                           "elements": [
                             [type: "button",text: [type: "plain_text",text: "Build logs"],url: "${env.BUILD_URL}console"]
                           ]
                          ]
                        ]
                        postSlackBlocks( blocks )
                    }
                }
            }
        }
    }
    post {
        cleanup {
            script {
                make("clean")
            }
        }
    }
}
