pipeline {
  // Some steps hang forever. Rather than take an agent, we are good Jenkins denizens and explicitly say when we want
  // a jenkins worker
  agent none
  options {
    timestamps()
    ansiColor('xterm')
  }

  stages {
    stage("Set up") {
      agent {
        // Usually we let this stage run on "any" agent, which runs as the jenkins user.
        // This sometimes fails because we've had previous bad builds that created files owned by root.
        // The jenkins user doesn't have permissions to delete these files.
        // To work around this, we will run our clean up as root.
        docker {
          image 'docker-registry.internal.justin.tv/devtools/xenial/go1.13.3:latest'
          args '-u root'
        }
      }
      steps {
        script {
          // Put the short git SHA in the build name so we can find a build by SHA on the UI
          currentBuild.displayName = env.GIT_COMMIT[0..6] + " #" + env.BUILD_NUMBER
        }

        // Clean the workspace, removing files created by other builds.
        sh 'git clean -ffdx'
      }
    }

    stage("Build go binaries") {
      agent {
        docker {
          image 'docker-registry.internal.justin.tv/devtools/xenial/go1.13.3:latest'
          args '-u root'
        }
      }
      environment {
        // Set this env variable so our make command builds our binaries in a directory called "build".
        BUILD_DIR = 'build'
      }
      steps {
        // Print some debug info
        sh 'go version'
        sh 'go env'

        // We can't compile yet because Jenkins does not mount the code into the Go workspace
        // Fix this by copying the code into the Go workspace.
        sh 'mkdir -p $GOPATH/src/code.justin.tv/twitch-events/gea'
        sh 'cp -R . $GOPATH/src/code.justin.tv/twitch-events/gea'

        // Setup jenkins for building binaries
        sh 'make jenkins-setup'

        // Build our binaries
        sh 'make build-binaries'

        // The files that we built are owned by the root user.  This is a problem because the rest
        // of the build runs as the jenkins user and won't have permission to access them.
        // Fix this by changing the owner to the jenkins user.
        // https://wiki.twitch.com/display/DTA/Jenkins+User+Guide#JenkinsUserGuide-WhyismydockerbasedJenkinsjobfailingwithpermissiondeniederrors?
        sh 'chown -R 61000:61000 build'

        // Stash the binaries so they will be available in other stages.
        stash name: 'gea-binary', includes: 'build/gea/gea'
        stash name: 'ecs-deploy-binary', includes: 'build/ecs-deploy/ecs-deploy'
      }
    }

    stage("Build and push docker image") {
      agent any
      steps {
        sh 'docker --version'

        // Populate the build/gea directory with the files needed to build the docker image.
        unstash name: 'gea-binary'
        sh 'cp -R config build/gea'
        sh 'cp cmd/gea/Dockerfile build/gea'
        
        // Build and push docker image.
        sh 'docker build -t docker-registry.internal.justin.tv/twitch-events/gea:$GIT_COMMIT build/gea'
        sh 'docker push docker-registry.internal.justin.tv/twitch-events/gea:$GIT_COMMIT'
      }
    }

    stage("Deploy to Integration") {
      agent any
      when {
        branch 'master';
      }
      environment { 
        ENVIRONMENT = 'integration' 
        AWS_PROFILE = 'default'
        AWS_CONFIG_FILE = credentials('aws-events-integration')
        AWS_ASSUME_ROLE_ARN = 'arn:aws:iam::724951484461:role/events-integration-build-deployment'
      }
      steps {
        unstash name: 'ecs-deploy-binary'
        sh 'build/ecs-deploy/ecs-deploy'
      }
    }

    stage("Deploy to Staging") {
      agent any
      when {
        branch 'master';
      }
      environment { 
        ENVIRONMENT = 'staging' 
        AWS_PROFILE = 'default'
        AWS_CONFIG_FILE = credentials('aws-events-staging')
        AWS_ASSUME_ROLE_ARN = 'arn:aws:iam::724951484461:role/events-staging-build-deployment'
      }
      steps {
        unstash name: 'ecs-deploy-binary'
        sh 'build/ecs-deploy/ecs-deploy'
      }
    }

    stage("Confirm deploy to Canary") {
      // Note: Do input inside `agent none` so we don't claim a jenkins worker while waiting for input
      agent none
      when {
        branch 'master';
      }
      steps {
        // Input stops the build and waits for a user to click OK
        input message: "Proceed?"
      }
    }

    stage("Deploy to Canary") {
      agent any
      when {
        branch 'master';
      }
      environment { 
        ENVIRONMENT = 'canary'
        AWS_PROFILE = 'default'
        AWS_CONFIG_FILE = credentials('aws-events-canary')
        AWS_ASSUME_ROLE_ARN = 'arn:aws:iam::914569885343:role/events-canary-build-deployment'
      }
      steps {
        unstash name: 'ecs-deploy-binary'
        sh 'build/ecs-deploy/ecs-deploy'
      }
    }

    stage("Confirm deploy to Production") {
      agent none
      when {
        branch 'master';
      }
      steps {
        input message: "Proceed?"
      }
    }    

    stage("Deploy to Production") {
      agent any
      when {
        branch 'master';
      }
      environment { 
        ENVIRONMENT = 'production'
        AWS_PROFILE = 'default'
        AWS_CONFIG_FILE = credentials('aws-events-production')
        AWS_ASSUME_ROLE_ARN = 'arn:aws:iam::914569885343:role/events-production-build-deployment'
      }
      steps {
        unstash name: 'ecs-deploy-binary'
        sh 'build/ecs-deploy/ecs-deploy'
      }
    }
  }
}
