Deploy Multi-Language Projects to Heroku

In my current technology playground chatty I use Java, TypeScript and JavaScript as programming languages. For the TypeScript/HTML based Web UI I use a node/grunt based build, for the Java parts I use Gradle. Heroku is a great cloud platform, deploying software is done using a git push. Using the predefined build-packs, it is pretty easy to deploy Java OR Node based applications, but how to deploy a multi-language project that uses both?

Here the heroku-buildpack-multi helps a lot. Simply invoke

$ heroku config:add BUILDPACK_URL=https://github.com/ddollar/heroku-buildpack-multi.git

and add all buildpacks to a top-level .buildpack file, that’s it. Then, each build is done sequentially as specified in the .buildpack file. The .buildpack for chatty looks like

https://github.com/mbuchetics/heroku-buildpack-nodejs-grunt.git
https://github.com/heroku/heroku-buildpack-gradle.git

Another important thing to know about these buildpacks assume that the corresponding project is located at top-level. So the node build expects a package.json in the root directory. Since chatty is a multi-project build, the web part is located in subprojects/com.toedter.chatty.client.web. For me, the easiest solution was to copy the package json to the root directory, and the provide a grunt file, that copies all node_modules to the subproject. Additionally I use the grunt contribution grunt-hub to invoke the gruntfile located in the subproject with target distBoot (to provide a distribution of the JacaScript/HTML/CSS/libs that can be deployed together with the Spring Boot based server part. The last thing is to define a grunt task named ‘heroku’ that is invoked by the buildpack. The whole top-level grunt file looks like:

module.exports = function (grunt) {
    'use strict';

    grunt.initConfig({
        hub: {
            all: {
                src: ['subprojects/com.toedter.chatty.client.web/Gruntfile.js'],
                tasks: ['distBoot']
            }
        },
        copy: {
            node_modules: {
                expand: true,
                src: 'node_modules/**/*',
                dest: 'subprojects/com.toedter.chatty.client.web/'
            }
        }
    });

    grunt.loadNpmTasks('grunt-hub');
    grunt.loadNpmTasks('grunt-contrib-copy');

    grunt.registerTask('heroku', ['copy:node_modules', 'hub']);
}

The Java part is pretty straight forward since gradle is the master build system of chatty. The only subproject I want to deploy to heroku is the Spring Boot based server, located in subprojects/com.toedter.chatty.server.boot. In the gradle.build file I just added a new gradle task ‘stage’:

task stage(dependsOn: ['jar', 'bootRepackage'])

that creates the fat jar for the chatty spring boot application. The resulting web application demo is then deployed to Heroku, you can check it out at https://chatty42.herokuapp.com/chatty/chatty.html.

Regarding IDE integration there are Heroku plugins for IntelliJ IDEA and Eclipse. In the next blog of this series, I will explain how to use Travis-CI for a continuous delivery, including the automatic deployment to Heroku after a successful build.

Leave a Reply

I accept the Privacy Policy