#!groovy

import org.csanchez.jenkins.plugins.kubernetes.pipeline.PodTemplateAction

// static properties
class Globals {
    static extensionName = "extended-attribute-type"
    static vendorName = "akeneo"
    static extensionRepoUrl = "https://github.com/akeneo/ExtendedAttributeTypeBundle.git"
    static extensionVersion = "dev-master"

    static phpVersion = "7.1"
    static phpunitVersion = "^5.7"
    static pimRepoUrl = [
        ce: "https://github.com/akeneo/pim-community-standard.git",
        ee: "https://github.com/akeneo/pim-enterprise-standard.git"
    ]
}

// user input
String launchUnitTests = "yes"
String launchIntegrationTests = "yes"
String[] pimVersions = ["2.0"]
String[] pimEditions = ["ee", "ce"]

def installExtension(pimEdition, extensionPath) {

    if (pimEdition.equals("ce")) {
        sh "cp ${extensionPath}/.ci/resources/parameters_test.yml app/config/parameters_test.yml"
    } else if (pimEdition.equals("ee")) {
        sh "cp ${extensionPath}/.ci/resources/parameters_test_ee.yml app/config/parameters_test.yml"
    }

    sh """
        cp ${extensionPath}/.ci/resources/phpunit.xml app/phpunit.xml
        sed -i 's#// your app bundles should be registered here#\\0\\nnew Pim\\\\Bundle\\\\ExtendedAttributeTypeBundle\\\\PimExtendedAttributeTypeBundle(),#' app/AppKernel.php
        rm ./var/cache/* -rf
    """

    sh "sleep 5"
    sh 'composer dump-autoload -o'
    sh "./bin/console --env=test pim:installer:db"
}

stage("Build") {
    milestone 1
    if (env.BRANCH_NAME =~ /^PR-/) {
        userInput = input(message: 'Launch tests?', parameters: [
            choice(choices: 'yes\nno', description: 'Run unit tests', name: 'launchUnitTests'),
            choice(choices: 'yes\nno', description: 'Run integration tests', name: 'launchIntegrationTests'),
            string(defaultValue: "${pimVersions.join(',')}", description: 'Pim versions', name: 'pimVersions'),
            string(defaultValue: "${pimEditions.join(',')}", description: 'Pim editions', name: 'pimEditions')
        ])

        launchUnitTests = userInput['launchUnitTests']
        launchIntegrationTests = userInput['launchIntegrationTests']
        pimVersions = userInput['pimVersions'].tokenize(',')
        pimEditions = userInput['pimEditions'].tokenize(',')
    }

    milestone 2
    podPHP(Globals.extensionName, Globals.phpVersion, {

        sh "mkdir -p ${env.WORKSPACE}/cache"

        dir("extension") {
            checkout scm
            sh "composer config cache-dir ${env.WORKSPACE}/cache"
            sh "composer install --optimize-autoloader --no-interaction --no-progress --prefer-dist"
            stash "extension"
            sh "chmod -R 777 ${env.WORKSPACE}/extension"
            deleteDir()
        }

        if (launchIntegrationTests.equals("yes")) {
            pimVersions.each { pimVersion ->
                pimEditions.each { pimEdition ->
                    dir("${env.WORKSPACE}/pim") {
                        checkout([$class: 'GitSCM',
                            branches: [[name: "${pimVersion}"]],
                            userRemoteConfigs: [[credentialsId: 'github-credentials', url: "${Globals.pimRepoUrl[pimEdition]}"]]
                        ])

                        sh "chmod -R 777 ${env.WORKSPACE}/pim"
                        sh "composer config cache-dir ${env.WORKSPACE}/cache"
                        sh "composer config repositories.extension '{\"type\": \"vcs\", \"url\": \"${Globals.extensionRepoUrl}\"}'"
                        sh "composer require phpunit/phpunit:${Globals.phpunitVersion} ${Globals.vendorName}/${Globals.extensionName}:${Globals.extensionVersion} --no-ansi --optimize-autoloader --no-interaction --no-progress --prefer-dist --no-suggest"
                        stash "pim_${pimEdition}_${pimVersion}"
                        sh "chmod -R 777 ${env.WORKSPACE}/pim"
                        deleteDir()
                    }
                }
            }
        }
    })
}

stage("Test") {

    try {
        def tasks = [:]
        if (launchUnitTests.equals("yes")) {
            tasks["phpspec"] = {runPhpSpecTest()}
            tasks["php-cs-fixer"] = {runPhpCsFixerTest()}
        } else {
            echo "Skipping phpspec and php-cs-fixer tests"
        }
        if (launchIntegrationTests.equals("yes")) {
            pimVersions.each { pimVersion ->
                pimEditions.each { pimEdition ->
                    tasks["phpunit-${pimVersion}-${pimEdition}"] = {runIntegrationTest(pimVersion, pimEdition)}
                }
            }
        } else {
            echo "Skipping phpunit integration tests"
        }

        parallel tasks

    } finally {
        clearTemplateNames()
    }
}

def runPhpSpecTest() {
    podPHP(Globals.extensionName, Globals.phpVersion, {
        try {
            sh "chmod -R 777 ${env.WORKSPACE}"
            unstash "extension"
            sh "mkdir -p build/logs/"
            sh "./vendor/bin/phpspec run --no-interaction --format=junit > build/logs/phpspec.xml"
        } finally {
            junit "build/logs/phpspec.xml"
        }
    })
}

def runPhpCsFixerTest() {
    podPHP(Globals.extensionName, Globals.phpVersion, {
        try {
            sh "chmod -R 777 ${env.WORKSPACE}"
            unstash "extension"
            sh "mkdir -p build/logs/"
            sh "./vendor/bin/php-cs-fixer fix --diff --dry-run -vv --format=junit > build/logs/phpcs.xml"
        } finally {
            junit "build/logs/phpcs.xml"
        }
    })
}

def runIntegrationTest(pimVersion, pimEdition) {
    podIntegration(Globals.extensionName, Globals.phpVersion, {
        container("php") {
            try {
                unstash "pim_${pimEdition}_${pimVersion}"
                sh "chmod -R 777 ${env.WORKSPACE}"

                def extensionPath = "vendor/${Globals.vendorName}/${Globals.extensionName}"
                dir(extensionPath) {
                    unstash "extension"
                }
                echo "Install extension"
                installExtension(pimEdition, extensionPath)
                echo "End install extension"

                sh "mkdir -p build/logs/"
                sh "./vendor/bin/phpunit -c app/phpunit.xml --log-junit build/logs/phpunit.xml"
            } finally {
                junit "build/logs/phpunit.xml"
            }
        }
    })
}

def podPHP(podname, phpVersion, body) {
    def podName = "${podname}-" + UUID.randomUUID().toString()
    withCredentials([string(credentialsId: 'composer-token', variable: 'token')]) {
        podTemplate(label: podName, containers: [
            containerTemplate(name: "php", ttyEnabled: true, command: 'cat', image: "akeneo/php:${phpVersion}", resourceRequestCpu: '750m', resourceRequestMemory: '1000Mi',
                envVars: [
                    envVar(key: "COMPOSER_AUTH", value: "{\"github-oauth\":{\"github.com\": \"$token\"}}")
                ]
            ),
        ]) {
            node(podName) {
                container("php") {
                    body()
                }
            }
        }
    }
}

def podIntegration(podname, phpVersion, body) {
    def podName = "${podname}-" + UUID.randomUUID().toString()
    withCredentials([string(credentialsId: 'composer-token', variable: 'token')]) {
        podTemplate(label: podName, containers: [
            containerTemplate(name: "elasticsearch", image: "elasticsearch:5.5", resourceRequestCpu: '100m', resourceRequestMemory: '200Mi',
                envVars: [
                    envVar(key: "ES_JAVA_OPTS", value: "-Xms256m -Xmx512m"),
                    envVar(key: "FORCE", value: "true"),
                ]
            ),
            containerTemplate(name: "mysql", image: "mysql:5.7", resourceRequestCpu: '100m', resourceRequestMemory: '200Mi',
                envVars: [
                    envVar(key: "MYSQL_ROOT_PASSWORD", value: "root"),
                    envVar(key: "MYSQL_USER", value: "akeneo_pim"),
                    envVar(key: "MYSQL_PASSWORD", value: "akeneo_pim"),
                    envVar(key: "MYSQL_DATABASE", value: "akeneo_pim"),
                ], volumes: [

                    emptyDirVolume(memory: false, mountPath: "/var/lib/mysql"),
                    emptyDirVolume(memory: false, mountPath: "/tmp")
                ]

            ),
            containerTemplate(name: "php", ttyEnabled: true, command: 'cat', image: "akeneo/php:${phpVersion}", resourceRequestCpu: '200m', resourceRequestMemory: '1000Mi',
                envVars: [
                    envVar(key: "COMPOSER_AUTH", value: "{\"github-oauth\":{\"github.com\": \"$token\"}}")
                ]
            ),
        ]) {
            node(podName) {
                body()
            }
        }
    }
}

@NonCPS
def clearTemplateNames() {
    // see https://issues.jenkins-ci.org/browse/JENKINS-42184
    currentBuild.rawBuild.getAction( PodTemplateAction.class )?.stack?.clear()
}
