import java.util.regex.Matcher

/**
 * Pipeline to release a stable version of the Silverpeas SSO library from a given build version of
 * the project.
 *
 * In order to get the build version, the pipeline requires the Jenkins job aimed at constructing
 * such build version to be named 'Silverpeas_SSO_AutoDeploy'.
 *
 * This pipeline requires the following parameters:
 * BUILD_VERSION the build version of Silverpeas SSO from which the release has to 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.
 */
pipeline {

  agent {
    docker {
      image "silverpeas/silverbuild:6.4"
      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(
        description: 'The build version of Silverpeas SSO from which the release has to be done',
        name: 'BUILD_VERSION'
    )
  }

  environment {
    gitRepo = 'https://github.com/Silverpeas/Silverpeas-Sso'
    gitCredential = 'cacc0467-7c85-41d1-bf4e-eaa470dd5e59'
    commit = ''
    version = ''
    nextVersion = ''
    parentVersion = ''
    silverpeasVersion = ''
    artifact = 'target/release.yaml'
  }

  stages {
    stage('Prepare the release') {
      steps {
        copyArtifacts projectName: 'Silverpeas_SSO_AutoDeploy', flatten: true,
            selector: specific(params.BUILD_VERSION)
        script {
          def lastBuild = readYaml file: 'build.yaml'
          version = lastBuild.release
          commit = lastBuild.commit
          nextVersion = getNextVersion(version)
        }
        sh 'rm -f build.yaml'
      }
    }
    stage('Checkout the build version') {
      steps {
        git url: gitRepo, credentialsId: gitCredential
        sh """
          git checkout ${commit}
          git checkout -b release-${version}
          """
        script {
          def pom = readMavenPom()
          parentVersion = pom.parent.version
          silverpeasVersion = pom.properties['silverpeas.version']
        }
      }
    }
    stage('Check POM parent version') {
      when {
        expression { !isStableVersion(parentVersion) }
      }
      steps {
        error "The POM parent must be at a stable version"
      }
    }
    stage('Check Silverpeas version') {
      when {
        expression { !isStableVersion(silverpeasVersion) }
      }
      steps {
        error "The dependency on Silverpeas must be at a stable version"
      }
    }
    stage('Release') {
      environment {
        GIT_AUTH = credentials("${gitCredential}")
      }
      steps {
        sh """
          mvn -U versions:set -DgenerateBackupPoms=false -DnewVersion=${version}
          mvn clean deploy -Dmaven.test.skip=true -Pdeployment -Prelease-sign-artifacts
          git commit -am "Release of ${version} from ${params.BUILD_VERSION} (commit ${commit})"
          git tag ${version}
          """
        sh '''
          git config --local credential.helper "!f() { echo username=\\${GIT_AUTH_USR}; echo password=\\$GIT_AUTH_PSW; }; f"
          git push origin --tags
          '''
      }
    }
    stage('Prepare the development of the next version') {
      environment {
        GIT_AUTH = credentials("${gitCredential}")
      }
      steps {
        sh """
          git checkout master
          sed -i -e "s/<next.release>[0-9.]\\+/<next.release>${nextVersion}/g" pom.xml
          mvn -U versions:set -DgenerateBackupPoms=false -DnewVersion=${nextVersion}-SNAPSHOT
          mvn clean install -Dmaven.test.skip=true
          git commit -am "${version} has been released from build ${params.BUILD_VERSION} (${commit}).\\
Prepare for development iteration of next version ${nextVersion}"
          """
        sh '''
          git config --local credential.helper "!f() { echo username=\\${GIT_AUTH_USR}; echo password=\\$GIT_AUTH_PSW; }; f"
          git push origin HEAD:master
          '''
      }
    }
    stage('Create YAML release report') {
      steps {
        script {
          writeYaml file: artifact, data: ['release'   : version,
                                           'from'      : ['version': params.BUILD_VERSION,
                                                          'commit' : commit.trim()],
                                           'parent'    : parentVersion,
                                           'silverpeas': silverpeasVersion]
        }
      }
    }
  }
  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])
    }
  }
}

static String getNextVersion(String version) {
  String[] parts = version.split('\\.')
  "${parts[0]}.${(parts[1] as Integer) + 1}"
}

static String isStableVersion(String version) {
  Matcher matcher = version =~ '^(\\d+.\\d+(.\\d)*)$'
  return matcher.matches()
}