pipeline {
    agent none

    environment {
        RACK_ENV  = "test"
        RAILS_ENV = "test"
        SKIP_CHROMEDRIVER_LOGGER = "1"
        IMAGE_NAME = "docker.io/nahaylo/onapp-5-ruby"
        BUNDLE_INSTALL_DIR = '${WORKSPACE}/../cached_gems_6.0'
        // this is the main trick where the folder on jenkins which holds all installed gems
        // is mounted to containers so bundler thinks the gems are already installed
        DOCKER_ARGS = '-u root:root -v ${HOME}/onapp-interface/gems-6.0:${BUNDLE_INSTALL_DIR} -v ${HOME}/onapp-interface/.webdrivers:/root/.webdrivers'
        RSPEC_PROFILE_SPECS = "0"
    }

    post {
        success {
            emailext (
                subject: "SUCCESSFUL: Job '${env.JOB_NAME} [${env.BUILD_NUMBER}]'",
                mimeType: "text/html",
                to: "core@onapp.com",
                body: """<p>SUCCESSFUL: Job '${env.JOB_NAME} [${env.BUILD_NUMBER}]':</p>
                    <p>Check console output at <a href='${env.BUILD_URL}'>${env.JOB_NAME} [${env.BUILD_NUMBER}]</a></p>""")
        }

        failure {
            emailext (
                subject: "FAILED: Job '${env.JOB_NAME} [${env.BUILD_NUMBER}]'",
                mimeType: "text/html",
                to: "core@onapp.com",
                body: """<p>FAILED: Job '${env.JOB_NAME} [${env.BUILD_NUMBER}]':</p>
                    <p>Check console output at <a href='${env.BUILD_URL}'>${env.JOB_NAME} [${env.BUILD_NUMBER}]</a></p>""")
        }
    }

    stages {
        stage("Run tests") {
            parallel {
                stage("interface/lib+models+models_permissions+presenters") {
                    agent {
                        docker {
                            image env.IMAGE_NAME
                            args env.DOCKER_ARGS
                        }
                    }

                    post {
                        always {
                            saveSpecResults()
                        }

                        cleanup {
                            cleanWorkspace()
                        }
                    }

                    steps {
                        defaultPreparations()

                        runSpecs 'spec/lib spec/models spec/models_permissions spec/presenters'
                    }
                }

                stage("interface/policies+services+transactions+acceptance") {
                    agent {
                        docker {
                            image env.IMAGE_NAME
                            args env.DOCKER_ARGS
                        }
                    }

                    post {
                        always {
                            saveSpecResults()
                        }

                        cleanup {
                            cleanWorkspace()
                        }
                    }

                    steps {
                        defaultPreparations()

                        runSpecs 'spec/services spec/policies spec/transactions spec/acceptance'
                    }
                }

                stage("interface/others") {
                    agent {
                        docker {
                            image env.IMAGE_NAME
                            args env.DOCKER_ARGS
                        }
                    }

                    post {
                        always {
                            saveSpecResults()
                        }

                        cleanup {
                            cleanWorkspace()
                        }
                    }

                    steps {
                        defaultPreparations()

                        sh "bundle exec rake assets:precompile"

                        runSpecs "spec --exclude-pattern '{lib,policies,services,models,models_permissions,transactions,acceptance,presenters}/**/*_spec.rb'"
                    }
                }

                stage("onapp-backups") {
                    agent {
                        docker {
                            image env.IMAGE_NAME
                            args env.DOCKER_ARGS
                        }
                    }

                    post {
                        always {
                            saveSpecResults()
                        }

                        cleanup {
                            cleanWorkspace()
                        }
                    }

                    steps {
                        defaultComponentPreparations()

                        dir('components/onapp-backups') {
                            bundleInstall()
                            prepareDb()

                            runSpecs 'spec'
                        }
                    }
                }

                stage("onapp-messaging") {
                    agent {
                        docker {
                            image env.IMAGE_NAME
                            args env.DOCKER_ARGS
                        }
                    }

                    post {
                        always {
                            saveSpecResults()
                        }

                        cleanup {
                            cleanWorkspace()
                        }
                    }

                    steps {
                        defaultComponentPreparations()

                        dir('components/messaging') {
                            bundleInstall()
                            prepareComponentDb()

                            runSpecs 'spec'
                        }
                    }
                }

                stage("onapp-networking") {
                    agent {
                        docker {
                            image env.IMAGE_NAME
                            args env.DOCKER_ARGS
                        }
                    }

                    post {
                        always {
                            saveSpecResults()
                        }

                        cleanup {
                            cleanWorkspace()
                        }
                    }

                    steps {
                        startServices()
                        addKeysToKnownHosts()
                        ensureConfigIsSet()

                        sh "echo -e \"---\npath: `pwd`\" > components/onapp-networking/config/main_app_info.yml"
                        sh "cp -f Gemfile.lock components/onapp-networking/"

                        dir('components/onapp-networking') {
                            sh 'gem install bundler:1.17.1'
                            bundleInstall()
                            prepareComponentDb()

                            runSpecs 'spec'
                        }
                    }
                }

                stage("networking-sdn") {
                    agent {
                        docker {
                            image env.IMAGE_NAME
                            args env.DOCKER_ARGS
                        }
                    }

                    post {
                        always {
                            saveSpecResults()
                        }

                        cleanup {
                            cleanWorkspace()
                        }
                    }

                    steps {
                        startServices()
                        addKeysToKnownHosts()
                        configureBundler()


                        sh "cp components/dummy_database.test.yml components/onapp-networking/networking-sdn/spec/dummy/config/database.yml"

                        dir('components/onapp-networking/networking-sdn/spec/dummy') {
                            bundleInstall()
                            prepareDb()
                        }

                        dir('components/onapp-networking/networking-sdn') {
                            sh "BUNDLE_GEMFILE=spec/dummy/Gemfile bundle exec rspec spec --format progress --format RspecJunitFormatter --out ../../../rspec_results/results-${STAGE_NAME}.xml --deprecation-out /dev/null --profile=${env.RSPEC_PROFILE_SPECS} --backtrace"
                        }
                    }
                }
            }
        }
    }
}

def saveSpecResults() {
    path = "rspec_results/results-${STAGE_NAME}.xml"
    archiveArtifacts path
    junit testResults: path, allowEmptyResults: true
}

def cleanWorkspace() {
    // no need in deleting the whole dir, only the files created during specs
    sh "git clean -fdx"

    // as it turns out we DO need to remove the dir since jenkins doesn't do that
    deleteDir()

    dir("${WORKSPACE}@tmp") {
        deleteDir()
    }

    dir("${WORKSPACE}@script") {
        deleteDir()
    }
}

def startServices() {
    sh "/etc/init.d/mysqld start"
    sh "/etc/init.d/redis start"
}

def addKeysToKnownHosts() {
    sh "ssh-keyscan bitbucket.org >> /root/.ssh/known_hosts"
    sh "ssh-keyscan github.com >> /root/.ssh/known_hosts"
}

def configureBundler() {
    sh "bundle config path ${env.BUNDLE_INSTALL_DIR}"
    sh "bundle config jobs 8"
}

def ensureConfigIsSet() {
    configureBundler()

    sh "cp config/on_app.yml.example config/on_app.yml"
    sh "cp config/database.test.yml config/database.yml"
    sh "cp config/redis.test.yml config/redis.yml"
    sh "touch config/keys/private"
    sh "touch config/keys/public"
}

def bundleInstall() {
    sshagent (credentials: ['7ce580c0-7d01-412f-bff1-485b4ca6196a']) {
        sh "bundle install"
    }
}

def prepareDb() {
    sh "bundle exec rake db:create db:schema:load"
}

def prepareComponentDb() {
    sh "bundle exec rake app:db:create app:db:schema:load"
}

def prepareComponent() {
    sh "cp components/dummy_database.test.yml components/dummy_database.yml"
}

def defaultPreparations() {
    startServices()
    addKeysToKnownHosts()
    ensureConfigIsSet()
    bundleInstall()
    prepareDb()
}

def defaultComponentPreparations() {
    startServices()
    addKeysToKnownHosts()
    configureBundler()

    prepareComponent()
}

def runSpecs(specsPatterns) {
    sh "bundle exec rspec ${specsPatterns} --format progress --format RspecJunitFormatter --out ${env.WORKSPACE}/rspec_results/results-${STAGE_NAME}.xml --deprecation-out /dev/null --profile=${env.RSPEC_PROFILE_SPECS} --backtrace"
}
