diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md new file mode 100644 index 00000000..3032ff3a --- /dev/null +++ b/.github/ISSUE_TEMPLATE.md @@ -0,0 +1,55 @@ +##### Type of problem + + + - Failure to build + - Runtime problem after the build succeeds + +##### Summary + + + +##### Contents of `.meteor/release` + + +``` + +``` + +##### Buildpack version + +``` + +``` + +##### Logs + + +``` + +``` + +##### Deployment target + diff --git a/README.md b/README.md index 8c0d0b35..0c182c7e 100644 --- a/README.md +++ b/README.md @@ -7,12 +7,12 @@ A heroku buildpack for Meteor v1+, designed to be as simple and readable as poss To use this with your meteor app and heroku: 1. Set up your app to [deploy to heroku with git](https://devcenter.heroku.com/articles/git). -2. Set this repository as the buildpack URL: +2. Set your buildpack to the latest version from the [registry](https://devcenter.heroku.com/articles/buildpack-registry): - heroku buildpacks:set https://github.com/AdmitHub/meteor-buildpack-horse.git + heroku buildpacks:set admithub/meteor-horse 3. Add the MongoLab addon: - + heroku addons:create mongolab 4. Set the `ROOT_URL` environment variable. This is required for bundling and running the app. Either define it explicitly, or enable the [Dyno Metadata](https://devcenter.heroku.com/articles/dyno-metadata) labs addon to default to `https://.herokuapp.com`. @@ -28,16 +28,19 @@ Once that's done, you can deploy your app using this build pack any time by push The following are some important environment variables for bundling and running your meteor app on heroku. Depending on your settings, you may need to override these on heroku. See [heroku's documentation](https://devcenter.heroku.com/articles/config-vars) for how to set these. - `ROOT_URL`: The root URL for your app, needed for bundling as well as running. If you enable the [Dyno Metadata](https://devcenter.heroku.com/articles/dyno-metadata) labs addon and `ROOT_URL` is undefined, it will default to `https://.herokuapp.com`). - - `MONGO_URL`: The URL to mongodb. It not defined, it will default the value of `MONGODB_URI`, `MONGOLAB_URI`, or `MONGOHQ_URL` (in order). If you don't use mongolab as a regular addon (and none of the fallbacks are defined), you'll need to set this. + - `MONGO_URL`: The URL to mongodb. If not defined, it will default the value of `MONGODB_URI`, `MONGOLAB_URI`, or `MONGOHQ_URL` (in order). If you don't use mongolab as a regular addon (and none of the fallbacks are defined), you'll need to set this. - `METEOR_APP_DIR`: The relative path to the root of your meteor app within your git repository (i.e. the path to the directory that contains `.meteor/`). The buildpack will look in the root of your repository and `app/` subdirectory; if you put your app anywhere else (like `src/`), define this variable to tell the buildpack where to look. - `BUILDPACK_PRELAUNCH_METEOR`: If your app uses packages that need to compile their assets on first run, you may need meteor to launch prior to bundling. If this applies for you, define `BUILDPACK_PRELAUNCH_METEOR=1`. [Reference issue](https://github.com/meteor/meteor/issues/2606). - `BUILDPACK_VERBOSE`: Set `BUILDPACK_VERBOSE=1` to enable verbose bash debugging during slug compilation. Only takes effect after the environment variables have been loaded. + - `BUILDPACK_CLEAR_CACHE`: This buildpack stores the meteor installation in the [CACHE_DIR](https://devcenter.heroku.com/articles/buildpack-api#caching) to speed up subsequent builds. Set `BUILDPACK_CLEAR_CACHE=1` to clear this cache on startup and after build is done. + - `BUILD_OPTIONS`: Set to any additional options you'd like to add to the invocation of `meteor build`, for example `--debug` or `--allow-incompatible-update`. + - `NODEJS_PARAMS`: additional parameters for running `node` binary. This can be used eg. for [adjusting garbage collector settings](https://devcenter.heroku.com/articles/node-best-practices#avoid-garbage) by putting `--optimize_for_size --max_old_space_size=460 --gc_interval=100` here ## Extras The basic buildpack should function correctly for any normal-ish meteor app, with or without npm-container. For extra steps needed for your particular build, -just add shell scripts to the `extra` folder and they will get sourced into the +just add shell scripts to the `extra` folder and they will get sourced into the build. Extras included in this branch: @@ -55,6 +58,12 @@ subdirectories. Those directories are added to `$PATH` and So `$COMPILE_DIR/bin` etc are great places to put any extra binaries or stuff if you need to in custom extras. +## Using the latest buildpack code + +The `admithub/meteor-horse` buildpack from the [Heroku Registry](https://devcenter.heroku.com/articles/buildpack-registry) contains the latest stable version of the buildpack. If you'd like to use the latest buildpack code from this Github repository, you can set your buildpack to the Github URL: + + heroku buildpacks:set https://github.com/AdmitHub/meteor-buildpack-horse + ## Tips & Tricks Please help us add tips and tricks to the [wiki](https://github.com/AdmitHub/meteor-buildpack-horse/wiki) for further help, like usage with Dokku or other environments. @@ -68,3 +77,5 @@ outdated or broken, and it's really hard to keep them straight. So this one is the horse one. README image credit: wikicommons contributor [Arsdelicata](https://commons.wikimedia.org/wiki/User:Arsdelicata) + + diff --git a/bin/compile b/bin/compile index cf6fe48a..8deb398e 100755 --- a/bin/compile +++ b/bin/compile @@ -1,4 +1,4 @@ -#!/bin/sh +#!/bin/bash # # Heroku buildpack for Meteor @@ -27,14 +27,20 @@ export_env_dir $3 # Enable verbose debugging if configured to -- though this has to come after # we've loaded environment configs. -if [ -n "${BUILDPACK_VERBOSE+1}" ]; then +if [ -n "$BUILDPACK_VERBOSE" ]; then set -x fi + # Get the path to dir one above this file. BUILDPACK_DIR=$(cd -P -- "$(dirname -- "$0")" && cd .. && pwd -P) # Get the directory our app is checked out in (the "BUILD_DIR"), passed by Heroku APP_CHECKOUT_DIR=$1 +CACHE_DIR=$2 +if [ -n "$BUILDPACK_CLEAR_CACHE" ]; then + echo "-----> Clearing cache dir." + rm -rf "$CACHE_DIR/*" +fi # # Find the meteor app ($APP_SOURCE_DIR). @@ -54,12 +60,12 @@ if [ ! -d "$APP_SOURCE_DIR/.meteor" ] && [ -d "$APP_SOURCE_DIR/app/.meteor" ]; t APP_SOURCE_DIR="$APP_SOURCE_DIR/app/" fi if [ ! -d "$APP_SOURCE_DIR/.meteor" ]; then - echo "FATAL: Can't find meteor app. Set METEOR_APP_DIR to the relative location of the meteor app within your repository if it's not in the root or 'app/' supdirectory. (Tried ${APP_SOURCE_DIR})" + echo "FATAL: Can't find meteor app. Set METEOR_APP_DIR to the relative location of the meteor app within your repository if it's not in the root or 'app/' subdirectory. (Tried ${APP_SOURCE_DIR})" exit 1 fi # Where we will install meteor. Has to be outside the APP_CHECKOUT_DIR. -METEOR_DIR=`mktemp -d "$BUILDPACK_DIR"/meteor-XXXX` +METEOR_DIR="$CACHE_DIR/meteor" # Where we'll put things we compile. COMPILE_DIR_SUFFIX=".meteor/heroku_build" COMPILE_DIR="$APP_CHECKOUT_DIR"/"$COMPILE_DIR_SUFFIX" @@ -69,10 +75,8 @@ if [ -z "$BUILDPACK_VERBOSE" ]; then fi # Create directories as needed. -mkdir -p "$APP_CHECKOUT_DIR" "$METEOR_DIR" "$COMPILE_DIR" - -# Update the path so we get npm, etc. -PATH="$METEOR_DIR/.meteor:$COMPILE_DIR/bin:$PATH" +mkdir -p "$APP_CHECKOUT_DIR" "$METEOR_DIR" +mkdir -p "$COMPILE_DIR" "$COMPILE_DIR/bin" "$COMPILE_DIR/lib" # Set a default ROOT_URL if one is not defined. Currently, HEROKU_APP_NAME is # only available if you enable the labs addon "Heroku Dyno Metadata": @@ -87,91 +91,120 @@ if [ -z "$ROOT_URL" ] ; then exit 1 fi -# -# Install node -# -echo "-----> Installing node" -NODE_VERSION=`curl -sS --get https://semver.io/node/resolve/0.10.x` -NODE_URL="http://s3pository.heroku.com/node/v$NODE_VERSION/node-v$NODE_VERSION-linux-x64.tar.gz" -curl -sS $NODE_URL -o - | tar -zxf - -C $COMPILE_DIR --strip 1 -# Export some environment variables for npm to use when compiling stuff. -export npm_config_prefix="$COMPILE_DIR" -export CPATH="$COMPILE_DIR"/include -export CPPPATH="$CPATH" - # # Install meteor # -echo "-----> Installing meteor" -curl -sS https://install.meteor.com | HOME="$METEOR_DIR" /bin/sh -METEOR="$METEOR_DIR/.meteor/meteor" # The meteor binary. - -# Maybe update release. Upgrade only if needed because it's slow. -CUR_RELEASE=`HOME=$METEOR_DIR $METEOR --version | sed -e 's/Meteor /METEOR@/'` -APP_RELEASE=`cat "$APP_SOURCE_DIR/.meteor/release"` -if test "$CUR_RELEASE" != "$APP_RELEASE" ; then - # Sort CUR_RELEASE and APP_RELEASE and find the oldest - OLDER_RELEASE=`echo "$CUR_RELEASE\n$APP_RELEASE" | sort --version-sort | head -n1` - if [ "$CUR_RELEASE" = "$OLDER_RELEASE" ]; then - echo "-----> Upgrading meteor to $APP_RELEASE" - HOME=$METEOR_DIR $METEOR update --release $APP_RELEASE - fi + +# Install the latest meteor, and rely on meteor to upgrade/downgrade itself to +# the .meteor/release target. +if [ -e "$METEOR_DIR/.meteor/meteor" ]; then + echo "-----> Existing meteor installation found, using it." +else + echo "-----> Installing meteor" + curl -sS "https://install.meteor.com/" | HOME="$METEOR_DIR" /bin/sh fi +# Function to execute meteor with proper HOME. +function METEOR { + ARGS=$@ + HOME="$METEOR_DIR" "$METEOR_DIR/.meteor/meteor" $ARGS +} # # Build the meteor app! # -echo "-----> Bundling bundle" -cd $APP_SOURCE_DIR -# Determine if we have --server-only flag capability. Allow non-zero return from grep. +# Change into the project directory. Once we're there, 'meteor' commands will +# run with the context of the target release (project .meteor/release) rather +# than the "latest" that is installed by install.meteor.com. +cd "$APP_SOURCE_DIR" + +echo "-----> Target Meteor version: `METEOR --version`" + +# Deal with non-server build targets. Determine if we have --server-only flag +# capability (Meteor 1.3 and up). echo "-----> Checking if this meteor version supports --server-only" +# Allow non-zero return from grep. set +e -HAS_SERVER_ONLY=`HOME=$METEOR_DIR $METEOR help build | grep -e '--server-only'` +HAS_SERVER_ONLY=`METEOR help build | grep -e '--server-only'` set -e if [ -n "$HAS_SERVER_ONLY" ] ; then SERVER_ONLY_FLAG='--server-only' else SERVER_ONLY_FLAG="" fi -# Remove the Android platform if we don't support the --server-only flag. iOS -# platform gets ignored properly. +# Remove the Android platform if we don't support the --server-only flag +# (Meteor 1.2 and below). iOS platform gets ignored properly. if [ -z "$SERVER_ONLY_FLAG" ]; then echo "-----> Attempting to remove android platform." - HOME=$METEOR_DIR $METEOR remove-platform android || true + METEOR remove-platform android || true echo "-----> Moving on." fi +# Identify the npm/node to use. We need to copy the node binary out to get the +# correct version in the built slug (e.g. 0.10.x for Meteor<1.4, 4.x for +# Meteor>=1.4). We can't copy the whole meteor world because that's too large +# (Issue #125). + +# Query node for its own path. As long as the Meteor version we got from +# install.meteor.com is >=1.3, "meteor node" is available, even if the target +# release predates that feature. +METEOR_NODE=`METEOR node -e "process.stdout.write(process.execPath)"` +# Assume npm is in the same dir as node. +METEOR_NPM="`dirname "$METEOR_NODE"`/npm" + +if [ -z "$METEOR_NPM" ] || [ -z "$METEOR_NODE" ] ; then + echo "FATAL: Can't find npm/node within meteor bundle. This is a bug. Please open an issue at https://github.com/AdmitHub/meteor-buildpack-horse."; + exit 1 +fi + +# Copy node into place for production. +NODE="$COMPILE_DIR"/bin/node +cp "$METEOR_NODE" "$NODE" +chmod a+x "$NODE" + +# Add npm and node path so that 1.4's npm-rebuild.js will function. +PATH="$METEOR_DIR/.meteor:`dirname $METEOR_NPM`:$COMPILE_DIR/bin:$PATH" + +echo "-----> Using node: `$NODE --version`" +echo "-----> and npm: `$METEOR_NPM --version`" + # If we use npm on root, run npm install. Don't use `--production` here, as we # may need devDependencies (e.g. webpack) in order to build the meteor app. if [ -e "$APP_SOURCE_DIR"/package.json ]; then - npm install + $METEOR_NPM install fi -# Related to https://github.com/meteor/meteor/issues/2796 and +# Related to https://github.com/meteor/meteor/issues/2796 and # https://github.com/meteor/meteor/issues/2606. Some packages only build their # assets at runtime, and thus they are not available for bundling unless meteor # has been launched. To opt-in to this, set BUILDPACK_PRELAUNCH_METEOR=1. -if [ -n "${BUILDPACK_PRELAUNCH_METEOR+1}" ]; then +if [ -n "$BUILDPACK_PRELAUNCH_METEOR" ]; then echo "-----> BUILDPACK_PRELAUNCH_METEOR: Pre-launching meteor to build packages assets" # Remove the Android platform because it fails due to the Android tools not # being installed, but leave the iOS platform because it's ignored. - HOME=$METEOR_DIR $METEOR remove-platform android || true - HOME=$METEOR_DIR timeout -s9 60 $METEOR --settings settings.json || true + METEOR remove-platform android || true + HOME=$METEOR_DIR timeout -s9 60 $METEOR_DIR/.meteor/meteor --settings settings.json || true fi -# Now on to bundling. Don't put the bundle in $APP_CHECKOUT_DIR, or it will -# recurse, trying to bundle up its own bundling. +# Now on to bundling. Don't put the bundle in $APP_CHECKOUT_DIR during +# bundling, or it will recurse, trying to bundle up its own bundling. + +echo "-----> Building Meteor app with ROOT_URL: $ROOT_URL" BUNDLE_DEST=`mktemp -d "$BUILDPACK_DIR/build-XXXX"` -echo "-----> Building Meteor with ROOT_URL: $ROOT_URL" -HOME=$METEOR_DIR $METEOR build --server $ROOT_URL $SERVER_ONLY_FLAG --directory $BUNDLE_DEST + +# The actual invocation of `meteor build`! +METEOR build $BUILD_OPTIONS --server $ROOT_URL $SERVER_ONLY_FLAG --directory $BUNDLE_DEST + +echo "-----> Moving built slug to $COMPILE_DIR/app" mv $BUNDLE_DEST/bundle "$COMPILE_DIR/app" rmdir $BUNDLE_DEST -# Run npm install on the built slug; only for `--production` dependencies. +# Run npm install on the built slug; only for '--production' dependencies. +echo "-----> Installing npm production dependencies on built slug" if [ -e "$COMPILE_DIR"/app/programs/server/package.json ]; then cd "$COMPILE_DIR"/app/programs/server - npm install --production + $METEOR_NPM install --production + cd "$APP_SOURCE_DIR" fi # @@ -196,3 +229,11 @@ echo "-----> Running extras" for file in `ls "$BUILDPACK_DIR"/extra | sort`; do . "$BUILDPACK_DIR"/extra/$file done + +# +# Clear cache after build is done +# +if [ -n "$BUILDPACK_CLEAR_CACHE" ]; then + echo "-----> Clearing cache dir." + rm -rf $METEOR_DIR +fi diff --git a/bin/release b/bin/release index 2652ea95..3970dc76 100755 --- a/bin/release +++ b/bin/release @@ -1,8 +1,6 @@ #!/bin/sh cat < "$APP_CHECKOUT_DIR"/.profile.d/mongo_url.sh <