mirror of
https://github.com/kennethreitz/heroku-buildpack-python.git
synced 2026-06-05 23:10:16 +00:00
7279ddded8
Previously the pip/setuptools/wheel install step was skipped so long as Python hadn't just been clean installed (ie so long as not a new app, emptied cache, Python upgrade, stack change) and pip was the expected version. This meant that setuptool/wheel could be the wrong version (or even just not installed at all), and this would not be corrected. Now, we now use pip itself to determine whether the installed packages are up to date, since parsing pip's output is fragile (eg #1003) and would be tedious given there would be three packages to check. Unfortunately `get-pip.py` uses `--force-reinstall` which means performing this step every time is not the no-op it would otherwise be, but this will be resolved by switching away from `get-pip.py` in the next commit. Fixes #1000. Fixes #1003. Closes #999.
170 lines
6.3 KiB
Bash
Executable File
170 lines
6.3 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
|
|
set +e
|
|
runtime-fixer runtime.txt
|
|
PYTHON_VERSION=$(cat runtime.txt)
|
|
|
|
# The location of the pre-compiled python binary.
|
|
VENDORED_PYTHON="${VENDOR_URL}/runtimes/$PYTHON_VERSION.tar.gz"
|
|
|
|
SECURITY_UPDATE="Python has released a security update! Please consider upgrading to"
|
|
|
|
ONLY_SUPPORTED_2_VERSION="Only the latest version of Python 2 is supported on the platform. Please consider upgrading to"
|
|
|
|
PYTHON_2_EOL_UPDATE="Python 2 has reached it's community EOL. Upgrade your Python runtime to maintain a secure application as soon as possible."
|
|
|
|
# check if runtime exists
|
|
if curl --output /dev/null --silent --head --fail "$VENDORED_PYTHON"; then
|
|
if [[ "$PYTHON_VERSION" == $PY38* ]]; then
|
|
# do things to alert the user of security release available
|
|
if [ "$PYTHON_VERSION" != "$LATEST_38" ]; then
|
|
puts-warn "$SECURITY_UPDATE" "$LATEST_38"
|
|
echo " Learn More: https://devcenter.heroku.com/articles/python-runtimes"
|
|
fi
|
|
fi
|
|
if [[ "$PYTHON_VERSION" == $PY37* ]]; then
|
|
# do things to alert the user of security release available
|
|
if [ "$PYTHON_VERSION" != "$LATEST_37" ]; then
|
|
puts-warn "$SECURITY_UPDATE" "$LATEST_37"
|
|
echo " Learn More: https://devcenter.heroku.com/articles/python-runtimes"
|
|
fi
|
|
fi
|
|
if [[ "$PYTHON_VERSION" == $PY36* ]]; then
|
|
# security update note
|
|
if [ "$PYTHON_VERSION" != "$LATEST_36" ]; then
|
|
puts-warn "$SECURITY_UPDATE" "$LATEST_36"
|
|
echo " Learn More: https://devcenter.heroku.com/articles/python-runtimes"
|
|
fi
|
|
fi
|
|
if [[ "$PYTHON_VERSION" == $PY35* ]]; then
|
|
# security update note
|
|
if [ "$PYTHON_VERSION" != "$LATEST_35" ]; then
|
|
puts-warn "$SECURITY_UPDATE" "$LATEST_35"
|
|
echo " Learn More: https://devcenter.heroku.com/articles/python-runtimes"
|
|
fi
|
|
fi
|
|
if [[ "$PYTHON_VERSION" == $PY34* ]]; then
|
|
# security update note
|
|
if [ "$PYTHON_VERSION" != "$LATEST_34" ]; then
|
|
puts-warn "$SECURITY_UPDATE" "$LATEST_34"
|
|
echo " Learn More: https://devcenter.heroku.com/articles/python-runtimes"
|
|
fi
|
|
fi
|
|
if [[ "$PYTHON_VERSION" == $PY27* ]]; then
|
|
# security update note
|
|
if [[ "$(date "+%Y")" -gt "2019" ]]; then
|
|
puts-warn "$PYTHON_2_EOL_UPDATE"
|
|
echo " Learn More: https://devcenter.heroku.com/articles/python-2-7-eol-faq"
|
|
fi
|
|
if [ "$PYTHON_VERSION" != "$LATEST_27" ]; then
|
|
puts-warn "$ONLY_SUPPORTED_2_VERSION" "$LATEST_27"
|
|
echo " Learn More: https://devcenter.heroku.com/articles/python-runtimes"
|
|
fi
|
|
fi
|
|
if [[ "$PYTHON_VERSION" == $PYPY27* ]]; then
|
|
# security update note
|
|
if [ "$PYTHON_VERSION" != "$PYPY_27" ]; then
|
|
puts-warn "Could not find that Pypy version. Did you mean" "${PYPY_27}?"
|
|
echo " Learn More: https://devcenter.heroku.com/articles/python-runtimes"
|
|
fi
|
|
fi
|
|
if [[ "$PYTHON_VERSION" == $PYPY36* ]]; then
|
|
# security update note
|
|
if [ "$PYTHON_VERSION" != "$PYPY_36" ]; then
|
|
puts-warn "Could not find that Pypy version. Did you mean" "${PYPY_36}?"
|
|
echo " Learn More: https://devcenter.heroku.com/articles/python-runtimes"
|
|
fi
|
|
fi
|
|
else
|
|
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"
|
|
exit 1
|
|
fi
|
|
|
|
if [[ "$STACK" != "$CACHED_PYTHON_STACK" ]]; then
|
|
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
|
|
fi
|
|
|
|
if [ -f .heroku/python-version ]; then
|
|
if [ ! "$(cat .heroku/python-version)" = "$PYTHON_VERSION" ]; then
|
|
puts-step "Found $(cat .heroku/python-version), removing"
|
|
rm -fr .heroku/python
|
|
else
|
|
SKIP_INSTALL=1
|
|
fi
|
|
fi
|
|
|
|
# Check if we should reinstall python dependencies
|
|
if [[ ! -f "$CACHE_DIR/.heroku/requirements.txt" ]]; then
|
|
# IF there's no cached dependencies, update cached version of requirements.txt
|
|
# This should only run for new apps and first deploys after this update
|
|
cp -R "$BUILD_DIR/requirements.txt" "$CACHE_DIR/.heroku/requirements.txt"
|
|
else
|
|
# IF there IS a cached directory, check for differences with the new one
|
|
if ! diff "$BUILD_DIR/requirements.txt" "$CACHE_DIR/.heroku/requirements.txt" &> /dev/null; then
|
|
puts-step "Requirements file has been changed, clearing cached dependencies"
|
|
# if there are any differences, clear the Python cache
|
|
# Installing Python over again does not take noticably more time
|
|
cp -R "$BUILD_DIR/requirements.txt" "$CACHE_DIR/.heroku/requirements.txt"
|
|
rm -rf .heroku/python
|
|
unset SKIP_INSTALL
|
|
else
|
|
puts-step "No change in requirements detected, installing from cache"
|
|
fi
|
|
fi
|
|
|
|
if [ ! "$SKIP_INSTALL" ]; then
|
|
puts-step "Installing $PYTHON_VERSION"
|
|
|
|
# Prepare destination directory.
|
|
mkdir -p .heroku/python
|
|
|
|
mcount "version.python.$PYTHON_VERSION"
|
|
|
|
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 "Aborting. More info: https://devcenter.heroku.com/articles/python-support"
|
|
exit 1
|
|
fi
|
|
|
|
# Record for future reference.
|
|
echo "$PYTHON_VERSION" > .heroku/python-version
|
|
echo "$STACK" > .heroku/python-stack
|
|
|
|
hash -r
|
|
fi
|
|
|
|
PIP_VERSION='20.0.2'
|
|
SETUPTOOLS_VERSION='39.0.1'
|
|
WHEEL_VERSION='0.34.2'
|
|
|
|
if [[ "${PYTHON_VERSION}" == ${PY34}* ]]; then
|
|
# Python 3.4 support was dropped in pip 19.2+ and wheel 0.34.0+.
|
|
PIP_VERSION='19.1.1'
|
|
WHEEL_VERSION='0.33.6'
|
|
fi
|
|
|
|
if [[ -f "$BUILD_DIR/Pipfile" ]]; then
|
|
# The buildpack is pinned to old pipenv, which requires older pip.
|
|
PIP_VERSION='9.0.2'
|
|
fi
|
|
|
|
# Heroku uses the get-pip utility maintained by the Python community to vendor Pip.
|
|
# https://github.com/pypa/get-pip
|
|
GETPIP_URL="https://lang-python.s3.amazonaws.com/etc/get-pip.py"
|
|
GETPIP_PY="${TMPDIR:-/tmp}/get-pip.py"
|
|
|
|
if ! curl -s "${GETPIP_URL}" -o "$GETPIP_PY" &> /dev/null; then
|
|
mcount "failure.python.get-pip"
|
|
echo "Failed to pull down get-pip"
|
|
exit 1
|
|
fi
|
|
|
|
puts-step "Installing pip ${PIP_VERSION}, setuptools ${SETUPTOOLS_VERSION} and wheel ${WHEEL_VERSION}"
|
|
|
|
/app/.heroku/python/bin/python "$GETPIP_PY" pip=="${PIP_VERSION}" "setuptools==${SETUPTOOLS_VERSION}" "wheel==${WHEEL_VERSION}" &> /dev/null
|
|
|
|
set -e
|
|
hash -r
|