mirror of
https://github.com/kennethreitz/heroku-buildpack-python.git
synced 2026-06-05 23:10:16 +00:00
Compare commits
29 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| ac8fd555b8 | |||
| f825896c4e | |||
| fcf696b835 | |||
| a98ef91566 | |||
| e67235f906 | |||
| b1690e9f47 | |||
| b250300b74 | |||
| 096709dcf7 | |||
| ff8945c0c2 | |||
| 4e78b5d57c | |||
| b74a41395e | |||
| c550143a59 | |||
| 838f4c125b | |||
| 0020aae078 | |||
| 63651e042f | |||
| c0609a881c | |||
| ef4696a922 | |||
| 6c612a7fb1 | |||
| f91f4ee4ce | |||
| eea9a7fd0f | |||
| 215a3e3670 | |||
| 4505968fcb | |||
| 37d1474bee | |||
| 40167d83f6 | |||
| 64fb396b73 | |||
| eb6ee49dfe | |||
| 64abfb2978 | |||
| 12d1cbb3be | |||
| 7817aa3fc3 |
@@ -34,6 +34,10 @@ env:
|
|||||||
- STACK=heroku-18 TEST_CMD=test/run-deps
|
- STACK=heroku-18 TEST_CMD=test/run-deps
|
||||||
- STACK=heroku-18 TEST_CMD=test/run-versions
|
- STACK=heroku-18 TEST_CMD=test/run-versions
|
||||||
- STACK=heroku-18 TEST_CMD=test/run-features
|
- STACK=heroku-18 TEST_CMD=test/run-features
|
||||||
|
|
||||||
|
- STACK=heroku-20 TEST_CMD=test/run-deps
|
||||||
|
- STACK=heroku-20 TEST_CMD=test/run-versions
|
||||||
|
- STACK=heroku-20 TEST_CMD=test/run-features
|
||||||
global:
|
global:
|
||||||
- HATCHET_RETRIES=3
|
- HATCHET_RETRIES=3
|
||||||
- IS_RUNNING_ON_CI=true
|
- IS_RUNNING_ON_CI=true
|
||||||
|
|||||||
@@ -3,6 +3,31 @@
|
|||||||
## Unreleased
|
## Unreleased
|
||||||
|
|
||||||
|
|
||||||
|
## v183 (2020-10-12)
|
||||||
|
|
||||||
|
- Add support for Heroku-20 (#968).
|
||||||
|
|
||||||
|
## v182 (2020-10-06)
|
||||||
|
|
||||||
|
- Python 3.9.0 is now available (CPython) (#1090).
|
||||||
|
- Migrate from the `lang-python` S3 bucket to `heroku-buildpack-python` (#1089).
|
||||||
|
- Remove `vendor/shunit2` (#1086).
|
||||||
|
- Replace `BUILDPACK_VENDOR_URL` and `USE_STAGING_BINARIES` with `BUILDPACK_S3_BASE_URL` (#1085).
|
||||||
|
|
||||||
|
## v181 (2020-09-29)
|
||||||
|
|
||||||
|
- PyPy 2.7 and 3.6, version 7.3.2 are now available (Note: PyPy support is in beta) (#1081).
|
||||||
|
|
||||||
|
## v180 (2020-09-24)
|
||||||
|
|
||||||
|
- Python 3.8.6 is now available (CPython) (#1072).
|
||||||
|
|
||||||
|
## v179 (2020-09-23)
|
||||||
|
|
||||||
|
- Remove duplicate pipenv metric event (#1070).
|
||||||
|
- Emit metrics for how the Python version was chosen for an app (#1069).
|
||||||
|
- Emit Python version metric events for all builds, not just clean installs (#1066).
|
||||||
|
|
||||||
## v178 (2020-09-07)
|
## v178 (2020-09-07)
|
||||||
|
|
||||||
- Python 3.5.10 is now available (CPython) (#1062).
|
- Python 3.5.10 is now available (CPython) (#1062).
|
||||||
|
|||||||
+3
-3
@@ -9,11 +9,11 @@ GEM
|
|||||||
excon
|
excon
|
||||||
moneta
|
moneta
|
||||||
multi_json (>= 1.9.2)
|
multi_json (>= 1.9.2)
|
||||||
heroku_hatchet (7.1.1)
|
heroku_hatchet (7.3.1)
|
||||||
excon (~> 0)
|
excon (~> 0)
|
||||||
platform-api (~> 3)
|
platform-api (~> 3)
|
||||||
rrrretry (~> 1)
|
rrrretry (~> 1)
|
||||||
thor (~> 0)
|
thor (~> 1)
|
||||||
threaded (~> 0)
|
threaded (~> 0)
|
||||||
moneta (1.0.0)
|
moneta (1.0.0)
|
||||||
multi_json (1.15.0)
|
multi_json (1.15.0)
|
||||||
@@ -43,7 +43,7 @@ GEM
|
|||||||
rspec-retry (0.6.2)
|
rspec-retry (0.6.2)
|
||||||
rspec-core (> 3.3)
|
rspec-core (> 3.3)
|
||||||
rspec-support (3.9.3)
|
rspec-support (3.9.3)
|
||||||
thor (0.20.3)
|
thor (1.0.1)
|
||||||
threaded (0.0.4)
|
threaded (0.0.4)
|
||||||
|
|
||||||
PLATFORMS
|
PLATFORMS
|
||||||
|
|||||||
@@ -1,15 +1,18 @@
|
|||||||
# These targets are not files
|
# These targets are not files
|
||||||
.PHONY: check test buildenv-heroku-16 buildenv-heroku-18 tools
|
.PHONY: check test builder-image buildenv deploy-runtimes tools
|
||||||
|
|
||||||
STACK ?= heroku-18
|
STACK ?= heroku-18
|
||||||
|
STACKS ?= cedar-14 heroku-16 heroku-18
|
||||||
TEST_CMD ?= test/run-versions && test/run-features && test/run-deps
|
TEST_CMD ?= test/run-versions && test/run-features && test/run-deps
|
||||||
|
ENV_FILE ?= builds/dockerenv.default
|
||||||
|
BUILDER_IMAGE_PREFIX := heroku-python-build
|
||||||
|
|
||||||
ifeq ($(STACK),cedar-14)
|
ifeq ($(STACK),cedar-14)
|
||||||
# Cedar-14 doesn't have a build image varient.
|
# Cedar-14 doesn't have a build image varient.
|
||||||
IMAGE_TAG := heroku/cedar:14
|
STACK_IMAGE_TAG := heroku/cedar:14
|
||||||
else
|
else
|
||||||
# Converts a stack name of `heroku-NN` to its build Docker image tag of `heroku/heroku:NN-build`.
|
# Converts a stack name of `heroku-NN` to its build Docker image tag of `heroku/heroku:NN-build`.
|
||||||
IMAGE_TAG := heroku/$(subst -,:,$(STACK))-build
|
STACK_IMAGE_TAG := heroku/$(subst -,:,$(STACK))-build
|
||||||
endif
|
endif
|
||||||
|
|
||||||
check:
|
check:
|
||||||
@@ -19,37 +22,42 @@ check:
|
|||||||
|
|
||||||
test:
|
test:
|
||||||
@echo "Running tests using: STACK=$(STACK) TEST_CMD='$(TEST_CMD)'"
|
@echo "Running tests using: STACK=$(STACK) TEST_CMD='$(TEST_CMD)'"
|
||||||
@echo ""
|
|
||||||
@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)'
|
|
||||||
@echo ""
|
|
||||||
|
|
||||||
buildenv-heroku-16:
|
|
||||||
@echo "Creating build environment (heroku-16)..."
|
|
||||||
@echo
|
@echo
|
||||||
@docker build --pull -f $(shell pwd)/builds/heroku-16.Dockerfile -t python-buildenv-heroku-16 .
|
@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)'
|
||||||
|
@echo
|
||||||
|
|
||||||
|
builder-image:
|
||||||
|
@echo "Generating binary builder image for $(STACK)..."
|
||||||
|
@echo
|
||||||
|
@docker build --pull -f builds/$(STACK).Dockerfile -t "$(BUILDER_IMAGE_PREFIX)-$(STACK)" .
|
||||||
|
@echo
|
||||||
|
|
||||||
|
buildenv: builder-image
|
||||||
|
@echo "Starting build environment for $(STACK)..."
|
||||||
@echo
|
@echo
|
||||||
@echo "Usage..."
|
@echo "Usage..."
|
||||||
@echo
|
@echo
|
||||||
@echo " $$ export AWS_ACCESS_KEY_ID=foo AWS_SECRET_ACCESS_KEY=bar # Optional unless deploying"
|
@echo " $$ bob build runtimes/python-X.Y.Z"
|
||||||
@echo " $$ bob build runtimes/python-2.7.13"
|
|
||||||
@echo " $$ bob deploy runtimes/python-2.7.13"
|
|
||||||
@echo
|
@echo
|
||||||
@docker run -it --rm python-buildenv-heroku-16
|
@docker run --rm -it --env-file="$(ENV_FILE)" -v $(PWD)/builds:/app/builds "$(BUILDER_IMAGE_PREFIX)-$(STACK)" bash
|
||||||
|
|
||||||
buildenv-heroku-18:
|
deploy-runtimes:
|
||||||
@echo "Creating build environment (heroku-18)..."
|
ifndef RUNTIMES
|
||||||
|
$(error No runtimes specified! Use: "make deploy-runtimes RUNTIMES='python-X.Y.Z ...' [STACKS='heroku-18 ...'] [ENV_FILE=...]")
|
||||||
|
endif
|
||||||
|
@echo "Using: RUNTIMES='$(RUNTIMES)' STACKS='$(STACKS)' ENV_FILE='$(ENV_FILE)'"
|
||||||
@echo
|
@echo
|
||||||
@docker build --pull -f $(shell pwd)/builds/heroku-18.Dockerfile -t python-buildenv-heroku-18 .
|
@set -eu; for stack in $(STACKS); do \
|
||||||
@echo
|
$(MAKE) builder-image STACK=$${stack}; \
|
||||||
@echo "Usage..."
|
for runtime in $(RUNTIMES); do \
|
||||||
@echo
|
echo "Generating/deploying $${runtime} for $${stack}..."; \
|
||||||
@echo " $$ export AWS_ACCESS_KEY_ID=foo AWS_SECRET_ACCESS_KEY=bar # Optional unless deploying"
|
echo; \
|
||||||
@echo " $$ bob build runtimes/python-2.7.13"
|
docker run --rm -it --env-file="$(ENV_FILE)" "$(BUILDER_IMAGE_PREFIX)-$${stack}" bob deploy "runtimes/$${runtime}"; \
|
||||||
@echo " $$ bob deploy runtimes/python-2.7.13"
|
echo; \
|
||||||
@echo
|
done; \
|
||||||
@docker run -it --rm python-buildenv-heroku-18
|
done
|
||||||
|
|
||||||
tools:
|
tools:
|
||||||
git clone https://github.com/kennethreitz/pip-pop.git
|
git clone https://github.com/kennethreitz/pip-pop.git
|
||||||
mv pip-pop/bin/* vendor/pip-pop/
|
mv pip-pop/bin/* vendor/pip-pop/
|
||||||
rm -fr pip-pop
|
rm -rf pip-pop
|
||||||
|
|||||||
@@ -62,7 +62,8 @@ Specify a Python Runtime
|
|||||||
|
|
||||||
Supported runtime options include:
|
Supported runtime options include:
|
||||||
|
|
||||||
- `python-3.8.5`
|
- `python-3.9.0`
|
||||||
|
- `python-3.8.6`
|
||||||
- `python-3.7.9`
|
- `python-3.7.9`
|
||||||
- `python-3.6.12`
|
- `python-3.6.12`
|
||||||
- `python-2.7.18`
|
- `python-2.7.18`
|
||||||
|
|||||||
+22
-13
@@ -37,23 +37,27 @@ ENV_DIR=$3
|
|||||||
# Export Path variables, for use in sub-scripts.
|
# Export Path variables, for use in sub-scripts.
|
||||||
export BUILD_DIR CACHE_DIR ENV_DIR
|
export BUILD_DIR CACHE_DIR ENV_DIR
|
||||||
|
|
||||||
# Set the Buildpack's internet target for downloading Python distributions.
|
# Set the base URL for downloading buildpack assets like Python runtimes.
|
||||||
# The user can provide BUILDPACK_VENDOR_URL to specify a custom target.
|
# The user can provide BUILDPACK_S3_BASE_URL to specify a custom target.
|
||||||
# Note: this is designed for non-Heroku use, as it does not use the user-provided
|
# Note: this is designed for non-Heroku use, as it does not use the user-provided
|
||||||
# environment variable mechanism (the ENV_DIR).
|
# environment variable mechanism (the ENV_DIR).
|
||||||
VENDOR_URL="https://lang-python.s3.amazonaws.com/$STACK"
|
if [[ "${STACK}" == "cedar-14" ]]; then
|
||||||
if [[ -n ${BUILDPACK_VENDOR_URL:-} ]]; then
|
# Since Cedar-14 is EOL on 2020-11-02 it's not worth migrating it to the new bucket.
|
||||||
VENDOR_URL="$BUILDPACK_VENDOR_URL"
|
DEFAULT_S3_BASE_URL='https://lang-python.s3.amazonaws.com'
|
||||||
elif [[ -n ${USE_STAGING_BINARIES} ]]; then
|
else
|
||||||
VENDOR_URL="$USE_STAGING_BINARIES/$STACK"
|
DEFAULT_S3_BASE_URL='https://heroku-buildpack-python.s3.amazonaws.com'
|
||||||
fi
|
fi
|
||||||
export VENDOR_URL
|
S3_BASE_URL="${BUILDPACK_S3_BASE_URL:-${DEFAULT_S3_BASE_URL}}"
|
||||||
|
# This has to be exported since it's used by the geo-libs step which is run in a subshell.
|
||||||
|
# TODO: Stop exporting once the geo-libs step is removed or no longer uses `sub_env`.
|
||||||
|
export S3_BASE_URL
|
||||||
|
|
||||||
# Default Python Versions
|
# Default Python Versions
|
||||||
# shellcheck source=bin/default_pythons
|
# shellcheck source=bin/default_pythons
|
||||||
source "$BIN_DIR/default_pythons"
|
source "$BIN_DIR/default_pythons"
|
||||||
|
|
||||||
# Supported Python Branches
|
# Supported Python Branches
|
||||||
|
PY39="python-3.9"
|
||||||
PY38="python-3.8"
|
PY38="python-3.8"
|
||||||
PY37="python-3.7"
|
PY37="python-3.7"
|
||||||
PY36="python-3.6"
|
PY36="python-3.6"
|
||||||
@@ -189,7 +193,7 @@ source "$BIN_DIR/steps/hooks/pre_compile"
|
|||||||
# continue to use that version of Python in perpituity (warnings will be raised if
|
# continue to use that version of Python in perpituity (warnings will be raised if
|
||||||
# they are out–of–date).
|
# they are out–of–date).
|
||||||
if [ -f "$CACHE_DIR/.heroku/python-version" ]; then
|
if [ -f "$CACHE_DIR/.heroku/python-version" ]; then
|
||||||
DEFAULT_PYTHON_VERSION=$(cat "$CACHE_DIR/.heroku/python-version")
|
CACHED_PYTHON_VERSION=$(cat "$CACHE_DIR/.heroku/python-version")
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# We didn't always record the stack version. This code is in place because of that.
|
# We didn't always record the stack version. This code is in place because of that.
|
||||||
@@ -206,9 +210,14 @@ fi
|
|||||||
# shellcheck source=bin/steps/pipenv-python-version
|
# shellcheck source=bin/steps/pipenv-python-version
|
||||||
source "$BIN_DIR/steps/pipenv-python-version"
|
source "$BIN_DIR/steps/pipenv-python-version"
|
||||||
|
|
||||||
# If no runtime was provided by the user, assume the default Python runtime version.
|
if [[ -f runtime.txt ]]; then
|
||||||
if [ ! -f runtime.txt ]; then
|
mcount "version.reason.python.specified"
|
||||||
echo "$DEFAULT_PYTHON_VERSION" > runtime.txt
|
elif [[ -n "${CACHED_PYTHON_VERSION:-}" ]]; then
|
||||||
|
mcount "version.reason.python.cached"
|
||||||
|
echo "${CACHED_PYTHON_VERSION}" > runtime.txt
|
||||||
|
else
|
||||||
|
mcount "version.reason.python.default"
|
||||||
|
echo "${DEFAULT_PYTHON_VERSION}" > runtime.txt
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Create the directory for .profile.d, if it doesn't exist.
|
# Create the directory for .profile.d, if it doesn't exist.
|
||||||
@@ -304,7 +313,7 @@ mtime "nltk.download.time" "${start}"
|
|||||||
# and copying it into the proper place (the logical place to do this was early, but it must be done here).
|
# and copying it into the proper place (the logical place to do this was early, but it must be done here).
|
||||||
# In CI, $BUILD_DIR is /app.
|
# In CI, $BUILD_DIR is /app.
|
||||||
if [[ ! "$BUILD_DIR" == "/app" ]]; then
|
if [[ ! "$BUILD_DIR" == "/app" ]]; then
|
||||||
rm -fr "$BUILD_DIR/.heroku/src"
|
rm -rf "$BUILD_DIR/.heroku/src"
|
||||||
deep-cp /app/.heroku/src "$BUILD_DIR/.heroku/src"
|
deep-cp /app/.heroku/src "$BUILD_DIR/.heroku/src"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|||||||
+4
-3
@@ -6,11 +6,12 @@
|
|||||||
# shellcheck disable=2034
|
# shellcheck disable=2034
|
||||||
|
|
||||||
DEFAULT_PYTHON_VERSION="python-3.6.12"
|
DEFAULT_PYTHON_VERSION="python-3.6.12"
|
||||||
LATEST_38="python-3.8.5"
|
LATEST_39="python-3.9.0"
|
||||||
|
LATEST_38="python-3.8.6"
|
||||||
LATEST_37="python-3.7.9"
|
LATEST_37="python-3.7.9"
|
||||||
LATEST_36="python-3.6.12"
|
LATEST_36="python-3.6.12"
|
||||||
LATEST_35="python-3.5.10"
|
LATEST_35="python-3.5.10"
|
||||||
LATEST_34="python-3.4.10"
|
LATEST_34="python-3.4.10"
|
||||||
LATEST_27="python-2.7.18"
|
LATEST_27="python-2.7.18"
|
||||||
LATEST_PYPY_36="pypy3.6-7.3.1"
|
LATEST_PYPY_36="pypy3.6-7.3.2"
|
||||||
LATEST_PYPY_27="pypy2.7-7.3.1"
|
LATEST_PYPY_27="pypy2.7-7.3.2"
|
||||||
|
|||||||
+5
-2
@@ -10,7 +10,7 @@
|
|||||||
# This script is invoked by [`bin/compile`](/).
|
# This script is invoked by [`bin/compile`](/).
|
||||||
|
|
||||||
# The location of the pre-compiled cryptography binary.
|
# The location of the pre-compiled cryptography binary.
|
||||||
VENDORED_GDAL="${VENDOR_URL}/libraries/vendor/gdal.tar.gz"
|
VENDORED_GDAL="${S3_BASE_URL}/${STACK}/libraries/vendor/gdal.tar.gz"
|
||||||
|
|
||||||
PKG_CONFIG_PATH="/app/.heroku/vendor/lib/pkgconfig:$PKG_CONFIG_PATH"
|
PKG_CONFIG_PATH="/app/.heroku/vendor/lib/pkgconfig:$PKG_CONFIG_PATH"
|
||||||
|
|
||||||
@@ -21,8 +21,11 @@ source "$BIN_DIR/utils"
|
|||||||
# If GDAL exists within requirements, use vendored gdal.
|
# If GDAL exists within requirements, use vendored gdal.
|
||||||
if (pip-grep -s requirements.txt GDAL gdal pygdal &> /dev/null) then
|
if (pip-grep -s requirements.txt GDAL gdal pygdal &> /dev/null) then
|
||||||
|
|
||||||
if [ ! -f ".heroku/vendor/bin/gdalserver" ]; then
|
if [[ ! -f ".heroku/vendor/bin/gdalserver" && "${STACK}" == 'heroku-20' ]]; then
|
||||||
|
puts-warn "The buildpack's built-in GDAL functonality is not supported on Heroku-20."
|
||||||
|
puts-warn "Please use this buildpack instead: https://github.com/heroku/heroku-geo-buildpack"
|
||||||
|
|
||||||
|
elif [[ ! -f ".heroku/vendor/bin/gdalserver" ]]; then
|
||||||
puts-warn "The vendored GDAL package in the Heroku Python Buildpack now deprecated."
|
puts-warn "The vendored GDAL package in the Heroku Python Buildpack now deprecated."
|
||||||
puts-warn "To enable GDAL use an alternative buildpack is available here - https://github.com/heroku/heroku-geo-buildpack"
|
puts-warn "To enable GDAL use an alternative buildpack is available here - https://github.com/heroku/heroku-geo-buildpack"
|
||||||
|
|
||||||
|
|||||||
+8
-5
@@ -10,9 +10,9 @@
|
|||||||
# This script is invoked by [`bin/compile`](/).
|
# This script is invoked by [`bin/compile`](/).
|
||||||
|
|
||||||
# The location of the pre-compiled cryptography binary.
|
# The location of the pre-compiled cryptography binary.
|
||||||
VENDORED_GDAL="${VENDOR_URL}/libraries/vendor/gdal.tar.gz"
|
VENDORED_GDAL="${S3_BASE_URL}/${STACK}/libraries/vendor/gdal.tar.gz"
|
||||||
VENDORED_GEOS="${VENDOR_URL}/libraries/vendor/geos.tar.gz"
|
VENDORED_GEOS="${S3_BASE_URL}/${STACK}/libraries/vendor/geos.tar.gz"
|
||||||
VENDORED_PROJ="${VENDOR_URL}/libraries/vendor/proj.tar.gz"
|
VENDORED_PROJ="${S3_BASE_URL}/${STACK}/libraries/vendor/proj.tar.gz"
|
||||||
|
|
||||||
PKG_CONFIG_PATH="/app/.heroku/vendor/lib/pkgconfig:$PKG_CONFIG_PATH"
|
PKG_CONFIG_PATH="/app/.heroku/vendor/lib/pkgconfig:$PKG_CONFIG_PATH"
|
||||||
|
|
||||||
@@ -20,8 +20,11 @@ PKG_CONFIG_PATH="/app/.heroku/vendor/lib/pkgconfig:$PKG_CONFIG_PATH"
|
|||||||
# shellcheck source=bin/utils
|
# shellcheck source=bin/utils
|
||||||
source "$BIN_DIR/utils"
|
source "$BIN_DIR/utils"
|
||||||
|
|
||||||
# If GDAL exists within requirements, use vendored gdal.
|
if [[ "$BUILD_WITH_GEO_LIBRARIES" && "${STACK}" == 'heroku-20' ]]; then
|
||||||
if [[ "$BUILD_WITH_GEO_LIBRARIES" ]]; then
|
puts-warn "The GDAL, GEOS and PROJ binaries and BUILD_WITH_GEO_LIBRARIES functonality is not supported on Heroku-20."
|
||||||
|
puts-warn "Please use this buildpack for GDAL, GEOS and PROJ: https://github.com/heroku/heroku-geo-buildpack"
|
||||||
|
puts-warn "To hide this message, unset the BUILD_WITH_GEO_LIBRARIES variable using: heroku config:unset BUILD_WITH_GEO_LIBRARIES"
|
||||||
|
elif [[ "$BUILD_WITH_GEO_LIBRARIES" ]]; then
|
||||||
mcount "buildvar.BUILD_WITH_GEO_LIBRARIES"
|
mcount "buildvar.BUILD_WITH_GEO_LIBRARIES"
|
||||||
|
|
||||||
puts-warn "The GDAL, GEOS and PROJ binaries and BUILD_WITH_GEO_LIBRARIES functonality are now deprecated."
|
puts-warn "The GDAL, GEOS and PROJ binaries and BUILD_WITH_GEO_LIBRARIES functonality are now deprecated."
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ if [ ! "$SKIP_PIP_INSTALL" ]; then
|
|||||||
mcount "failure.bad-requirements"
|
mcount "failure.bad-requirements"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
rm -fr requirements-declared.txt
|
rm -rf requirements-declared.txt
|
||||||
|
|
||||||
if [[ -s .heroku/python/requirements-stale.txt ]]; then
|
if [[ -s .heroku/python/requirements-stale.txt ]]; then
|
||||||
puts-step "Uninstalling stale dependencies"
|
puts-step "Uninstalling stale dependencies"
|
||||||
|
|||||||
+1
-4
@@ -9,10 +9,7 @@ set -e
|
|||||||
if [[ -f Pipfile.lock ]]; then
|
if [[ -f Pipfile.lock ]]; then
|
||||||
if [[ -f .heroku/python/Pipfile.lock.sha256 ]]; then
|
if [[ -f .heroku/python/Pipfile.lock.sha256 ]]; then
|
||||||
if [[ $(openssl dgst -sha256 Pipfile.lock) == $(cat .heroku/python/Pipfile.lock.sha256) ]]; then
|
if [[ $(openssl dgst -sha256 Pipfile.lock) == $(cat .heroku/python/Pipfile.lock.sha256) ]]; then
|
||||||
# Measure that we're using Pipenv.
|
# Don't skip installation if there are git deps.
|
||||||
mcount "tool.pipenv"
|
|
||||||
|
|
||||||
# Don't skip installation of there are git deps.
|
|
||||||
if ! grep -q 'git' Pipfile.lock; then
|
if ! grep -q 'git' Pipfile.lock; then
|
||||||
echo "Skipping installation, as Pipfile.lock hasn't changed since last deploy." | indent
|
echo "Skipping installation, as Pipfile.lock hasn't changed since last deploy." | indent
|
||||||
|
|
||||||
|
|||||||
@@ -30,6 +30,9 @@ if [[ -f $BUILD_DIR/Pipfile ]]; then
|
|||||||
if [ "$PYTHON" = 3.8 ]; then
|
if [ "$PYTHON" = 3.8 ]; then
|
||||||
echo "$LATEST_38" > "$BUILD_DIR/runtime.txt"
|
echo "$LATEST_38" > "$BUILD_DIR/runtime.txt"
|
||||||
fi
|
fi
|
||||||
|
if [ "$PYTHON" = 3.9 ]; then
|
||||||
|
echo "$LATEST_39" > "$BUILD_DIR/runtime.txt"
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -15,7 +15,7 @@ if [[ "$STACK" != "cedar-14" ]]; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# The location of the pre-compiled libmemcached binary.
|
# The location of the pre-compiled libmemcached binary.
|
||||||
VENDORED_MEMCACHED="${VENDOR_URL}/libraries/vendor/libmemcache.tar.gz"
|
VENDORED_MEMCACHED="${S3_BASE_URL}/${STACK}/libraries/vendor/libmemcache.tar.gz"
|
||||||
|
|
||||||
# Syntax sugar.
|
# Syntax sugar.
|
||||||
# shellcheck source=bin/utils
|
# shellcheck source=bin/utils
|
||||||
|
|||||||
+12
-6
@@ -5,7 +5,7 @@ runtime-fixer runtime.txt
|
|||||||
PYTHON_VERSION=$(cat runtime.txt)
|
PYTHON_VERSION=$(cat runtime.txt)
|
||||||
|
|
||||||
# The location of the pre-compiled python binary.
|
# The location of the pre-compiled python binary.
|
||||||
VENDORED_PYTHON="${VENDOR_URL}/runtimes/$PYTHON_VERSION.tar.gz"
|
VENDORED_PYTHON="${S3_BASE_URL}/${STACK}/runtimes/${PYTHON_VERSION}.tar.gz"
|
||||||
|
|
||||||
SECURITY_UPDATE="Python has released a security update! Please consider upgrading to"
|
SECURITY_UPDATE="Python has released a security update! Please consider upgrading to"
|
||||||
SECURITY_UPDATE_PYPY="The PyPy project has released a security update! Please consider upgrading to"
|
SECURITY_UPDATE_PYPY="The PyPy project has released a security update! Please consider upgrading to"
|
||||||
@@ -16,6 +16,12 @@ PYTHON_2_EOL_UPDATE="Python 2 has reached it's community EOL. Upgrade your Pytho
|
|||||||
|
|
||||||
# check if runtime exists
|
# check if runtime exists
|
||||||
if curl --output /dev/null --silent --head --fail "$VENDORED_PYTHON"; then
|
if curl --output /dev/null --silent --head --fail "$VENDORED_PYTHON"; then
|
||||||
|
if [[ "$PYTHON_VERSION" == $PY39* ]]; then
|
||||||
|
if [ "$PYTHON_VERSION" != "$LATEST_39" ]; then
|
||||||
|
puts-warn "$SECURITY_UPDATE" "$LATEST_39"
|
||||||
|
echo " Learn More: https://devcenter.heroku.com/articles/python-runtimes"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
if [[ "$PYTHON_VERSION" == $PY38* ]]; then
|
if [[ "$PYTHON_VERSION" == $PY38* ]]; then
|
||||||
# do things to alert the user of security release available
|
# do things to alert the user of security release available
|
||||||
if [ "$PYTHON_VERSION" != "$LATEST_38" ]; then
|
if [ "$PYTHON_VERSION" != "$LATEST_38" ]; then
|
||||||
@@ -80,15 +86,17 @@ else
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
mcount "version.python.${PYTHON_VERSION}"
|
||||||
|
|
||||||
if [[ "$STACK" != "$CACHED_PYTHON_STACK" ]]; then
|
if [[ "$STACK" != "$CACHED_PYTHON_STACK" ]]; then
|
||||||
puts-step "Stack has changed from $CACHED_PYTHON_STACK to $STACK, clearing cache"
|
puts-step "Stack has changed from $CACHED_PYTHON_STACK to $STACK, clearing cache"
|
||||||
rm -fr .heroku/python-stack .heroku/python-version .heroku/python .heroku/vendor .heroku/python .heroku/python-sqlite3-version
|
rm -rf .heroku/python-stack .heroku/python-version .heroku/python .heroku/vendor .heroku/python .heroku/python-sqlite3-version
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ -f .heroku/python-version ]; then
|
if [ -f .heroku/python-version ]; then
|
||||||
if [ ! "$(cat .heroku/python-version)" = "$PYTHON_VERSION" ]; then
|
if [ ! "$(cat .heroku/python-version)" = "$PYTHON_VERSION" ]; then
|
||||||
puts-step "Found $(cat .heroku/python-version), removing"
|
puts-step "Found $(cat .heroku/python-version), removing"
|
||||||
rm -fr .heroku/python
|
rm -rf .heroku/python
|
||||||
else
|
else
|
||||||
SKIP_INSTALL=1
|
SKIP_INSTALL=1
|
||||||
fi
|
fi
|
||||||
@@ -119,8 +127,6 @@ if [ ! "$SKIP_INSTALL" ]; then
|
|||||||
# Prepare destination directory.
|
# Prepare destination directory.
|
||||||
mkdir -p .heroku/python
|
mkdir -p .heroku/python
|
||||||
|
|
||||||
mcount "version.python.$PYTHON_VERSION"
|
|
||||||
|
|
||||||
if ! curl "${VENDORED_PYTHON}" -s | tar zxv -C .heroku/python &> /dev/null; then
|
if ! curl "${VENDORED_PYTHON}" -s | tar zxv -C .heroku/python &> /dev/null; then
|
||||||
puts-warn "Requested runtime ($PYTHON_VERSION) is not available for this stack ($STACK)."
|
puts-warn "Requested runtime ($PYTHON_VERSION) is not available for this stack ($STACK)."
|
||||||
puts-warn "Aborting. More info: https://devcenter.heroku.com/articles/python-support"
|
puts-warn "Aborting. More info: https://devcenter.heroku.com/articles/python-support"
|
||||||
@@ -160,7 +166,7 @@ fi
|
|||||||
# Instead, we use the pip wheel to install itself, using the method described here:
|
# Instead, we use the pip wheel to install itself, using the method described here:
|
||||||
# https://github.com/pypa/pip/issues/2351#issuecomment-69994524
|
# https://github.com/pypa/pip/issues/2351#issuecomment-69994524
|
||||||
PIP_WHEEL_FILENAME="pip-${PIP_VERSION}-py2.py3-none-any.whl"
|
PIP_WHEEL_FILENAME="pip-${PIP_VERSION}-py2.py3-none-any.whl"
|
||||||
PIP_WHEEL_URL="https://lang-python.s3.amazonaws.com/common/${PIP_WHEEL_FILENAME}"
|
PIP_WHEEL_URL="${S3_BASE_URL}/common/${PIP_WHEEL_FILENAME}"
|
||||||
PIP_WHEEL="${TMPDIR:-/tmp}/${PIP_WHEEL_FILENAME}"
|
PIP_WHEEL="${TMPDIR:-/tmp}/${PIP_WHEEL_FILENAME}"
|
||||||
|
|
||||||
if ! curl -sSf "${PIP_WHEEL_URL}" -o "$PIP_WHEEL"; then
|
if ! curl -sSf "${PIP_WHEEL_URL}" -o "$PIP_WHEEL"; then
|
||||||
|
|||||||
+61
-38
@@ -1,57 +1,80 @@
|
|||||||
# Python Buildpack Binaries
|
# Python Buildpack Binaries
|
||||||
|
|
||||||
## Building the Docker Images
|
The binaries for this buildpack are built in Docker containers based on the Heroku stack image.
|
||||||
|
|
||||||
**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:
|
|
||||||
|
|
||||||
$ docker build --pull --tag heroku-python-build-cedar-14 --file $(pwd)/builds/cedar-14.Dockerfile .
|
|
||||||
$ docker build --pull --tag heroku-python-build-heroku-16 --file $(pwd)/builds/heroku-16.Dockerfile .
|
|
||||||
$ docker build --pull --tag heroku-python-build-heroku-18 --file $(pwd)/builds/heroku-18.Dockerfile .
|
|
||||||
|
|
||||||
## Using the Image
|
|
||||||
|
|
||||||
You can e.g. `bash` into each of the images you built using their tag:
|
|
||||||
|
|
||||||
docker run --rm -ti heroku-python-build-cedar-14 bash
|
|
||||||
docker run --rm -ti heroku-python-build-heroku-16 bash
|
|
||||||
docker run --rm -ti heroku-python-build-heroku-18 bash
|
|
||||||
|
|
||||||
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`:
|
|
||||||
|
|
||||||
docker run --rm -ti heroku-python-build-heroku-18 bob build runtimes/python-2.7.15
|
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
|
||||||
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`.
|
In order to publish binaries AWS credentials must be passed to the build container.
|
||||||
|
If you are testing only the build (ie: `bob build`), these are optional.
|
||||||
|
|
||||||
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.
|
In addition, unless you are building the official binaries for Heroku (which use the defaults
|
||||||
|
specified in each `Dockerfile`), you will need to override `S3_BUCKET` and `S3_PREFIX` to
|
||||||
|
match your own S3 bucket/use case.
|
||||||
|
|
||||||
### Passing AWS credentials to the container
|
If you only need to set AWS credentials, you can do so by setting the environment variables
|
||||||
|
`AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` before calling the make commands.
|
||||||
|
|
||||||
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.
|
For example:
|
||||||
|
|
||||||
#### Passing credentials explicitly
|
```bash
|
||||||
|
set +o history # Disable bash history
|
||||||
|
export AWS_ACCESS_KEY_ID=...
|
||||||
|
export AWS_SECRET_ACCESS_KEY=...
|
||||||
|
set -o history # Re-enable bash history
|
||||||
|
make ...
|
||||||
|
```
|
||||||
|
|
||||||
docker run --rm -ti -e AWS_ACCESS_KEY_ID=... -e AWS_SECRET_ACCESS_KEY=... heroku-python-build-heroku-18 bash
|
If you need to override the default S3 bucket, or would prefer not to use credentials via
|
||||||
|
environment variables, then you need to instead use a Docker env file like so:
|
||||||
|
|
||||||
#### Passing credentials through the environment
|
1. Copy the `builds/dockerenv.default` env file to a location outside the buildpack repository.
|
||||||
|
2. Edit the new file, adding at a minimum the values for the variables
|
||||||
|
`AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` (see Docker
|
||||||
|
[env-file documentation](https://docs.docker.com/engine/reference/commandline/run/#set-environment-variables--e---env---env-file)).
|
||||||
|
3. Pass the path of the file to the make commands using `ENV_FILE`. For example:
|
||||||
|
|
||||||
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:
|
```bash
|
||||||
|
make ... ENV_FILE=~/.dockerenv.python-buildpack
|
||||||
|
```
|
||||||
|
|
||||||
AWS_ACCESS_KEY_ID=... AWS_SECRET_ACCESS_KEY=... docker run --rm -ti --env-file=builds/dockerenv.default heroku-python-build-heroku-18 bash
|
## Launching an interactive build environment
|
||||||
|
|
||||||
or
|
To start an interactive version of the build environment (ideal for development) use the
|
||||||
|
`buildenv` make target, passing in the desired `STACK` name. For example:
|
||||||
|
|
||||||
export AWS_ACCESS_KEY_ID=...
|
```bash
|
||||||
export AWS_SECRET_ACCESS_KEY=...
|
make buildenv STACK=heroku-18
|
||||||
docker run --rm -ti --env-file=builds/dockerenv.default heroku-python-build-heroku-18 bash
|
```
|
||||||
|
|
||||||
#### Passing credentials through a separate env file
|
This will create the builder docker image based on the latest image for that stack, and
|
||||||
|
then start a bash shell where you can run `bob build`, `bob deploy`, and so forth.
|
||||||
|
|
||||||
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.
|
The `builds/` directory is bind-mounted into the running container, so local build formula
|
||||||
|
changes will appear there immediately without the need to rebuild the image.
|
||||||
|
|
||||||
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`.
|
## Bulk deploying runtimes
|
||||||
|
|
||||||
docker run --rm -ti --env-file=../SOMEPATHOUTSIDE/s3.env heroku-python-build-heroku-18 bash
|
When a new Python version is released, binaries have to be generated for multiple stacks.
|
||||||
|
To automate this, use the `deploy-runtimes` make target, which will ensure the builder
|
||||||
|
image is up to date, and then run `bob deploy` for each runtime-stack combination.
|
||||||
|
|
||||||
|
The build formula name(s) are passed using `RUNTIMES`, like so:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
make deploy-runtimes RUNTIMES='python-X.Y.Z'
|
||||||
|
```
|
||||||
|
|
||||||
|
By default this will deploy to all supported stacks (see `STACKS` in `Makefile`),
|
||||||
|
but this can be overridden using `STACKS`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
make deploy-runtimes RUNTIMES='python-X.Y.Z' STACKS='heroku-16 heroku-18'
|
||||||
|
```
|
||||||
|
|
||||||
|
Multiple runtimes can also be specified (useful for when adding a new stack), like so:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
make deploy-runtimes RUNTIMES='python-A.B.C python-X.Y.Z' STACKS='heroku-20'
|
||||||
|
```
|
||||||
|
|
||||||
|
Note: Both `RUNTIMES` and `STACKS` are space delimited.
|
||||||
|
|||||||
@@ -1,15 +1,21 @@
|
|||||||
FROM heroku/cedar:14
|
FROM heroku/cedar:14
|
||||||
|
|
||||||
WORKDIR /app
|
|
||||||
ENV WORKSPACE_DIR="/app/builds" \
|
ENV WORKSPACE_DIR="/app/builds" \
|
||||||
S3_BUCKET="lang-python" \
|
S3_BUCKET="lang-python" \
|
||||||
S3_PREFIX="cedar-14/" \
|
S3_PREFIX="cedar-14/" \
|
||||||
DEBIAN_FRONTEND=noninteractive \
|
|
||||||
STACK="cedar-14"
|
STACK="cedar-14"
|
||||||
|
|
||||||
RUN apt-get update && apt-get install -y python-pip libsqlite3-dev realpath && rm -rf /var/lib/apt/lists/*
|
RUN apt-get update \
|
||||||
|
&& DEBIAN_FRONTEND=noninteractive apt-get install --no-install-recommends -y \
|
||||||
|
libsqlite3-dev \
|
||||||
|
python3-pip \
|
||||||
|
realpath \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
COPY requirements.txt /app/
|
COPY requirements.txt /app/
|
||||||
RUN pip install -r /app/requirements.txt
|
# Can't use `--disable-pip-version-check --no-cache-dir` since not supported by Ubuntu 14.04's pip.
|
||||||
|
RUN pip3 install -r /app/requirements.txt
|
||||||
|
|
||||||
COPY . /app
|
COPY . /app
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
|
# Since no values are specified here, these variables will be read from the environment at run time:
|
||||||
|
# https://docs.docker.com/engine/reference/commandline/run/#set-environment-variables--e---env---env-file
|
||||||
AWS_ACCESS_KEY_ID
|
AWS_ACCESS_KEY_ID
|
||||||
AWS_SECRET_ACCESS_KEY
|
AWS_SECRET_ACCESS_KEY
|
||||||
S3_BUCKET
|
|
||||||
S3_PREFIX
|
# Uncomment these if you need to override the default S3 bucket and/or path prefixes.
|
||||||
S3_REGION
|
# S3_BUCKET
|
||||||
|
# S3_PREFIX
|
||||||
|
|||||||
@@ -1,15 +1,20 @@
|
|||||||
FROM heroku/heroku:16-build
|
FROM heroku/heroku:16-build
|
||||||
|
|
||||||
WORKDIR /app
|
|
||||||
ENV WORKSPACE_DIR="/app/builds" \
|
ENV WORKSPACE_DIR="/app/builds" \
|
||||||
S3_BUCKET="lang-python" \
|
S3_BUCKET="heroku-buildpack-python" \
|
||||||
S3_PREFIX="heroku-16/" \
|
S3_PREFIX="heroku-16/" \
|
||||||
DEBIAN_FRONTEND=noninteractive \
|
|
||||||
STACK="heroku-16"
|
STACK="heroku-16"
|
||||||
|
|
||||||
RUN apt-get update && apt-get install -y python-pip libsqlite3-dev && rm -rf /var/lib/apt/lists/*
|
RUN apt-get update \
|
||||||
|
&& DEBIAN_FRONTEND=noninteractive apt-get install --no-install-recommends -y \
|
||||||
|
libsqlite3-dev \
|
||||||
|
python3-pip \
|
||||||
|
python3-setuptools \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
COPY requirements.txt /app/
|
COPY requirements.txt /app/
|
||||||
RUN pip install --disable-pip-version-check --no-cache-dir -r /app/requirements.txt
|
RUN pip3 install --disable-pip-version-check --no-cache-dir -r /app/requirements.txt
|
||||||
|
|
||||||
COPY . /app
|
COPY . /app
|
||||||
|
|||||||
@@ -1,15 +1,20 @@
|
|||||||
FROM heroku/heroku:18-build
|
FROM heroku/heroku:18-build
|
||||||
|
|
||||||
WORKDIR /app
|
|
||||||
ENV WORKSPACE_DIR="/app/builds" \
|
ENV WORKSPACE_DIR="/app/builds" \
|
||||||
S3_BUCKET="lang-python" \
|
S3_BUCKET="heroku-buildpack-python" \
|
||||||
S3_PREFIX="heroku-18/" \
|
S3_PREFIX="heroku-18/" \
|
||||||
DEBIAN_FRONTEND=noninteractive \
|
|
||||||
STACK="heroku-18"
|
STACK="heroku-18"
|
||||||
|
|
||||||
RUN apt-get update && apt-get install --no-install-recommends -y python-pip-whl=9.0.1-2 python-pip=9.0.1-2 python-setuptools python-wheel libsqlite3-dev && rm -rf /var/lib/apt/lists/*
|
RUN apt-get update \
|
||||||
|
&& DEBIAN_FRONTEND=noninteractive apt-get install --no-install-recommends -y \
|
||||||
|
libsqlite3-dev \
|
||||||
|
python3-pip \
|
||||||
|
python3-setuptools \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
COPY requirements.txt /app/
|
COPY requirements.txt /app/
|
||||||
RUN pip install --disable-pip-version-check --no-cache-dir -r /app/requirements.txt
|
RUN pip3 install --disable-pip-version-check --no-cache-dir -r /app/requirements.txt
|
||||||
|
|
||||||
COPY . /app
|
COPY . /app
|
||||||
|
|||||||
@@ -0,0 +1,20 @@
|
|||||||
|
FROM heroku/heroku:20-build
|
||||||
|
|
||||||
|
ENV WORKSPACE_DIR="/app/builds" \
|
||||||
|
S3_BUCKET="heroku-buildpack-python" \
|
||||||
|
S3_PREFIX="heroku-20/" \
|
||||||
|
STACK="heroku-20"
|
||||||
|
|
||||||
|
RUN apt-get update \
|
||||||
|
&& DEBIAN_FRONTEND=noninteractive apt-get install --no-install-recommends -y \
|
||||||
|
libsqlite3-dev \
|
||||||
|
python3-pip \
|
||||||
|
python3-setuptools \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
COPY requirements.txt /app/
|
||||||
|
RUN pip3 install --disable-pip-version-check --no-cache-dir -r /app/requirements.txt
|
||||||
|
|
||||||
|
COPY . /app
|
||||||
@@ -19,4 +19,4 @@ make install
|
|||||||
|
|
||||||
# Cleanup
|
# Cleanup
|
||||||
cd ..
|
cd ..
|
||||||
rm -fr sqlite
|
rm -rf sqlite
|
||||||
|
|||||||
@@ -13,11 +13,11 @@ dep_version=${dep_formula##*"/${dep_name}-"} # "subtract" our name from full ver
|
|||||||
dep_package=${dep_name}-v${dep_version} # it's always "pypy2-…"
|
dep_package=${dep_name}-v${dep_version} # it's always "pypy2-…"
|
||||||
dep_dirname=${dep_package}-linux64
|
dep_dirname=${dep_package}-linux64
|
||||||
dep_archive_name=${dep_dirname}.tar.bz2
|
dep_archive_name=${dep_dirname}.tar.bz2
|
||||||
dep_url=https://bitbucket.org/pypy/pypy/downloads/${dep_archive_name}
|
dep_url="https://downloads.python.org/pypy/${dep_archive_name}"
|
||||||
|
|
||||||
echo "Building PyPy…"
|
echo "Building PyPy…"
|
||||||
echo "${dep_url}"
|
echo "${dep_url}"
|
||||||
|
|
||||||
curl -L "${dep_url}" | tar jx -C "${OUT_PREFIX}" --strip-components 1 # extract to $OUT_PREFIX, drop the first directory level, which is the archive name
|
curl -fL "${dep_url}" | tar jx -C "${OUT_PREFIX}" --strip-components 1 # extract to $OUT_PREFIX, drop the first directory level, which is the archive name
|
||||||
|
|
||||||
ln "$OUT_PREFIX/bin/pypy" "$OUT_PREFIX/bin/python"
|
ln "$OUT_PREFIX/bin/pypy" "$OUT_PREFIX/bin/python"
|
||||||
|
|||||||
Executable
+4
@@ -0,0 +1,4 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# Build Path: /app/.heroku/python/
|
||||||
|
|
||||||
|
source $(dirname $0)/pypy2.7
|
||||||
@@ -13,11 +13,11 @@ dep_version=${dep_formula##*"/${dep_name}-"} # "subtract" our name from full ver
|
|||||||
dep_package=${dep_name}${dep_version_prefix:-}-v${dep_version}${dep_version_suffix:-}
|
dep_package=${dep_name}${dep_version_prefix:-}-v${dep_version}${dep_version_suffix:-}
|
||||||
dep_dirname=${dep_package}-linux64
|
dep_dirname=${dep_package}-linux64
|
||||||
dep_archive_name=${dep_dirname}.tar.bz2
|
dep_archive_name=${dep_dirname}.tar.bz2
|
||||||
dep_url=https://bitbucket.org/pypy/pypy/downloads/${dep_archive_name}
|
dep_url="https://downloads.python.org/pypy/${dep_archive_name}"
|
||||||
|
|
||||||
echo "Building PyPy3…"
|
echo "Building PyPy3…"
|
||||||
echo "${dep_url}"
|
echo "${dep_url}"
|
||||||
|
|
||||||
curl -L "${dep_url}" | tar jx -C "${OUT_PREFIX}" --strip-components 1 # extract to $OUT_PREFIX, drop the first directory level, which is the archive name
|
curl -fL "${dep_url}" | tar jx -C "${OUT_PREFIX}" --strip-components 1 # extract to $OUT_PREFIX, drop the first directory level, which is the archive name
|
||||||
|
|
||||||
ln "$OUT_PREFIX/bin/pypy3" "$OUT_PREFIX/bin/python"
|
ln "$OUT_PREFIX/bin/pypy3" "$OUT_PREFIX/bin/python"
|
||||||
|
|||||||
Executable
+4
@@ -0,0 +1,4 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# Build Path: /app/.heroku/python/
|
||||||
|
|
||||||
|
source $(dirname $0)/pypy3.6
|
||||||
Executable
+4
@@ -0,0 +1,4 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# Build Path: /app/.heroku/python/
|
||||||
|
|
||||||
|
source $(dirname $0)/python3
|
||||||
Executable
+4
@@ -0,0 +1,4 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# Build Path: /app/.heroku/python/
|
||||||
|
|
||||||
|
source $(dirname $0)/python3
|
||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
---
|
---
|
||||||
- - "./repos/python/python-getting-started"
|
- - "./repos/python/python-getting-started"
|
||||||
- master
|
- main
|
||||||
- - "./repos/python/python_default"
|
- - "./repos/python/python_default"
|
||||||
- ca947f69027b2a30be5d26f9a42f25e54f4d7a1a
|
- ca947f69027b2a30be5d26f9a42f25e54f4d7a1a
|
||||||
|
|||||||
+5
-2
@@ -1,3 +1,6 @@
|
|||||||
docopt==0.6.2
|
# Dependencies for generating/publishing Python binaries.
|
||||||
bob-builder==0.0.18
|
bob-builder==0.0.19
|
||||||
|
|
||||||
|
# Sub-dependencies of bob-builder.
|
||||||
boto==2.49.0
|
boto==2.49.0
|
||||||
|
docopt==0.6.2
|
||||||
|
|||||||
Vendored
-1
@@ -1 +0,0 @@
|
|||||||
python-3.6.6
|
|
||||||
+1
-1
@@ -6,4 +6,4 @@ verify_ssl = true
|
|||||||
requests = "*"
|
requests = "*"
|
||||||
|
|
||||||
[requires]
|
[requires]
|
||||||
python_full_version = "3.6.3"
|
python_full_version = "3.7.8"
|
||||||
|
|||||||
+2
-15
@@ -1,24 +1,11 @@
|
|||||||
{
|
{
|
||||||
"_meta": {
|
"_meta": {
|
||||||
"hash": {
|
"hash": {
|
||||||
"sha256": "22a052f4d1cfe6518b2f236fe45c3208c587a9ab1323bdd390632e27278b541e"
|
"sha256": "8a36860f0f9cb55716222098062cea5c5e0f8127cafb9d0c694de327bac9fbc0"
|
||||||
},
|
|
||||||
"host-environment-markers": {
|
|
||||||
"implementation_name": "cpython",
|
|
||||||
"implementation_version": "3.6.3",
|
|
||||||
"os_name": "posix",
|
|
||||||
"platform_machine": "x86_64",
|
|
||||||
"platform_python_implementation": "CPython",
|
|
||||||
"platform_release": "16.7.0",
|
|
||||||
"platform_system": "Darwin",
|
|
||||||
"platform_version": "Darwin Kernel Version 16.7.0: Thu Jun 15 17:36:27 PDT 2017; root:xnu-3789.70.16~2/RELEASE_X86_64",
|
|
||||||
"python_full_version": "3.6.3",
|
|
||||||
"python_version": "3.6",
|
|
||||||
"sys_platform": "darwin"
|
|
||||||
},
|
},
|
||||||
"pipfile-spec": 6,
|
"pipfile-spec": 6,
|
||||||
"requires": {
|
"requires": {
|
||||||
"python_full_version": "3.6.3"
|
"python_full_version": "3.7.8"
|
||||||
},
|
},
|
||||||
"sources": [
|
"sources": [
|
||||||
{
|
{
|
||||||
|
|||||||
Vendored
+1
-1
@@ -1 +1 @@
|
|||||||
pypy2.7-7.3.1
|
pypy2.7-7.3.2
|
||||||
|
|||||||
+1
-1
@@ -1 +1 @@
|
|||||||
pypy2.7-7.2.0
|
pypy2.7-7.3.1
|
||||||
|
|||||||
Vendored
+1
-1
@@ -1 +1 @@
|
|||||||
pypy3.6-7.3.1
|
pypy3.6-7.3.2
|
||||||
|
|||||||
+1
-1
@@ -1 +1 @@
|
|||||||
pypy3.6-7.2.0
|
pypy3.6-7.3.1
|
||||||
|
|||||||
-1
@@ -1 +0,0 @@
|
|||||||
requests
|
|
||||||
-1
@@ -1 +0,0 @@
|
|||||||
python-2.7.99
|
|
||||||
-1
@@ -1 +0,0 @@
|
|||||||
requests
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
flask
|
|
||||||
-1
@@ -1 +0,0 @@
|
|||||||
python-3.4.99
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
flask
|
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
flask
|
|
||||||
-1
@@ -1 +0,0 @@
|
|||||||
python-3.5.99
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
flask
|
|
||||||
|
|||||||
Vendored
+1
-1
@@ -1 +1 @@
|
|||||||
python-3.6.8
|
python-3.6.12
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
flask
|
|
||||||
-1
@@ -1 +0,0 @@
|
|||||||
python-3.6.99
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
requests
|
|
||||||
+1
-1
@@ -1 +1 @@
|
|||||||
python-3.6.7
|
python-3.6.11
|
||||||
|
|||||||
Vendored
+1
-1
@@ -1 +1 @@
|
|||||||
python-3.7.2
|
python-3.7.9
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
flask
|
|
||||||
-1
@@ -1 +0,0 @@
|
|||||||
python-3.7.99
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
requests
|
|
||||||
+1
-1
@@ -1 +1 @@
|
|||||||
python-3.7.1
|
python-3.7.8
|
||||||
|
|||||||
Vendored
+1
-1
@@ -1 +1 @@
|
|||||||
python-3.8.2
|
python-3.8.6
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
flask
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
requests
|
|
||||||
|
|||||||
+1
-1
@@ -1 +1 @@
|
|||||||
python-3.8.0
|
python-3.8.5
|
||||||
|
|||||||
Vendored
+1
@@ -0,0 +1 @@
|
|||||||
|
python-3.9.0
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
python-3.9.0
|
||||||
@@ -1 +0,0 @@
|
|||||||
flask
|
|
||||||
Vendored
+15
-17
@@ -21,16 +21,13 @@ testGEOS() {
|
|||||||
local env_dir="$(mktmpdir)"
|
local env_dir="$(mktmpdir)"
|
||||||
echo '1' > "${env_dir}/BUILD_WITH_GEO_LIBRARIES"
|
echo '1' > "${env_dir}/BUILD_WITH_GEO_LIBRARIES"
|
||||||
compile 'geos' '' "${env_dir}"
|
compile 'geos' '' "${env_dir}"
|
||||||
assertCaptured "geos"
|
if [[ $STACK == "heroku-20" ]]; then
|
||||||
assertCapturedSuccess
|
assertCaptured " ! The GDAL, GEOS and PROJ binaries and BUILD_WITH_GEO_LIBRARIES functonality is not supported on Heroku-20."
|
||||||
}
|
else
|
||||||
|
assertCaptured " ! The GDAL, GEOS and PROJ binaries and BUILD_WITH_GEO_LIBRARIES functonality are now deprecated."
|
||||||
testGEOSDeprecation() {
|
fi
|
||||||
local env_dir="$(mktmpdir)"
|
# This should assertCapturedError on Heroku-20, but the test doesn't actually
|
||||||
echo '1' > "${env_dir}/BUILD_WITH_GEO_LIBRARIES"
|
# install anything that uses GEOS so succeeds (see W-8145375)
|
||||||
compile 'geos' '' "${env_dir}"
|
|
||||||
assertCaptured " ! The GDAL, GEOS and PROJ binaries and BUILD_WITH_GEO_LIBRARIES functonality are now deprecated.
|
|
||||||
! An alternative buildpack to enable GDAL, GEOS and PROJ use is available here - https://github.com/heroku/heroku-geo-buildpack"
|
|
||||||
assertCapturedSuccess
|
assertCapturedSuccess
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -43,7 +40,9 @@ testNLTK() {
|
|||||||
echo 'ignore::RuntimeWarning' > "${env_dir}/PYTHONWARNINGS"
|
echo 'ignore::RuntimeWarning' > "${env_dir}/PYTHONWARNINGS"
|
||||||
compile 'nltk' '' "${env_dir}"
|
compile 'nltk' '' "${env_dir}"
|
||||||
assertCaptured "[nltk_data] Downloading package city_database" "STD_ERR"
|
assertCaptured "[nltk_data] Downloading package city_database" "STD_ERR"
|
||||||
assertCapturedSuccess
|
# Can't use `assertCapturedSuccess` since the NLTK downloader outputs all
|
||||||
|
# progress/status messages to stderr (W-8146040).
|
||||||
|
assertCapturedSuccessWithStdErr
|
||||||
}
|
}
|
||||||
|
|
||||||
testPsycopg2() {
|
testPsycopg2() {
|
||||||
@@ -53,17 +52,16 @@ testPsycopg2() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
testPysqlite() {
|
testPysqlite() {
|
||||||
|
# pysqlite does not support Python 3 (since the sqlite3 stdlib can be used there),
|
||||||
|
# so we have to test with Python 2, which we've not made available for Heroku-20.
|
||||||
|
if [[ $STACK == "heroku-20" ]]; then
|
||||||
|
return
|
||||||
|
fi
|
||||||
compile "pysqlite"
|
compile "pysqlite"
|
||||||
assertCaptured "pysqlite"
|
assertCaptured "pysqlite"
|
||||||
assertCapturedSuccess
|
assertCapturedSuccess
|
||||||
}
|
}
|
||||||
|
|
||||||
testSqliteInstall() {
|
|
||||||
compile "pythonDefault"
|
|
||||||
assertNotCaptured "Sqlite3 failed to install."
|
|
||||||
assertCapturedSuccess
|
|
||||||
}
|
|
||||||
|
|
||||||
testCffi() {
|
testCffi() {
|
||||||
compile "cffi"
|
compile "cffi"
|
||||||
assertCaptured "cffi"
|
assertCaptured "cffi"
|
||||||
|
|||||||
+34
-13
@@ -33,7 +33,9 @@ testStackChange() {
|
|||||||
testSetupPy() {
|
testSetupPy() {
|
||||||
compile "setup-py"
|
compile "setup-py"
|
||||||
assertCaptured "maya"
|
assertCaptured "maya"
|
||||||
assertCapturedSuccess
|
# Can't use `assertCapturedSuccess` since stderr contains:
|
||||||
|
# "cp: cannot stat '/tmp/build_*/requirements.txt': No such file or directory" (W-7924941)
|
||||||
|
assertCapturedSuccessWithStdErr
|
||||||
}
|
}
|
||||||
|
|
||||||
testStandardRequirements() {
|
testStandardRequirements() {
|
||||||
@@ -45,29 +47,48 @@ testStandardRequirements() {
|
|||||||
testPipenv() {
|
testPipenv() {
|
||||||
compile "pipenv"
|
compile "pipenv"
|
||||||
assertCaptured "Installing pip 9.0.2, setuptools 47.1.1 and wheel 0.34.2"
|
assertCaptured "Installing pip 9.0.2, setuptools 47.1.1 and wheel 0.34.2"
|
||||||
assertCapturedSuccess
|
# Can't use `assertCapturedSuccess` since stderr contains:
|
||||||
|
# "cp: cannot stat '/tmp/build_*/requirements.txt': No such file or directory" (W-7924941)
|
||||||
|
assertCapturedSuccessWithStdErr
|
||||||
}
|
}
|
||||||
|
|
||||||
testPipenvLock() {
|
testPipenvLock() {
|
||||||
compile "pipenv-lock"
|
compile "pipenv-lock"
|
||||||
assertCapturedSuccess
|
# Can't use `assertCapturedSuccess` since stderr contains:
|
||||||
|
# "cp: cannot stat '/tmp/build_*/requirements.txt': No such file or directory" (W-7924941)
|
||||||
|
assertCapturedSuccessWithStdErr
|
||||||
}
|
}
|
||||||
|
|
||||||
testPipenvVersion() {
|
testPipenvPythonVersion3_6() {
|
||||||
compile "pipenv-version"
|
compile "pipenv-version"
|
||||||
assertCaptured $DEFAULT_PYTHON_VERSION
|
assertCaptured "Installing ${LATEST_36}"
|
||||||
assertCapturedSuccess
|
# Can't use `assertCapturedSuccess` since stderr contains:
|
||||||
|
# "cp: cannot stat '/tmp/build_*/requirements.txt': No such file or directory" (W-7924941)
|
||||||
|
assertCapturedSuccessWithStdErr
|
||||||
}
|
}
|
||||||
|
|
||||||
testPipenvVersion2() {
|
testPipenvPythonVersion2_7() {
|
||||||
|
# Python 2.7 is EOL, so it has not been built for Heroku-20.
|
||||||
|
if [[ $STACK == "heroku-20" ]]; then
|
||||||
|
return
|
||||||
|
fi
|
||||||
compile "pipenv-version2"
|
compile "pipenv-version2"
|
||||||
assertCaptured $LATEST_27
|
assertCaptured "Installing ${LATEST_27}"
|
||||||
assertCapturedSuccess
|
# Can't use `assertCapturedSuccess` since stderr contains:
|
||||||
|
# "cp: cannot stat '/tmp/build_*/requirements.txt': No such file or directory" (W-7924941)
|
||||||
|
assertCapturedSuccessWithStdErr
|
||||||
}
|
}
|
||||||
testPipenvFullVersion() {
|
|
||||||
|
testPipenvPythonFullVersion() {
|
||||||
|
# Python 3.7+ requires newer libssl than is present on Cedar-14.
|
||||||
|
if [[ "${STACK}" = "cedar-14" ]]; then
|
||||||
|
return
|
||||||
|
fi
|
||||||
compile "pipenv-full-version"
|
compile "pipenv-full-version"
|
||||||
assertCaptured "3.6.3"
|
assertCaptured "3.7.8"
|
||||||
assertCapturedSuccess
|
# Can't use `assertCapturedSuccess` since stderr contains:
|
||||||
|
# "cp: cannot stat '/tmp/build_*/requirements.txt': No such file or directory" (W-7924941)
|
||||||
|
assertCapturedSuccessWithStdErr
|
||||||
}
|
}
|
||||||
|
|
||||||
testNoRequirements() {
|
testNoRequirements() {
|
||||||
@@ -113,10 +134,10 @@ testHooks() {
|
|||||||
PROFILE_PATH
|
PROFILE_PATH
|
||||||
PWD
|
PWD
|
||||||
PYTHONUNBUFFERED
|
PYTHONUNBUFFERED
|
||||||
|
S3_BASE_URL
|
||||||
SHLVL
|
SHLVL
|
||||||
SOME_APP_CONFIG_VAR
|
SOME_APP_CONFIG_VAR
|
||||||
STACK
|
STACK
|
||||||
VENDOR_URL
|
|
||||||
)
|
)
|
||||||
if [[ "${STACK}" == "cedar-14" || "${STACK}" == "heroku-16" ]]; then
|
if [[ "${STACK}" == "cedar-14" || "${STACK}" == "heroku-16" ]]; then
|
||||||
# Remove "OLDPWD" from expected_env_vars since for bash <4.4 it's not exported to subshells:
|
# Remove "OLDPWD" from expected_env_vars since for bash <4.4 it's not exported to subshells:
|
||||||
|
|||||||
+166
-126
@@ -4,67 +4,78 @@
|
|||||||
# shellcheck source=bin/default_pythons
|
# shellcheck source=bin/default_pythons
|
||||||
source "bin/default_pythons"
|
source "bin/default_pythons"
|
||||||
|
|
||||||
testPythonDefault() {
|
testPythonVersionUnspecified() {
|
||||||
updateVersion "pythonDefault" $DEFAULT_PYTHON_VERSION
|
compile "python_version_unspecified"
|
||||||
compile "pythonDefault"
|
assertCaptured "Installing ${DEFAULT_PYTHON_VERSION}"
|
||||||
assertCaptured $DEFAULT_PYTHON_VERSION
|
|
||||||
assertNotCaptured "security update"
|
assertNotCaptured "security update"
|
||||||
assertCaptured "Installing pip 20.1.1, setuptools 47.1.1 and wheel 0.34.2"
|
assertCaptured "Installing pip 20.1.1, setuptools 47.1.1 and wheel 0.34.2"
|
||||||
assertCaptured "Installing SQLite3"
|
assertCaptured "Installing SQLite3"
|
||||||
assertCapturedSuccess
|
assertCapturedSuccess
|
||||||
}
|
}
|
||||||
|
|
||||||
testPython2() {
|
testPython2_7() {
|
||||||
updateVersion "python2" $LATEST_27
|
# Python 2.7 is EOL, so it has not been built for Heroku-20.
|
||||||
echo $LATEST_27 > "runtime.txt"
|
if [[ $STACK == "heroku-20" ]]; then
|
||||||
compile "python2"
|
return
|
||||||
assertCaptured $LATEST_27
|
fi
|
||||||
assertCaptured "python-2-7-eol-faq";
|
compile "python2"
|
||||||
assertNotCaptured "security update"
|
assertCaptured "Installing ${LATEST_27}"
|
||||||
assertCaptured "Installing pip 20.1.1, setuptools 44.1.1 and wheel 0.34.2"
|
assertCaptured "python-2-7-eol-faq";
|
||||||
assertCaptured "Installing SQLite3"
|
assertNotCaptured "security update"
|
||||||
assertCapturedSuccess
|
assertCaptured "Installing pip 20.1.1, setuptools 44.1.1 and wheel 0.34.2"
|
||||||
|
assertCaptured "Installing SQLite3"
|
||||||
|
assertCapturedSuccess
|
||||||
}
|
}
|
||||||
|
|
||||||
testPython2_warn() {
|
testPython2_7_warn() {
|
||||||
compile "python2_warn"
|
# Python 2.7 is EOL, so it has not been built for Heroku-20.
|
||||||
assertCaptured "python-2.7.15"
|
if [[ $STACK == "heroku-20" ]]; then
|
||||||
assertCaptured "python-2-7-eol-faq";
|
return
|
||||||
assertCaptured "Only the latest version"
|
fi
|
||||||
assertCaptured "Installing SQLite3"
|
compile "python2_warn"
|
||||||
assertCapturedSuccess
|
assertCaptured "Installing python-2.7.15"
|
||||||
}
|
assertCaptured "python-2-7-eol-faq";
|
||||||
|
assertCaptured "Only the latest version"
|
||||||
testPython2_fail() {
|
assertCaptured "${LATEST_27}"
|
||||||
compile "python2_fail"
|
assertCapturedSuccess
|
||||||
assertCaptured "Aborting"
|
|
||||||
assertCapturedError
|
|
||||||
}
|
}
|
||||||
|
|
||||||
testPython3_4() {
|
testPython3_4() {
|
||||||
|
# Python 3.4 is EOL, so it has not been built for Heroku-20.
|
||||||
|
if [[ $STACK == "heroku-20" ]]; then
|
||||||
|
return
|
||||||
|
fi
|
||||||
compile "python3_4"
|
compile "python3_4"
|
||||||
assertCaptured $LATEST_34
|
assertCaptured "Installing ${LATEST_34}"
|
||||||
assertNotCaptured "security update"
|
assertNotCaptured "security update"
|
||||||
assertCaptured "Installing pip 19.1.1, setuptools 43.0.0 and wheel 0.33.6"
|
assertCaptured "Installing pip 19.1.1, setuptools 43.0.0 and wheel 0.33.6"
|
||||||
assertCapturedSuccess
|
assertCaptured "Installing SQLite3"
|
||||||
|
# Can't use `assertCapturedSuccess` since Pip outputs a Python 3.4 EOL warning to stderr,
|
||||||
|
# and the newest Pip that works on Python 3.4 doesn't support `PIP_NO_PYTHON_VERSION_WARNING`.
|
||||||
|
assertCapturedSuccessWithStdErr
|
||||||
}
|
}
|
||||||
|
|
||||||
testPython3_4_warn() {
|
testPython3_4_warn() {
|
||||||
|
# Python 3.4 is EOL, so it has not been built for Heroku-20.
|
||||||
|
if [[ $STACK == "heroku-20" ]]; then
|
||||||
|
return
|
||||||
|
fi
|
||||||
compile "python3_4_warn"
|
compile "python3_4_warn"
|
||||||
assertCaptured "python-3.4.9"
|
assertCaptured "Installing python-3.4.9"
|
||||||
assertCaptured "security update!"
|
assertCaptured "security update!"
|
||||||
assertCapturedSuccess
|
assertCaptured "${LATEST_34}"
|
||||||
}
|
# Can't use `assertCapturedSuccess` since Pip outputs a Python 3.4 EOL warning to stderr,
|
||||||
|
# and the newest Pip that works on Python 3.4 doesn't support `PIP_NO_PYTHON_VERSION_WARNING`.
|
||||||
testPython3_4_fail() {
|
assertCapturedSuccessWithStdErr
|
||||||
compile "python3_4_fail"
|
|
||||||
assertCaptured "Aborting"
|
|
||||||
assertCapturedError
|
|
||||||
}
|
}
|
||||||
|
|
||||||
testPython3_5() {
|
testPython3_5() {
|
||||||
|
# Python 3.5 is EOL, so it has not been built for Heroku-20.
|
||||||
|
if [[ $STACK == "heroku-20" ]]; then
|
||||||
|
return
|
||||||
|
fi
|
||||||
compile "python3_5"
|
compile "python3_5"
|
||||||
assertCaptured $LATEST_35
|
assertCaptured "Installing ${LATEST_35}"
|
||||||
assertNotCaptured "security update"
|
assertNotCaptured "security update"
|
||||||
assertCaptured "Installing pip 20.1.1, setuptools 47.1.1 and wheel 0.34.2"
|
assertCaptured "Installing pip 20.1.1, setuptools 47.1.1 and wheel 0.34.2"
|
||||||
assertCaptured "Installing SQLite3"
|
assertCaptured "Installing SQLite3"
|
||||||
@@ -72,22 +83,20 @@ testPython3_5() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
testPython3_5_warn() {
|
testPython3_5_warn() {
|
||||||
|
# Python 3.5 is EOL, so it has not been built for Heroku-20.
|
||||||
|
if [[ $STACK == "heroku-20" ]]; then
|
||||||
|
return
|
||||||
|
fi
|
||||||
compile "python3_5_warn"
|
compile "python3_5_warn"
|
||||||
assertCaptured "python-3.5.6"
|
assertCaptured "Installing python-3.5.6"
|
||||||
assertCaptured "security update!"
|
assertCaptured "security update!"
|
||||||
|
assertCaptured "${LATEST_35}"
|
||||||
assertCapturedSuccess
|
assertCapturedSuccess
|
||||||
}
|
}
|
||||||
|
|
||||||
testPython3_5_fail() {
|
|
||||||
compile "python3_5_fail"
|
|
||||||
assertCaptured "Aborting"
|
|
||||||
assertCapturedError
|
|
||||||
}
|
|
||||||
|
|
||||||
testPython3_6() {
|
testPython3_6() {
|
||||||
updateVersion "python3_6" $LATEST_36
|
|
||||||
compile "python3_6"
|
compile "python3_6"
|
||||||
assertCaptured $LATEST_36
|
assertCaptured "Installing ${LATEST_36}"
|
||||||
assertNotCaptured "security update"
|
assertNotCaptured "security update"
|
||||||
assertCaptured "Installing pip 20.1.1, setuptools 47.1.1 and wheel 0.34.2"
|
assertCaptured "Installing pip 20.1.1, setuptools 47.1.1 and wheel 0.34.2"
|
||||||
assertCaptured "Installing SQLite3"
|
assertCaptured "Installing SQLite3"
|
||||||
@@ -96,122 +105,153 @@ testPython3_6() {
|
|||||||
|
|
||||||
testPython3_6_warn() {
|
testPython3_6_warn() {
|
||||||
compile "python3_6_warn"
|
compile "python3_6_warn"
|
||||||
assertCaptured "python-3.6.7"
|
assertCaptured "Installing python-3.6.11"
|
||||||
assertCaptured "security update!"
|
assertCaptured "security update!"
|
||||||
|
assertCaptured "${LATEST_36}"
|
||||||
|
assertCapturedSuccess
|
||||||
|
}
|
||||||
|
|
||||||
|
testPython3_7() {
|
||||||
|
# Python 3.7+ requires newer libssl than is present on Cedar-14.
|
||||||
|
if [[ "${STACK}" = "cedar-14" ]]; then
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
compile "python3_7"
|
||||||
|
assertCaptured "Installing ${LATEST_37}"
|
||||||
|
assertNotCaptured "security update"
|
||||||
|
assertCaptured "Installing pip 20.1.1, setuptools 47.1.1 and wheel 0.34.2"
|
||||||
assertCaptured "Installing SQLite3"
|
assertCaptured "Installing SQLite3"
|
||||||
assertCapturedSuccess
|
assertCapturedSuccess
|
||||||
}
|
}
|
||||||
|
|
||||||
testPython3_6_fail() {
|
|
||||||
compile "python3_6_fail"
|
|
||||||
assertCaptured "Aborting"
|
|
||||||
assertCapturedError
|
|
||||||
}
|
|
||||||
|
|
||||||
testPython3_7() {
|
|
||||||
updateVersion "python3_7" $LATEST_37
|
|
||||||
compile "python3_7"
|
|
||||||
if [[ $STACK = "cedar-14" ]]; then
|
|
||||||
assertCapturedError
|
|
||||||
else
|
|
||||||
assertNotCaptured "security update"
|
|
||||||
assertCaptured $LATEST_37
|
|
||||||
assertCaptured "Installing pip 20.1.1, setuptools 47.1.1 and wheel 0.34.2"
|
|
||||||
assertCaptured "Installing SQLite3"
|
|
||||||
assertCapturedSuccess
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
testPython3_7_warn() {
|
testPython3_7_warn() {
|
||||||
|
# Python 3.7+ requires newer libssl than is present on Cedar-14.
|
||||||
|
if [[ "${STACK}" = "cedar-14" ]]; then
|
||||||
|
return
|
||||||
|
fi
|
||||||
compile "python3_7_warn"
|
compile "python3_7_warn"
|
||||||
if [[ $STACK = "cedar-14" ]]; then
|
assertCaptured "Installing python-3.7.8"
|
||||||
assertCapturedError
|
assertCaptured "security update!"
|
||||||
else
|
assertCaptured "${LATEST_37}"
|
||||||
assertCaptured "python-3.7.1"
|
assertCapturedSuccess
|
||||||
assertCaptured "security update!"
|
|
||||||
assertCaptured "Installing SQLite3"
|
|
||||||
assertCapturedSuccess
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
testPython3_7_fail() {
|
|
||||||
compile "python3_7_fail"
|
|
||||||
assertCaptured "Aborting"
|
|
||||||
assertCapturedError
|
|
||||||
}
|
|
||||||
|
|
||||||
testPython3_7_warn() {
|
|
||||||
compile "python3_8_warn"
|
|
||||||
if [[ $STACK = "cedar-14" ]]; then
|
|
||||||
assertCapturedError
|
|
||||||
else
|
|
||||||
assertCaptured "python-3.8.0"
|
|
||||||
assertCaptured "security update!"
|
|
||||||
assertCaptured "Installing SQLite3"
|
|
||||||
assertCapturedSuccess
|
|
||||||
fi
|
|
||||||
}
|
}
|
||||||
|
|
||||||
testPython3_8() {
|
testPython3_8() {
|
||||||
updateVersion "python3_8" $LATEST_38
|
# Python 3.7+ requires newer libssl than is present on Cedar-14.
|
||||||
compile "python3_8"
|
if [[ "${STACK}" = "cedar-14" ]]; then
|
||||||
if [[ $STACK = "cedar-14" ]]; then
|
return
|
||||||
assertCapturedError
|
|
||||||
else
|
|
||||||
assertNotCaptured "security update"
|
|
||||||
assertCaptured $LATEST_38
|
|
||||||
assertCaptured "Installing pip 20.1.1, setuptools 47.1.1 and wheel 0.34.2"
|
|
||||||
assertCaptured "Installing SQLite3"
|
|
||||||
assertCapturedSuccess
|
|
||||||
fi
|
fi
|
||||||
|
compile "python3_8"
|
||||||
|
assertCaptured "Installing ${LATEST_38}"
|
||||||
|
assertNotCaptured "security update"
|
||||||
|
assertCaptured "Installing pip 20.1.1, setuptools 47.1.1 and wheel 0.34.2"
|
||||||
|
assertCaptured "Installing SQLite3"
|
||||||
|
assertCapturedSuccess
|
||||||
}
|
}
|
||||||
|
|
||||||
testPython3_8_fail() {
|
testPython3_8_warn() {
|
||||||
compile "python3_8_fail"
|
# Python 3.7+ requires newer libssl than is present on Cedar-14.
|
||||||
|
if [[ "${STACK}" = "cedar-14" ]]; then
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
compile "python3_8_warn"
|
||||||
|
assertCaptured "Installing python-3.8.5"
|
||||||
|
assertCaptured "security update!"
|
||||||
|
assertCaptured "${LATEST_38}"
|
||||||
|
assertCapturedSuccess
|
||||||
|
}
|
||||||
|
|
||||||
|
testPython3_9() {
|
||||||
|
# Cedar-14 is EOL, so we're not building new major Python versions for it.
|
||||||
|
if [[ "${STACK}" = "cedar-14" ]]; then
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
compile "python3_9"
|
||||||
|
assertCaptured "Installing ${LATEST_39}"
|
||||||
|
assertNotCaptured "security update"
|
||||||
|
assertCaptured "Installing pip 20.1.1, setuptools 47.1.1 and wheel 0.34.2"
|
||||||
|
assertCaptured "Installing SQLite3"
|
||||||
|
assertCapturedSuccess
|
||||||
|
}
|
||||||
|
|
||||||
|
testPython3_9_warn() {
|
||||||
|
# Cedar-14 is EOL, so we're not building new major Python versions for it.
|
||||||
|
if [[ "${STACK}" = "cedar-14" ]]; then
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
# Can't test the version warning until there is at least one old version of Python 3.9.
|
||||||
|
if [[ "${LATEST_39}" = "python-3.9.0" ]]; then
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
compile "python3_9_warn"
|
||||||
|
assertCaptured "Installing python-3.9.0"
|
||||||
|
assertCaptured "security update!"
|
||||||
|
assertCaptured "${LATEST_39}"
|
||||||
|
assertCapturedSuccess
|
||||||
|
}
|
||||||
|
|
||||||
|
testPythonVersionInvalid() {
|
||||||
|
compile "python_version_invalid"
|
||||||
|
assertCaptured "Requested runtime (python-3.8.99) is not available for this stack"
|
||||||
assertCaptured "Aborting"
|
assertCaptured "Aborting"
|
||||||
assertCapturedError
|
assertCapturedError
|
||||||
}
|
}
|
||||||
|
|
||||||
testPypy3_6() {
|
testPypy3_6() {
|
||||||
compile "pypy3_6"
|
compile "pypy3_6"
|
||||||
assertCaptured "Installing pypy"
|
assertCaptured "Installing ${LATEST_PYPY_36}"
|
||||||
assertNotCaptured "security update"
|
assertNotCaptured "security update"
|
||||||
assertCaptured "$LATEST_PYPY_36"
|
|
||||||
assertCaptured "Installing pip 20.1.1, setuptools 47.1.1 and wheel 0.34.2"
|
assertCaptured "Installing pip 20.1.1, setuptools 47.1.1 and wheel 0.34.2"
|
||||||
assertCapturedSuccess
|
assertCapturedSuccess
|
||||||
}
|
}
|
||||||
|
|
||||||
testPypy3_6_warn() {
|
testPypy3_6_warn() {
|
||||||
compile "pypy3_6_warn"
|
compile "pypy3_6_warn"
|
||||||
if [[ $STACK = "cedar-14" ]]; then
|
assertCaptured "Installing pypy3.6-7.3.1"
|
||||||
assertCapturedError
|
assertCaptured "security update!"
|
||||||
else
|
assertCaptured "${LATEST_PYPY_36}"
|
||||||
assertCaptured "Installing pypy"
|
assertCapturedSuccess
|
||||||
assertCaptured "security update!"
|
|
||||||
assertCaptured "$LATEST_PYPY_36"
|
|
||||||
assertCapturedSuccess
|
|
||||||
fi
|
|
||||||
}
|
}
|
||||||
|
|
||||||
testPypy2_7() {
|
testPypy2_7() {
|
||||||
compile "pypy2_7"
|
compile "pypy2_7"
|
||||||
assertCaptured "Installing pypy"
|
assertCaptured "Installing ${LATEST_PYPY_27}"
|
||||||
assertNotCaptured "security update"
|
assertNotCaptured "security update"
|
||||||
assertCaptured "$LATEST_PYPY_27"
|
|
||||||
assertCaptured "Installing pip 20.1.1, setuptools 44.1.1 and wheel 0.34.2"
|
assertCaptured "Installing pip 20.1.1, setuptools 44.1.1 and wheel 0.34.2"
|
||||||
assertCapturedSuccess
|
assertCapturedSuccess
|
||||||
}
|
}
|
||||||
|
|
||||||
testPypy2_7_warn() {
|
testPypy2_7_warn() {
|
||||||
compile "pypy2_7_warn"
|
compile "pypy2_7_warn"
|
||||||
if [[ $STACK = "cedar-14" ]]; then
|
assertCaptured "Installing pypy2.7-7.3.1"
|
||||||
assertCapturedError
|
assertCaptured "security update!"
|
||||||
else
|
assertCaptured "${LATEST_PYPY_27}"
|
||||||
assertCaptured "Installing pypy"
|
assertCapturedSuccess
|
||||||
assertCaptured "security update!"
|
}
|
||||||
assertCaptured "$LATEST_PYPY_27"
|
|
||||||
assertCapturedSuccess
|
testStickyPythonVersion() {
|
||||||
fi
|
local cache_dir="$(mktmpdir)"
|
||||||
|
compile "python3_6_warn" "$cache_dir"
|
||||||
|
assertCaptured "Installing python-3.6.11"
|
||||||
|
assertCapturedSuccess
|
||||||
|
compile "python_version_unspecified" "$cache_dir"
|
||||||
|
assertNotCaptured "Installing python"
|
||||||
|
assertCaptured "security update!"
|
||||||
|
assertCapturedSuccess
|
||||||
|
# Whilst this file seems like an implementation detail (so something that should
|
||||||
|
# not be tested), we must guarantee the filename remains consistent for backwards
|
||||||
|
# compatibility across buildpack versions for already-built apps.
|
||||||
|
assertFile "python-3.6.11" ".heroku/python-version"
|
||||||
|
}
|
||||||
|
|
||||||
|
testPythonVersionChange() {
|
||||||
|
local cache_dir="$(mktmpdir)"
|
||||||
|
compile "python3_6_warn" "$cache_dir"
|
||||||
|
assertCaptured "Installing python-3.6.11"
|
||||||
|
assertCapturedSuccess
|
||||||
|
compile "python3_6" "$cache_dir"
|
||||||
|
assertCaptured "Found python-3.6.11, removing"
|
||||||
|
assertCapturedSuccess
|
||||||
}
|
}
|
||||||
|
|
||||||
pushd $(dirname 0) >/dev/null
|
pushd $(dirname 0) >/dev/null
|
||||||
|
|||||||
+21
-13
@@ -56,11 +56,6 @@ resetCapture()
|
|||||||
unset rtrn # deprecated
|
unset rtrn # deprecated
|
||||||
}
|
}
|
||||||
|
|
||||||
updateVersion()
|
|
||||||
{
|
|
||||||
echo "$2" > "test/fixtures/${1}/runtime.txt"
|
|
||||||
}
|
|
||||||
|
|
||||||
assertCapturedEquals()
|
assertCapturedEquals()
|
||||||
{
|
{
|
||||||
assertEquals "$@" "$(cat ${STD_OUT})"
|
assertEquals "$@" "$(cat ${STD_OUT})"
|
||||||
@@ -85,12 +80,20 @@ assertNotCaptured()
|
|||||||
assertCapturedSuccess()
|
assertCapturedSuccess()
|
||||||
{
|
{
|
||||||
assertEquals "Captured exit code -" "0" "${RETURN}"
|
assertEquals "Captured exit code -" "0" "${RETURN}"
|
||||||
# assertEquals "STD_ERR -" "" "$(cat ${STD_ERR})"
|
assertEquals "STD_ERR -" "" "$(cat ${STD_ERR})"
|
||||||
|
|
||||||
if [ $RETURN -ne 0 -a -z "$(cat ${STD_ERR})" ]; then
|
if [ $RETURN -ne 0 -o -n "$(cat ${STD_ERR})" ]; then
|
||||||
# Failing exit code but stderr was empty. Display stdout to help debugging.
|
debug
|
||||||
cat $STD_OUT
|
fi
|
||||||
echo
|
}
|
||||||
|
|
||||||
|
assertCapturedSuccessWithStdErr()
|
||||||
|
{
|
||||||
|
assertEquals "Captured exit code -" "0" "${RETURN}"
|
||||||
|
assertNotEquals "STD_ERR -" "" "$(cat ${STD_ERR})"
|
||||||
|
|
||||||
|
if [ ${RETURN} -ne 0 ]; then
|
||||||
|
debug
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -151,9 +154,14 @@ _assertContains()
|
|||||||
|
|
||||||
debug()
|
debug()
|
||||||
{
|
{
|
||||||
cat $STD_OUT
|
echo
|
||||||
echo '^^^^^^'
|
echo '### STD_OUT ###'
|
||||||
cat $STD_ERR
|
cat "${STD_OUT}"
|
||||||
|
echo
|
||||||
|
echo '### STD_ERR ###'
|
||||||
|
cat "${STD_ERR}"
|
||||||
|
echo
|
||||||
|
echo
|
||||||
}
|
}
|
||||||
|
|
||||||
assertContains()
|
assertContains()
|
||||||
|
|||||||
Vendored
-1048
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user