Skip to content

Commit 57ede39

Browse files
authored
Merge pull request #12 from weibeld/dev
Add optional loading of config variables as environment variables
2 parents e4aa4f0 + af474e6 commit 57ede39

3 files changed

Lines changed: 93 additions & 99 deletions

File tree

README.md

Lines changed: 37 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -4,68 +4,70 @@ Run custom commands during the build process.
44

55
## Description
66

7-
This buildpack allows to specify arbitrary commands that will be run in sequence during the build process.
7+
This buildpack allows specifying custom scripts or other commands that will be run during the build process. If any command exits with a non-zero status code, the build is aborted.
88

9-
If any command exits with a non-zero code, the build is aborted.
9+
## Usage
1010

11-
## Enable
11+
### Using the `buildpack-run.sh` script
1212

13-
Add the buildpack in addition to any other buildpacks:
13+
By default, the buildpack looks for a script named `buildpack-run.sh` in the root directory of your app. So, you can do the following:
1414

1515
```bash
16-
heroku buildpacks:add https://github.com/weibeld/heroku-buildpack-run
16+
echo -e '#!/bin/bash\necho "Hello World"' >buildpack-run.sh
17+
chmod +x buildpack-run.sh
18+
git add buildpack-run.sh && git commit
19+
git push heroku master
1720
```
1821

19-
Set the buildpack as the only buildpack:
20-
21-
```bash
22-
heroku buildpacks:set https://github.com/weibeld/heroku-buildpack-run
23-
```
22+
The above example will print `Hello World` during the build.
2423

25-
## Configure
24+
### Using the `BUILDPACK_RUN` config variable
2625

27-
The commands to run are specified in the `BUILDPACK_RUN` [config variable](https://devcenter.heroku.com/articles/config-vars) by using colons as delimiters.
26+
Alternatively to using `buildpack-run.sh`, you can specify custom commands in the `BUILDPACK_RUN` config variable:
2827

29-
A command can be anything from a user-provided shell script or binary to a native UNIX command. Commands may have arguments as well.
28+
```bash
29+
heroku config:set BUILDPACK_RUN='echo "Hello World"
30+
```
3031
31-
**All commands must be executable. That means, shell scripts must have a shebang line (`#!/bin/bash` or similar) and must have the executable bit set (run `chmod +x script.sh` on your local machine, then commit and push as usual).**
32+
The above example will print `Hello World` during the build.
3233
33-
### Example
34+
You can also specify multiple commands by separating them with colons:
3435
3536
```bash
36-
heroku config:set BUILDPACK_RUN='./script.sh:ls -l:bin/myexec foo bar'
37-
git push heroku master
37+
heroku config:set BUILDPACK_RUN='echo "Hello World":uname -a:./myscript.sh foo bar
3838
```
3939

40-
This causes the buildpack to run the following commands in sequence:
40+
In the above example, the buildpack will execute the following commands in sequence:
4141

42-
1. `./script.sh`
43-
2. `ls -l`
44-
3. `bin/myexec foo bar`
42+
1. `echo "Hello World"`
43+
1. `uname -a`
44+
1. `./myscript.sh foo bar`
4545

46-
Notes:
46+
## Loading config variables
4747

48-
- `./script.sh` is a user-provided shell script
49-
- `ls -l` refers to the native `ls` command on the build dyno
50-
- `bin/myexec` is a user-provided binary
48+
By default, the app's [config variables](https://devcenter.heroku.com/articles/config-vars) are only available as files in a specific directory in the build environment (see [`ENV_DIR`](#default-environment-variables) below). You can load all these config variables as environment variables by setting the `BUILDPACK_RUN_LOAD_CONFIG` config variable:
5149

52-
### Default value
50+
```bash
51+
heroku config:set BUILDPACK_RUN_LOAD_CONFIG=1
52+
```
5353

54-
If the `BUILDPACK_RUN` config variable is unset, then `./buildpack-run.sh` is used as the default command.
54+
Now, all the app's config variables will be available to your commands as environment variables.
5555

56-
So, if you want to run only a shell script, you can name it `buildpack-run.sh` and omit setting the `BUILDPACK_RUN` config variable.
56+
If you want to prevent certain config variables from being loaded as environment variables (for example, to prevent overwriting native environment variables), you can specify them in the `BUILDPACK_RUN_LOAD_CONFIG_SKIP` config variable (separated by colons):
5757

58-
_Don't forget to make the script executable by running `chmod +x buildpack-run.sh` on your local machine, then commit and push as usual._
58+
```bash
59+
heroku config:set BUILDPACK_RUN_LOAD_CONFIG_SKIP=FOO:BAR:BAZ
60+
```
5961

60-
## Environment variables
62+
In the above example, the config variables named `FOO`, `BAR`, and `BAZ` will _not_ be loaded as environment variables. Note that this may be especially useful for config variables like `PATH` that you might _not_ want to overwrite in the build environment.
6163

62-
The following special environment variables are available to your commands during the build:
64+
## Default environment variables
6365

64-
- `BUILD_DIR`: absolute path of your app's root directory on the build dyno
65-
- `CACHE_DIR`: cache directory that persists between builds
66-
- `ENV_DIR`: directory containing the values of all config variables in files
66+
The following special environment variables are always available to your commands:
6767

68-
`BUILD_DIR` corresponds to the working directory during the execution of the buildpack.
68+
- `BUILD_DIR`: your app's root directory in the build environment
69+
- `CACHE_DIR`: directory that persists between builds and can be used as a cache
70+
- `ENV_DIR`: directory containing the app's config variables as files
6971

7072
## License
7173

bin/compile

Lines changed: 50 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1,77 +1,72 @@
11
#!/usr/bin/env bash
22
#
3-
# This buildpacks allows to run custom commands on the build dyno.
4-
#
5-
# Example:
6-
# heroku config:set BUILDPACK_RUN='./myexec-1:ls -l:bin/myexec-2 foo bar'
7-
# git push heroku master
8-
#
9-
# The above example runs the following three commands during the build:
10-
# 1. ./myexec-1
11-
# 2. ls -l
12-
# 3. bin/myexec-2 foo bar
13-
#
14-
# Notes:
15-
# - If BUILDPACK_RUN is unset, then './buildpack-run.sh' is used by default
16-
# - All commands must be executable (i.e. the exec flag must be set)
17-
# - If any command exits with a non-zero code, the build is aborted
18-
#
19-
# ---
20-
#
213
# The 'compile' script is executed by the slug compiler with three arguments:
22-
# $1: build_dir, location of your app directory on the build dyno
23-
# $2: cache_dir, directory on the build dyno that persists between builds
24-
# $3: env_dir, directory holding all the app's config vars as files
4+
#
5+
# - $1: build_dir, location of your app directory on the build dyno
6+
# - $2: cache_dir, directory on the build dyno that persists between builds
7+
# - $3: env_dir, directory holding all the app's config vars as files
258
#
269
# More information here: https://devcenter.heroku.com/articles/buildpack-api
2710
#------------------------------------------------------------------------------#
2811

29-
# Indent stdin
30-
i() { sed 's/^/ /'; }
31-
a() { sed 's/^/-----> /'; }
32-
I() { sed "s/^/$(printf '\033')[31m /;s/$/$(printf '\033')[0m/"; }
33-
A() { sed "s/^/$(printf '\033')[31m-----> /;s/$/$(printf '\033')[0m/"; }
34-
12+
# Indentation
13+
indent() { sed 's/^/ /'; }
14+
arrow() { sed 's/^/-----> /'; }
15+
indent-err() { sed "s/^/$(printf '\033')[31m /;s/$/$(printf '\033')[0m/"; }
16+
arrow-err() { sed "s/^/$(printf '\033')[31m-----> /;s/$/$(printf '\033')[0m/"; }
3517

36-
# These environment variables can be accessed from the user-supplied commands
18+
# Default enviroment variables
3719
export BUILD_DIR=$1
3820
export CACHE_DIR=$2
3921
export ENV_DIR=$3
4022

4123
cd "$BUILD_DIR"
4224

43-
# Extract commands from BUILDPACK_RUN config variable
25+
# If BUILDPACK_RUN_LOAD_CONFIG is set, create env vars for all of the app's
26+
# config vars (except thos specified in BUILDPACK_RUN_LOAD_CONFIG_SKIP). The
27+
# env vars are not created immediately, but the commands to create them are
28+
# written to a file, which is then sourced before the user-supplied commands
29+
# are executed (this is to prevent name clashes between the config vars and
30+
# env vars used by this script).
31+
BUILDPACK_RUN_CONFIG_FILE=$(mktemp)
32+
if [[ -f "$ENV_DIR/BUILDPACK_RUN_LOAD_CONFIG" ]]; then
33+
echo "Loading config vars into environment" | arrow
34+
skip='^()$'
35+
if [[ -f "$ENV_DIR/BUILDPACK_RUN_LOAD_CONFIG_SKIP" ]]; then
36+
skip="^($(tr ':' '|' <"$ENV_DIR/BUILDPACK_RUN_LOAD_CONFIG_SKIP"))$"
37+
echo "(except: $(cat "$ENV_DIR/BUILDPACK_RUN_LOAD_CONFIG_SKIP"))" | indent
38+
fi
39+
shopt -s nullglob
40+
for f in "$ENV_DIR"/*; do
41+
if ! grep -qE "$skip" <<<$(basename "$f"); then
42+
echo "export $(basename "$f")=\$(cat "$f")" >>"$BUILDPACK_RUN_CONFIG_FILE"
43+
fi
44+
done
45+
fi
46+
47+
# Extract commands from BUILDPACK_RUN config var
4448
if [[ -f "$ENV_DIR/BUILDPACK_RUN" ]]; then
45-
COMMANDS=$(cat "$ENV_DIR/BUILDPACK_RUN")
46-
elif [[ -f ./buildpack-run.sh ]]; then
47-
COMMANDS=./buildpack-run.sh
49+
BUILDPACK_RUN_COMMANDS=$(cat "$ENV_DIR/BUILDPACK_RUN")
50+
elif [[ -f buildpack-run.sh ]]; then
51+
BUILDPACK_RUN_COMMANDS=./buildpack-run.sh
4852
else
49-
echo "Error: can't apply buildpack." | A
50-
echo "You must specify one ore more colon-delimited commands in" | I
51-
echo "BUILDPACK_RUN or use the default file ./buildpack-run.sh." | I
52-
echo "See https://github.com/weibeld/heroku-buildpack-run#configure." | I
53-
echo
53+
echo "Error: can't apply buildpack" | arrow-err
54+
cat <<EOF | indent-err
55+
You must either create an executable script named buildpack-run.sh
56+
in the root directory of your app, or specify one or more commands
57+
to execute in the BUILDPACK_RUN config variable (colon-delimited).
58+
See https://github.com/weibeld/heroku-buildpack-run#configure
59+
EOF
5460
exit 1
5561
fi
56-
IFS=':' COMMANDS=($COMMANDS)
62+
IFS=':' BUILDPACK_RUN_COMMANDS=($BUILDPACK_RUN_COMMANDS)
5763

5864
# Run commands
59-
for c in ${COMMANDS[@]}; do
60-
# Test if local file is executable (breaking change from previous version)
61-
file=$(echo "$c" | cut -f 1 -d " ")
62-
if [[ -f "$file" && ! -x "$file" ]]; then
63-
echo "Error: $file is not executable." | A
64-
echo "Make it executable by running 'chmod +x $file'" | I
65-
echo "on your local machine, then commit and push as usual." | I
65+
for BUILDPACK_RUN_CMD in ${BUILDPACK_RUN_COMMANDS[@]}; do
66+
echo "Running: $BUILDPACK_RUN_CMD" | arrow
67+
. "$BUILDPACK_RUN_CONFIG_FILE"
68+
eval "$BUILDPACK_RUN_CMD" || {
69+
echo "Aborting: '$BUILDPACK_RUN_CMD' exited with exit code $?" | arrow-err
6670
exit 1
67-
fi
68-
echo "Running: $c" | a
69-
eval "$c"
70-
EXIT_CODE=$?
71-
if [[ "$EXIT_CODE" != 0 ]]; then
72-
echo "Aborting build because '$c' exited with a non-zero code ($EXIT_CODE)" | A
73-
exit 1
74-
fi
71+
}
7572
done
76-
77-
exit 0

bin/detect

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,16 @@
33
# Detect if the buildpack can be applied to the app. In this case, it is always
44
# true, as the check is made in the 'compile' script.
55
#
6-
# ---
7-
#
86
# The 'detect' script is executed by the slug compiler with one argument:
9-
# $1: build_dir, location of your app directory on the build dyno
107
#
11-
# If 'detect' exits with status code 0:
12-
# stdout is inserted in "-----> <X> app detected" and 'compile' script is run
13-
# If 'detect' exits with status code != 0:
14-
# the buildpack is not used
8+
# - $1: build_dir, location of your app directory on the build dyno
159
#
16-
# More information here: https://devcenter.heroku.com/articles/buildpack-api
10+
# If 'detect' exits with status code 0: stdout is inserted in "-----> <X> app
11+
# detected" and 'compile' script is run
1712
#
18-
# Daniel Weibel <daniel@weibeld.net> March 2015 - April 2018
13+
# If 'detect' exits with status code != 0: the buildpack is not used
14+
#
15+
# More information here: https://devcenter.heroku.com/articles/buildpack-api
1916
#------------------------------------------------------------------------------#
2017

2118
echo "Run"

0 commit comments

Comments
 (0)