/* Scenarios:
  1. Main + no FORCE_VERSIONS + new go version (auto build, occasional)
  2. Main + no FORCE_VERSIONS + no new go version (most common)
  3. Main + FORCE_VERSIONS + push anyway (manual Jenkins run to update existing image)
  4. Non-main + no FORCE_VERSIONS + new go version (rare during testing)
  5. Non-main + no FORCE_VERSIONS + no new go version (common during testing)
  6. Non-main + FORCE_VERSIONS + build and test (Manual Jenkins run against branch w/ parameter)
** Responses:
  1. Build, test and deploy new Go version.
  2. No builds, no tests, everything skipped.
  3. Build, test and deploy provided (possibly existing) Go version(s).
  4. Build and test new Go version(s). No Deploy.
  5. Build and test existing Go versions. No deploy.
  6. Build and test provided (possibly existing) Go versions. No deploy.
*/

properties([
  parameters([
    string(defaultValue: '', name: 'VERSIONS', description:
      '(Optional) When run from main, this also deploys. ' +
      'Force build specific Go versions. space-separated, ex: go1.15.12 go1.16.4',
    ),
    string(defaultValue: 'v1.40.1', name: 'GOLANGCI_LINT_VERSION', description:
      'Version of golangci-lint to install into the container. If left blank, latest it used.',
    ),
  ]), // parameters
  pipelineTriggers([cron('H 4 * * *')]), // This pipeline runs automatically every day at 4 AM UTC.
]) // properties

// All commits to non-main branches trigger image builds without deploying them.
// The 'main' branch is deployed on request (when a custom version is provided),
// or when a new version (missing from Artifactory) is available from golang.org.
def get_stages(version, shortver){
  return { stage("build_${shortver}") {
    if (env.BRANCH_NAME != "main") {  // Scenarios 4, 5, 6
      echo "==> Building and testing branch ${env.BRANCH_NAME}: ${shortver} (golangci-lint: ${params.GOLANGCI_LINT_VERSION})"
      sh "scripts/build.sh - ${version} ${params.GOLANGCI_LINT_VERSION}"
    } else if (env.VERSIONS == "" && env.NEEDED != "") { // Scenario 1
      echo "==> Building, testing and deploying: ${shortver} (golangci-lint: ${params.GOLANGCI_LINT_VERSION})"
      sh "scripts/build.sh deploy ${version} ${params.GOLANGCI_LINT_VERSION}"
    } else if (env.VERSIONS == "" && env.NEEDED == "") { // Scenario 2
      echo "No new Go versions to build or deploy!"
    } else { // Scenario 3
      echo "==> Building, testing and deploying: ${shortver} (golangci-lint: ${params.GOLANGCI_LINT_VERSION})"
      sh "scripts/build.sh deploy ${version} ${params.GOLANGCI_LINT_VERSION}"
    }
  }}
} // get_stages

node {
  checkout scm

  try {
    // These variables are referenced by scripts and by get_stages() above.
    env.VERSIONS = params.VERSIONS
    env.LATEST   = sh(script: "scripts/getlatest.sh", returnStdout: true).trim() // this script uses $VERSIONS
    env.NEEDED   = sh(script: "scripts/getneeded.sh", returnStdout: true).trim() // this script uses $LATEST

    // Make sure we have _something_ to process.
    // We check later if we're _supposed_ to process.
    env.NEWVERSIONS = env.NEEDED
    if (env.NEWVERSIONS == "" || env.BRANCH_NAME != "main") {
      env.NEWVERSIONS = env.LATEST
    }

    build_stages = [:]
    // Each VERSION is a "go:sha:os" combo.
    env.NEWVERSIONS.split().each { VERSION ->
      v = VERSION.split(':')
      v = "${v[0]}_${v[2]}" // make a short version; easier to read in logs.
      build_stages[v] = get_stages(VERSION, v)
    } // env.NEWVERSIONS.each

    parallel build_stages
  } catch(err) {
    withCredentials([string(credentialsId: 'slack_aws_infra_bawt', variable: 'SLACKURL')]) {
      sh "scripts/slack.sh fail"
    }
    throw(err)
  }

  stage("notify_slack_ok") {
    withCredentials([string(credentialsId: 'slack_aws_infra_bawt', variable: 'SLACKURL')]) {
      if (env.BRANCH_NAME != "main" || env.VERSIONS != "" || env.NEEDED != "") {
        sh "scripts/slack.sh ok"
      }
      if (env.BRANCH_NAME == "main" && (env.VERSIONS != "" || env.NEEDED != "")) {
        // Send a "new images" message to #golang
        sh "scripts/slack.sh new"
      }
    }
  }
} // node
