@Library('StanUtils')
import org.stan.Utils

def utils = new org.stan.Utils()

/* Functions that runs a sh command and returns the stdout */
def runShell(String command){
    def output = sh (returnStdout: true, script: "${command}").trim()
    return "${output}"
}

def tagName() {
    if (env.TAG_NAME) {
        env.TAG_NAME
    } else if (env.BRANCH_NAME == 'master') {
        'nightly'
    } else {
        'unknown-tag'
    }
}

def checkoutRepository(os_type) {
    if(params.git_branch.contains("PR-")){
        pr_number = params.git_branch.split("-")[1]

        if(os_type == "sh"){
            sh "git fetch origin pull/${pr_number}/head:pr/${pr_number}"
            sh "git checkout pr/${pr_number}"
        }
        else if(os_type == "bat"){
            bat "git fetch origin pull/${pr_number}/head:pr/${pr_number}"
            bat "git checkout pr/${pr_number}"
        }
    }
    else{
        if(os_type == "sh"){
            sh "git checkout master && git pull && git checkout ${params.git_branch} && git pull origin ${params.git_branch}"
        }
        else if(os_type == "bat"){
            bat "git checkout master && git pull && git checkout ${params.git_branch} && git pull origin ${params.git_branch}"
        }
    }
}

pipeline {
    agent none
    parameters {
        string(defaultValue: 'master', name: 'git_branch',
               description: "Please specify a git branch ( develop ), git hash ( aace72b6ccecbb750431c46f418879b325416c7d ), pull request ( PR-123 ), pull request from fork ( PR-123 )")
    }
    environment {
        GITHUB_TOKEN = credentials('6e7c1e8f-ca2c-4b11-a70e-d934d3f6b681')
    }
    options {parallelsAlwaysFailFast()}
    stages {

        stage("Dune tests") {
            agent {
                docker {
                    image 'stanorg/stanc3:debian-ocaml-4.14'
                    //Forces image to ignore entrypoint
                    args "--entrypoint=\'\'"
                }
            }
            steps {
                runShell("""
                    eval \$(opam env)
                    dune runtest --verbose
                """)
            }
            post { always { runShell("rm -rf ./*") }}
        }

        stage("Build") {
            agent {
                docker {
                    image 'stanorg/stanc3:debian-ocaml-4.14'
                    args "--entrypoint=\'\'"
                }
            }
            steps {
                script {
                    checkoutRepository("sh")
                }
                runShell("""
                    eval \$(opam env)
                    dune build @install
                """)
                sh "mkdir -p bin && mv _build/default/src/stanc/stanc.exe bin/stanc"
                archiveArtifacts 'bin/*'
            }
            post { always { runShell("rm -rf ./*") }}
        }

        stage("Build & test Mac OS X binary") {
            agent { label 'osx' }
            steps {
                script {
                    checkoutRepository("sh")
                }
                runShell("""
                    export PATH=/Users/jenkins/brew/bin:\$PATH
                    eval \$(opam env)
                    opam update || true
                    bash -x scripts/install_build_deps.sh
                    dune subst
                    dune build @install
                """)
                sh "mkdir -p bin && mv `find _build -name stanc.exe` bin/mac-stanc"
                archiveArtifacts 'bin/*'
            }
            post { always { runShell("rm -rf ./*") }}
        }

        stage("Build stanc.js") {
            agent {
                docker {
                    image 'stanorg/stanc3:debian-ocaml-4.14'
                    //Forces image to ignore entrypoint
                    args "--entrypoint=\'\'"
                }
            }
            steps {
                script {
                    checkoutRepository("sh")
                }
                runShell("""
                    eval \$(opam env)
                    dune subst
                    dune build --profile release src/stancjs
                """)
                sh "mkdir -p bin && mv `find _build -name stancjs.bc.js` bin/stanc.js"
                sh "mv `find _build -name index.html` bin/load_stanc.html"
                archiveArtifacts 'bin/*'
            }
            post {always { runShell("rm -rf ./*")}}
        }

        stage("Build & test a static Linux binary") {
            agent {
                docker {
                    image 'stanorg/stanc3:static-ocaml-4.14'
                    //Forces image to ignore entrypoint
                    args "--entrypoint=\'\'"
                }
            }
            steps {
                script {
                    checkoutRepository("sh")
                }
                runShell("""
                    eval \$(opam env)
                    dune subst
                    dune build @install --profile static
                """)
                sh "mkdir -p bin && mv `find _build -name stanc.exe` bin/linux-stanc"
                archiveArtifacts 'bin/*'
            }
            post {always { runShell("rm -rf ./*")}}
        }

        stage("Build & test static Windows binary") {
            agent {
                docker {
                    image 'stanorg/stanc3:debian-windows-ocaml-4.14'
                    //Forces image to ignore entrypoint
                    args "--entrypoint=\'\'"
                }
            }
            steps {
                script {
                    checkoutRepository("sh")
                }
                runShell("""
                    eval \$(opam env)
                    dune subst
                    dune build -x windows
                """)
                sh "mkdir -p bin && mv _build/default.windows/src/stanc/stanc.exe bin/windows-stanc"
                stash name:'windows-exe', includes:'bin/*'
                archiveArtifacts 'bin/*'
            }
            post {always { runShell("rm -rf ./*")}}
        }
    }
}
