├── .editorconfig ├── LICENSE ├── README.md ├── bin ├── compile └── detect ├── buildpack.toml └── lib ├── dependencies.sh ├── environment.sh └── output.sh /.editorconfig: -------------------------------------------------------------------------------- 1 | # Editor configuration, see http://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | indent_style = tab 7 | indent_size = 4 8 | end_of_line = lf 9 | insert_final_newline = true 10 | trim_trailing_whitespace = true 11 | 12 | [*.md] 13 | trim_trailing_whitespace = false 14 | indent_style = space 15 | indent_size = 4 16 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Carloluis Rodríguez 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Heroku Buildpack for Node.js Build 2 | 3 | > Buildpack for Node.js apps with a build step defined on the package.json 4 | 5 | [![GitHub license](https://img.shields.io/github/license/carloluis/heroku-bp-node-build.svg)](https://github.com/carloluis/heroku-bp-node-build/blob/master/LICENSE) 6 | [![GitHub release](https://img.shields.io/github/release/carloluis/heroku-bp-node-build.svg)](https://github.com/carloluis/heroku-bp-node-build/releases) 7 | 8 | ## How it works? 9 | 10 | Inspect for a `package.json` file and a _build_ task defined within the _scripts_ section. 11 | 12 | ## Configure from `CLI` 13 | 14 | Use after nodejs buildpack: 15 | 16 | ```bash 17 | # create the app with nodejs buildpack 18 | heroku create my-app --buildpack heroku/nodejs 19 | 20 | # add heroku-bp-node-build 21 | heroku buildpacks:add --index 2 https://github.com/carloluis/heroku-bp-node-build 22 | ``` 23 | 24 | ## Configure from _app.json_ manifest: 25 | 26 | ```json 27 | { 28 | "buildpacks": [ 29 | { 30 | "url": "heroku/nodejs" 31 | }, 32 | { 33 | "url": "https://github.com/carloluis/heroku-bp-node-build" 34 | } 35 | ] 36 | } 37 | ``` 38 | 39 | ## Locking to a buildpack version 40 | 41 | Lock your buildpack to one specific version: 42 | * First, find the version you want from [buildpack versions](https://github.com/carloluis/heroku-bp-node-build/releases). 43 | * Then, specify that version with `buildpacks:set` 44 | 45 | ```bash 46 | heroku buildpacks:set https://github.com/carloluis/heroku-bp-node-build#v0.1.0 -a my-app 47 | ``` 48 | 49 | ## More 50 | 51 | Read related info with buildpacks [here](https://devcenter.heroku.com/articles/buildpacks). 52 | 53 |
54 | Buildpack Registry 55 | 56 | This buildpack is available as `carloluis/node-build` on the [Heroku Buildpack Registry](https://devcenter.heroku.com/articles/buildpack-registry). 57 | 58 |
59 | 60 | ## License 61 | 62 | MIT © [Carloluis](https://github.com/carloluis) 63 | -------------------------------------------------------------------------------- /bin/compile: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # bin/compile 3 | 4 | ### Configure environment 5 | set -o errexit 6 | set -o pipefail 7 | 8 | ### Configure directories 9 | 10 | readonly BUILD_DIR="${1:-}" 11 | readonly CACHE_DIR="${2:-}" 12 | readonly ENV_DIR="${3:-}" 13 | 14 | readonly BP_DIR=$(cd "$(dirname "${0:-}")"; cd ..; pwd) 15 | 16 | ### Load dependencies 17 | 18 | # shellcheck source=$BP_DIR/lib/output.sh 19 | source "$BP_DIR"/lib/output.sh 20 | # shellcheck source=$BP_DIR/lib/environment.sh 21 | source "$BP_DIR"/lib/environment.sh 22 | # shellcheck source=$BP_DIR/lib/dependencies.sh 23 | source "$BP_DIR"/lib/dependencies.sh 24 | 25 | ### Runtime environment 26 | 27 | header "runtime environment" 28 | 29 | # can't pipe this because piping causes subshells, preventing exports 30 | export_env_dir "$ENV_DIR" 31 | 32 | ### Check initial state 33 | 34 | [[ -d "$BUILD_DIR/node_modules" ]] && PREBUILD=true || PREBUILD=false 35 | [[ -f "$BUILD_DIR/yarn.lock" ]] && YARN=true || YARN=false 36 | 37 | ### Set up development 38 | 39 | header "set up development" 40 | 41 | _NPM_CONFIG_PRODUCTION_="${NPM_CONFIG_PRODUCTION:-true}" 42 | _NODE_ENV_="${NODE_ENV:-production}" 43 | 44 | info "------ previous config.: ------" 45 | info "NPM_CONFIG_PRODUCTION=${_NPM_CONFIG_PRODUCTION_}" 46 | info "NODE_ENV=${_NODE_ENV_}" 47 | 48 | export NPM_CONFIG_PRODUCTION=false 49 | export NODE_ENV='development' 50 | 51 | ### Restore /node_modules/ 52 | 53 | function restore_dependencies() { 54 | header "restore dependencies..." 55 | 56 | # save root project dependencies 57 | $PREBUILD && mv "$BUILD_DIR/node_modules" "$BUILD_DIR/.node_modules" 58 | 59 | # check subdirectories (first level) -> save dependencies copy for subprojects 60 | save_subprojects_dependencies "$BUILD_DIR" 61 | 62 | # install dependencies... 63 | if $YARN; then 64 | yarn_node_modules "$BUILD_DIR" | indent 65 | else 66 | npm_node_modules "$BUILD_DIR" | indent 67 | fi 68 | 69 | # check for dependencies in subprojects... 70 | check_subproject_dependencies "$BUILD_DIR" 71 | } 72 | 73 | restore_dependencies 74 | 75 | ### Build-step 76 | 77 | function build_step() { 78 | header "build step..." 79 | 80 | cd "$BUILD_DIR" 81 | 82 | info "set NODE_ENV=production" 83 | export NODE_ENV=production 84 | 85 | # execute build step 86 | info "npm run build" 87 | npm run build 88 | 89 | rm -r "$BUILD_DIR/node_modules" 2>/dev/null || true 90 | [[ -d "$BUILD_DIR/.node_modules" ]] && mv "$BUILD_DIR/.node_modules" "$BUILD_DIR/node_modules" 91 | 92 | # restore subprojects dependencies to initial state 93 | restore_subprojects "$BUILD_DIR" 94 | } 95 | 96 | build_step 97 | 98 | ### Restore environmet 99 | 100 | info "restore environment" 101 | 102 | export NPM_CONFIG_PRODUCTION="$_NPM_CONFIG_PRODUCTION_" 103 | export NODE_ENV="$_NODE_ENV_" 104 | 105 | header "build succeeded!" 106 | -------------------------------------------------------------------------------- /bin/detect: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # bin/detect 3 | 4 | if [[ $(cat "$1/package.json" | grep '"build"') ]]; then 5 | echo "heroku-bp-node-build" 6 | exit 0 7 | else 8 | exit 1 9 | fi 10 | -------------------------------------------------------------------------------- /buildpack.toml: -------------------------------------------------------------------------------- 1 | [buildpack] 2 | name = "node-build" 3 | 4 | [publish.Ignore] 5 | files = [ 6 | ".editorconfig", 7 | ".gitignore" 8 | ] 9 | -------------------------------------------------------------------------------- /lib/dependencies.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | function yarn_node_modules() { 4 | local build_dir="${1:-}" 5 | echo "yarn install" 6 | cd "$build_dir" 7 | yarn install --pure-lockfile --ignore-engines 2>&1 8 | } 9 | 10 | function npm_node_modules() { 11 | local build_dir="${1:-}" 12 | if [ -e "$build_dir"/package.json ]; then 13 | echo "npm install" 14 | cd "$build_dir" 15 | npm install --unsafe-perm --userconfig "$build_dir"/.npmrc 2>&1 16 | else 17 | echo "Skipping (no package.json)" 18 | fi 19 | } 20 | 21 | function save_subprojects_dependencies() { 22 | local build_dir="${1:-}" 23 | 24 | for file in "$build_dir/"*; do 25 | if [[ -d "$file" && -f "$file/package.json" ]]; then 26 | if [[ -d "$file/node_modules" ]]; then 27 | mv "$file/node_modules" "$file/.node_modules" 28 | fi 29 | fi 30 | done 31 | } 32 | 33 | function check_subproject_dependencies() { 34 | local build_dir="${1:-}" 35 | 36 | for file in "$build_dir/"*; do 37 | if [[ -d "$file" && -d "$file/.node_modules" ]]; then 38 | if [[ ! -d "$file/node_modules" ]]; then 39 | mv "$file/.node_modules" "$file/node_modules" 40 | fi 41 | fi 42 | done 43 | } 44 | 45 | function restore_subprojects() { 46 | local build_dir="${1:-}" 47 | 48 | for file in "$build_dir/"*; do 49 | if [[ -d "$file" && -d "$file/.node_modules" ]]; then 50 | rm -r "$file/node_modules" 2>/dev/null || true 51 | mv "$file/.node_modules" "$file/node_modules" 52 | fi 53 | done 54 | } 55 | -------------------------------------------------------------------------------- /lib/environment.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | function export_env_dir() { 4 | local env_dir="$1" 5 | local blacklist_regex="${2:-'^(PATH|GIT_DIR|CPATH|CPPATH|LD_PRELOAD|LIBRARY_PATH|LANG)$'}" 6 | 7 | if [[ -d "$env_dir" ]]; then 8 | for e in $(ls "$env_dir"); do 9 | echo " $e=$(cat $env_dir/$e)" 10 | echo "$e" | grep -qvE "$blacklist_regex" && export "$e=$(cat $env_dir/$e)" 11 | : 12 | done 13 | fi 14 | } 15 | -------------------------------------------------------------------------------- /lib/output.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | function info() { 4 | echo " $*" || true 5 | } 6 | 7 | function header() { 8 | echo "" || true 9 | echo "-----> $*" || true 10 | } 11 | 12 | function indent() { 13 | sed -u 's/^/ /' 14 | } 15 | 16 | function print() { 17 | echo "$*" | indent 18 | } 19 | --------------------------------------------------------------------------------