#!/usr/bin/env groovy
import groovy.json.JsonOutput
import groovy.transform.Field

//
// These buckets names must match the service_template output for jenkins_artifact_bucket_name
// A map of branch names to the s3 bucket that the artifacts get uploaded to for deploying
//
@Field
def artifact_bucket = [
  "master": "twitch-ext-orc-dev-orchestrator-nginx-us-west-2-builds",
  "production": "twitch-ext-orc-prod-orchestrator-nginx-us-west-2-builds",
]

//
// A map of branch names to the accounts they get deployed to
//
@Field
def account_names = [
  "master": "twitch-ext-orc-dev",
  "production": "twitch-ext-orc-prod",
]
//
// A map of branch names to staging environments
//
@Field
def environment_names = [
    "master": "staging",
    "production": "production"
]

//
// A map of nginx config buckets to branches. These will be written to a file so
// that the service can download the configuration from the correct bucket as necessary.
//
@Field
def nginx_config_buckets = [
    "master": "twitch-ext-orc-dev-orchestrator-nginx-config",
    "production": "twitch-ext-orc-prod-orchestrator-nginx-config"
]

//
// slack_channel is the channel that Jenkins should notify when a production deploy is triggered.
//
@Field
def slack_channel = "#ext-anchors-oncall"

//
// slack_username is the username that Jenkins will message as.
//
@Field
def slack_username = "orchestratorNginxDeploy"

@Field
def repo_path = "code.justin.tv/extensions/orchestrator-nginx"

//
// We have to provide the git-aws URL in the slack message so the click-through works.
//
@Field
def github_repo_path = "git-aws.internal.justin.tv/extensions/orchestrator-nginx"

//
// the component we are building is called orchestrator and is in $repo_path/cmd/orchestrator/
//
@Field
def component_name = "orchestrator"

//
// This MUST match what the service_template output for jenkins_artifact_filename, as that is what
// CodeBuild will look for.  This works with the fargate terraform service template which configures
// CodeBuild to look for this file.
//
@Field
def build_artifact_filename = "${component_name}-nginx.zip"

node {
    def status = "success"
    def shouldDeployBranch = account_names.containsKey(env.BRANCH_NAME)

    wrap([$class: 'AnsiColorBuildWrapper', colorMapName: 'xterm']) {
        stage('Checkout') {
            checkout scm
        }

        stage('Build and Test') {
            test()
            build()
        }

        if (shouldDeployBranch) {
            stage('Deploy') {
                deploy()
            }
        }
        cleanWs()
    }
}

def build() {
    //
    // zips a file containing the git sha, the binary that was built and tested, a Dockerfile for the runtime container, a buildspec, and a config directory
    // The git sha is carried through to the environment variables of the running container so it is easy to cross-reference
    // what is currently running with the commit that triggered the deploy.
    //
    sh "echo ${getCommit()} > gitCommit.txt"
    sh "cp nginx.${environment_names[env.BRANCH_NAME] != null ? environment_names[env.BRANCH_NAME] : 'local'}.conf nginx.conf"
    sh "echo ${nginx_config_buckets[env.BRANCH_NAME]} > s3_bucket.txt"
    sh "zip -r ${build_artifact_filename} gitCommit.txt Dockerfile buildspec.yml nginx.conf update_nginx_config.cron update_nginx_config.sh s3_bucket.txt"
    archiveArtifacts "${build_artifact_filename}"
}

def test() {
    sh "./check_configs.sh"
}

def deploy() {
    def branch = env.BRANCH_NAME
    def account = account_names[branch]
    def bucket = artifact_bucket[branch]

    //
    // Jenkins goes looking for the credentials on a per-component basis, on the assumption that you may have multiple
    // repositories and components deploying into the same account, so they need to be namespaced to the component.
    //
    withAWS(credentials: "${account}-${component_name}-deploy-creds") {
        if (branch == "production") {
            slackMsg()
        }

        sh "aws s3api put-object --bucket ${bucket} --key ${build_artifact_filename} --body ${build_artifact_filename}"
    }
}

def getCommit() {
    return sh(returnStdout: true, script: "git log -n 1 --pretty=format:'%H'").trim()
}

def slackMsg() {
    def branch = env.BRANCH_NAME
    def account = account_names[branch]

    // NOTE: you have to manually add this secret to Jenkins
    withCredentials([string(credentialsId: 'slack-webhook-url', variable: 'URL')]) {
        def json = JsonOutput.toJson([
            text: '',
            channel: "${slack_channel}",
            username: "${slack_username}",
            icon_emoji: ":ohno:",
            attachments: [[
                title: "#${env.BUILD_NUMBER}: ${repo_path} branch ${env.BRANCH_NAME} is deploying to ${account}",
                title_link: "${env.BUILD_URL}",
                fields: [[
                    title: "Commit",
                    value: "<https://${github_repo_path}/commit/${getCommit()}|${getCommit()}",
                    short: false,
                ]]
            ]]
        ])

        writeFile(file: 'payload.json', text: json)
        sh('curl --fail -X POST --data-urlencode payload@payload.json $URL')
    }
}
