pipeline() {
  environment{
    def productAcronym="TAS"
    def productMajorVersion='01'
    def productMinorVersion='00'
    def productRev="${BUILD_NUMBER}"
    def packageVersion="${productAcronym}.${productMajorVersion}.${productMinorVersion}.${productRev}"
    def hcRoom = '3242078'
    def dateString = new Date(currentBuild.startTimeInMillis).format('yyyyMMdd_HHmmss')
    def ARTIFACT_LOCATION = "${WORKSPACE}/artifacts/${dateString}"
    def DIST_OUTPUT_FILENAME=''
    def DIST_OUTPUT_FILE=''
    def lastCommitID=''
    def packageName=''
    def WEB_BASEDIR="/var/www/html"
    def STAGING_DIR="${WEB_BASEDIR}/dev/tas"
    def index="./src/index.html"
    def PHANTOMJS_CDNURL="${MCCF_PUB_REPO_URL}/npm/sinopia/phantomjs"
    def SASS_BINARY_NAME="linux-x64-57"
    def SASS_BINARY_SITE="${MCCF_PUB_REPO_URL}/npm/sinopia/node-sass"
    def mccf_git_repo="https://bitbucket.org/halfaker/mccf_tas_core"
    def buildResultUUID=''
    def TASWorkspace="${WORKSPACE}"
    def TAS_WEBUI="MCCF_EDI_TAS_WebUI"
    def TAS_BUILD_ARTIFACTS="Build_Artifacts"
    def lastGitTag=''
    def scmtool="/opt/ibm/teamconcert/6.0.1/jazz/scmtools/eclipse/scm.sh"
    def localTMP="${WORKSPACE}/tmp"
    def branch_name=''
  }
  agent any
  stages{
    stage('Prepare workspace with source code') {
      steps{
        script{
          def bldENV=ENV?.trim().toUpperCase()
          echo "determine region for ${bldENV}"
          def region=bldENV[0..2]
          echo "determine main env for region ${region}, (aka ${bldENV})"
          def mainENV=bldENV[-3..-1]
          echo "determine action for ${bldENV}, (aka ${region}, ${mainENV})"
          switch(region){
            case "AWS":
              echo "AWS environment, Prepare Halfaker workspace"
              dir("${TAS_WEBUI}"){
                getHalfakerCode()
              }
              break
            case "EDE":
            case "MAG":
              echo ("Initialize workspace from RTC")
              if (!TGT_STREAM?.trim().toUpperCase().equals("DEV")){
                STAGING_DIR="${WEB_BASEDIR}/rtc/tas"
              }
              teamconcert([
                buildType: [
                  buildDefinition: "${buildDefinitionId}",
                  value: 'buildDefinition'
                ]
              ])
              echo ("Verify component (${TAS_WEBUI}) exists")
              sh '''
                if [[ -d "${TAS_WEBUI}" ]]
                then
                  echo "Component (${TAS_WEBUI}) exists, safe to proceed"
                else
                  fail "FAIL: No component (${TAS_WEBUI}) found"
                fi
              '''
              echo "EDE environment, determine SRC_STREAM"
              if(mainENV.equals("DEV") &&  SRC_STREAM?.trim().toUpperCase().equals("HAF")){
                echo "need to get HAF code"
                dir("${localTMP}"){
                  getHalfakerCode()
                  echo "need to check lastGitCommit against lastGitTag"
                }
                dir("${TAS_WEBUI}"){
                  sh 'cp -p .project ../taswebui.project'
                  sh 'rsync -acvWh "${localTMP}/" . --exclude ".git" --del'
                  sh 'mv ../taswebui.project .project'
                }
              }
              break
            default:
              echo "local environment, Prepare Halfaker workspace"
              dir("${TAS_WEBUI}"){
                getHalfakerCode()
              }
          }
        }
      }
    }
    stage('Pre-Build Setup'){
      steps{
        echo ("create artifact location for jenkins (${ARTIFACT_LOCATION})")
        sh 'mkdir -p ${ARTIFACT_LOCATION}'

        echo ("prepare npm")
        echo 'npm cache clean --force'
        sh 'npm cache clean --force'

        sh 'sudo npm set registry ${NPM_REGISTRY} -g'
        sh 'sudo npm set phantomjs_cdnurl ${PHANTOMJS_CDNURL} -g'
        sh 'sudo npm config delete phantomjs_downloadurl -g'
        sh 'sudo npm set sass_binary_name ${SASS_BINARY_NAME} -g'
        sh 'sudo npm set sass_binary_site ${SASS_BINARY_SITE} -g'

        echo ("set progress bars to false")
        sh 'sudo npm set progress=false -g'
        sh 'npm config list'
        echo "set final packageVersion"
        dir("${TAS_WEBUI}"){
          script{
            if(ENV?.trim().toUpperCase().startsWith("EDE") || ENV?.trim().toUpperCase().startsWith("MAG")){
              echo "building in EDE, do not use git commit in packageVersion"
              packageVersion="${packageVersion}_${dateString}"
            }
            else {
              echo "git build, get lastCommitId"
              lastCommitID=getLastGitCommit()
              echo "last commit is ${lastCommitID}"
              if(branch_name?.trim()){
                if(branch_name?.trim().toLowerCase() == 'master'){
                  packageVersion="${packageVersion}_${lastCommitID}"
                }
                else {
                  packageVersion="${packageVersion}_${branch_name}-${lastCommitID}"
                }                
              }
              else{
                packageVersion="${packageVersion}_${lastCommitID}"
              }
            }
            echo "final packageVersion for tag ${packageVersion}"
            packageName=getPackageName()
            DIST_OUTPUT_FILENAME="${packageName}_${packageVersion}.tar.gz"
            echo "building for package ${DIST_OUTPUT_FILENAME}"
            echo "updating metadata for ${index}"
            updateIndexMetaData()
          }
          echo "execute npm install"
          sh 'npm install 2>&1 | tee npm_install.log'

          echo "check npm_install.log for download syntax"
          script{
            if (fileExists("npm_install.log")){
              def STR_TEST=checkNpmInstallLog("npm_install.log")
              if(STR_TEST?.trim().toUpperCase().startsWith("PROCEED")){
                echo "${STR_TEST}"
              }
              else{
                currentBuild.result='FAILED'
                error("FAIL: npm install is trying to download content")
              }
            }
          }
          echo "check dependencies"
          sh 'check-dependencies --verbose |& tee npm-check-dependencies.log'
          echo "check npm-check-dependencies for 'not installed'"
          script{
            if (fileExists("npm-check-dependencies.log")){
              def STR_TEST=checkDependenciesLog("npm-check-dependencies.log")
              if(STR_TEST?.trim().toUpperCase().startsWith("PROCEED")){
                echo "${STR_TEST}"
              }
              else{
                currentBuild.result='FAILED'
                error("FAIL: dependency check failed")
              }
            }
          }
        }
      }
    }
    stage('Pre-Build Tests'){
      environment{
        seleniumTestDir = "node_modules/protractor/node_modules/webdriver-manager/selenium"
        seleniumTestPath = "${WORKSPACE}/${TAS_WEBUI}/${seleniumTestDir}"
      }
      steps{
        echo "execute ng test for ${TAS_WEBUI}"
        dir("${TAS_WEBUI}"){
          echo "execute ng test"
          sh 'npm run test'

          echo ("Verify unit test summary exists")
          sh '''
            if [[ -f "unit_test_report_summary.html" ]]
            then
              echo "move unit_test_report_summary.html to (${WORKSPACE})"
              mv "unit_test_report_summary.html" "${WORKSPACE}"
            else
              echo "no unit_test_report_summary.html found"
            fi
          '''
          echo ("Verify coverage tests exist")
          sh '''
            if [[ -d "coverage" ]]
            then
              echo "move tests to (${WORKSPACE})"
              mv "coverage" "${WORKSPACE}"
            else
              echo "no coverage tests found"
            fi
          '''
          echo "create selenium test directory"
          sh " if [[ -d ${seleniumTestPath} ]]; then echo 'directory exists'; else mkdir -p ${seleniumTestPath};fi"

          echo "execute e2e tests"
          sh 'npm run e2e'

          echo ("Verify e2e test results exist")
          sh '''
            if [[ -d "e2e/reports" ]]
            then
              echo "move tests to (${WORKSPACE})"
              mv "e2e/reports" "${WORKSPACE}/e2e_results"
            else
              echo "no e2e test results found"
            fi
            if [[ -f "e2e/logs/testresults.xml" ]]
            then
              echo "move tests to (${WORKSPACE})"
              mv "e2e/logs/testresults.xml" "${WORKSPACE}/e2e_testresults.xml"
            else
              echo "no e2e test results found"
            fi
          '''
        }
      }
    }
    stage('Build'){
      steps{
        echo "build the project ${TAS_WEBUI}"
        dir ("${TAS_WEBUI}"){
          sh 'npm run build'
          script{
            if (fileExists("${WORKSPACE}/${TAS_WEBUI}/dist/index.html")) {
              echo "${WORKSPACE}/${TAS_WEBUI}/dist/index.html created, ready to package"
            } 
            else {
              error("FAIL: ${WORKSPACE}/${TAS_WEBUI}/dist/index.html not ready")
            }
          }
        }
      }
    }
    stage('Prepare Package') {
      steps{
        echo ("Prepare to package ${DIST_OUTPUT_FILENAME}")
        dir ("${TAS_WEBUI}"){
          echo ("packaging ${packageName} for distribution")
          script{
            DIST_OUTPUT_FILE="${WORKSPACE}/${DIST_OUTPUT_FILENAME}"
            echo "packaging ${DIST_OUTPUT_FILE}"
            sh "tar czf ${DIST_OUTPUT_FILE} -C ${WORKSPACE}/${TAS_WEBUI}/dist/ ."
            echo "verify package created"
            if (fileExists("${DIST_OUTPUT_FILE}")) {
              echo "${DIST_OUTPUT_FILE} created, ready to deploy"
            } 
            else {
              error("FAIL: ${DIST_OUTPUT_FILE} not created")
            }
          }
        }
      }
    }
    stage('Stage Package') {
      steps{
        echo "stage the packaged distribution (${DIST_OUTPUT_FILE}) for ${packageName}"
        stageLatestArtifact("${DIST_OUTPUT_FILE}")
      }
    }
  }
  post{
    always{
      echo "POST always: all tasks are completed, collecting environment variables to ${WORKSPACE}/${BUILD_TAG}.log"
      sh 'printenv >> $WORKSPACE/$BUILD_TAG.log'
      echo "POST always: archiving all logs and artifacts specified"
      publishHTML target: [allowMissing: true, alwaysLinkToLastBuild: false, keepAll: true, reportDir: 'coverage', reportFiles: 'index.html', reportName: 'CodeCoverage', reportTitles: '']
      junit allowEmptyResults: true, healthScaleFactor: 1.0, testResults: 'e2e_testresults.xml'
    }
    success{
      echo 'POST success: check environment to determine commit actions'
      script {
        def myENV="${ENV}"
        def subENV=myENV[0..2]
        def EDE_ARTIFACT_LOCATION = "${WORKSPACE}/${TAS_BUILD_ARTIFACTS}/${packageVersion}"
        echo "POST success: determine proper commit action for ${myENV}, (aka ${subENV})"
        switch(subENV.toUpperCase()){
          case "AWS":
            echo "POST success: AWS environment, use git to tag this build"
            gitTagBuild()
            echo "POST success: in AWS, make hipchat notification"
            notifyHipchat(currentBuild.result,hcRoom)
            break
          case "EDE":
          case "MAG":
            echo "POST success: copy packaged artifact (${DIST_OUTPUT_FILE}) to ${TAS_BUILD_ARTIFACTS}"
            sh """
              mkdir -p "${EDE_ARTIFACT_LOCATION}"
              cp "${DIST_OUTPUT_FILE}" "${EDE_ARTIFACT_LOCATION}/"
              echo "POST success: check ${EDE_ARTIFACT_LOCATION}/${DIST_OUTPUT_FILENAME}"
              if [[ -f "${EDE_ARTIFACT_LOCATION}/${DIST_OUTPUT_FILENAME}" ]]
              then
                echo "POST success: Artifact (${EDE_ARTIFACT_LOCATION}/${DIST_OUTPUT_FILENAME}) exists, safe to proceed"
              else
                fail "FAIL: POST success: No artifact (${EDE_ARTIFACT_LOCATION}/${DIST_OUTPUT_FILENAME}) found"
              fi
             """
            echo "cleanup prior to checkin and deliver"
            dir("${TAS_WEBUI}"){
              sh "mv ${index}.bak ${index}"
              sh 'rm -rf node_modules'
              sh 'rm -rf e2e/logs'
              sh 'rm -rf dist'
              sh 'find . -name "*.log" -type f -delete'
            }
            rtcCheckin()
            rtcDeliver()
            echo "POST success: send email notification"
            notifyBuildStatus(currentBuild.result)
          break
          default:
           echo "POST success: local environment, send no notices"
           echo "POST success: local environment, do not commit any tag"
        }
      }
      echo "POST success: collecting console log"
      getConsoleLog()
      archiveArtifacts allowEmptyArchive: true, artifacts: '**/*.log, *.html, *.tar.gz, e2e_testresults.xml' , onlyIfSuccessful: false
      echo 'POST success: Performing cleanup tasks after build success'
      deleteDir()
    }
    failure{
      script{
        if(BUILD_URL.toLowerCase().contains("aws")){
          echo "POST failure: in AWS, make hipchat notification"
          notifyHipchat(currentBuild.result,hcRoom)
        }
        if(ENV.toLowerCase().contains("local")){
            echo "POST failure: local environment, send no notices"
        }
        else{
          echo "POST failure: send email notification"
          notifyBuildStatus(currentBuild.result)
        }
      }
      echo "POST failure: collecting console log"
      getConsoleLog()
      archiveArtifacts allowEmptyArchive: true, artifacts: '**/*.log, *.html, *.tar.gz, e2e_testresults.xml' , onlyIfSuccessful: false
      echo 'POST failure: Performing cleanup tasks for build failure'
      deleteDir()
    }
  }
}
// RTC steps for checkin and deliver
def rtcCheckin(){
  withCredentials([usernamePassword(credentialsId: 'RTC_BUILD', usernameVariable: 'rtcUser', passwordVariable: 'rtcPass')]) {
  // available as an env variable, but will be masked if you try to print it out any which way
    def MYHOSTNAME=getHostname()
    def lastBuildDate=new Date(currentBuild.startTimeInMillis).format('MMM dd, yyyy HH:mm:ss Z')
    def versionString="version: ${packageVersion}"
    def buildDateString="lastBuildDate: ${lastBuildDate}"
    def distributionString="distributionFileName: <staging_url>/${DIST_OUTPUT_FILENAME}"
    def commitComment = /"${versionString}, ${buildDateString}, ${distributionString},jenkins-${JOB_BASE_NAME}-${BUILD_NUMBER}-${MYHOSTNAME}"/
    def workitem = "${RTC_WORKITEM}"
    def components= ["${TAS_WEBUI}"]

    echo "show scm status"
    sh """
      ${scmtool} show status -u ${rtcUser} -P ${rtcPass} -v --all -d ${TASWorkspace}
      echo "----- ----- ----- ----- -----"
    """
    
    echo "prepare to checkin components"
    for (component in components){
      echo "loop through each file in $component"
      sh """
        find $component -maxdepth 1 -type f -name '.*' -exec ${scmtool} checkin -u ${rtcUser} -P ${rtcPass} --comment ${commitComment} --workitem ${workitem} -v -d ${TASWorkspace} ${TASWorkspace}/{} \\;
      """
      echo "${scmtool} checkin $component/*"
      sh "${scmtool} checkin -u ${rtcUser} -P ${rtcPass} --comment ${commitComment} --workitem ${workitem} -v -d ${TASWorkspace} ${TASWorkspace}/$component/*"
      echo "----- ----- ----- ----- -----"
    }
    // the following is not valid until rtc 6.0.4
    //step([$class: 'RTCPostBuildDeliverPublisher', failOnError: true])
  }
}

def rtcDeliver(){
  withCredentials([usernamePassword(credentialsId: 'RTC_BUILD', usernameVariable: 'rtcUser', passwordVariable: 'rtcPass')]) {
  // available as an env variable, but will be masked if you try to print it out any which way
    def workitem = "${RTC_WORKITEM}"
    echo "show scm status"
    sh """
      ${scmtool} show status -u ${rtcUser} -P ${rtcPass} -v --all -d ${TASWorkspace}
      echo "----- ----- ----- ----- -----"
    """
    echo "RTC ${rtcUser} deliver "
    def deliverStatus=sh (
    script: "${scmtool} deliver -u ${rtcUser} -P ${rtcPass} -v",
    returnStatus: true
    )
    if (deliverStatus == 0 || deliverStatus == 52 || deliverStatus == 53){
      echo "Deliver succeed"
      return 0
    }
    else {
      currentBuild.result='FAILED'
      error("FAIL: SCM deliver failed with ${deliverStatus}")
    }
    // the following is not valid until rtc 6.0.4
    //step([$class: 'RTCPostBuildDeliverPublisher', failOnError: true])
  }
}

def rtcBaseline(){
  withCredentials([usernamePassword(credentialsId: 'RTC_BUILD', usernameVariable: 'rtcUser', passwordVariable: 'rtcPass')]) {
  // available as an env variable, but will be masked if you try to print it out any which way
    echo "RTC list workspaces "
    def workspaceList=sh (
    script: "${scmtool} list workspaces -r local -v",
    returnStdout: true
    ).trim()

    echo "workspace: ${workspaceList}"

    echo "RTC ${rtcUser} create baseline "
    sh """
      ${scmtool} create baseline -u ${rtcUser} -P ${rtcPass} --all ${workspaceList} ${packageVersion} 
    """
    // the following is not valid until rtc 6.0.4
    //step([$class: 'RTCPostBuildDeliverPublisher', failOnError: true])
  }
}

def getBranchName(){
  def branch="${GIT_BRANCH}"
  return branch.tokenize('/')[1].toLowerCase()
}
// load workspace
def getHalfakerCode(){
  branch_name=getBranchName()
  echo "(${branch_name}), [${GIT_BRANCH}]"
  echo "get the code"
  sh """
    git config --global core.autocrlf false
  """
  git credentialsId: 'mccf_jenkins_build', url: "${mccf_git_repo}", poll: false, branch: "${branch_name}"
  echo ("get last git tag")
  lastGitTag=gitDescribe()
  def lastCommit=getLastGitCommit()
  echo ("check lastGitTag (${lastGitTag})")
  echo ("need to verify last commit (${lastCommit}) is part of last tag (${lastGitTag}), so we can checkin")
  if ( lastGitTag?.trim() ){
    echo ("Ready to build ${lastGitTag} (${lastCommit})")
  }
  else {
    error("FAIL: no source pulled from ${mccf_git_repo}")
  }
 }

 // git functions
def getChangesets(){
    def changeLogSets = currentBuild.changeSets
    echo "reviewing changesets:"
    def commitMessage=""
    for (int i = 0; i < changeLogSets.size(); i++) {
        def entries = changeLogSets[i].items
        for (int j = 0; j < entries.length; j++) {
            def entry = entries[j]
            commitMessage="${commitMessage} \n ${entry.commitId} by ${entry.author} on ${new Date(entry.timestamp)}"
            echo "${entry.commitId} by ${entry.author} on ${new Date(entry.timestamp)}: ${entry.msg}"
            def files = new ArrayList(entry.affectedFiles)
            for (int k = 0; k < files.size(); k++) {
                def file = files[k]
                echo "  ${file.editType.name} ${file.path}"
            }
        }
    }
    return "${commitMessage}"
}

def gitDescribe(){
  echo "getting last git tag"
  def MYINFO
  def tagExists=sh(returnStdout: true, script: 'git tag --list').trim()
  if ( tagExists?.trim() ) {
    MYINFO=sh(returnStdout: true, script: 'git describe').trim()
  }
  else {
    MYINFO=sh(returnStdout: true, script: 'git describe --always').trim()
  }
  echo ("we need to parse ${MYINFO} to determine if the latest tag is the latest commit")
  MYINFO
}

def getLastGitCommit(){
  echo "getting last git commit"
  def LAST_COMMIT
  LAST_COMMIT = sh (
    script: 'git rev-parse HEAD',
    returnStdout: true
  ).trim()
  echo ("the last commit is ${LAST_COMMIT[0..6]}")
  LAST_COMMIT[0..6]
}

def gitTagBuild(){
  withCredentials([string(credentialsId: 'mccf_jenkins_build', variable: 'bitbucket_access')]) {
    def MYHOSTNAME=getHostname()
    def commit_message = /"jenkins-${JOB_BASE_NAME}-${BUILD_NUMBER}-${MYHOSTNAME}"/
    sh """
      git config --global push.default simple
      git config alias.versionlog "notes --ref=versionlog append"
      git config --add remote.origin.push '+refs/notes/*:refs/notes/*'
      git config --add remote.origin.fetch '+refs/notes/*:refs/notes/*'
      git config --list 
      """
    echo "append version note to this commit"
    addGitVersionLog()
    echo "tag this commit"
    sh """
      git tag -a ${packageVersion} -m '${commit_message}' ${lastCommitID}
      echo "push changes to remote"
      git push origin --tags --verbose
    """
  }
}

def addGitVersionLog(){
  def lastBuildDate=new Date(currentBuild.startTimeInMillis).format('MMM dd, yyyy HH:mm:ss Z')
  def versionString="version: ${packageVersion}"
  def buildDateString="lastBuildDate: ${lastBuildDate}"
  def distributionString="distributionFileName: <staging_url>/${DIST_OUTPUT_FILENAME}"
  sh """
    git versionlog ${lastCommitID} -m "${versionString}, ${buildDateString}, ${distributionString}"
  """
}

// helper functions
def getHostname(){
  def THISHOSTNAME
  if(isUnix()){
    THISHOSTNAME = sh (
      script: 'hostname',
      returnStdout: true
    ).trim()
  }
  else {
    THISHOSTNAME = bat (
      script: 'hostname',
      returnStdout: true
    ).trim()
  }
  THISHOSTNAME
}

def getPackageName(){
  echo "getting package name"
  def MYNAME
  MYNAME = sh (
      script: 'npm run env | grep npm_package_name | cut -d \"=\" -f 2',
      returnStdout: true
    ).trim()
  MYNAME
}

def updateIndexMetaData(){
  def lastBuildDate=new Date(currentBuild.startTimeInMillis).format('MMM dd, yyyy HH:mm:ss Z')
  def metaData=["distributionFileName":"${DIST_OUTPUT_FILENAME}", "lastBuildDate":"${lastBuildDate}", "version":"${packageVersion}" ]
  echo 'backup the index file bfore editing'
  sh "cp ${index} ${index}.bak"
  for (kv in mapToList(metaData)){
     def name=kv[0]
     def content=kv[1]
     echo "update meta tag name=\"${name}\", content=\"${content}\""
     sh """
       sed -i '/<head>/a <meta name=\"${name}\" content=\"${content}\" >' "${index}"
     """      
  }
}

def checkNpmInstallLog(log){
  echo "checking npm install log for 'Downloading.*github'"
  def MYRESULT
  MYRESULT = sh (
      script: """
        if grep -Exq "Downloading.*github" ${log}
        then
          echo "FAILED: unauthorized download"
        else
          echo "PROCEED: Nothing incriminating found in log"
        fi
        """,
      returnStdout: true
    ).trim()
  return MYRESULT
}

def checkDependenciesLog(log){
  echo "checking  log for 'not installed'"
  def MYRESULT
  MYRESULT = sh (
      script: """
        if grep -Exq ".*not installed.*" ${log}
        then
          echo "FAILED: packages not installed"
        else
          echo "PROCEED: All packages installed"
        fi
        """,
      returnStdout: true
    ).trim()
  return MYRESULT
}

def stageLatestArtifact(artifact){
    echo "stage the latest build artifact(${artifact}) for deployment"
    def artifact_name= artifact.tokenize('/').last()
    def staging = STAGING_DIR.trim().toLowerCase()
    def latest = "${WEB_BASEDIR}/latest_dev"
    echo "check for TGT_STREAM"
    if(env.branch_name && env.branch_name?.trim().toLowerCase() != 'master'){
      echo "staging for branch build (${branch_name})"
      def link=branch_name?.trim().toLowerCase()
      latest = "${WEB_BASEDIR}/latest_${link}"
    }
    else{
      if(env.TGT_STREAM && env.TGT_STREAM?.trim()){
        echo "TGT_STREAM found (${TGT_STREAM})"
        def link=TGT_STREAM.trim().toLowerCase()
        latest = "${WEB_BASEDIR}/latest_${link}"
      }
    }
    try {
        echo "check ${staging} directory exist"
        sh "[[ -d ${staging} ]] || sudo mkdir -p ${staging}"
        echo "fix directory permissions"
        sh """
          set -x
          sudo find \$(dirname ${STAGING_DIR}) -type d -exec chmod 0755 {} \\;
        """
        echo "copy ${artifact} to ${staging}/"
        sh "sudo cp ${artifact} ${staging}/"
        echo "create symbolic link to staged artifact"
        sh "sudo ln -sfn ${staging}/${artifact_name} ${latest}"
        echo "verify link created"
        def linkExists=sh (
            script: "readlink ${latest}",
            returnStdout: true
            ).trim()
        sh """
            if [[ -n "${linkExists}" ]]; then
                echo "link exists for ${latest}"
            else
                echo "link not found ${latest}"
            fi
        """
    } catch(Exception e){
        echo "something bad happened while staging artifact, throw and fail"
        echo e.toString()
        throw e
    }
}
// notifyHipchat
// will send color coded notifications to hipchat
//
def notifyHipchat(String buildStatus = 'STARTED', String hcRoom = '3242078') {
// build status of null means successful
  buildStatus =  buildStatus ?: 'SUCCESSFUL'

  def lastBuild = currentBuild.getPreviousBuild()

  // Default values
  def color = 'RED'
  def colorCode = '#FF0000'
  def subject = "${buildStatus}: Job '${env.JOB_NAME} [${env.BUILD_NUMBER}]'"
  def summary = "${subject} (${env.BUILD_URL})"

    // Override default values based on build status
  if (buildStatus == 'STARTED') {
    color = 'YELLOW'
    colorCode = '#FFFF00'
  } 
  else if (buildStatus == 'SUCCESSFUL') {
    color = 'GREEN'
    colorCode = '#00FF00'
    if( lastBuild && lastBuild.getResult().toString()=="FAILURE" ){
      buildStatus = 'FIXED'
    }
  } 
  else if (buildStatus == 'ABORTED') {
    color = 'PURPLE'
    colorCode = '#800080'
  }
  else if (buildStatus == 'UNSTABLE') {
    color = 'GRAY'
    colorCode = '#808080'
  }
  else {
    color = 'RED'
    colorCode = '#FF0000'
  }
 
   // Send notifications
  echo "send notice of ${buildStatus} to hipchat room: ${hcRoom}"
  def hcMessage=getChangesets()
  if(buildStatus == 'SUCCESSFUL'){
    echo "only send notice if previous build failed"
    if( lastBuild && lastBuild.getResult().toString()=="FAILURE" ){
      echo "the previous build ${lastBuild.getId()} failed, send update"
      hipchatSend (
        color: color, 
        credentialId: 'jenkins_hc_notification', 
        message: summary + ": changesets:  " + hcMessage, 
        notify: true, 
        room: hcRoom, 
        sendAs: 'jenkins_build', 
        textFormat: false, 
        v2enabled: true
      )
    }
    else {
      echo "the previous build " + lastBuild.getResult().toString()
    }
  }
  else {
    echo "this build ${buildStatus}"
    hipchatSend (
      color: color,
      credentialId: 'jenkins_hc_notification',
      message: summary + ": changesets:  " + hcMessage,
      notify: true,
      room: hcRoom,
      sendAs: 'jenkins_build',
      textFormat: false,
      v2enabled: true
    )
  }
}

def notifyBuildStatus(String buildStatus = 'STARTED') {
  // build status of null means successful
  buildStatus =  buildStatus ?: 'SUCCESSFUL'

//recipientProviders (optional)
//$class: CulpritsRecipientProvider
//Sends email to the list of users who committed a change since the last non-broken build till now.
//This list at least always include people who made changes in this build, but if the previous build 
//was a failure it also includes the culprit list from there.

//$class: DevelopersRecipientProvider
//Sends email to all the people who caused a change in the change set.

//$class: FailingTestSuspectsRecipientProvider
//Sends email to the list of users suspected of causing a unit test to begin failing.
//This list includes committers and requestors of the build where the test began to fail,
//and those for any consecutive failed builds prior to the build in which the test began to fail.

//$class: FirstFailingBuildSuspectsRecipientProvider
//Sends email to the list of users suspected of causing the build to begin failing.

//$class: ListRecipientProvider
//Sends email to the list of recipients defined in the "Project Recipient List."

//$class: RequesterRecipientProvider
//Sends email to the user who initiated the build.

//$class: UpstreamComitterRecipientProvider
//Sends email to the list of users who committed changes in upstream builds that triggered this build
// Default values           ListRecipientProvider
  def recipients=[[$class: 'ListRecipientProvider']]
  def subject = "${buildStatus}: Job '${env.JOB_NAME} [${env.BUILD_NUMBER}]'"
  def replyto = "${env.DEFAULT_REPLYTO}"
  def mimeType = "text/html"
  def sendto = "${env.DEFAULT_RECIPIENTS}"
  def details = """
    <p>Job: '${env.JOB_NAME} build: [${env.BUILD_NUMBER}]':</p>
    <p>Check console output at "<a href="${env.BUILD_URL}">${env.JOB_NAME} [${env.BUILD_NUMBER}]</a>"</p>
    """

    // Override default values based on build status
  if (buildStatus == 'STARTED' || buildStatus == 'SUCCESSFUL' || buildStatus == 'FIXED') {
    recipients = [[$class: 'DevelopersRecipientProvider']]
  } 
 
  else if (buildStatus == 'ABORTED' || buildStatus == 'UNSTABLE') {
    recipients = [[$class: 'DevelopersRecipientProvider']]
  }
  else {
    echo "unknown status"
    recipients = [[$class: 'CulpritsRecipientProvider'], [$class: 'RequesterRecipientProvider']]
  }
//examples
//Notify Culprits and Requester via default EMail plugin
//step([$class: 'Mailer', notifyEveryUnstableBuild: true, recipients: emailextrecipients([[$class: 'CulpritsRecipientProvider'], [$class: 'RequesterRecipientProvider']])])

//Send an email to abc plus any addresses returned by the providers
//emailext body: 'A Test EMail', 
//         recipientProviders: [[$class: 'DevelopersRecipientProvider'], [$class: 'RequesterRecipientProvider']], 
//         subject: 'Test', 
//         to: 'abc'
  echo "send email to recipients (${recipients}) for ${buildStatus}"
  echo """
      subject: ${subject},
      body: ${details},
      recipientProviders: ${recipients},
      replyTo: ${replyto},
      to: ${sendto}
      """
  mail (
      body: details, 
      cc: 'lee.benhart@halfaker.com', 
      mimeType: 'text/html', 
      replyTo: replyto, 
      subject: subject, 
      to: sendto
      )
}

//save log to workspace
def getConsoleLog(){
   //JENKINS_HOME=/var/lib/jenkins
    //JENKINS_URL=http://aws-master.mccf.halfakerlabs.com:8080/
    //BUILD_URL=http://aws-master.mccf.halfakerlabs.com:8080/job/MCCF_TAS/job/MCCF_TAS_Core/512/
    //JOB_URL=http://aws-master.mccf.halfakerlabs.com:8080/job/MCCF_TAS/job/MCCF_TAS_Core/
    //log location is /var/lib/jenkins/jobs/MCCF_TAS/jobs/MCCF_TAS_Core/builds/512
  echo "getConsoleLog: prepare logfilename to get console log"
  def logFilename="${JOB_URL}"
  def workspaceLog="${WORKSPACE}/${JOB_BASE_NAME}_${BUILD_NUMBER}_console.log"
  echo "getConsoleLog: console log is ${logFilename} (same as job url)"
  logFilename=logFilename.trim().replace("${JENKINS_URL}","${JENKINS_HOME}/")
  echo "getConsoleLog: console log is changed to ${logFilename}"
  logFilename=logFilename.trim().replaceAll("job","jobs")
  echo "getConsoleLog: console log is changed again to ${logFilename}"
  logFilename="${logFilename}builds/${BUILD_NUMBER}/log"
  echo "getConsoleLog: console log is finally  ${logFilename}"
  echo "getConsoleLog: prepare to write to ${workspaceLog}"
  sh """
    sed -e "s,\\x1b\\[[0-9]*.*\\x1b\\[0m,,g;s,\\bactive\\b,active\\n\\r,gm;s,\\x08,.,gm" "${logFilename}" > "tmp.log"
    sed -e "s,\\x1b\\[3[0-9][mGKA],,gm;s,\\x1b\\[1A,,gm;s,\\x1b\\[2K,,gm;" "tmp.log" > "${workspaceLog}"
    rm "tmp.log"
    echo "getConsoleLog: verify ${workspaceLog} ready for archival"
    if [[ -f "${workspaceLog}" ]]
    then
      echo "getConsoleLog: local console log (${workspaceLog}) exists, safe to proceed"
    else
      echo "getConsoleLog: No local console log (${workspaceLog}) found"
    fi
  """
}
// Required due to JENKINS-27421
@NonCPS
List<List<?>> mapToList(Map map) {
  return map.collect { it ->
    [it.key, it.value]
  }
}
