Heroku sbt Plugin
This plugin is used to deploy Scala and Play applications directly to Heroku without pushing to a Git repository. This is can be useful when deploying from a CI server.
Using the Plugin
Add the following to your project/plugins.sbt
file:
addSbtPlugin("com.heroku" % "sbt-heroku" % "2.1.4")
If you're not using Play, then you'll also need to add the
sbt-native-packager plugin, which creates a stage
task.
Alternatively, you can deploy a fat JAR using sbt-assembly.
Next, add something like this to your build.sbt
if you do not have a Heroku Git repo in your git remote
s.
herokuAppName in Compile := "your-heroku-app-name"
Now, if you have the Heroku CLI installed, run:
$ sbt stage deployHeroku
If you do not have the CLI installed, then run:
$ HEROKU_API_KEY="xxx-xxx-xxxx" sbt stage deployHeroku
And replace "xxx-xxx-xxxx" with the value of your Heroku API token.
Requirements
-
It is required that you use sbt 0.13.5 or greater.
-
You must use Java 1.7 or higher locally.
-
This plugin has not been tested with Play 2.0 or 2.1.
Configuring the Plugin
You may set the desired JDK version like so:
herokuJdkVersion in Compile := "11"
For a list of supported JDK versions, refer to the Heroku Java Support DevCenter article.
You can (but probably should not) set configuration variables like so:
herokuConfigVars in Compile := Map(
"MY_VAR" -> "some value",
"JAVA_OPTS" -> "-XX:+UseCompressedOops"
)
If you adhere to the principles of the 12 Factor app,
Configuration should be strictly seperated from code. Thus, you do not want to tie your
configuration to your codebase. There are a few exceptions to this, such as conf/routes
,
and some JAVA_OPTS
may be universal. But please use herokuConfigVars
sparingly.
Any variable defined in herokuConfigVars
will override defaults. However, if you remove
a variable from this list, it will not automatically be removed from your Heroku app
(even on the next deploy).
You may set process types (similar to a Procfile
) with herokuProcessTypes
:
herokuProcessTypes in Compile := Map(
"web" -> "target/universal/stage/bin/my-app -Dhttp.port=$PORT",
"worker" -> "java -jar target/universal/stage/lib/my-worker.jar"
)
You can include additional directories in the slug (they must be relative to the project root):
herokuIncludePaths in Compile := Seq(
"app", "conf/routes", "public/javascripts"
)
You can run the plugin against all sub-projects (in addition to the root project) by setting the following option:
herokuSkipSubProjects in Compile := false
This defaults to true
(and currently it only runs against all sub-projects or none).
You can disable the upload progress in the console by setting the heroku.log.format
system property to false
, like this:
$ sbt -Dheroku.log.format=false deployHeroku
See the src/sbt-test
directory for examples.
Deploying a Fat JAR
If you are packaging your application with sbt-assembly or any other plugin that
produces a "fat JAR", you can deploy that file by adding the following configuration to your build.sbt
:
herokuFatJar in Compile := Some((assemblyOutputPath in assembly).value)
If not using sbt-assembly, you may replace (assemblyOutputPath in assembly).value
with the relative path to your JAR file.
Then you can deploy by running:
$ sbt assembly deployHeroku
The sbt-heroku plugin will skip the sbt-native-packager bits and deploy your JAR directly to Heroku.
Running a Remote Console
When using sbt-native-packager
version 0.7.6 or greater, sbt-heroku will create a
console
process type for you. This command can be run like so:
$ heroku run console -a <appname>
Running `console` attached to terminal... up, run.5154
Picked up JAVA_TOOL_OPTIONS: -Xmx384m -Djava.rmi.server.useCodebaseOnly=true
Failed to created JLineReader: java.lang.NoClassDefFoundError: scala/tools/jline/console/completer/Completer
Falling back to SimpleReader.
Welcome to Scala version 2.10.4 (OpenJDK 64-Bit Server VM, Java 1.8.0_20).
Type in expressions to have them evaluated.
Type :help for more information.
scala>
For older versions of Play 2.x it might be necessary to upgrade sbt-native-packager
manually.
You can do this by adding the following line of code to your project/plugins.sbt
:
addSbtPlugin("com.typesafe.sbt" % "sbt-native-packager" % "0.7.6")
Additionally, the is a bug in Scala 2.11.6 that causes this console task to fail. Upgrading to Scala 2.11.7 fixes the issue.
Deploying to Multiple Environments
To deploy to multiple Heroku app environments, you can use either system properties, environment variables, or any other native sbt/Java configuration method. For example, you might define your appName
as a Map and choose a value with
the system property as a key.
herokuAppName in Compile := Map(
"test" -> "your-heroku-app-test",
"stg" -> "your-heroku-app-stage",
"prod" -> "your-heroku-app-prod"
).getOrElse(sys.props("appEnv"), "your-heroku-app-dev")
Then run the sbt command like so:
$ sbt -DappEnv=test stage deployHeroku
Deploying from Git Branches
Another option when using multiple environments is to deploy from a Git branch that corresponds to the environment. This is particularly useful if you are using git-flow or a similar process.
First, add the sbt-git plugin ot your project/plugins.sbt
like this:
resolvers += "jgit-repo" at "http://download.eclipse.org/jgit/maven"
addSbtPlugin("com.typesafe.sbt" % "sbt-git" % "0.6.4")
Then in your build.sbt
you can configure the sbt-heroku plugin to deploy to the environment that corresponds to the current Git branch like this:
import com.typesafe.sbt.SbtGit._
// ...
herokuAppName in Compile := Map(
"testing" -> "myapp-testing",
"staging" -> "myapp-staging",
"production" -> "myapp"
).getOrElse(git.gitCurrentBranch.value, "myapp-dev")
showCurrentGitBranch
Hacking
In order to run the test suite, you must have the Heroku CLI installed. Then run:
$ sbt scripted
To run an individual test, use a command like this:
$ sbt "scripted settings/config_vars"
The heavy lifting for this plugin is done by the heroku-deploy
library. The source code for that project can be found
in the heroku-maven-plugin repository. If you
need to update that library, do this:
$ git clone https://github.com/heroku/heroku-maven-plugin
$ cd heroku-maven-plugin/heroku-deploy
# make your changes
$ mvn clean install
Then update the heroku-deploy
dependency version in the sbt-heroku build.sbt
to whatever
version is specified in the heroku-deploy pom.xml
. The next time you run the scripted
tests it will pick up the
snapshot version from your local Maven repository.