Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding automation for releasing *and* directly release to bintray. #157

Merged
merged 1 commit into from
Feb 11, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ sbtVersion in Global := {

scalaVersion in Global := "2.9.2"

crossScalaVersions := Seq("2.9.2", "2.10.2")

name := "sbt-native-packager"

organization := "com.typesafe.sbt"
Expand All @@ -30,14 +32,16 @@ ghpages.settings

git.remoteRepo := "[email protected]:sbt/sbt-native-packager.git"

publishTo := Some(Resolver.url("sbt-plugin-releases", new URL("http://scalasbt.artifactoryonline.com/scalasbt/sbt-plugin-releases/"))(Resolver.ivyStylePatterns))
Bintray.settings

publishMavenStyle := false

scriptedSettings

scriptedLaunchOpts <+= version apply { v => "-Dproject.version="+v }

Release.settings




Expand Down
49 changes: 49 additions & 0 deletions project/bintray.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import sbt._
import sbt.Keys._

object Bintray {
val bintrayPublishAllStaged = TaskKey[Unit]("bintray-publish-all-staged", "Publish all staged artifacts on bintray.")
val checkBintrayCredentials = TaskKey[Unit]("bintray-check-credentials", "Checks to see if bintray credentials are configured.")
val bintrayPluginId = "sbt-plugin-releases"
val bintrayPluginUrl = "https://api.bintray.com/content/sbt/sbt-plugin-releases/"
val bintrayPluginLayout = "[module]/[revision]/"+ Resolver.localBasePattern

def bintrayCreds(creds: Seq[sbt.Credentials]): (String, String) = {
val matching =
for {
c <- creds
if c.isInstanceOf[sbt.DirectCredentials]
val cred = c.asInstanceOf[sbt.DirectCredentials]
if cred.host == "api.bintray.com"
} yield cred.userName -> cred.passwd

matching.headOption getOrElse sys.error("Unable to find bintray credentials (api.bintray.com)")
}

def publishContent(pkg: String, repo: String, version: String, creds: Seq[sbt.Credentials]): Unit = {
val subject = "sbt" // Sbt org - TODO - don't hardcode
val uri = s"https://bintray.com/api/v1/content/$subject/$repo/$pkg/$version/publish"

val (u,p) = bintrayCreds(creds)
import dispatch.classic._
// TODO - Log the output
Http(url(uri).POST.as(u,p).>|)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does this exactly do? Sometimes the symbolic operators are... difficult xD
POST something to uri with credentials

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just executes a POST with no parameters and ignores the response (but throws an exception on failure).

}

def settings: Seq[Setting[_]] =
Seq(
publishTo := {
val resolver = Resolver.url("bintray-"+bintrayPluginId, new URL(bintrayPluginUrl))(Patterns(false, bintrayPluginLayout))
Some(resolver)
},
checkBintrayCredentials := {
val creds = credentials.value
val (user, _) = bintrayCreds(creds)
streams.value.log.info(s"Using $user for bintray login.")
},
bintrayPublishAllStaged := {
val creds = credentials.value
publishContent(projectID.value.name, bintrayPluginId, version.value, creds)
}
)
}
3 changes: 3 additions & 0 deletions project/plugins.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,6 @@ libraryDependencies <+= (sbtVersion) { sv =>

// Scripted plugin needs to declare this as a dependency
libraryDependencies += "jline" % "jline" % "2.11"

// For our bintray publishing
libraryDependencies += "net.databinder" %% "dispatch-http" % "0.8.10"
68 changes: 68 additions & 0 deletions project/release.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import sbt._
import Keys._

import complete.DefaultParsers._
import complete.Parser
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this from databinder.net or scala parser-combinator?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

neither. Sbt has its own parser combinator library that includes autocompletion options. org.scala-sbt % completion, i think. Used by all input tasks + commands.


object Release {

val versionNumberParser: Parser[String] = {
val classifier: Parser[String] = ("-" ~ ID) map {
case (dash, id) => dash + id
}
val version: Parser[String] = (Digit ~ chars(".0123456789").* ~ classifier) map {
case ((first, rest), rest2) => ((first +: rest).mkString + rest2)
}
val complete = (chars("v") ~ token(version, "<version number>")) map {
case (v, num) => v + num
}
complete
}

def releaseParser(state: State): Parser[String] =
Space ~> versionNumberParser


val releaseHelp = Help("release",
"release <git tag>" -> "Runs the release script for a given version number",
"""|release <git tag>
|
|Runs our release script. This will:
|1. Run all the tests (unit + scripted) for the current OS.
|2. Tag the git repo with the given tag (v<version>).
|3. Reload the build with the new version number from the git tag.
|4. publish all the artifacts to bintray.""".stripMargin
)

def scriptedForPlatform: String = {
// TODO - Implement. Instead of only running tests we can, we should
// probably ping some service to see if all platform tests have
// succeeded.
"scripted universal/* debian/* rpm/*"
}

def releaseAction(state: State, tag: String): State = {
// TODO - Ensure we're releasing on JDK 6, so we're binary compatible.
// First check to ensure we have a sane publishing environment...
"bintrayCheckCredentials" ::
"+ test" ::
// Workaround for 0.12.4 scripted issue
"set scalaVersion in Global := \"2.10.2\"" ::
scriptedForPlatform ::
// TODO - Signed tags, possibly using pgp keys?
("git tag " + tag) ::
"reload" ::
// TODO - once we figure out bintray + pubishSigned, switch to signed
// releases.
"+ publishSigned" ::
"bintrayPublishAllStaged" ::
("git push origin " + tag) ::
state
}

val releaseCommand =
Command("release", releaseHelp)(releaseParser)(releaseAction)

def settings: Seq[Setting[_]]=
Seq(commands += releaseCommand)
}