import java.util.regex.Matcher

/**
 * Pipeline to test the process of a new installation of the last build version of Silverpeas.
 *
 * Because this pipeline is based upon some convention rules, some expectations have to be
 * fulfilled:
 * Dependent Jenkins job name: the name of the job producing a build version of Silverpeas upon
 *                             which this project depend must be named as
 *                             'Silverpeas_Master_AutoDeploy'
 *
 * The build is performed within a dedicated Docker image in order to ensure the reproducibility of
 * the builds and to containerize them from the host OS.
 */
pipeline {

  agent {
    docker {
      image 'silverpeas/silverbuild'
      args '''
          -v $HOME/.m2/settings.xml:/home/silverbuild/.m2/settings.xml 
          -v $HOME/.m2/settings-security.xml:/home/silverbuild/.m2/settings-security.xml 
          -v $HOME/.gitconfig:/home/silverbuild/.gitconfig 
          -v $HOME/.ssh:/home/silverbuild/.ssh 
          -v $HOME/.gnupg:/home/silverbuild/.gnupg
          '''
    }
  }

  environment {
    mavenRepo = 'https://nexus3.silverpeas.org/repository/silverpeas'
    gitRepo = 'https://github.com/mmoqui/Silverpeas-installation-tests'
    fileRepo = 'https://www.silverpeas.org/files'
    silverpeasBuildJobName = 'Silverpeas_Master_AutoDeploy'
    buildVersion = ''
    silverpeas = ''
    wildfly = ''
    dbConf = null
  }

  stages {
    stage('Fetch the last build version of Silverpeas') {
      steps {
        sh 'rm -rf * ~/.gradle'
        sh 'mkdir logs/'
        copyArtifacts projectName: silverpeasBuildJobName, flatten: true
        script {
          def lastBuild = readYaml file: 'build.yaml'
          buildVersion = lastBuild.version

          // figure out the wildfly and silverpeas distributions to use
          String parentVersion = lastBuild.parent
          sh "curl -fsSL -o pom.xml ${mavenRepo}/org/silverpeas/silverpeas-project/${parentVersion}/silverpeas-project-${parentVersion}.pom"
          def pom = readMavenPom()
          wildfly = "wildfly-${pom.properties['wildfly.version']}.zip"
          silverpeas = silverpeasDistribMatching(buildVersion, wildfly)
          sh 'rm -f pom.xml'
        }
        sh 'rm -f build.yaml'
      }
    }
    stage('Set up the test environment') {
      steps {
        git url: gitRepo, poll: false
        script {
          dbConf = readYaml file: 'conf/database.yaml'
        }
        sh """
          curl -fsSL -o ${silverpeas} ${fileRepo}/${silverpeas}
          unzip ${silverpeas}
          mv ${silverpeas.substring(0, silverpeas.length() - 4)} silverpeas
          curl -fsSL -o ${wildfly} ${fileRepo}/${wildfly}
          unzip ${wildfly}
          mv ${wildfly.substring(0, wildfly.length() - 4)} wildfly
          cp conf/*.xml silverpeas/configuration/silverpeas/
          cp lib/ojdbc7.jar silverpeas/bin/lib/
          """
      }
    }
    stage('Test installation against PostgreSQL') {
      environment {
        AUTH = credentials('77f54fe3-921f-4461-a70f-142122191933')
      }
      steps {
        script {
          def db = [
              name    : dbConf.postgresql.inst,
              type    : 'POSTGRESQL',
              host    : dbConf.postgresql.host,
              url     : dbConf.postgresql.url,
              driver  : dbConf.postgresql.driver,
              port    : 5433
          ]
          try {
            generateConfigFileFor(db)
            sh "${env.WORKSPACE}/scripts/setupDB.sh '${env.WORKSPACE}' -a CREATE -t ${db.type} -n ${db.name} -d ${db.driver} -u ${db.url} -U \\$AUTH_USR -P \\$AUTH_PSW"
            runTest()
          } finally {
            postfixLogFile('postgresql')
            sh "${env.WORKSPACE}/scripts/setupDB.sh '${env.WORKSPACE}' -a DELETE -t ${db.type} -n ${db.name} -d ${db.driver} -u ${db.url} -U \\$AUTH_USR -P \\$AUTH_PSW"
          }
        }
      }
    }
    stage('Test installation against MS-SQLServer') {
      environment {
        AUTH = credentials('a063da26-fbad-4576-9825-ff5e5b338d9e')
      }
      steps {
        script {
          def db = [
              name    : dbConf.mssql.inst,
              type    : 'MSSQL',
              host    : dbConf.mssql.host,
              url     : dbConf.mssql.url,
              driver  : dbConf.mssql.driver,
              port    : 1433
          ]
          try {
            generateConfigFileFor(db)
            sh "${env.WORKSPACE}/scripts/setupDB.sh '${env.WORKSPACE}' -a CREATE -t ${db.type} -n ${db.name} -d ${db.driver} -u ${db.url} -U \\$AUTH_USR -P \\$AUTH_PSW"
            runTest()
          } finally {
            postfixLogFile('mssql')
            sh "${env.WORKSPACE}/scripts/setupDB.sh '${env.WORKSPACE}' -a DELETE -t ${db.type} -n ${db.name} -d ${db.driver} -u ${db.url} -U \\$AUTH_USR -P \\$AUTH_PSW"
          }
        }
      }
    }
    stage('Test installation against Oracle') {
      environment {
        AUTH = credentials('c8c17c16-0843-4009-aa5a-64dbbfd4a565')
      }
      steps {
        script {
          def db = [
              name    : dbConf.oracle.inst,
              type    : 'ORACLE',
              host    : dbConf.oracle.host,
              url     : dbConf.oracle.url,
              driver  : dbConf.oracle.driver,
              port    : 1521
          ]
          try {
            generateConfigFileFor(db)
            sh "${env.WORKSPACE}/scripts/setupDB.sh '${env.WORKSPACE}' -a CREATE -t ${db.type} -n ${db.name} -d ${db.driver} -u ${db.url} -U \\$AUTH_USR -P \\$AUTH_PSW"
            runTest()
          } finally {
            postfixLogFile('oracle')
            sh "${env.WORKSPACE}/scripts/setupDB.sh '${env.WORKSPACE}' -a DELETE -t ${db.type} -n ${db.name} -d ${db.driver} -u ${db.url} -U \\$AUTH_USR -P \\$AUTH_PSW"
          }
        }
      }
    }
    stage('Test installation against H2') {
      environment {
        AUTH = credentials('a1257830-edbc-42f1-9abc-adc84097843c')
      }
      steps {
        script {
          def db = [
                  name    : dbConf.h2.inst,
                  type    : 'H2',
                  host    : dbConf.h2.host,
                  url     : dbConf.h2.url,
                  driver  : dbConf.h2.driver,
                  port    : 9092
          ]
          try {
            sh "${env.WORKSPACE}/scripts/h2.sh '${env.WORKSPACE}' start"
            generateConfigFileFor(db)
            sh "${env.WORKSPACE}/scripts/setupDB.sh '${env.WORKSPACE}' -a CREATE -t ${db.type} -n ${db.name} -d ${db.driver} -u ${db.url} -U \\$AUTH_USR -P \\$AUTH_PSW"
            runTest()
          } finally {
            postfixLogFile('h2')
            sh "${env.WORKSPACE}/scripts/setupDB.sh '${env.WORKSPACE}' -a DELETE -t ${db.type} -n ${db.name} -d ${db.driver} -u ${db.url} -U \\$AUTH_USR -P \\$AUTH_PSW"
            sh "${env.WORKSPACE}/scripts/h2.sh '${env.WORKSPACE}' stop"
          }
        }
      }
    }
  }
  post {
    always {
      script {
        currentBuild.displayName = buildVersion
      }
      archiveArtifacts artifacts: 'logs/*', fingerprint: true, allowEmptyArchive: true
      step([$class                  : 'Mailer',
            notifyEveryUnstableBuild: true,
            recipients              : "miguel.moquillon@silverpeas.org, silveryocha@chastagnier.com",
            sendToIndividuals       : true])
    }
  }
}

void runTest() {
  sh '''
    SILVERPEAS_HOME="`pwd`/silverpeas" JBOSS_HOME="`pwd`/wildfly" silverpeas/bin/silverpeas clean install
    '''
}

void generateConfigFileFor(db) {
  withCredentials([usernamePassword(credentialsId: 'c58d4674-64f5-47c0-8ab0-463140ff7314',
      usernameVariable: 'DB_USR', passwordVariable: 'DB_PSW')]) {
    sh """
      rm -f silverpeas/configuration/config.properties
      echo "DB_NAME=${db.name}" > silverpeas/configuration/config.properties
      echo "DB_SERVERTYPE=${db.type}"  >> silverpeas/configuration/config.properties
      echo "DB_SERVER=${db.host}" >> silverpeas/configuration/config.properties
      echo "DB_PORT_${db.type}=${db.port}" >> silverpeas/configuration/config.properties
      """
    sh '''
      echo "DB_USER=$DB_USR" >> silverpeas/configuration/config.properties
      echo "DB_PASSWORD=$DB_PSW" >> silverpeas/configuration/config.properties
      '''
  }
}

void postfixLogFile(String postfix) {
  String buildLog = sh returnStdout: true, script: "ls silverpeas/log | grep 'build-[0-9]\\+_[0-9]\\+.log'"
  sh "mv silverpeas/log/${buildLog.trim()} logs/build-${postfix}.log"
}

String silverpeasDistribMatching(version, wildfly) {
  Matcher m = wildfly =~ /^wildfly-(\d+)\..+$/
  if (!m.matches()) {
    error "No Silverpeas distribution matching the Wildfly distribution ${wildfly}"
  }
  return "silverpeas-${version}-wildfly${m.group(1)}.zip"
}

