heroku-maven-plugin
This plugin is used to deploy Java applications directly to Heroku without pushing to a Git repository. It uses Heroku's Platform API. This is can be useful when deploying from a CI server, deploying pre-built JAR or WAR files.
The plugin has two main goals:
heroku:deploy
andheroku:deploy-only
for deploying standalone applicationsheroku:deploy-war
for deploying WAR files
In addition to those two main goals, three additional goals are available:
heroku:dashboard
to open the Heroku dashboard for the configured applicationheroku:run-war
to locally running WAR filesheroku:eclipse-launch-config
to generate launch configurations for Eclipse IDE
Requirements
- Maven 3.5.x
- Java 8u101 or higher (versions < u101 might experience difficulties displaying build log output)
Table of Contents
- Global Configuration
- Cookbook
- Deploying a Standalone Application
- Deploying a WAR File
- Running a WAR File Locally
- Deploying to Multiple Apps (i.e.: staging/production setups)
- Plugin Configuration
- Advanced Features
- Hacking
Global Configuration
Heroku API Key
This plugin uses Heroku's Platform API and thus requires an API key to function. If you have the Heroku CLI installed and logged in with heroku login
, the plugin will automatically pick up your API key. Alternatively, you can use the HEROKU_API_KEY
environment variable to set your API key:
$ HEROKU_API_KEY="xxx-xxx-xxxx" mvn heroku:deploy
Cookbook
Deploying a Standalone Application
Add the following to your pom.xml
, but replace the <web>
element with the command used to run your application.
<build>
<plugins>
<plugin>
<groupId>com.heroku.sdk</groupId>
<artifactId>heroku-maven-plugin</artifactId>
<version>3.0.4</version>
<configuration>
<appName>${heroku.appName}</appName>
<processTypes>
<web>java $JAVA_OPTS -cp target/classes:target/dependency/* com.example.Main</web>
</processTypes>
</configuration>
</plugin>
</plugins>
</build>
You can then run the following command to deploy your application:
$ mvn heroku:deploy
Deploying a WAR File
NOTE: This requires that you use <packaging>war</packaging>
in your pom.xml
.
Add the following to your pom.xml
.
<build>
<plugins>
<plugin>
<groupId>com.heroku.sdk</groupId>
<artifactId>heroku-maven-plugin</artifactId>
<version>3.0.4</version>
<configuration>
<appName>${heroku.appName}</appName>
</configuration>
</plugin>
</plugins>
</build>
This assumes your project will generate a WAR file in the target
directory. If the WAR file is located somewhere else, you can specify this with the <warFile>
configuration element. The <processTypes>
element is not needed and will be ignored because the plugin will determine the appropriate process type for you.
You can then run the following command to deploy your application:
$ mvn heroku:deploy-war
Running a WAR File Locally
You can execute your WAR file locally by running the following command:
$ mvn heroku:run-war
This will start the web application in a way that is very similar to how it is run on Heroku. If you need more control over how the WAR file is being run, you can use webapp-runner directly.
Deploying to Multiple Apps
In most real-world scenarios, you will need to deploy your application to dev, test and prod environments. There are several ways of handling this.
Using Maven Profiles
Use a profile for each app, and configure the plugin accordingly. For example:
<build>
<plugins>
<plugin>
<groupId>com.heroku.sdk</groupId>
<artifactId>heroku-maven-plugin</artifactId>
<version>3.0.4</version>
<configuration>
<processTypes>
<web>java $JAVA_OPTS -cp target/classes:target/dependency/* Main</web>
</processTypes>
</configuration>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>test</id>
<build>
<plugins>
<plugin>
<groupId>com.heroku.sdk</groupId>
<artifactId>heroku-maven-plugin</artifactId>
<configuration>
<appName>myapp-test</appName>
</configuration>
</plugin>
</plugins>
</build>
</profile>
<profile>
<id>prod</id>
<build>
<plugins>
<plugin>
<groupId>com.heroku.sdk</groupId>
<artifactId>heroku-maven-plugin</artifactId>
<configuration>
<appName>myapp-prod</appName>
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles>
Using System Properties
You can provide the application name as a system property like this:
$ mvn heroku:deploy -Dheroku.appName=myapp
Using a Heroku Properties File
This solution is best when multiple developers each need their own apps. Create a heroku.properties
file in the root directory of your application and put the following code in it (but replace "myapp" with the name of your Heroku application):
heroku.appName=myapp
Then add the file to your .gitignore
so that each developer can have their own local versions of the file. The value in heroku.properties
will take precedence over anything configured in your pom.xml
.
Plugin Configuration
appName
The name of the application to deploy.
<appName>my-app-name</appName>
The plugin will detect the appName from the following places in this order:
- The
heroku.properties
file - The
heroku.appName
system property - The Maven configuration (shown above)
- The "heroku" Git remote
For example, if you specify the heroku.appName
system property, the Maven configuration shown above will have no effect. This is useful for deploying multiple apps.
jdkVersion
The JDK version to use for your application.
<jdkVersion>11</jdkVersion>
The plugin will look for the required JDK version in the following places, in order:
- The Maven configuration (shown above)
- The
heroku.jdkVersion
system property - The
java.runtime.version
insystem.properties
located in the root directory of your project
For valid values and the current default, refer to Heroku's DevCenter article about specifing a Java version.
configVars
Sets configuration variables for the application on each deploy.
<configVars>
<MY_VAR>SomeValue</MY_VAR>
<JAVA_OPTS>-Xss512k -XX:+UseCompressedOops</JAVA_OPTS>
</configVars>
Any variable defined in configVars
will override defaults and previously defined config variables.
Note: If you adhere to the principles of the 12 Factor app, configuration should be strictly separated from code. Thus, you do not want to tie your configuration to your codebase. There are a few exceptions to this, like some JAVA_OPTS may be universal. If possible, you should not use configVars
at all.
includes
Allows you to include additional files and directories.
<includes>
<include>etc/readme.txt</include>
</includes>
Included files and directories must be located within your project root directory.
includeTarget
Allows you to disable automatic inclusion of the target
directory. (Default is true
)
<includeTarget>false</includeTarget>
This is useful in cases where you build a single fat JAR with all dependencies you want to deploy.
logProgress
Enables or disables logging of the source blob upload progress. (Default is false
)
<logProgress>true</logProgress>
Enabling this will log the upload progress status at DEBUG
level.
buildpacks
Defines the buildpacks used by your application.
<buildpacks>
<buildpack>https://github.com/DuckyTeam/heroku-buildpack-imagemagick</buildpack>
<buildpack>heroku/jvm</buildpack>
</buildpacks>
It can sometimes be useful to use more than just the default heroku/jvm
buildpack for your application. In the above example, you can see how an additional buildpack is used to install imagemagick.
You can also define your buildpacks using the Heroku Dashboard or the Heroku CLI (i.e. the heroku buildpacks
command).
processTypes
Adds process types to the generated Procfile for your application.
<processTypes>
<web>java $JAVA_OPTS -cp target/classes:target/dependency/* Main</web>
<worker>java $JAVA_OPTS -cp target/classes:target/dependency/* Worker</worker>
</processTypes>
The plugin will generate a Procfile
for your application and include it. You can use this configuration to add more process types. It will also pick up entries in the Procfile
within your project root directory, but the plugin configuration will take precedence.
warFile
Specifies the WAR file to use for heroku:deploy-war
and heroku:run-war
goals.
<warFile>custom/directory/webapp.war</warFile>
Normally, the plugin looks for a WAR file in target
and deploys it. This means you usually don't have to configure this, unless you want to deploy a WAR file located somewhere else.
webappRunnerVersion
Configures the version of webapp-runner to use for heroku:deploy-war
and heroku:run-war
.
<webappRunnerVersion>9.0.30.0</webappRunnerVersion>
Advanced Features
Customizing the JDK
You can customize the JDK by creating a .jdk-overlay
directory as described in this Dev Center article. This plugin will automatically include this directory if present.
Hacking
To run the entire suite of integration tests, use the following command:
$ ./mvnw clean install -Pit
To run an individual integration test, use a command like this:
$ ./mvnw clean install -Pit -Dinvoker.test=simple-deploy-test