├── .gitignore ├── LICENSE ├── README.md ├── app.json ├── bin ├── boot.sh ├── common.sh ├── compile ├── detect ├── release ├── test └── yarn.sh ├── config ├── htpasswd.rb ├── mime.types ├── nginx.conf.erb └── nginx.d │ └── README.md └── vendor └── jq /.gitignore: -------------------------------------------------------------------------------- 1 | .anvil 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License: 2 | 3 | Copyright (C) 2014 Tony Coconate. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 10 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # WARNING! This buildpack has been deprecated! 2 | 3 | Please use the Heroku buildpack here: https://github.com/heroku/heroku-buildpack-emberjs 4 | 5 | # Notes 6 | 7 | A recent change to the buildpack has made caching much more aggressive. If you are having trouble deploying run... 8 | 9 | $ heroku config:set REBUILD_ALL=true 10 | $ heroku plugins:install heroku-repo 11 | $ heroku repo:purge_cache -a APPNAME 12 | 13 | Be sure to replace `APPNAME` with your app's name. Now, push your repo up. Once that build is complete, your dependencies are rebuilt and cached. Now, unset the var... 14 | 15 | $ heroku config:unset REBUILD_ALL 16 | 17 | Future deploys should now work much faster! 18 | 19 | # Heroku Buildpack for Ember CLI Applications 20 | 21 | This buildpack will work out of the box with Ember CLI generated applications. It installs Node, Nginx and generates a production build with the Ember CLI. 22 | 23 | ## Usage 24 | 25 | Creating a new Heroku instance from an Ember CLI application's parent directory: 26 | 27 | $ heroku create --buildpack https://github.com/tonycoco/heroku-buildpack-ember-cli.git 28 | 29 | $ git push heroku master 30 | ... 31 | -----> Heroku receiving push 32 | -----> Fetching custom buildpack 33 | ... 34 | 35 | Or, use the Heroku Deploy button: 36 | 37 | [![Deploy](https://www.herokucdn.com/deploy/button.png)](https://heroku.com/deploy) 38 | 39 | ## Configuration 40 | 41 | You can set a few different environment variables to turn on features in this buildpack. 42 | 43 | ### Nginx Workers 44 | 45 | Set the number of workers for Nginx (Default: `4`): 46 | 47 | $ heroku config:set NGINX_WORKERS=4 48 | 49 | This will depend on your Heroku instance size and the amount of dynos. 50 | 51 | ### API Proxy 52 | 53 | Set an API proxy URL: 54 | 55 | $ heroku config:set API_URL=http://api.example.com/ 56 | 57 | Set your API's prefix path (Default: `/api/`): 58 | 59 | $ heroku config:set API_PREFIX_PATH=/api/ 60 | 61 | *Trailing slashes are important. For more information about API proxies and avoiding CORS, [read this](http://oskarhane.com/avoid-cors-with-nginx-proxy_pass).* 62 | 63 | ### Authentication 64 | 65 | Setting `BASIC_AUTH_USER` and `BASIC_AUTH_PASSWORD` in your Heroku application will activate basic authentication: 66 | 67 | $ heroku config:set BASIC_AUTH_USER=EXAMPLE_USER 68 | $ heroku config:set BASIC_AUTH_PASSWORD=EXAMPLE_PASSWORD 69 | 70 | *Be sure to use HTTPS for added security.* 71 | 72 | ### Force HTTPS/SSL 73 | 74 | For most Ember applications that make any kind of authenticated requests HTTPS should be used. It supports the headers `X-Forwarded-Proto` ([used by Heroku](https://devcenter.heroku.com/articles/http-routing#heroku-headers)) and `CF-Visitor` ([used by CloudFlare](https://support.cloudflare.com/hc/en-us/articles/200170536-How-do-I-redirect-HTTPS-traffic-with-Flexible-SSL-and-Apache-)). Enable this feature in Nginx by setting `FORCE_HTTPS`: 75 | 76 | $ heroku config:set FORCE_HTTPS=true 77 | 78 | ### LetsEncrypt support 79 | 80 | Using `heroku config:set ACME_CHALLENGE=` allows the app to respond correctly to the call from a manual `certbot` command that is used to generate a LetsEncrypt SSL certificate. 81 | 82 | Follow these steps to get your free SSL certificate installed. (Assumes you have [SNI-SSL](https://devcenter.heroku.com/articles/ssl-beta) installed on your app.) 83 | 84 | $ sudo certbot certonly --email= --manual -d 85 | $ heroku config:set ACME_CHALLENGE='' 86 | # copy fullchain.pem privkey.pem locally from the path certbot put them 87 | $ heroku _certs:update fullchain.pem privkey.pem 88 | $ heroku config:unset ACME_CHALLENGE 89 | 90 | ### Prerender.io 91 | 92 | [Prerender.io](https://prerender.io) allows your application to be crawled by search engines. 93 | 94 | Set the service's host and token: 95 | 96 | $ heroku config:set PRERENDER_HOST=service.prerender.io 97 | $ heroku config:set PRERENDER_TOKEN= 98 | 99 | *Sign up for the hosted [Prerender.io](https://prerender.io) service or host it yourself. See the [project's repo](https://github.com/prerender/prerender) for more information.* 100 | 101 | ### Naked Domain Redirection 102 | 103 | Visitors can be redirected from your "naked domain" (`example.com`) to `www.example.com`. Set your naked domain: 104 | 105 | $ heroku config:set NAKED_DOMAIN=example.com 106 | 107 | *This uses a HTTP 301 redirect to forward the request. All parameters are preserved.* 108 | 109 | ### Private Repositories 110 | 111 | Configure a `GIT_SSH_KEY` to allow Heroku access to private repositories: 112 | 113 | $ heroku config:set GIT_SSH_KEY= 114 | 115 | If present, the buildpack expects the base64 encoded contents of a private key whose public key counterpart has been registered with GitHub on an account with access to any private repositories needed by the application. Prior to executing `npm install` and `bower install` it decodes the contents into a file, launches ssh-agent and registers that keyfile. Once NPM install is finished, it cleans up the environment and file system of the key contents. 116 | 117 | Private NPM dependency URLs must be in the form of `git+ssh://git@github.com:[user]/[repo].git`. Private Bower dependency URLs must be in the form of `git@github.com:[user]/[repo].git`. Either NPM or Bower URLs may have a trailing `#semver`. 118 | 119 | ### Environment 120 | 121 | Choose the environment you want to build by setting: 122 | 123 | $ heroku config:set EMBER_ENV=production 124 | 125 | ### Before and After Hooks 126 | 127 | Have the buildpack run your own scripts before and after the `ember build` by creating a `hooks/before_hook.sh` or `hooks/after_hook.sh` file in your Ember CLI application: 128 | 129 | $ mkdir -p hooks 130 | 131 | For a before build hook: 132 | 133 | $ touch hooks/before_hook.sh 134 | $ chmod +x hooks/before_hook.sh 135 | 136 | For an after build hook: 137 | 138 | $ touch hooks/after_hook.sh 139 | $ chmod +x hooks/after_hook.sh 140 | 141 | *See below for examples.* 142 | 143 | #### Example Before Hook: Compass 144 | 145 | [Compass](http://compass-style.org) can be installed using the before build hook. Create `hooks/before_hook.sh` and add the following script: 146 | 147 | ```bash 148 | #!/usr/bin/env bash 149 | 150 | export GEM_HOME=$build_dir/.gem/ruby/2.2.0 151 | export PATH=$GEM_HOME/bin:$PATH 152 | 153 | if test -d $cache_dir/ruby/.gem; then 154 | status "Restoring ruby gems directory from cache" 155 | cp -r $cache_dir/ruby/.gem $build_dir 156 | HOME=$build_dir gem update compass --user-install --no-rdoc --no-ri 157 | else 158 | HOME=$build_dir gem install compass --user-install --no-rdoc --no-ri 159 | fi 160 | 161 | rm -rf $cache_dir/ruby 162 | mkdir -p $cache_dir/ruby 163 | 164 | if test -d $build_dir/.gem; then 165 | status "Caching ruby gems directory for future builds" 166 | cp -r $build_dir/.gem $cache_dir/ruby 167 | fi 168 | ``` 169 | 170 | ### Force Rebuilds 171 | 172 | Sometimes it is necessary to rebuild NPM modules or Bower dependencies from scratch. This can become necessary when updating Ember or EmberCLI midway through a project and cleaning the Bower and NPM caches doesn't always refresh the cache in the Dyno during the next deployment. In those cases, here is a simple and clean way to force a rebuild. 173 | 174 | To force a rebuild of NPM modules *and* Bower dependencies: 175 | 176 | heroku config:set REBUILD_ALL=true 177 | git commit -am 'rebuild' --allow-empty 178 | git push heroku master 179 | heroku config:unset REBUILD_ALL 180 | 181 | To force a rebuild of just the NPM modules: 182 | 183 | heroku config:set REBUILD_NODE_PACKAGES=true 184 | git commit -am 'rebuild' --allow-empty 185 | git push heroku master 186 | heroku config:unset REBUILD_NODE_PACKAGES 187 | 188 | To force a rebuild of Bower dependencies: 189 | 190 | heroku config:set REBUILD_BOWER_PACKAGES=true 191 | git commit -am 'rebuild' --allow-empty 192 | git push heroku master 193 | heroku config:unset REBUILD_BOWER_PACKAGES 194 | 195 | ### Custom Nginx 196 | 197 | You can install a custom build of Nginx by setting the $NGINX_URL: 198 | 199 | $ heroku config:set NGINX_URL= 200 | 201 | Without this set, the version of Nginx installed will be 1.6.0. 202 | 203 | ### Custom Nginx config 204 | 205 | In your Ember CLI application, add a `config/nginx.conf.erb` file and add your own Nginx configuration. 206 | 207 | *You should copy the existing configuration file in this repo and make changes to it for best results.* 208 | 209 | ### Caching 210 | 211 | The Ember CLI buildpack caches your NPM and Bower dependencies by default. This is similar to the [Heroku Buildpack for Node.js](https://github.com/heroku/heroku-buildpack-nodejs). This makes typical deployments much faster. Note that dependencies like [`components/ember#canary`](http://www.ember-cli.com/#using-canary-build-instead-of-release) will not be updated on each deploy. 212 | 213 | To [purge the cache](https://github.com/heroku/heroku-repo#purge_cache) and reinstall all dependencies, run: 214 | 215 | $ heroku plugins:install https://github.com/heroku/heroku-repo.git 216 | $ heroku repo:purge_cache -a APPNAME 217 | 218 | ### IP Whitelist 219 | 220 | Setting `IP_WHITELIST` in your Herkou application to a comma delimited list of IP addresses or CIDR blocks will restrict access to your application to only those values. 221 | 222 | $ heroku config:set IP_WHITELIST=192.168.0.0/24,192.168.1.42 223 | 224 | ### Yarn 225 | 226 | The Ember CLI buildpack supports yarn. If a `yarn.lock` file is present, the buildpack will use `yarn install` instead of `npm install`. 227 | 228 | If a specific version of yarn is specified in `engines.yarn` within your `package.json`, it will use that version. Otherwise it will install the latest version. 229 | 230 | ## Troubleshooting 231 | 232 | Clean your project's dependencies: 233 | 234 | $ npm cache clear 235 | $ bower cache clean 236 | $ rm -rf node_modules bower_components 237 | $ npm install --no-optional 238 | $ bower install 239 | 240 | Be sure to save any Bower or NPM resolutions. Now, let's build your Ember CLI application locally: 241 | 242 | $ ember build 243 | 244 | Check your `git status` and see if that process has made any changes to your application's code. Now, try your Heroku deployment again. 245 | 246 | ### NPM not installing anything in production 247 | 248 | Heroku will run npm scripts in `production` mode if your `NODE_ENV` is set to `production`. Since all Ember dependencies are in devDependencies, nothing will install. To fix this, run: 249 | 250 | $ heroku config:set NPM_CONFIG_PRODUCTION=false 251 | 252 | ## Contributing 253 | 254 | 1. Fork it 255 | 2. Create your feature branch (`git checkout -b my-new-feature`) 256 | 3. Commit your changes (`git commit -am 'Add some feature'`) 257 | 4. Push to the branch (`git push origin my-new-feature`) 258 | 5. Create new Pull Request 259 | 260 | ## Contributors 261 | 262 | A special thanks to everyone who maintains and helps out on the project! 263 | 264 | - Aaron Chambers 265 | - Aaron Ortbals 266 | - Aaron Renner 267 | - Adriaan 268 | - Adriaan van Rossum 269 | - Bill Curtis 270 | - Brett Chalupa 271 | - Chris Santero 272 | - Donal Byrne 273 | - GabKlein 274 | - Gabriel Klein 275 | - John Griffin 276 | - Jonas Brusman 277 | - Jonathan Johnson 278 | - Jonathan Zempel 279 | - Jordan Morano 280 | - Juan Pablo Pinilla Ossa 281 | - Kori Roys 282 | - Matt McGinnis 283 | - Mayank Patel 284 | - Optimal Cadence 285 | - Peter Brown 286 | - Rob Guilfoyle 287 | - Ryan LeFevre 288 | - Tony Coconate 289 | - harianus 290 | - sbl 291 | 292 | _Generated with: `git log --format='%aN' | sort -u`._ 293 | -------------------------------------------------------------------------------- /app.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Ember CLI Application", 3 | "description": "Ready for your Ember CLI application with the Ember CLI Buildpack set up", 4 | "repository": "https://github.com/tonycoco/heroku-buildpack-ember-cli", 5 | "logo": "http://emberjs.com/images/logos/ember-logo.png", 6 | "keywords": ["ember", "ember.js", "ember-cli"], 7 | "env": { 8 | "BUILDPACK_URL": "https://github.com/tonycoco/heroku-buildpack-ember-cli.git" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /bin/boot.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ruby $HOME/config/htpasswd.rb 4 | erb $HOME/config/nginx.conf.erb > $HOME/config/nginx.conf 5 | 6 | mkdir -p $HOME/logs/nginx 7 | touch $HOME/logs/nginx/access.log $HOME/logs/nginx/error.log 8 | 9 | (tail -f -n 0 $HOME/logs/nginx/*.log &) 10 | 11 | exec $HOME/vendor/nginx/sbin/nginx -p $HOME -c $HOME/config/nginx.conf 12 | -------------------------------------------------------------------------------- /bin/common.sh: -------------------------------------------------------------------------------- 1 | error() { 2 | echo " ! $*" >&2 3 | exit 1 4 | } 5 | 6 | status() { 7 | echo "-----> $*" 8 | } 9 | 10 | protip() { 11 | echo 12 | echo "PRO TIP: $*" | indent 13 | echo "See https://devcenter.heroku.com/articles/nodejs-support" | indent 14 | echo 15 | } 16 | 17 | # sed -l basically makes sed replace and buffer through stdin to stdout 18 | # so you get updates while the command runs and dont wait for the end 19 | # e.g. npm install | indent 20 | indent() { 21 | c='s/^/ /' 22 | case $(uname) in 23 | Darwin) sed -l "$c";; # mac/bsd sed: -l buffers on line boundaries 24 | *) sed -u "$c";; # unix/gnu sed: -u unbuffered (arbitrary) chunks of data 25 | esac 26 | } 27 | 28 | cat_npm_debug_log() { 29 | test -f $build_dir/npm-debug.log && cat $build_dir/npm-debug.log 30 | } 31 | 32 | export_env_dir() { 33 | env_dir=$1 34 | whitelist_regex=${2:-''} 35 | blacklist_regex=${3:-'^(PATH|GIT_DIR|CPATH|CPPATH|LD_PRELOAD|LIBRARY_PATH)$'} 36 | if [ -d "$env_dir" ]; then 37 | for e in $(ls $env_dir); do 38 | echo "$e" | grep -E "$whitelist_regex" | grep -qvE "$blacklist_regex" && 39 | export "$e=$(cat $env_dir/$e)" 40 | : 41 | done 42 | fi 43 | } 44 | 45 | needs_resolution() { 46 | local semver=$1 47 | if ! [[ "$semver" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then 48 | return 0 49 | else 50 | return 1 51 | fi 52 | } 53 | 54 | -------------------------------------------------------------------------------- /bin/compile: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e # fail fast 4 | set -o pipefail # don't ignore exit codes when piping output 5 | # set -x # enable debugging 6 | 7 | build_dir=$1 8 | cache_dir=$2 9 | env_dir=$3 10 | bp_dir=$(cd $(dirname $0); cd ..; pwd) 11 | 12 | # Fix leak 13 | unset GIT_DIR 14 | # Load some convenience functions like status(), echo(), and indent() 15 | source $bp_dir/bin/common.sh 16 | # Load functions for yarn compatibility 17 | source $bp_dir/bin/yarn.sh 18 | 19 | status "Exporting config vars to environment" 20 | export_env_dir $env_dir 21 | 22 | if [ "$BUILD_DEBUG" == "true" ]; then 23 | status "Enable debugging" 24 | set -x 25 | fi 26 | 27 | build_env=${EMBER_ENV:-production} 28 | status "Building environment: $build_env" 29 | 30 | mkdir -p $build_dir/vendor 31 | 32 | # Output npm debug info on error 33 | trap cat_npm_debug_log ERR 34 | 35 | # Look in package.json's engines.node field for a semver range 36 | semver_range=$($bp_dir/vendor/jq -r .engines.node $build_dir/package.json) 37 | 38 | # Resolve node version using semver.io 39 | node_version=$(curl --silent --get --data-urlencode "range=${semver_range}" https://semver.io/node/resolve) 40 | 41 | # Recommend using semver ranges in a safe manner 42 | if [ "$semver_range" == "null" ]; then 43 | protip "Specify a node version in package.json" 44 | semver_range="" 45 | elif [ "$semver_range" == "*" ]; then 46 | protip "Avoid using semver ranges like '*' in engines.node" 47 | elif [ ${semver_range:0:1} == ">" ]; then 48 | protip "Avoid using semver ranges starting with '>' in engines.node" 49 | fi 50 | 51 | # Output info about requested range and resolved node version 52 | if [ "$semver_range" == "" ]; then 53 | status "Defaulting to latest stable node: $node_version" 54 | else 55 | status "Requested node range: $semver_range" 56 | status "Resolved node version: $node_version" 57 | fi 58 | 59 | # Download node from Heroku's S3 mirror of nodejs.org/dist 60 | status "Downloading and installing node" 61 | node_url="http://s3pository.heroku.com/node/v$node_version/node-v$node_version-linux-x64.tar.gz" 62 | curl $node_url -s -o - | tar xzf - -C $build_dir 63 | 64 | # Move node (and npm) into ./vendor and make them executable 65 | mkdir -p $build_dir/vendor 66 | mv $build_dir/node-v$node_version-linux-x64 $build_dir/vendor/node 67 | chmod +x $build_dir/vendor/node/bin/* 68 | PATH=$build_dir/vendor/node/bin:$PATH 69 | 70 | # Optionally bootstrap a different npm version 71 | npm_engine=$($bp_dir/vendor/jq -r .engines.npm $build_dir/package.json) 72 | 73 | if [ "$npm_engine" != "null" ]; then 74 | if ! [[ "$npm_engine" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then 75 | status "Resolving npm version ${npm_engine} via semver.io..." 76 | npm_engine=$(curl --silent --get --data-urlencode "range=${npm_engine}" https://semver.herokuapp.com/npm/resolve) 77 | fi 78 | if [[ `npm --version` == "$npm_engine" ]]; then 79 | status "npm `npm --version` already installed with node" 80 | else 81 | status "Downloading and installing npm $npm_engine (replacing version `npm --version`)..." 82 | npm install --unsafe-perm --quiet -g npm@$npm_engine 2>&1 >/dev/null | indent 83 | fi 84 | if [ "${npm_engine:0:1}" -lt "2" ]; then 85 | latest_npm=$(curl --silent --get https://semver.herokuapp.com/npm/stable) 86 | protip "This version of npm ($npm_engine) has several known issues - consider upgrading to the latest release ($latest_npm)" 87 | fi 88 | else 89 | status "Using default npm version: `npm --version`" 90 | fi 91 | 92 | status "Downloading and installing nginx" 93 | nginx_url=${NGINX_URL:-https://s3.amazonaws.com/devmynd-github/heroku-nginx-1.6.0.tar.gz} 94 | curl $nginx_url -s -o - | tar xzf - -C $build_dir/vendor 95 | 96 | status "Adding boot script" 97 | cp $bp_dir/bin/boot.sh $build_dir 98 | 99 | status "Copying configs" 100 | mkdir -p $build_dir/config 101 | cp $bp_dir/config/htpasswd.rb $build_dir/config 102 | cp $bp_dir/config/mime.types $build_dir/config 103 | 104 | if [[ ! -f $build_dir/config/nginx.conf.erb ]]; then 105 | cp $bp_dir/config/nginx.conf.erb $build_dir/config 106 | else 107 | status "Custom nginx config found" 108 | fi 109 | 110 | cd $build_dir 111 | 112 | if [ "$REBUILD_ALL" == "true" ] || [ "$REBUILD_NODE_PACKAGES" == "true" ]; then 113 | status "Forcing rebuild of all node_modules. Pruning all node_modules." 114 | rm -rf $build_dir/node_modules $cache_dir/node_modules 115 | fi 116 | 117 | if [ "$REBUILD_ALL" == "true" ] || [ "$REBUILD_BOWER_PACKAGES" == "true" ]; then 118 | status "Forcing re-installation of all bower_components. Pruning all bower_components." 119 | rm -rf $build_dir/bower_components $cache_dir/bower_components 120 | fi 121 | 122 | # If node_modules directory is checked into source control then 123 | # rebuild any native deps. Otherwise, restore from the build cache. 124 | if test -d $build_dir/node_modules; then 125 | status "Found existing node_modules directory; skipping cache" 126 | status "Rebuilding any native dependencies" 127 | npm rebuild 2>&1 | indent 128 | else 129 | if test -d $cache_dir/node_modules; then 130 | status "Restoring node_modules directory from cache" 131 | else 132 | status "Creating node_modules cache directory" 133 | mkdir -p $cache_dir/node_modules 134 | fi 135 | 136 | ln -s $cache_dir/node_modules $build_dir/node_modules 137 | 138 | if test -f $cache_dir/.heroku/node-version && [ $(cat $cache_dir/.heroku/node-version) != "$node_version" ]; then 139 | status "Node version changed since last build; rebuilding dependencies" 140 | npm rebuild 2>&1 | indent 141 | fi 142 | fi 143 | 144 | # Restore bower_components from cache if it exists 145 | if test -d $build_dir/bower_components; then 146 | status "Found existing bower_components directory; skipping cache" 147 | else 148 | if test -d $cache_dir/bower_components; then 149 | status "Restoring bower_components directory from cache" 150 | else 151 | status "Creating bower_components cache directory" 152 | mkdir -p $cache_dir/bower_components 153 | fi 154 | 155 | ln -s $cache_dir/bower_components $build_dir/bower_components 156 | fi 157 | 158 | 159 | if [ "$GIT_SSH_KEY" != "" ]; then 160 | status "Detected SSH key for git. launching ssh-agent and loading key" 161 | echo $GIT_SSH_KEY | base64 --decode > id_rsa 162 | # launch ssh-agent, we'll use it to serve our ssh key 163 | # and kill it towards the end of the buildpack's run 164 | eval `ssh-agent -s` 165 | # ssh-add doesn't like the default 644 166 | chmod 600 id_rsa 167 | # We're not supporting passphrases at this time. We could pull that in 168 | # from config as well, but then we'd have to setup expect or some other 169 | # terminal automation tool to feed it into ssh-add. 170 | ssh-add id_rsa 171 | rm id_rsa 172 | # Add github to the list of known hosts - ignore the warning or else set -e will abort the deployment 173 | ssh -oStrictHostKeyChecking=no -T git@github.com || true 174 | fi 175 | 176 | status "Pruning cached dependencies not specified in package.json" 177 | npm prune 2>&1 | indent 178 | 179 | status "Installing dependencies" 180 | 181 | 182 | [ -f "$build_dir/bower.json" ] && use_bower=true || use_bower=false 183 | # we install bower before "yarn install", because a common practice is to have 184 | # a "postinstall": "bower install" step in package.json which would get run 185 | # after "yarn install" 186 | if $use_bower; then 187 | status "Detected bower.json" 188 | 189 | PATH=$build_dir/node_modules/.bin:$PATH 190 | 191 | if type bower > /dev/null 2>&1 || test -e $build_dir/node_modules/bower/bin/bower; then 192 | status "Bower already exists" 193 | else 194 | status "Installing bower which is required by other dependencies" 195 | npm install bower --save-dev --quiet --no-optional --userconfig $build_dir/.npmrc 2>&1 | indent 196 | fi 197 | fi 198 | 199 | if [ -f "$build_dir/yarn.lock" ]; then 200 | status "Detected yarn.lock, installing yarn" 201 | 202 | install_yarn 203 | 204 | echo "Installing node modules using yarn" 205 | cd $build_dir 206 | yarn install --pure-lockfile --ignore-engines 2>&1 207 | else 208 | status "Installing node modules using npm" 209 | 210 | # Make npm output to STDOUT instead of its default STDERR 211 | npm install --quiet --no-optional --userconfig $build_dir/.npmrc 2>&1 | indent 212 | fi 213 | 214 | if $use_bower; then 215 | PATH=$build_dir/node_modules/bower/bin:$PATH 216 | 217 | status "Pruning cached bower dependencies not specified in bower.json" 218 | bower prune 2>&1 | indent 219 | 220 | bower install --quiet | indent 221 | fi 222 | 223 | # Add the project's and ember-cli's dependencies' binaries to the PATH 224 | PATH=$build_dir/node_modules/.bin:$build_dir/node_modules/ember-cli/node_modules/.bin:$PATH 225 | 226 | # Persist goodies like node-version in the slug 227 | mkdir -p $build_dir/.heroku 228 | # Save resolved node version in the slug for later reference 229 | echo $node_version > $build_dir/.heroku/node-version 230 | # Copy goodies to the cache 231 | cp -r $build_dir/.heroku $cache_dir/ 232 | 233 | status "Cleaning up node-gyp and npm artifacts" 234 | rm -rf "$build_dir/.node-gyp" 235 | rm -rf "$build_dir/.npm" 236 | 237 | if [ "$GIT_SSH_KEY" != "" ]; then 238 | # Now that npm & bower have finished running, we should not need the ssh key anymore. Kill ssh-agent 239 | eval `ssh-agent -k` 240 | # Clear that sensitive key data from the environment 241 | export GIT_SSH_KEY=0 242 | fi 243 | 244 | if test -f $build_dir/hooks/before_hook.sh; then 245 | status "Before hook detected. Running..." 246 | source $build_dir/hooks/before_hook.sh 247 | fi 248 | 249 | status "Building Ember CLI application $build_env distribution" 250 | $build_dir/node_modules/ember-cli/bin/ember build --environment $build_env | indent 251 | 252 | if test -f $build_dir/hooks/after_hook.sh; then 253 | status "After hook detected. Running..." 254 | source $build_dir/hooks/after_hook.sh 255 | fi 256 | -------------------------------------------------------------------------------- /bin/detect: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # bin/detect 3 | 4 | if [ -f $1/package.json ]; then 5 | echo "Ember CLI" && exit 0 6 | else 7 | echo "no" && exit 1 8 | fi 9 | -------------------------------------------------------------------------------- /bin/release: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # bin/release 3 | 4 | cat <; 4 | 5 | events { 6 | use epoll; 7 | accept_mutex on; 8 | multi_accept on; 9 | worker_connections 1024; 10 | } 11 | 12 | http { 13 | gzip on; 14 | gzip_disable "MSIE [1-6]\.(?!.*SV1)"; 15 | gzip_comp_level 2; 16 | gzip_min_length 512; 17 | gzip_proxied any; 18 | gzip_vary on; 19 | gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript; 20 | 21 | server_tokens off; 22 | 23 | tcp_nopush on; 24 | tcp_nodelay on; 25 | 26 | log_format l2met "measure#nginx.service=$request_time request_id=$http_x_request_id"; 27 | access_log logs/nginx/access.log l2met; 28 | error_log logs/nginx/error.log; 29 | 30 | include mime.types; 31 | default_type application/octet-stream; 32 | sendfile on; 33 | 34 | <% if ENV["NAKED_DOMAIN"] && !ENV["NAKED_DOMAIN"].empty? %> 35 | server { 36 | listen <%= ENV["PORT"] %>; 37 | server_name <%= ENV["NAKED_DOMAIN"] %>; 38 | return 301 $scheme://www.<%= ENV["NAKED_DOMAIN"] %>$request_uri; 39 | } 40 | <% end %> 41 | 42 | server { 43 | <% if ENV["NAKED_DOMAIN"] && !ENV["NAKED_DOMAIN"].empty? %> 44 | server_name www.<%= ENV["NAKED_DOMAIN"] %>; 45 | <% else %> 46 | server_name _; 47 | <% end %> 48 | 49 | listen <%= ENV["PORT"] %>; 50 | keepalive_timeout 5; 51 | root dist; 52 | index index.html; 53 | port_in_redirect off; 54 | include <%= ENV["HOME"] %>/config/nginx.d/*.conf; 55 | 56 | <% if ENV["CLIENT_MAX_BODY_SIZE"] %> 57 | client_max_body_size <%= ENV["CLIENT_MAX_BODY_SIZE"] %>; 58 | <% end %> 59 | 60 | <% if ENV["FORCE_HTTPS"] && ENV["FORCE_HTTPS"] == "true" %> 61 | set $cloudflare NO; 62 | if ($http_cf_visitor ~* 'http') { 63 | set $cloudflare YES; 64 | } 65 | if ($http_cf_visitor ~* '"http"') { 66 | return 301 https://$host$request_uri; 67 | } 68 | set $cloudflare_heroku "${cloudflare}"; 69 | if ($http_x_forwarded_proto ~* 'http') { 70 | set $cloudflare_heroku "${cloudflare_heroku}YES"; 71 | } 72 | if ($http_x_forwarded_proto !~* 'https') { 73 | set $cloudflare_heroku "${cloudflare_heroku}HTTP"; 74 | } 75 | if ($cloudflare_heroku = NOYESHTTP) { 76 | return 301 https://$host$request_uri; 77 | } 78 | <% end %> 79 | 80 | <% if ENV["BASIC_AUTH_USER"] && ENV["BASIC_AUTH_PASSWORD"] %> 81 | auth_basic "Restricted"; 82 | auth_basic_user_file <%= "#{ENV["HOME"]}/config/htpasswd" %>; 83 | <% end %> 84 | 85 | <% if ENV["API_URL"] %> 86 | location <%= ENV["API_PREFIX_PATH"] || "/api/" %> { 87 | proxy_pass <%= ENV["API_URL"] %>; 88 | proxy_set_header Real-IP $remote_addr; 89 | proxy_set_header Forwarded-For $proxy_add_x_forwarded_for; 90 | proxy_set_header NginX-Proxy true; 91 | proxy_ssl_session_reuse off; 92 | proxy_redirect off; 93 | <% if ENV["NGINX_DEBUG"] %>add_header Ember-Cli-Proxy on;<% end %> 94 | } 95 | <% end %> 96 | 97 | <% if ENV["ACME_CHALLENGE"] %> 98 | location ^~ /.well-known/acme-challenge/ { 99 | return 200 '<%= ENV['ACME_CHALLENGE'] %>'; 100 | add_header Content-Type text/plain; 101 | } 102 | <% end %> 103 | 104 | <% if ENV["PRERENDER_HOST"] %> 105 | # Based on the official Prerender.io gist https://gist.github.com/thoop/8165802 106 | location @prerender { 107 | <% if ENV["PRERENDER_TOKEN"] %> 108 | proxy_set_header X-Prerender-Token <%= ENV["PRERENDER_TOKEN"] %>; 109 | <% end %> 110 | 111 | set $prerender 0; 112 | if ($http_user_agent ~* "baiduspider|twitterbot|facebookexternalhit|rogerbot|linkedinbot|embedly|quora link preview|showyoubot|outbrain|pinterest|slackbot|whatsapp") { 113 | set $prerender 1; 114 | } 115 | if ($args ~ "_escaped_fragment_") { 116 | set $prerender 1; 117 | } 118 | if ($http_user_agent ~ "Prerender") { 119 | set $prerender 0; 120 | } 121 | if ($uri ~ "\.(js|css|xml|less|png|jpg|jpeg|gif|pdf|doc|txt|ico|rss|zip|mp3|rar|exe|wmv|doc|avi|ppt|mpg|mpeg|tif|wav|mov|psd|ai|xls|mp4|m4a|swf|dat|dmg|iso|flv|m4v|torrent)") { 122 | set $prerender 0; 123 | } 124 | 125 | # Resolve using Google's DNS server to force DNS resolution and prevent caching of IPs 126 | resolver 8.8.8.8; 127 | 128 | if ($prerender = 1) { 129 | # Setting Prerender.io as a variable forces DNS resolution since Nginx caches IPs and doesn't play well with load balancing 130 | set $prerender <%= ENV["PRERENDER_HOST"] %>; 131 | 132 | <% if ENV["FORCE_HTTPS"] && ENV["FORCE_HTTPS"] == "true" %> 133 | rewrite .* /https://$host$request_uri? break; 134 | <% else %> 135 | rewrite .* /$scheme://$host$request_uri? break; 136 | <% end %> 137 | 138 | proxy_pass http://$prerender; 139 | } 140 | if ($prerender = 0) { 141 | rewrite .* /index.html break; 142 | } 143 | } 144 | <% end %> 145 | 146 | location ~* \index.html$ { 147 | expires -1; 148 | <% if ENV["NGINX_DEBUG"] %>add_header Ember-Cli-Html on;<% end %> 149 | } 150 | 151 | location ~* \.(ogg|ogv|svgz|mp4|css|rss|atom|js|jpg|jpeg|gif|png|ico|zip|tgz|gz|rar|bz2|doc|xls|exe|ppt|tar|mid|midi|wav|bmp|rtf|html|txt|htm)$ { 152 | expires max; 153 | log_not_found off; 154 | access_log off; 155 | add_header Cache-Control public; 156 | fastcgi_hide_header Set-Cookie; 157 | <% if ENV["NGINX_DEBUG"] %>add_header Ember-Cli-Speed on;<% end %> 158 | } 159 | 160 | location ~* \.(eot|oft|svg|ttf|woff)$ { 161 | add_header Access-Control-Allow-Origin *; 162 | expires max; 163 | log_not_found off; 164 | access_log off; 165 | add_header Cache-Control public; 166 | fastcgi_hide_header Set-Cookie; 167 | <% if ENV["NGINX_DEBUG"] %>add_header Ember-Cli-Font on;<% end %> 168 | } 169 | 170 | location ~ /\. { 171 | deny all; 172 | <% if ENV["NGINX_DEBUG"] %>add_header Ember-Cli-Denied on;<% end %> 173 | } 174 | 175 | location / { 176 | expires -1; 177 | 178 | <% if ENV["IP_WHITELIST"] %> 179 | set_real_ip_from 10.0.0.0/8; 180 | real_ip_header X-Forwarded-For; 181 | <% ENV["IP_WHITELIST"].split(",").each do |ip| %> 182 | allow <%= ip %>; 183 | <% end %> 184 | deny all; 185 | <% end %> 186 | <% if ENV["PRERENDER_HOST"] %> 187 | try_files $uri @prerender; 188 | <% else %> 189 | try_files $uri $uri/ /index.html =404; 190 | <% end %> 191 | 192 | <% if ENV["NGINX_DEBUG"] %>add_header Ember-Cli-Base-Location on;<% end %> 193 | } 194 | } 195 | } 196 | -------------------------------------------------------------------------------- /config/nginx.d/README.md: -------------------------------------------------------------------------------- 1 | # Extending NGINX configuration 2 | 3 | You can add snippets of NGINX configuration in this directory by creating files whose filenames end in `.conf`. These files will be included in the `server` section of the configuration, above the buildpack customisations. 4 | 5 | For example, if you need to use a reverse proxy to include a special `/admin` section of your site: 6 | 7 | ``` 8 | location /admin { 9 | proxy_pass https://my-app-admin.herokuapp.com/; 10 | proxy_set_header Real-IP $remote_addr; 11 | proxy_set_header Forwarded-For $proxy_add_x_forwarded_for; 12 | proxy_set_header NginX-Proxy true; 13 | proxy_ssl_session_reuse off; 14 | proxy_redirect off; 15 | } 16 | ``` 17 | -------------------------------------------------------------------------------- /vendor/jq: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tonycoco/heroku-buildpack-ember-cli/bba6e5cce944c44fc8c71bb8b7e0400bfd4a3ee0/vendor/jq --------------------------------------------------------------------------------