aboutsummaryrefslogblamecommitdiff
path: root/plugins/sonatype-release/src/sonatype/SonatypeLib.scala
blob: 08f7ee1d8636ac2065f9630e1b7e78aa89febace (plain) (tree)
1
2
3
4
5
6
7
8

                





                            











                                                                     
                                                                   
 
                                                                                      






                                                                       
                             




















                                                                                                                        







                                                                    
 
                                                                          





                                       


                                                                      
 


                                                                       
 
                                                        
                           
            

                                             
                         


                                                                       
           
     

                                                                        
        

   
    






                                                       
                                   

                                     
                                           



                                                                                                          

                                                         

                        





                                                                                 






                                                                                   
    
 
package cbt
package sonatype

import java.io.File
import java.net.URL
import java.nio.file.Files._
import java.nio.file.Paths

/**
  * Sonatype release process is:
  * • get your profile info to publish artifacts
  * • open staging repository to publish artifacts
  * • publish signed artifacts and signatures to staging repository
  * • close staging repository
  * • promote staging repository
  * • drop staging repository
  */

object SonatypeLib {

  val serviceURI: String = "https://oss.sonatype.org/service/local"

  val snapshotsURI: String = "https://oss.sonatype.org/content/repositories/snapshots"

  /**
    * login:password for Sonatype access.
    * Order of credentials lookup:
    * • environment variables SONATYPE_USERNAME and SONATYPE_PASSWORD
    * • ~/.cbt/sonatype-credentials
    */
  def credentials: String = {
    def fromEnv = for {
      username <- Option(System.getenv("SONATYPE_USERNAME"))
      password <- Option(System.getenv("SONATYPE_PASSWORD"))
    } yield s"$username:$password"

    def fromFile = {
      for {
        home <- Option(System.getProperty("user.home"))
        credsPath = Paths.get(home, ".cbt", "sonatype-credentials")
      } yield new String(readAllBytes(credsPath)).trim
    }

    fromEnv
      .orElse(fromFile)
      .getOrElse(throw new Exception(
        "No Sonatype credentials found! You can provide them via SONATYPE_USERNAME, SONATYPE_PASSWORD env variables, " +
          "or in ~/.cbt/sonatype-credentials file as login:password"
      ))
  }
}

final case class SonatypeLib(
  profileName: String,
  serviceURI: String = SonatypeLib.serviceURI,
  snapshotsURI: String = SonatypeLib.snapshotsURI,
  credentials: String = SonatypeLib.credentials
)( implicit logger: Logger ){
  private val lib: Lib = new Lib(logger)
  private def log: String => Unit = logger.log("sonatype-release",_)

  val api = new SonatypeHttpApi(serviceURI, credentials, profileName)(log)
  /*
   * Signed publish steps:
   * • create new staging repo
   * • create artifacts and sign them
   * • publish jars to created repo
  */
  def publishSigned( artifacts: Seq[File], releaseFolder: String ) = {
    import api._
    System.err.println(lib.blue("Publishing to Sonatype"))

    def publish(deployURI: String) = lib.publishSigned(
      artifacts, new URL(deployURI ++ releaseFolder), Some(credentials)
    )

    val urls = if (releaseFolder.endsWith("-SNAPSHOT")){
      publish(snapshotsURI)
    } else {
      val profile = getStagingProfile
      val repoId = createStagingRepo(profile)
      val urls = publish(
        serviceURI ++ "/staging/deployByRepositoryId/" ++ repoId.string
      )
      finishRelease( getStagingRepoById(repoId), profile )
      urls 
    }

    System.err.println(lib.green("Successfully published to Sonatype!"))
    urls
  }

  /*
  /**
    * Release is:
    * • find staging repo related to current profile;
    * • close this staging repo;
    * • wait until this repo is released;
    * • drop this repo.
    */
  private def release: ExitCode = {
    val profile = getStagingProfile()

    getStagingRepos(profile).toList match {
      case Nil =>
        System.err.println(lib.red("No staging repositories found, you need to publish artifacts first."))
        ExitCode.Failure
      case repo :: Nil =>
        finishRelease(repo, profile)
        log(lib.green(s"Successfully released artifact"))
        ExitCode.Success
      case repos =>
        lib.pickOne(
          lib.blue(s"More than one staging repo found. Select one of them:"),
          repos
        ){ repo => s"${repo.repositoryId} in state: ${repo.state}" }.map{ repo =>
          finishRelease(repo, profile)
          log(lib.green(s"Successfully released artifact"))
          ExitCode.Success
        } getOrElse {
          System.err.println(lib.red("Wrong repository number, try again please."))
          ExitCode.Failure
        }
    }
  }
  */
}