This is a Heroku Buildpack for Fantom.
Use this to run your Fantom
application on the Heroku cloud application platform.
See Fantom-Factory for further articles on Fantom and Heroku.
Contents:
[TOC]
Steps to Heroku Fantom fulfillment:
- Convert your Heroku application to use Fantom
- Create your Fantom environment
- Create your (web) process
- Git push your code
To run a Fantom application on Heroku you must first configure your heroku app to use this buildpack
.
To convert an existing Heroku app to use Fantom, type:
#!bash
C:\> heroku config:set BUILDPACK_URL=https://github.com/Fantom-Factory/heroku-buildpack-fantom.git -a <myapp>
To create a new Heroku app that uses Fantom, type:
#!bash
C:\> heroku create <myapp> --buildpack https://github.com/Fantom-Factory/heroku-buildpack-fantom.git
See Using A Custom Buildpack for more details.
As long as you have build.fan
in the root of your application directory, Heroku will recognise your app as a fantom app.
When this buildpack runs it downloads a fresh copy of Fantom (v1.0.74 at time of writing) and installs it in the directory /app/.fan/
.
The buildpack then compiles your application from source by running the following 2 commands:
#!bash
C:\> fan build.fan herokuPreCompile
C:\> fan build.fan compile
Because the Fantom installation is a fresh one, before your source can compile, it needs to download and install all external pods dependencies (such as the most excellent afIoc) into your Fantom environment. This is what the (optional) herokuPreComile
build target is for.
Note that the compile
build target is customisable.
For Heroku to launch your application, it requires a file called Procfile
in the root of your project dir:
#!bash
|-fan/
| |...
|-build.fan
`-Procfile
Procfile
contains the command Heroku should run, prefixed with the type of task. The simplest (and most common) Procfile
is just:
#!bash
web: fan <yourPod> $PORT
Which calls <yourPod>::Main.main(Str[] args)
passing in the port number your web app should listen on. Make sure this class and method exists to successfully launch your application.
If Procfile
does not exist then Fantom buildpack will create one for you, containing the line mentioned above. See Procfile for more details.
To deploy and run your application on Heroku, simply git push
your code as normal and hopefully you should see something like this:
#!bash
C:\> git push heroku master
-----> Fetching set buildpack... done
-----> Fantom app detected
-----> Reading file 'heroku.props'...
-----> Java version : 1.8
-----> Fantom version : 1.0.74
-----> Fantom download URL : https://xxx/fantom-1.0.74.zip
-----> Fantom build target : compile
-----> Creating file 'system.properties' for use by JVM Buildpack... done
-----> Installing OpenJDK 1.8... done
-----> Downloading http://xxx/fantom-1.0.74.zip ... done
-----> Installing Fantom 1.0.74... done
Fantom Launcher
Copyright (c) 2006-2013, Brian Frank and Andy Frank
Licensed under the Academic Free License version 3.0
Java Runtime:
java.version: 1.8.0_101
java.vm.name: OpenJDK 64-Bit Server VM
java.vm.vendor: Sun Microsystems Inc.
java.vm.version: 20.0-b12
java.home: /tmp/build/.jdk/jre
fan.platform: linux-x86_64
fan.version: 1.0.74
fan.env: sys::BootEnv
fan.home: /app/tmp/repo.git/.cache/fantom-1.0.74
-----> Calling Build Target: herokuPreCompile...
-----> Calling Build Target: compile...
compile [<myapp>]
Compile [<myapp>]
FindSourceFiles [18 files]
WritePod [file:/tmp/build/.fan/lib/fan/<myapp>.pod]
BUILD SUCCESS [100ms]!
-----> Creating Procfile...
web: fan <myapp> $PORT
-----> Discovering process types
Procfile declares types -> web
-----> Compiled slug size: 60.4MB
-----> Launching... done, v69
http://<myapp>.herokuapp.com deployed to Heroku
More than likely, your application has dependencies on external Fantom pods such as BedSheet and IoC. These pods need to be installed by the herokuPreCompile()
build task. The easiest means of doing so, is by programmatically calling fanr
.
You can install pods from a local fanr
repository as long as it is checked into your Heroku Git repository. For example, if your project had the following directory structure:
#!bash
|-fan/
| |...
|-lib-fanr/
| `-afBedSheet/
| `-afBedSheet-1.5.x.pod
`-build.fan
You could install BedSheet like this:
#!java
@Target { help = "Heroku pre-compile hook, use to install dependencies" }
Void herokuPreCompile() {
// install pods from a local fanr repository
fanr("install -y -r file:lib-fanr/ afBedSheet")
}
private Void fanr(Str args) {
fanr::Main().main(args.split)
}
This is useful when you're using pods developed by yourself, or ones that are not publicly available.
Most external pods are available publicly, usually from the Eggbox Repository. Here is a modified script that downloads and installs pods from there:
#!java
@Target { help = "Heroku pre-compile hook, use to install dependencies" }
Void herokuPreCompile() {
// install pods from a remote fanr repository
fanr("install -y -r http://eggbox.fantomfactory.org/fanr/ afIoc")
}
private Void fanr(Str args) {
fanr::Main().main(args.split)
}
If ALL your dependant pods are available from the same repository (probably Eggbox), then here is a useful script that installs everything for you:
#!java
@Target { help = "Heroku pre-compile hook, use to install dependencies" }
Void herokuPreCompile() {
// find all non-installed dependant pods
pods := depends.findAll |Str dep->Bool| {
depend := Depend(dep)
pod := Pod.find(depend.name, false)
return (pod == null) ? true : !depend.match(pod.version)
}
installFromRepo(pods, "http://eggbox.fantomfactory.org/fanr/") // repo = "file:lib/fanr/"
}
private Void installFromRepo(Str[] pods, Str repo) {
if (pods.isEmpty) return
cmd := "install -errTrace -y -r ${repo}".split.add(pods.join(","))
log.info("")
log.info("Installing pods...")
log.info("> fanr " + cmd.join(" ") { it.containsChar(' ') ? "\"$it\"" : it })
status := fanr::Main().main(cmd)
// abort build if something went wrong
if (status != 0) Env.cur.exit(status)
}
Output from a successful install should look like:
#!bash
Installing pods...
> fanr install -errTrace -y -r http://pods.fantomfactory.org/fanr/ "..."
afBedSheet [install] not-installed => 1.3.4
afIoc [install] not-installed => 1.5.4
afIocConfig [install] not-installed => 1.0.4
afIocEnv [install] not-installed => 1.0.2.1
afPlastic [install] not-installed => 1.0.10
Downloading afIocConfig ... Complete
Downloading afIoc ... Complete
Downloading afIocEnv ... Complete
Downloading afPlastic ... Complete
Downloading afBedSheet ... Complete
Download successful (5 pods)
Installing afIocConfig ... Complete
Installing afIoc ... Complete
Installing afIocEnv ... Complete
Installing afPlastic ... Complete
Installing afBedSheet ... Complete
Installation successful (5 pods)
Sometimes you have a dependency on a Java library. To install these, again make sure they are checked into your Heroku Git repository. Assuming the jars are in the following directory structure:
#!bash
|-fan/
| |...
|-lib-java/
| `-wotever-1.7.2.jar
`-build.fan
You can install them like this:
#!java
@Target { help = "Heroku pre-compile hook, use to install dependencies" }
Void herokuPreCompile() {
// install jar files from local
installJar(`lib/java/wotever-1.7.2.jar`)
}
private Void installJar(Uri jarFile) {
(scriptDir + jarFile).copyInto(Env.cur.homeDir + `lib/java/ext/`, ["overwrite" : true])
}
The buildpack can be customised by placing a heroku.props
file in the root of your project, next to your build.fan
:
#!bash
|-fan/
| |...
|-build.fan
`-heroku.props
A sample heroku.props
file looks like:
java.runtime.version=1.8
fantom.version=1.0.74
fantom.downloadUrl=http://example.com/fantom-custom.zip
fantom.buildTarget=compile
Note that (due to bash script restrictions) you must have a trailing new line \n
character on the last line of heroku.props
.
By default this buildpack installs OpenJDK 1.8, should you wish to install a different version then edit heroku.props
:
java.runtime.version=1.8
At the time of writing the following Java versions are supported:
- 1.8
- 1.7
- 1.6
For more details about setting the Java version, see Choose a JDK. You could also download the Java Common Buildpack and inspect the bin/java
script.
Note that this buildpack also creates a file called system.properties
that is used by the Java Buildpack. So if you create such a file, it will be overwritten!
By default this buildpack installs Fantom 1.0.74, should you wish to install a different version then edit heroku.props
:
fantom.version=1.0.68
At the time of writing the following Fantom versions are supported:
- 1.0.65 through to 1.0.74
You may also specify an alternative download location for Fantom:
fantom.version=1.0.68
fantom.downloadUrl=http://example.com/fantom-custom.zip
Note that if you specify fantom.downloadUrl
you must also specify fantom.version
.
To call a custom build target called on build.fan
, edit heroku.props
:
fantom.buildTarget=herokuCompile
Licensed under the MIT Licence. See licence.txt
for details.
Have fun!