mirror of
https://github.com/kennethreitz/heroku-buildpack-python.git
synced 2026-06-05 23:10:16 +00:00
64abfb2978
Previously the metric events describing the chosen Python version were only emitted when that Python version was installed, and not when it was being used from the build cache (the common case). Now the version is emitted for all builds, improving visibility into the distribution of Python usage, and helping determine the priority of features like opt-in automatic Python patch updates. Closes @W-8059668@.
188 lines
7.4 KiB
Bash
Executable File
188 lines
7.4 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"
|
|
SECURITY_UPDATE_PYPY="The PyPy project 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
|
|
puts-warn "$PYTHON_2_EOL_UPDATE"
|
|
echo " Learn More: https://devcenter.heroku.com/articles/python-2-7-eol-faq"
|
|
# security update note
|
|
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" != "$LATEST_PYPY_27" ]; then
|
|
puts-warn "$SECURITY_UPDATE_PYPY" "$LATEST_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" != "$LATEST_PYPY_36" ]; then
|
|
puts-warn "$SECURITY_UPDATE_PYPY" "$LATEST_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
|
|
|
|
mcount "version.python.${PYTHON_VERSION}"
|
|
|
|
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
|
|
|
|
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
|
|
|
|
set -e
|
|
|
|
PIP_VERSION='20.1.1'
|
|
# Must use setuptools <47.2.0 until we fix:
|
|
# https://github.com/heroku/heroku-buildpack-python/issues/1006
|
|
SETUPTOOLS_VERSION='47.1.1'
|
|
WHEEL_VERSION='0.34.2'
|
|
|
|
if [[ "${PYTHON_VERSION}" == ${PY34}* ]]; then
|
|
# Python 3.4 support was dropped in pip 19.2+, setuptools 44+ and wheel 0.34+.
|
|
PIP_VERSION='19.1.1'
|
|
SETUPTOOLS_VERSION='43.0.0'
|
|
WHEEL_VERSION='0.33.6'
|
|
elif [[ "${PYTHON_VERSION}" == ${PY27}* || "${PYTHON_VERSION}" == ${PYPY27}* ]]; then
|
|
# Python 2.7 support was dropped in setuptools 45+.
|
|
SETUPTOOLS_VERSION='44.1.1'
|
|
fi
|
|
|
|
# We don't use get-pip.py, since:
|
|
# - it uses `--force-reinstall`, which is unnecessary here and slows down repeat builds
|
|
# - it means downloading pip twice (once embedded in get-pip.py, and again during
|
|
# the install, since get-pip.py can't install the embedded version directly)
|
|
# - we would still have to manage several versions of get-pip.py, to support older Pythons.
|
|
# Instead, we use the pip wheel to install itself, using the method described here:
|
|
# https://github.com/pypa/pip/issues/2351#issuecomment-69994524
|
|
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="${TMPDIR:-/tmp}/${PIP_WHEEL_FILENAME}"
|
|
|
|
if ! curl -sSf "${PIP_WHEEL_URL}" -o "$PIP_WHEEL"; then
|
|
mcount "failure.python.download-pip"
|
|
puts-warn "Failed to download pip"
|
|
exit 1
|
|
fi
|
|
|
|
if [[ -f "$BUILD_DIR/Pipfile" ]]; then
|
|
# The buildpack is pinned to old pipenv, which requires older pip.
|
|
# Pip 9.0.2 doesn't support installing itself from a wheel, so we have to use split
|
|
# versions here (ie: installer pip version different from target pip version).
|
|
PIP_VERSION='9.0.2'
|
|
PIP_TO_INSTALL="pip==${PIP_VERSION}"
|
|
else
|
|
PIP_TO_INSTALL="${PIP_WHEEL}"
|
|
fi
|
|
|
|
puts-step "Installing pip ${PIP_VERSION}, setuptools ${SETUPTOOLS_VERSION} and wheel ${WHEEL_VERSION}"
|
|
|
|
/app/.heroku/python/bin/python "${PIP_WHEEL}/pip" install --quiet --disable-pip-version-check --no-cache \
|
|
"${PIP_TO_INSTALL}" "setuptools==${SETUPTOOLS_VERSION}" "wheel==${WHEEL_VERSION}"
|
|
|
|
hash -r
|