////////
// Define a helper and set the commit status with.
////
//// To mark the current stage as pending:
////
// setBuildStatus("${REPO}", "${STAGE_NAME}", "running", "PENDING", "${POSITION}")
////
//// To mark the current stage as ended differently depending on the stage result,
////    where "MESSAGE" is the GitHub status check message
////
// post {
//   success {
//     setBuildStatus("${REPO}", "${STAGE_NAME}", "MESSAGE", "SUCCESS", "${POSITION}")
//   }
//   failure {
//     setBuildStatus("${REPO}", "${STAGE_NAME}", "MESSAGE", "ERROR", "${POSITION}")
//   }
//   unstable {
//     setBuildStatus("${REPO}", "${STAGE_NAME}", "MESSAGE", "UNSTABLE", "${POSITION}")
//   }
// }
////////
void setBuildStatus(String repo, String context, String message, String state, String position) {
  step([
      $class: "GitHubCommitStatusSetter",
      reposSource: [$class: "ManuallyEnteredRepositorySource", url: "https://git.xarth.tv/${repo}"],
      contextSource: [$class: "ManuallyEnteredCommitContextSource", context: "${position}: ${context}"],
      errorHandlers: [[$class: "ChangingBuildStatusErrorHandler", result: "UNSTABLE"]],
      statusResultSource: [ $class: "ConditionalStatusResultSource", results: [[$class: "AnyBuildResult", message: message, state: state]] ]
  ]);
}

pipeline {
  agent any
  options {
    timestamps()
    ansiColor('xterm')
  }

  environment {
    REPO = "admin-services/admin-panel"
    PKG = "code.justin.tv/admin-services/admin-panel"
  }

  stages {
    stage("begin"){
      steps {
        script { env.COUNT = (1 as Integer) } // keep track of the number of stages we've gone through
        echo "====++++ Level ${env.COUNT} ++++===="
      }
    }

    stage('lint') {
      when {
        changeset "terraform/*"
      }
      parallel {
        stage('lint-tf') {
          environment { POSITION = "${env.COUNT}" }
          agent {
            docker {
              image 'hashicorp/terraform'
              args '--entrypoint=""'
            }
          }
          steps {
            setBuildStatus("${REPO}", "${STAGE_NAME}", "running", "PENDING", "${POSITION}")
            sh 'terraform fmt -check terraform'
          }
          post {
            success {
              setBuildStatus("${REPO}", "${STAGE_NAME}", "complete", "SUCCESS", "${POSITION}")
            }
            failure {
              setBuildStatus("${REPO}", "${STAGE_NAME}", "failed", "ERROR", "${POSITION}")
            }
            cleanup {
              script { env.COUNT = ((POSITION as Integer) + (1 as Integer)) }
              echo "====++++ Level ${env.COUNT} ++++===="
            }
          }
        }
      }
    }

    stage('build') {
      parallel {
        stage('build-app') {
          environment { POSITION = "${env.COUNT}" }
          steps {
            setBuildStatus("${REPO}", "${STAGE_NAME}", "running", "PENDING", "${POSITION}")
            withCredentials([
              [
                $class: 'AmazonWebServicesCredentialsBinding',
                credentialsId: 'team-sse-jenkins'
              ],
              [
                $class: 'StringBinding',
                credentialsId: 'admin-panel-codecov-token',
                variable: 'CODECOV_TOKEN'
              ]
            ]) {
              sshagent(['admin_services-admin_panel-ed25519']) {
                sh 'make build'
              }
            }
          }
          post {
            success {
              setBuildStatus("${REPO}", "${STAGE_NAME}", "complete", "SUCCESS", "${POSITION}")
            }
            failure {
              setBuildStatus("${REPO}", "${STAGE_NAME}", "failed", "ERROR", "${POSITION}")
            }
            cleanup {
              script { env.COUNT = ((POSITION as Integer) + (1 as Integer)) }
              echo "====++++ Level ${env.COUNT} ++++===="
            }
          }
        }

        stage('build-scripts') {
          environment { POSITION = "${env.COUNT}" }
          agent { docker { image 'docker.pkgs.xarth.tv/devtools/bionic/go1.14.7:latest' } }
          steps {
            setBuildStatus("${REPO}", "${STAGE_NAME}", "running", "PENDING", "${POSITION}")
            sh 'mkdir -p $(dirname $GOPATH/src/$PKG)'
            sh 'cp -r $(pwd) $GOPATH/src/$PKG'
            sh 'go test -v $PKG/... && go build -o bin/update-task-def $GOPATH/src/$PKG/scripts/update-task-def.go'
            stash name: 'bin', includes: 'bin/update-task-def'
          }
          post {
            success {
              setBuildStatus("${REPO}", "${STAGE_NAME}", "complete", "SUCCESS", "${POSITION}")
            }
            failure {
              setBuildStatus("${REPO}", "${STAGE_NAME}", "failed", "ERROR", "${POSITION}")
            }
            cleanup {
              script { env.COUNT = ((POSITION as Integer) + (1 as Integer)) }
              echo "====++++ Level ${env.COUNT} ++++===="
            }
          }
        }
      }
    }

    //////
    ////// These have been broken since DNXit; They should be fixed, but unlikely to happen before Toolkit
    //////
    // stage('integration-test') {
    //   environment { POSITION = "${env.COUNT}" }
    //   steps {
    //     setBuildStatus("${REPO}", "${STAGE_NAME}", "running", "PENDING", "${POSITION}")
    //     withCredentials([
    //       [
    //         $class: 'AmazonWebServicesCredentialsBinding',
    //         credentialsId: 'admin-platform-jenkins'
    //       ],
    //     ]) {
    //       script {
    //         try {
    //           sh 'make test-features'
    //         } catch (exc) {
    //           // don't fail on feature test failures - only mark as unstable.
    //           currentBuild.result = 'UNSTABLE'
    //         }
    //       }
    //     }
    //   }
    //   post {
    //     success {
    //       setBuildStatus("${REPO}", "${STAGE_NAME}", "passed", "SUCCESS", "${POSITION}")
    //     }
    //     failure {
    //       setBuildStatus("${REPO}", "${STAGE_NAME}", "crashed", "ERROR", "${POSITION}")
    //     }
    //     unstable {
    //       setBuildStatus("${REPO}", "${STAGE_NAME}", "failed", "FAILURE", "${POSITION}")
    //     }
    //     cleanup {
    //       sh 'make clean-features'
    //       script { env.COUNT = ((POSITION as Integer) + (1 as Integer)) }
    //       echo "====++++ Level ${env.COUNT} ++++===="
    //     }
    //   }
    // }

    stage('deploy-staging') {
      when { 
        anyOf {
          branch 'dev';
          expression { 
            BRANCH_NAME ==~ /^chore\/.+$/
          }
        }
      }
      stages {
        stage('deploy') { 
          environment { POSITION = "${env.COUNT}" }
          steps {
            setBuildStatus("${REPO}", "${STAGE_NAME}", "running", "PENDING", "${POSITION}")
            unstash name: 'bin'
            withCredentials([[
              $class: 'AmazonWebServicesCredentialsBinding',
              credentialsId: 'team-sse-jenkins'
            ]]) {
              sh 'ENVIRONMENT="staging" make deploy'
            }
          }
          post {
            success {
              setBuildStatus("${REPO}", "${STAGE_NAME}", "deployed", "SUCCESS", "${POSITION}")
            }
            failure {
              setBuildStatus("${REPO}", "${STAGE_NAME}", "failed", "ERROR", "${POSITION}")
            }
            cleanup {
              script { env.COUNT = ((POSITION as Integer) + (1 as Integer)) }
              echo "====++++ Level ${env.COUNT} ++++===="
            }
          }
        }
        stage('check-deployment') {
          environment { POSITION = "${env.COUNT}" }
          steps {
            setBuildStatus("${REPO}", "${STAGE_NAME}", "running", "PENDING", "${POSITION}")
            withCredentials([[
              $class: 'AmazonWebServicesCredentialsBinding',
              credentialsId: 'team-sse-jenkins'
            ]]) {
              sh 'ENVIRONMENT="staging" make await-deploy'
            }
          }
          post {
            success {
              setBuildStatus("${REPO}", "${STAGE_NAME}", "live!", "SUCCESS", "${POSITION}")
            }
            failure {
              setBuildStatus("${REPO}", "${STAGE_NAME}", "timed out", "ERROR", "${POSITION}")
            }
            cleanup {
              script { env.COUNT = ((POSITION as Integer) + (1 as Integer)) }
              echo "====++++ Level ${env.COUNT} ++++===="
            }
          }
        }
      }
    }

    stage('deploy-canary') {
      when {
        expression { BRANCH_NAME ==~ /^release\/.+$/ }
      }
      stages {
        stage('deploy') { 
          environment { POSITION = "${env.COUNT}" }
          steps {
            setBuildStatus("${REPO}", "${STAGE_NAME}", "running", "PENDING", "${POSITION}")
            unstash name: 'bin'
            withCredentials([[
              $class: 'AmazonWebServicesCredentialsBinding',
              credentialsId: 'team-sse-jenkins'
            ]]) {
              sh 'ENVIRONMENT="canary" make deploy'
            }
          }
          post {
            success {
              setBuildStatus("${REPO}", "${STAGE_NAME}", "deployed", "SUCCESS", "${POSITION}")
            }
            failure {
              setBuildStatus("${REPO}", "${STAGE_NAME}", "failed", "ERROR", "${POSITION}")
            }
            cleanup {
              script { env.COUNT = ((POSITION as Integer) + (1 as Integer)) }
              echo "====++++ Level ${env.COUNT} ++++===="
            }
          }
        }
        stage('check-deployment') {
          environment { POSITION = "${env.COUNT}" }
          steps {
            setBuildStatus("${REPO}", "${STAGE_NAME}", "running", "PENDING", "${POSITION}")
            withCredentials([[
              $class: 'AmazonWebServicesCredentialsBinding',
              credentialsId: 'team-sse-jenkins'
            ]]) {
              sh 'ENVIRONMENT="canary" make await-deploy'
            }
          }
          post {
            success {
              setBuildStatus("${REPO}", "${STAGE_NAME}", "live!", "SUCCESS", "${POSITION}")
            }
            failure {
              setBuildStatus("${REPO}", "${STAGE_NAME}", "timed out", "ERROR", "${POSITION}")
            }
            cleanup {
              script { env.COUNT = ((POSITION as Integer) + (1 as Integer)) }
              echo "====++++ Level ${env.COUNT} ++++===="
            }
          }
        }
      }
    }

    stage('deploy-production') {
      when {
        branch 'master'
      }
      stages {
        stage('deploy') { 
          environment { POSITION = "${env.COUNT}" }
          steps {
            setBuildStatus("${REPO}", "${STAGE_NAME}", "running", "PENDING", "${POSITION}")
            unstash name: 'bin'
            withCredentials([[
              $class: 'AmazonWebServicesCredentialsBinding',
              credentialsId: 'team-sse-jenkins'
            ]]) {
              sh 'ENVIRONMENT="production" make deploy'
            }
          }
          post {
            success {
              setBuildStatus("${REPO}", "${STAGE_NAME}", "deployed", "SUCCESS", "${POSITION}")
            }
            failure {
              setBuildStatus("${REPO}", "${STAGE_NAME}", "failed", "ERROR", "${POSITION}")
            }
            cleanup {
              script { env.COUNT = ((POSITION as Integer) + (1 as Integer)) }
              echo "====++++ Level ${env.COUNT} ++++===="
            }
          }
        }
        stage('check-deployment') {
          environment { POSITION = "${env.COUNT}" }
          steps {
            setBuildStatus("${REPO}", "${STAGE_NAME}", "running", "PENDING", "${POSITION}")
            withCredentials([[
              $class: 'AmazonWebServicesCredentialsBinding',
              credentialsId: 'team-sse-jenkins'
            ]]) {
              sh 'ENVIRONMENT="production" make await-deploy'
            }
          }
          post {
            success {
              setBuildStatus("${REPO}", "${STAGE_NAME}", "live!", "SUCCESS", "${POSITION}")
            }
            failure {
              setBuildStatus("${REPO}", "${STAGE_NAME}", "timed out", "ERROR", "${POSITION}")
            }
            cleanup {
              script { env.COUNT = ((POSITION as Integer) + (1 as Integer)) }
              echo "====++++ Level ${env.COUNT} ++++===="
            }
          }
        }
      }
    }
  }

  post {
    always {
      archiveArtifacts  '.manta/brakeman*'
      archiveArtifacts  '.manta/rspec-*'
    }
  }
}
