/**
 * Pipeline to release a stable version of the definition of Silverpeas projects from either the
 * main development branch or a patch development branch of a released stable major or minor
 * version. The definition of Silverpeas projects is made up of three projects:
 * silverpeas-dependencies-bom in which are declared the commons dependencies for Silverpeas,
 * silverpeas-test-dependencies-bom in which are declared the dependencies to run tests against
 * some parts of Silverpeas, and Silverpeas-Project that is the hat covering the two previous
 * projects and that define all that is required to build and publish a Silverpeas project as well
 * as to generate and publish its documentation.
 *
 * This pipeline expects the following environment variable to be set:
 * IMAGE_FOR_STABLE  the version of the Docker image to be used by this pipeline for stable version
 *                   of the project.
 *
 * This pipeline requires the following parameters:
 * BRANCH  the SCM branch from which the release will be done.
 *
 * 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.
 */

String imageVersion = params.BRANCH == 'master' ? 'latest' : env.IMAGE_FOR_STABLE

pipeline {

  agent {
    docker {
      image "silverpeas/silverbuild:${imageVersion}"
      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
          '''
    }
  }

  parameters {
    string(
        defaultValue: 'master',
        description: 'The SCM branch from which the release has to be done with the current state in that branch',
        name: 'BRANCH'
    )
  }

  environment {
    gitRepoOfProject = 'https://github.com/Silverpeas/Silverpeas-Project'
    gitRepoOfDependencies = 'https://github.com/Silverpeas/silverpeas-dependencies-bom'
    gitRepoOfTestDependencies = 'https://github.com/Silverpeas/silverpeas-test-dependencies-bom'
    gitCredential = 'cacc0467-7c85-41d1-bf4e-eaa470dd5e59'
    version = ''
    nextVersion = ''
    jcrAccessControl = ''
    artifact = 'target/release.yaml'
  }

  stages {
    stage('Prepare the release from master') {
      when {
        expression { params.BRANCH == 'master' }
      }
      steps {
        script {
          copyArtifacts projectName: 'Silverpeas_Project_Definition_AutoDeploy', flatten: true
          def lastBuild = readYaml file: 'build.yaml'
          version = lastBuild.release
          nextVersion = getNextVersion(lastBuild.release)
          sh 'rm -f build.yaml'
          jcrAccessControl = ''
        }
      }
    }
    stage ('Prepare the release from a given stable version branch') {
      when {
        expression { params.BRANCH != 'master' }
      }
      steps {
        script {
          sh "curl -fsSL -o pom.xml https://raw.githubusercontent.com/Silverpeas/Silverpeas-Project/${params.BRANCH}/pom.xml"
          def pom = readMavenPom()
          version = pom.properties['next.release']
          nextVersion = getNextVersion(version)
          sh 'rm -f pom.xml'
          jcrAccessControl = fetchJCRAccessControlLibVersion()
        }
      }
    }
    stage('Check dependencies') {
      when {
        expression {
          jcrAccessControl && (jcrAccessControl.contains('SNAPSHOT') || jcrAccessControl.contains('build'))
        }
      }
      steps {
        error "The Silverpeas JCR AccessControl dependency must be a stable version. Current version is $jcrAccessControl"
      }
    }
    stage("Release dependencies definition") {
      steps {
        dir('dependencies') {
          git([url: gitRepoOfDependencies, branch: params.BRANCH, credentialsId: gitCredential])
          releaseVersion(version)
          prepareNextVersion(nextVersion)
          pushToGithub()
        }
      }
    }
    stage("Release test dependencies definition") {
      steps {
        dir('test-dependencies') {
          git([url: gitRepoOfTestDependencies, branch: params.BRANCH, credentialsId: gitCredential])
          releaseVersion(version)
          prepareNextVersion(nextVersion)
          pushToGithub()
        }
      }
    }
    stage("Release project definition") {
      steps {
        dir('project') {
          git([url: gitRepoOfProject, branch: params.BRANCH, credentialsId: gitCredential])
          sh """
            sed -i -e "s/<silverpeas.bom.version>[0-9a-zA-Z.-]\\+/<silverpeas.bom.version>${version}/g" pom.xml
            """
          releaseVersion(version)
          sh """
            sed -i -e "s/<silverpeas.bom.version>${version}/<silverpeas.bom.version>${nextVersion}-SNAPSHOT/g" pom.xml
            """
          prepareNextVersion(nextVersion)
          pushToGithub()
        }
      }
    }
    stage('Create YAML release report') {
      steps {
        script {
          writeYaml file: artifact, data: ['release': version, 'branch': params.BRANCH]
        }
      }
    }
  }
  post {
    success {
      script {
        currentBuild.displayName = version
      }
      archiveArtifacts artifacts: artifact, fingerprint: true
    }
    always {
      step([$class                  : 'Mailer',
            notifyEveryUnstableBuild: true,
            recipients              : "miguel.moquillon@silverpeas.org, silveryocha@chastagnier.com",
            sendToIndividuals       : true])
    }
  }
}

void releaseVersion(String version) {
  echo " -> release version ${version}"
  sh """
    mvn -U versions:set -DgenerateBackupPoms=false -DnewVersion=${version}
    sed -i -e "s/<tag>[a-zA-Z0-9.\\-]\\+/<tag>${version}/g" pom.xml
    mvn clean deploy -Djava.awt.headless=true
    git commit -am "Release of ${version}"
    git tag ${version}
    """
}

void prepareNextVersion(String nextversion) {
  echo " -> prepare development of ${nextVersion}"
  sh """
    sed -i -e "s/<next.release>[0-9.]\\+/<next.release>${nextversion}/g" pom.xml
    sed -i -e "s/<tag>[a-zA-Z0-9.\\-]\\+/<tag>HEAD/g" pom.xml
    mvn -U versions:set -DgenerateBackupPoms=false -DnewVersion=${nextversion}-SNAPSHOT
    mvn clean install -Djava.awt.headless=true
    git commit -am "Prepare for development iteration of next version ${nextversion}"
    """
}

void pushToGithub() {
  withCredentials([usernamePassword(credentialsId: gitCredential,
      usernameVariable: 'GIT_AUTH_USR', passwordVariable: 'GIT_AUTH_PSW')]) {
    sh 'git config --local credential.helper "!f() { echo username=\\${GIT_AUTH_USR}; echo password=\\$GIT_AUTH_PSW; }; f"'
    sh """
       git push origin HEAD:${params.BRANCH}
       git push origin --tags
      """
  }
}

String getNextVersion(String version) {
  String[] parts = version.split('\\.')
  parts.length < 3 ?
      "${parts[0]}.${(parts[1] as int) + 1}" :
      "${parts[0]}.${parts[1]}.${(parts[2] as int) + 1}"
}

String fetchJCRAccessControlLibVersion() {
  sh "curl -fsSL -o pom.xml https://raw.githubusercontent.com/Silverpeas/silverpeas-dependencies-bom/$params.BRANCH/pom.xml"
  def pom = readMavenPom()
  jcrAccessControl = pom.properties['jcr.accesscontrol.version']
  sh 'rm -f pom.xml'
  return jcrAccessControl
}