import groovy.json.JsonOutput

STAGING_BRANCH = "master"
STAGING_ACCT = "twitch-eventbus-dev"
PROD_ACCT = "twitch-eventbus-prod"
AWS_REGION = "us-west-2"

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

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/dashboard/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}' "
  }
}

def prodChangeWindowCheck() {
  prodChangeWindowWarning = """
WARNING!
It is outside the production change window, as outlined by the
Platforms and Services organization. If this is an emergency
and you have received approval to do so, you may proceed. Otherwise,
please refrain from production changes until the change window opens up.
Production Change Window:
Monday-Thursday: 10AM-4PM PST
Friday: 10AM-1PM PST
"""

  // Get the UTC day of week (as single digit number) and hour of day (as single digit number)
  d = sh(script: "date -u +%u", returnStdout: true).trim().toInteger()
  h = sh(script: "date -u +%k", returnStdout: true).trim().toInteger()
  inProdChangeWindow = true
  if (d >= 1 && d <= 4) {
    if (h < 17 || h > 22) {
      inProdChangeWindow = false
    }
  }
  if (d == 5) {
    if (h < 17 || h > 19) {
      inProdChangeWindow = false
    }
  }
  if (d > 5) {
    inProdChangeWindow = false
  }
  if (!inProdChangeWindow) {
    input(message: prodChangeWindowWarning, id: "prodWindow")
  }
}

pipeline {
    agent any
    options {
        disableConcurrentBuilds()
        timeout(time: 1, unit: 'HOURS')
        ansiColor('xterm')
        timestamps()
    }
    stages {
        stage('Production Change Window Check') {
            when {
                branch 'master'
            }
            steps {
                prodChangeWindowCheck()
            }
        }
        stage('Build') {
            steps {
                make("docker-build")
            }
        }
        stage('Lint & Test') {
            steps {
                echo "Build environment"
                sh "env"
                echo "Running linter with `make lint`"
                make("docker-lint")
                echo "Running tests with `make test`"
                make("docker-test")
            }
        }
        stage('Deploy Staging') {
            when {
                branch STAGING_BRANCH
            }
            steps {
                withAWS(credentials: STAGING_ACCT, region: AWS_REGION) {
                    make("deploy_staging")
                }
            }
            post {
                success {
                    script {
                        text = "Deployed to dashboard staging successfully ✔ \nSuccessfully deployed commit ${commitLink()}"
                        prodJenkinsLink = "https://jenkins-og.xarth.tv/job/eventbus/job/dashboard/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 dashboard 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('Deploy Production') {
            when {
                branch 'master'
            }
            steps {
                input(message: "Deploy to production?", ok: 'Yes')
                withAWS(credentials: PROD_ACCT, region: AWS_REGION) {
                    make("deploy_prod")
                }
            }
            post {
                success {
                    script {
                        text = "Deployed to production successfully ✔ \nSuccessfully deployed commit ${commitLink()}"
                        blocks = [
                          [type: "section",text: [type: "mrkdwn",text: "${text}"]],
                        ]
                        postSlackBlocks( blocks )
                    }
                }
                failure {
                    script {
                        text = "Failed to deploy 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 )
                    }
                }
            }
        }
    }
}
