Skip to content

Commit 838f4c1

Browse files
authored
Simplify binary build process and documentation (#1083)
* Moves all manual build steps to make targets, to simplify the commands run, and reduce chance for error. * Removes the need to remember to rebuild the builder image by building it automatically prior to launching. * Adds a new make target for deploying multiple runtime versions at once to speed up the common case. * Reduces repetition/superfluous content in documentation. * Removes unused `S3_REGION` from `dockerenv.default` (the contents of S3 buckets inherit the region of the bucket). * Documents build dependencies in `requirements.txt`. Closes @W-8119717@. [skip changelog]
1 parent 0020aae commit 838f4c1

File tree

4 files changed

+96
-59
lines changed

4 files changed

+96
-59
lines changed

Makefile

Lines changed: 31 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,18 @@
11
# These targets are not files
2-
.PHONY: check test buildenv-heroku-16 buildenv-heroku-18 tools
2+
.PHONY: check test builder-image buildenv deploy-runtimes tools
33

44
STACK ?= heroku-18
5+
STACKS ?= cedar-14 heroku-16 heroku-18
56
TEST_CMD ?= test/run-versions && test/run-features && test/run-deps
7+
ENV_FILE ?= builds/dockerenv.default
8+
BUILDER_IMAGE_PREFIX := heroku-python-build
69

710
ifeq ($(STACK),cedar-14)
811
# Cedar-14 doesn't have a build image varient.
9-
IMAGE_TAG := heroku/cedar:14
12+
STACK_IMAGE_TAG := heroku/cedar:14
1013
else
1114
# Converts a stack name of `heroku-NN` to its build Docker image tag of `heroku/heroku:NN-build`.
12-
IMAGE_TAG := heroku/$(subst -,:,$(STACK))-build
15+
STACK_IMAGE_TAG := heroku/$(subst -,:,$(STACK))-build
1316
endif
1417

1518
check:
@@ -19,35 +22,40 @@ check:
1922

2023
test:
2124
@echo "Running tests using: STACK=$(STACK) TEST_CMD='$(TEST_CMD)'"
22-
@echo ""
23-
@docker run --rm -it -v $(PWD):/buildpack:ro -e "STACK=$(STACK)" "$(IMAGE_TAG)" bash -c 'cp -r /buildpack /buildpack_test && cd /buildpack_test && $(TEST_CMD)'
24-
@echo ""
25-
26-
buildenv-heroku-16:
27-
@echo "Creating build environment (heroku-16)..."
2825
@echo
29-
@docker build --pull -f $(shell pwd)/builds/heroku-16.Dockerfile -t python-buildenv-heroku-16 .
26+
@docker run --rm -it -v $(PWD):/buildpack:ro -e "STACK=$(STACK)" "$(STACK_IMAGE_TAG)" bash -c 'cp -r /buildpack /buildpack_test && cd /buildpack_test && $(TEST_CMD)'
3027
@echo
31-
@echo "Usage..."
28+
29+
builder-image:
30+
@echo "Generating binary builder image for $(STACK)..."
3231
@echo
33-
@echo " $$ export AWS_ACCESS_KEY_ID=foo AWS_SECRET_ACCESS_KEY=bar # Optional unless deploying"
34-
@echo " $$ bob build runtimes/python-2.7.13"
35-
@echo " $$ bob deploy runtimes/python-2.7.13"
32+
@docker build --pull -f builds/$(STACK).Dockerfile -t "$(BUILDER_IMAGE_PREFIX)-$(STACK)" .
3633
@echo
37-
@docker run -it --rm python-buildenv-heroku-16
3834

39-
buildenv-heroku-18:
40-
@echo "Creating build environment (heroku-18)..."
41-
@echo
42-
@docker build --pull -f $(shell pwd)/builds/heroku-18.Dockerfile -t python-buildenv-heroku-18 .
35+
buildenv: builder-image
36+
@echo "Starting build environment for $(STACK)..."
4337
@echo
4438
@echo "Usage..."
4539
@echo
46-
@echo " $$ export AWS_ACCESS_KEY_ID=foo AWS_SECRET_ACCESS_KEY=bar # Optional unless deploying"
47-
@echo " $$ bob build runtimes/python-2.7.13"
48-
@echo " $$ bob deploy runtimes/python-2.7.13"
40+
@echo " $$ bob build runtimes/python-X.Y.Z"
4941
@echo
50-
@docker run -it --rm python-buildenv-heroku-18
42+
@docker run --rm -it --env-file="$(ENV_FILE)" -v $(PWD)/builds:/app/builds "$(BUILDER_IMAGE_PREFIX)-$(STACK)" bash
43+
44+
deploy-runtimes:
45+
ifndef RUNTIMES
46+
$(error No runtimes specified! Use: "make deploy-runtimes RUNTIMES='python-X.Y.Z ...' [STACKS='heroku-18 ...'] [ENV_FILE=...]")
47+
endif
48+
@echo "Using: RUNTIMES='$(RUNTIMES)' STACKS='$(STACKS)' ENV_FILE='$(ENV_FILE)'"
49+
@echo
50+
@set -eu; for stack in $(STACKS); do \
51+
$(MAKE) builder-image STACK=$${stack}; \
52+
for runtime in $(RUNTIMES); do \
53+
echo "Generating/deploying $${runtime} for $${stack}..."; \
54+
echo; \
55+
docker run --rm -it --env-file="$(ENV_FILE)" "$(BUILDER_IMAGE_PREFIX)-$${stack}" bob deploy "runtimes/$${runtime}"; \
56+
echo; \
57+
done; \
58+
done
5159

5260
tools:
5361
git clone https://github.com/kennethreitz/pip-pop.git

builds/README.md

Lines changed: 55 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,57 +1,80 @@
11
# Python Buildpack Binaries
22

3-
## Building the Docker Images
3+
The binaries for this buildpack are built in Docker containers based on the Heroku stack image.
44

5-
**After every change to your formulae, perform the following** from the root of the Git repository (not from `builds/`) to rebuild the images for each stack:
6-
7-
$ docker build --pull --tag heroku-python-build-cedar-14 --file $(pwd)/builds/cedar-14.Dockerfile .
8-
$ docker build --pull --tag heroku-python-build-heroku-16 --file $(pwd)/builds/heroku-16.Dockerfile .
9-
$ docker build --pull --tag heroku-python-build-heroku-18 --file $(pwd)/builds/heroku-18.Dockerfile .
5+
## Configuration
106

11-
## Using the Image
7+
In order to publish binaries AWS credentials must be passed to the build container.
8+
If you are testing only the build (ie: `bob build`), these are optional.
129

13-
You can e.g. `bash` into each of the images you built using their tag:
10+
In addition, unless you are building the official binaries for Heroku (which use the defaults
11+
specified in each `Dockerfile`), you will need to override `S3_BUCKET` and `S3_PREFIX` to
12+
match your own S3 bucket/use case.
1413

15-
docker run --rm -ti heroku-python-build-cedar-14 bash
16-
docker run --rm -ti heroku-python-build-heroku-16 bash
17-
docker run --rm -ti heroku-python-build-heroku-18 bash
14+
If you only need to set AWS credentials, you can do so by setting the environment variables
15+
`AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` before calling the make commands.
1816

19-
You then have a shell where you can run `bob build`, `bob deploy`, and so forth. You can of course also invoke these programs directly with `docker run`:
17+
For example:
2018

21-
docker run --rm -ti heroku-python-build-heroku-18 bob build runtimes/python-2.7.15
19+
```bash
20+
set +o history # Disable bash history
21+
export AWS_ACCESS_KEY_ID=...
22+
export AWS_SECRET_ACCESS_KEY=...
23+
set -o history # Re-enable bash history
24+
make ...
25+
```
2226

23-
In order to `bob deploy`, AWS credentials must be set up, as well as name and prefix of your custom S3 bucket (unless you're deploying to the Heroku production buckets that are pre-defined in each `Dockerfile`); see next section for details.
27+
If you need to override the default S3 bucket, or would prefer not to use credentials via
28+
environment variables, then you need to instead use a Docker env file like so:
2429

25-
## Configuration
30+
1. Copy the `builds/dockerenv.default` env file to a location outside the buildpack repository.
31+
2. Edit the new file, adding at a minimum the values for the variables
32+
`AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` (see Docker
33+
[env-file documentation](https://docs.docker.com/engine/reference/commandline/run/#set-environment-variables--e---env---env-file)).
34+
3. Pass the path of the file to the make commands using `ENV_FILE`. For example:
2635

27-
File `dockerenv.default` contains a list of required env vars; most of these have default values defined in `Dockerfile`. You can copy this file to a location outside the buildpack and modify it with the values you desire and pass its location with `--env-file`, or pass the env vars to `docker run` using `--env`.
36+
```bash
37+
make ... ENV_FILE=~/.dockerenv.python-buildpack
38+
```
2839

29-
Out of the box, each `Dockerfile` has the correct values predefined for `S3_BUCKET`, `S3_PREFIX`, and `S3_REGION`. If you're building your own packages, you'll likely want to change `S3_BUCKET` and `S3_PREFIX` to match your info. Instead of setting `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` into that file, you may also pass them to `docker run` through the environment, or explicitly using `--env`, in order to prevent accidental commits of credentials.
40+
## Launching an interactive build environment
3041

31-
### Passing AWS credentials to the container
42+
To start an interactive version of the build environment (ideal for development) use the
43+
`buildenv` make target, passing in the desired `STACK` name. For example:
3244

33-
If you want to deploy packages and thus need to pass `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY`, you can either pass them explicitly, through your environment, or through an env file.
45+
```bash
46+
make buildenv STACK=heroku-18
47+
```
3448

35-
#### Passing credentials explicitly
49+
This will create the builder docker image based on the latest image for that stack, and
50+
then start a bash shell where you can run `bob build`, `bob deploy`, and so forth.
3651

37-
docker run --rm -ti -e AWS_ACCESS_KEY_ID=... -e AWS_SECRET_ACCESS_KEY=... heroku-python-build-heroku-18 bash
52+
The `builds/` directory is bind-mounted into the running container, so local build formula
53+
changes will appear there immediately without the need to rebuild the image.
3854

39-
#### Passing credentials through the environment
55+
## Bulk deploying runtimes
4056

41-
The two environment variables `AWS_ACCESS_KEY_ID`and `AWS_SECRET_ACCESS_KEY` are defined in `builds/dockerenv.default`, without values. This will cause Docker to "forward" values for these variables from the current environment, so you can pass them in:
57+
When a new Python version is released, binaries have to be generated for multiple stacks.
58+
To automate this, use the `deploy-runtimes` make target, which will ensure the builder
59+
image is up to date, and then run `bob deploy` for each runtime-stack combination.
4260

43-
AWS_ACCESS_KEY_ID=... AWS_SECRET_ACCESS_KEY=... docker run --rm -ti --env-file=builds/dockerenv.default heroku-python-build-heroku-18 bash
61+
The build formula name(s) are passed using `RUNTIMES`, like so:
4462

45-
or
63+
```bash
64+
make deploy-runtimes RUNTIMES='python-X.Y.Z'
65+
```
4666

47-
export AWS_ACCESS_KEY_ID=...
48-
export AWS_SECRET_ACCESS_KEY=...
49-
docker run --rm -ti --env-file=builds/dockerenv.default heroku-python-build-heroku-18 bash
67+
By default this will deploy to all supported stacks (see `STACKS` in `Makefile`),
68+
but this can be overridden using `STACKS`:
5069

51-
#### Passing credentials through a separate env file
70+
```bash
71+
make deploy-runtimes RUNTIMES='python-X.Y.Z' STACKS='heroku-16 heroku-18'
72+
```
5273

53-
This method is the easiest for users who want to build packages in their own S3 bucket, as they will have to adjust the `S3_BUCKET` and `S3_PREFIX` environment variable values anyway from their default values.
74+
Multiple runtimes can also be specified (useful for when adding a new stack), like so:
5475

55-
For this method, it is important to keep the credentials file in a location outside the buildpack, so that your credentials aren't accidentally committed. Copy `builds/dockerenv.default` **to a safe location outside the buildpack directory**, and insert your values for `AWS_ACCESS_KEY_ID`and `AWS_SECRET_ACCESS_KEY`.
76+
```bash
77+
make deploy-runtimes RUNTIMES='python-A.B.C python-X.Y.Z' STACKS='heroku-20'
78+
```
5679

57-
docker run --rm -ti --env-file=../SOMEPATHOUTSIDE/s3.env heroku-python-build-heroku-18 bash
80+
Note: Both `RUNTIMES` and `STACKS` are space delimited.

builds/dockerenv.default

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
1+
# Since no values are specified here, these variables will be read from the environment at run time:
2+
# https://docs.docker.com/engine/reference/commandline/run/#set-environment-variables--e---env---env-file
13
AWS_ACCESS_KEY_ID
24
AWS_SECRET_ACCESS_KEY
3-
S3_BUCKET
4-
S3_PREFIX
5-
S3_REGION
5+
6+
# Uncomment these if you need to override the default S3 bucket and/or path prefixes.
7+
# S3_BUCKET
8+
# S3_PREFIX

requirements.txt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1-
docopt==0.6.2
1+
# Dependencies for generating/publishing Python binaries.
22
bob-builder==0.0.18
3+
4+
# Sub-dependencies of bob-builder.
35
boto==2.49.0
6+
docopt==0.6.2

0 commit comments

Comments
 (0)