├── bin ├── release ├── detect └── compile └── README.md /bin/release: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | cat << EOF 4 | --- 5 | default_process_types: 6 | web: bin/main 7 | EOF 8 | -------------------------------------------------------------------------------- /bin/detect: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | BUILD_DIR=$1 3 | if stat -t ${BUILD_DIR}/*.opam.locked >/dev/null 2>&1; then 4 | echo "OCaml" 5 | exit 0 6 | elif stat -t ${BUILD_DIR}/*.opam >/dev/null 2>&1; then 7 | echo "No .opam.locked file detected" >&2 8 | echo "Generate one with [opam lock]" >&2 9 | exit 1 10 | else 11 | echo "No .opam.locked file detected" >&2 12 | exit 1 13 | fi 14 | -------------------------------------------------------------------------------- /bin/compile: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -eo pipefail 3 | 4 | BUILD_DIR=$1 5 | CACHE_DIR=$2 6 | 7 | if [[ ! -e $CACHE_DIR/bin/opam ]]; then 8 | echo "opam not cached, downloading" 9 | wget https://github.com/ocaml/opam/releases/download/2.0.7/opam-2.0.7-x86_64-linux 10 | mkdir -p $CACHE_DIR/bin 11 | install opam-2.0.7-x86_64-linux $CACHE_DIR/bin/opam 12 | fi 13 | export PATH=$CACHE_DIR/bin:$PATH 14 | if [[ -e $CACHE_DIR/.opam ]]; then 15 | echo ".opam cached" 16 | cp -r $CACHE_DIR/.opam ~/.opam 17 | else 18 | echo ".opam not cached, calling init" 19 | opam init --disable-sandboxing 20 | opam switch create heroku --empty 21 | fi 22 | cd $BUILD_DIR 23 | pwd 24 | opam switch heroku 25 | eval $(opam env) 26 | echo "Installing deps" 27 | OPAMSOLVERTIMEOUT=6000 opam install . --deps-only --locked -y 28 | eval $(opam env) 29 | echo "Building" 30 | dune build @install 31 | echo $BUILD_DIR 32 | dune install --prefix ~/_build 33 | if [[ -e $BUILD_DIR/Procfile ]]; then 34 | echo "procfile 1" 35 | cp $BUILD_DIR/Procfile ~/Procfile 36 | fi 37 | rm -rf $BUILD_DIR 38 | mv ~/_build $BUILD_DIR 39 | if [[ -e ~/Procfile ]]; then 40 | echo "procfile 2" 41 | mv ~/Procfile $BUILD_DIR/Procfile 42 | fi 43 | echo "Copying .opam" 44 | rm -rf $CACHE_DIR/.opam && cp -r ~/.opam $CACHE_DIR/.opam 45 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Heroku Buildpack: OCaml 2 | 3 | A buildpack for Heroku and compatible systems, for OCaml applications built by dune with dependencies managed by opam. 4 | 5 | ## How to use 6 | - Create a Heroku account (or set up a compatible system like [dokku](https://github.com/dokku/dokku)) 7 | - Get a git repository with an OCaml project that can be built by the buildpack (you can use https://github.com/roddyyaga/opium-heroku-example) 8 | - Clone the repo and run `heroku create some-globally-unique-name --buildpack https://github.com/roddyyaga/heroku-buildpack-ocaml` 9 | - Run `git push heroku master` 10 | - Go to the Heroku URL and check if the app is running 11 | 12 | ## Build process 13 | This buildpack is for OCaml projects with: 14 | - Dependencies specified by an opam lockfile in the root directory (you can make one with `opam lock`) 15 | - Binaries that will be built/installed by `dune build @install && dune install` in the root directory 16 | 17 | The build process will install dependencies, build the project, and then install the project under the directory 18 | where Heroku runs the app. For instance, if your app's entrypoint has a dune `public_name` of `server` then you 19 | should have a `Procfile` with contents `web: bin/server`. If no Procfile is provided, the buildpack will assume 20 | it is `web: bin/main`. 21 | 22 | As with all Heroku projects, your web server should use the port in the environment variable `PORT`. 23 | 24 | ## Caching 25 | The buildpack will create an opam switch and cache dependencies after each run. The behaviour should be the same 26 | as developing locally with a switch, where adding one dependency means only that dependency has to be installed 27 | on the next build (rather than any change to the lockfile forcing a complete reinstall). 28 | 29 | ## Caveats 30 | - opam sandboxing is disabled due to constraints of the Heroku build environment 31 | - Installing external dependencies is currently not supported and might not be possible (there is no package manager 32 | available in the build environment) 33 | --------------------------------------------------------------------------------