diff --git a/bin/compile b/bin/compile index d97af680d5428c3abb0d5f72444608a72df2248e..451a28680bc4bded63129177c9c6f7280731514b 100755 --- a/bin/compile +++ b/bin/compile @@ -52,14 +52,22 @@ export VENDOR_URL DEFAULT_PYTHON_VERSION="python-3.6.6" LATEST_36="python-3.6.6" LATEST_37="python-3.7.0" +LATEST_35="python-3.5.6" LATEST_2="python-2.7.15" +# Supported Python Branches +PY37="python-3.7" +PY36="python-3.6" +PY35="python-3.5" +PY27="python-2.7" + # Which stack is used (for binary downloading), if none is provided (e.g. outside of Heroku)? DEFAULT_PYTHON_STACK="cedar-14" # If pip doesn't match this version (the version we install), run the installer. PIP_UPDATE="9.0.2" export DEFAULT_PYTHON_VERSION DEFAULT_PYTHON_STACK PIP_UPDATE LATEST_2 LATEST_36 LATEST_37 +export PY37 PY36 PY35 PY27 # Common Problem Warnings: # This section creates a temporary file in which to stick the output of `pip install`. diff --git a/bin/steps/python b/bin/steps/python index ea623b1bfdf72daef78dcb7c12bfa766f44e352a..d8e2c3afa44fed9ac85fbb15a1f6f9600e865343 100755 --- a/bin/steps/python +++ b/bin/steps/python @@ -7,43 +7,47 @@ PYTHON_VERSION=$(cat runtime.txt) # The location of the pre-compiled python binary. VENDORED_PYTHON="${VENDOR_URL}/runtimes/$PYTHON_VERSION.tar.gz" -if [[ $PYTHON_VERSION =~ ^python-2 ]]; then - if [[ "$PYTHON_VERSION" != "$LATEST_2" ]]; then - puts-warn "The latest version of Python 2 is $LATEST_2 (you are using $PYTHON_VERSION, which is unsupported)." - puts-warn "We recommend upgrading by specifying the latest version ($LATEST_2)." - echo " Learn More: https://devcenter.heroku.com/articles/python-runtimes" - else - echo " Using supported version of Python 2 ($PYTHON_VERSION)" +# "https://lang-python.s3.amazonaws.com/heroku-16/runtimes/python-3.6.6.tar.gz" + +SECURITY_UPDATE="Python has released a security update! Please consider upgrading to " + +# check if runtime exists +if curl --output /dev/null --silent --head --fail $VENDORED_PYTHON; then + 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 -else - if [[ $PYTHON_VERSION =~ ^python-3 ]]; then - if [[ $PYTHON_VERSION =~ ^python-3.7 ]]; then - if [[ "$PYTHON_VERSION" != "$LATEST_37" ]]; then - puts-warn "The latest version of Python 3.7 is $LATEST_37 (you are using $PYTHON_VERSION, which is unsupported)." - puts-warn "We recommend upgrading by specifying the latest version ($LATEST_37)." + 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" - else - echo " Using supported version of Python 3.7 ($PYTHON_VERSION)" - fi - else - if [[ $PYTHON_VERSION =~ ^python-3.6 ]]; then - if [[ "$PYTHON_VERSION" != "$LATEST_36" ]]; then - puts-warn "The latest version of Python 3.6 is $LATEST_36 (you are using $PYTHON_VERSION, which is unsupported)." - puts-warn "We recommend upgrading by specifying the latest version ($LATEST_36)." - echo " Learn More: https://devcenter.heroku.com/articles/python-runtimes" - else - echo " Using supported version of Python 3.6 ($PYTHON_VERSION)" - fi - else - puts-warn "Heroku supports runtime versions $LATEST_37, $LATEST_36 and $LATEST_2." - puts-warn "You are using $PYTHON_VERSION, which is unsupported." - puts-warn "We recommend upgrading by specifying the default supported version ($LATEST_36)." - echo " Learn More: https://devcenter.heroku.com/articles/python-runtimes" - fi fi fi + if [[ $PYTHON_VERSION == $PY27* ]]; then + # security update note + if [ $PYTHON_VERSION != $LATEST_27 ]; then + puts-warn SECURITY_UPDATE $LATEST_27 + 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 diff --git a/builds/runtimes/python-3.4.9 b/builds/runtimes/python-3.4.9 new file mode 100755 index 0000000000000000000000000000000000000000..00cf5078458461fed5ca810e06d864419674dd09 --- /dev/null +++ b/builds/runtimes/python-3.4.9 @@ -0,0 +1,32 @@ +#!/usr/bin/env bash +# Build Path: /app/.heroku/python/ + +OUT_PREFIX=$1 +BIN_DIR="$(cd "$(dirname "$0")"/../.. || exit; pwd)/bin" +export BIN_DIR + +# shellcheck source=bin/utils +source "$BIN_DIR/steps/sqlite3" + +sqlite3_version +echo "Setting up SQLite3 Headers for $SQLITE3_VERSION" +sqlite3_install "$OUT_PREFIX" "$SQLITE3_VERSION" 1 + +echo "Building Python…" +SOURCE_TARBALL='https://python.org/ftp/python/3.4.9/Python-3.4.9.tgz' +curl -L $SOURCE_TARBALL | tar xz +mv Python-3.4.9 src +cd src + +./configure --prefix=$OUT_PREFIX --with-ensurepip=no +make +make install + +# Remove unneeded test directories, similar to the official Docker Python images: +# https://github.com/docker-library/python +find "${OUT_PREFIX}" \( -type d -a \( -name test -o -name tests \) \) -exec rm -rf '{}' + + +# Remove spare / +LOCATION=${OUT_PREFIX%?} + +ln $LOCATION/bin/python3 $LOCATION/bin/python diff --git a/test/fixtures/python3_4/requirements.txt b/test/fixtures/python3_4/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..7e1060246fd6746a14204539a72e199a25469a05 --- /dev/null +++ b/test/fixtures/python3_4/requirements.txt @@ -0,0 +1 @@ +flask diff --git a/test/fixtures/python3_4/runtime.txt b/test/fixtures/python3_4/runtime.txt new file mode 100644 index 0000000000000000000000000000000000000000..cc8325f75753b807e16f0c2a1d05ac2d24b269b0 --- /dev/null +++ b/test/fixtures/python3_4/runtime.txt @@ -0,0 +1 @@ +python-3.4.9 diff --git a/test/fixtures/python3_6/runtime.txt b/test/fixtures/python3_6/runtime.txt index 34b35b713f56868abc889d5798cab36939bec38f..1935e9778db66275403e99759f51768cc7599918 100644 --- a/test/fixtures/python3_6/runtime.txt +++ b/test/fixtures/python3_6/runtime.txt @@ -1 +1 @@ -python-3.6.7 +python-3.6.6 diff --git a/test/fixtures/python3_6_7/requirements.txt b/test/fixtures/python3_6_7/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..7e1060246fd6746a14204539a72e199a25469a05 --- /dev/null +++ b/test/fixtures/python3_6_7/requirements.txt @@ -0,0 +1 @@ +flask diff --git a/test/fixtures/python3_6_7/runtime.txt b/test/fixtures/python3_6_7/runtime.txt new file mode 100644 index 0000000000000000000000000000000000000000..34b35b713f56868abc889d5798cab36939bec38f --- /dev/null +++ b/test/fixtures/python3_6_7/runtime.txt @@ -0,0 +1 @@ +python-3.6.7 diff --git a/test/fixtures/python3_7/runtime.txt b/test/fixtures/python3_7/runtime.txt index 4255f73ae6037a2a4a5ddd6a1093c841fc339845..881a2db1abd7719381d1925771e0d4208fb46fb5 100644 --- a/test/fixtures/python3_7/runtime.txt +++ b/test/fixtures/python3_7/runtime.txt @@ -1 +1 @@ -python-3.7.1 +python-3.7.0 diff --git a/test/fixtures/python3_7_1/requirements.txt b/test/fixtures/python3_7_1/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..7e1060246fd6746a14204539a72e199a25469a05 --- /dev/null +++ b/test/fixtures/python3_7_1/requirements.txt @@ -0,0 +1 @@ +flask diff --git a/test/fixtures/python3_7_1/runtime.txt b/test/fixtures/python3_7_1/runtime.txt new file mode 100644 index 0000000000000000000000000000000000000000..4255f73ae6037a2a4a5ddd6a1093c841fc339845 --- /dev/null +++ b/test/fixtures/python3_7_1/runtime.txt @@ -0,0 +1 @@ +python-3.7.1 diff --git a/test/run b/test/run index c5126dad9335b1a2840fb2692bf8e24692e2c4e5..67d4113dbb6a0d1f8aed8bdca54d0f5ba45001a6 100755 --- a/test/run +++ b/test/run @@ -93,24 +93,46 @@ testPython2() { assertCapturedSuccess } +# This will succeed on Cedar-14 and fail on 16 and 18 +testPython3_4() { + compile "python3_4" + assertCaptured "python-3.4.9" + assertCapturedError +} + +# This will fail testPython3_5() { compile "python3_5" assertCaptured "python-3.5.6" - assertCapturedSuccess + assertCapturedError } testPython3_6() { compile "python3_6" - assertCaptured "python-3.6.7" + assertCaptured "python-3.6.6" assertCapturedSuccess } +# This will fail +testPython3_6_7() { + compile "python3_6_7" + assertCaptured "python-3.6.7" + assertCapturedError +} + testPython3_7() { compile "python3_7" - assertCaptured "python-3.7.1" + assertCaptured "python-3.7.0" assertCapturedSuccess } +# This will fail +testPython3_7_1() { + compile "python3_7_1" + assertCaptured "python-3.7.1" + assertCapturedError +} + testGitEgg() { compile "git-egg" assertCaptured "requests"