├── README.md ├── bin ├── compile ├── detect └── release └── opt └── rebar /README.md: -------------------------------------------------------------------------------- 1 | ## Heroku buildpack: Elixir 2 | 3 | This is a Heroku buildpack for Elixir apps. It uses 4 | [Mix](http://elixir-lang.org/getting_started/mix/1.html). 5 | 6 | ### Configure your Heroku App 7 | 8 | ```bash 9 | $ heroku config:add BUILDPACK_URL="https://github.com/goshakkk/heroku-buildpack-elixir.git" -a YOUR_APP 10 | ``` 11 | 12 | or 13 | 14 | ```bash 15 | $ heroku create --buildpack "https://github.com/goshakkk/heroku-buildpack-elixir.git" 16 | ``` 17 | 18 | ### Select an Erlang version 19 | 20 | The Erlang/OTP release version that will be used to build and run your 21 | application is now sourced from a dotfile called `.preferred_otp_version`. It 22 | needs to be the branch or tag name from the http://github.com/erlang/otp 23 | repository, and further, needs to be one of the versions that precompiled 24 | binaries are available for. 25 | 26 | Currently supported OTP versions: 27 | 28 | * master (R17A) 29 | * OTP_R16B02 30 | * OTP_R16B01 31 | * OTP_R16B 32 | * OTP_R15B03 33 | * OTP_R15B02 34 | * OTP_R15B01 35 | 36 | To select the version for your app: 37 | 38 | ```bash 39 | $ echo OTP_R16B02 > .preferred_otp_version 40 | $ git commit -m "Select R16B02 as preferred OTP version" .preferred_otp_version 41 | ``` 42 | 43 | If no version is explicitly specified, `master` will be used. 44 | 45 | ### Select an Elixir version 46 | 47 | The application will be compiled and run using Elixir master and Mix. 48 | 49 | You can specify custom branch or tag name from the 50 | https://github.com/elixir-lang/elixir repository in the 51 | `.preferred_elixir_version` dotfile. 52 | 53 | ### Setup a Procfile 54 | 55 | Heroku needs a Procfile in order to run your application. Create a Procfile with a `web` process defined: 56 | 57 | #### Dynamo 58 | 59 | ```bash 60 | $ echo 'web: mix server -p $PORT' > Procfile 61 | ``` 62 | 63 | The buildpack sets `MIX_ENV=prod` so you don't have to. 64 | 65 | **Important Note:** Single quotes are important here. `$PORT` is an environment variable supplied by Heroku. If you use double quotes 66 | in the above `echo` call, your local shell will try to interpolate the contents, and you'll end up with `-p ` and not `-p $PORT`. 67 | 68 | #### Cowboy 69 | 70 | ```bash 71 | $ echo 'web: mix run --no-halt' > Procfile 72 | ``` 73 | 74 | You should bind to port specified in `PORT` environment variable: 75 | 76 | ```elixir 77 | { :ok, _ } = :cowboy.start_http( 78 | :http, 100, 79 | [port: port(System.get_env("PORT"))], 80 | [env: [dispatch: dispatch]] 81 | ) 82 | ``` 83 | 84 | ```elixir 85 | def port(nil), do: 8080 86 | def port(value) do 87 | binary_to_integer(value) 88 | end 89 | ``` 90 | 91 | **Important Note:** If you bind to any other port than the assigned one, your process will be killed with an R11 error code. 92 | 93 | ### Bundling 94 | 95 | `heroku-elixir-buildpack` supports only applications which use 96 | [Mix](http://elixir-lang.org/getting_started/mix/1.html) to manage 97 | dependencies. 98 | 99 | ### Build your Heroku App 100 | 101 | ```bash 102 | $ git push heroku master 103 | ``` 104 | 105 | You may need to write a new commit and push if your code was already up to date. 106 | -------------------------------------------------------------------------------- /bin/compile: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | ## 4 | # usage: bin/compile 5 | 6 | indent() { 7 | sed -u 's/^/ /' 8 | } 9 | 10 | set -e 11 | bpdir=$(cd $(dirname $(dirname $0)); pwd) 12 | mkdir -p "$1" "$2" 13 | build=$(cd "$1/" && pwd) 14 | test -z ${build} && exit 15 | cache=$(cd "$2/" && pwd) 16 | test -z ${cache} && exit 17 | 18 | APP_NAME=$(grep "app: \(:\)" ${build}/mix.exs | cut -d ":" -f 3 | cut -d "," -f 1) 19 | APP_PATH=${build}/${APP_NAME} 20 | DEFAULT_OTP_VERSION="master" 21 | if [ -f ${build}/.preferred_otp_version ]; then 22 | OTP_VERSION=$(cat ${build}/.preferred_otp_version) 23 | fi 24 | erl_ver=${OTP_VERSION:=${DEFAULT_OTP_VERSION}} 25 | erl_tarball=${erl_ver}.tgz 26 | OTP_TARBALL_URL="https://s3.amazonaws.com/heroku-buildpack-erlang/${erl_tarball}" 27 | ERLROOT=${build}/otp 28 | 29 | DEFAULT_ELIXIR_VERSION="master" 30 | if [ -f ${build}/.preferred_elixir_version ]; then 31 | ELIXIR_VERSION=$(cat ${build}/.preferred_elixir_version) 32 | fi 33 | ex_ver=${ELIXIR_VERSION:=${DEFAULT_ELIXIR_VERSION}} 34 | ex_tarball=${ex_ver}.tar 35 | ELIXIR_TARBALL_URL="https://github.com/elixir-lang/elixir/tarball/${ex_ver}" 36 | EXROOT=${build}/ex 37 | 38 | mkdir ${APP_PATH} 39 | for file in ${build}/* ${build}/.*; do 40 | test "$file" != "$APP_PATH" && 41 | test "$file" != "${build}/Procfile" && 42 | test "$file" != "${build}/." && 43 | test "$file" != "${build}/.." && 44 | mv "$file" "$APP_PATH/"; 45 | done 46 | 47 | echo "-----> Using Erlang/OTP $erl_ver" 48 | 49 | ( 50 | set -e 51 | 52 | # Already cached? 53 | test -f ${cache}/${erl_tarball} && exit 54 | 55 | rm -rf ${cache}/* # be sure not to build up cruft 56 | cd ${cache} 57 | echo "-------> Fetching Erlang/OTP $erl_ver" 58 | curl -sO ${OTP_TARBALL_URL} || exit 1 59 | ) 60 | 61 | echo "-------> Unpacking Erlang/OTP $erl_ver" 62 | mkdir -p ${ERLROOT} 63 | tar zxf ${cache}/${erl_tarball} -C ${ERLROOT} --strip-components=2 64 | echo "-------> Installing Erlang/OTP $erl_ver" 65 | ln -s ${ERLROOT} /app/otp 66 | ${ERLROOT}/Install -minimal /app/otp 67 | 68 | PATH=/app/otp/bin:$PATH 69 | 70 | if [ ! -e "rebar" ]; then 71 | echo "-----> Installing Rebar from buildpack" 72 | cp ${bpdir}/opt/rebar $build 73 | PATH=${bpdir}/opt:$PATH 74 | fi 75 | 76 | echo "-----> Using Elixir $ex_ver" 77 | 78 | ( 79 | set -e 80 | 81 | # Already cached? 82 | test -f ${cache}/${ex_tarball} && exit 83 | 84 | rm -rf ${cache}/* # be sure not to build up cruft 85 | cd ${cache} 86 | echo "-------> Fetching Elixir $ex_ver" 87 | curl -LsO ${ELIXIR_TARBALL_URL} -o $ex_tarball || exit 1 88 | mv $ex_ver $ex_tarball 89 | ) 90 | 91 | echo "-------> Unpacking Elixir $ex_ver" 92 | mkdir -p ${EXROOT} 93 | tar xf ${cache}/${ex_tarball} -C ${EXROOT} --strip-components=1 94 | echo "-------> Installing Elixir $ex_ver" 95 | 96 | ( 97 | set -e 98 | 99 | cd ${EXROOT} 100 | make > /dev/null 101 | ) 102 | 103 | ln -s ${EXROOT} /app/ex 104 | 105 | PATH=/app/ex/bin:$PATH 106 | 107 | cd ${APP_PATH} 108 | 109 | echo "-----> Building with Mix" 110 | unset GIT_DIR 111 | 112 | echo "-----> Bundling dependencies" 113 | MIX_ENV=prod mix deps.get 2>&1 | indent 114 | 115 | echo "-----> Compiling app" 116 | MIX_ENV=prod mix compile 2>&1 | indent 117 | 118 | mkdir ${build}/.profile.d 119 | echo "cd /app/${APP_NAME}" > ${build}/.profile.d/path.sh 120 | -------------------------------------------------------------------------------- /bin/detect: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # this pack is valid for apps with a mix.exs in the root 4 | if [ -f $1/mix.exs ]; then 5 | echo "Elixir" 6 | exit 0 7 | else 8 | exit 1 9 | fi 10 | -------------------------------------------------------------------------------- /bin/release: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | cat << EOF 4 | --- 5 | config_vars: 6 | PATH: /app/otp/bin:/app/ex/bin:bin:/usr/bin:/bin 7 | MIX_ENV: prod 8 | EOF 9 | -------------------------------------------------------------------------------- /opt/rebar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/goshacmd/heroku-buildpack-elixir/b090e155d20c4c02a13e8f279814f2c3dee5f092/opt/rebar --------------------------------------------------------------------------------