diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000000000000000000000000000000000000..c19386392fbfd9c7d56a6be41c8bf8a55f28854c --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,5 @@ +repos: +- repo: git://github.com/detailyang/pre-commit-shell + rev: 1.0.4 + hooks: + - id: shell-lint diff --git a/.travis.yml b/.travis.yml index 9fc974add5b567748e8952aaa1c7477faf5d2b88..4390d4920b15ead9fd73d1a6f54556c1a652fefa 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,9 +5,7 @@ rvm: - 2.4.4 before_script: - gem install bundler -v 1.16.2 - - bundle exec rake hatchet:setup_travis -before_install: - - sudo bash etc/ci-setup.sh + - bundle exec hatchet ci:setup jobs: include: - stage: Bash linting (shellcheck) @@ -35,5 +33,6 @@ env: - HATCHET_RETRIES=3 - IS_RUNNING_ON_CI=true - HATCHET_APP_LIMIT=5 + - HATCHET_DEPLOY_STRATEGY=git - secure: yjtlPE5FbVxTKnjUy/tZUBgSEf4qADD3QOxtgziuid73S0U/1IEXlMGFULsQzIjtlHKmHeywZqpVVEpthIH4RuT7uoX1Pb7SSM/g0T8fT3VoEFbFK1uYl0oZQbUS4Klxv9tPiumj8if3m6ULEGIz1X0wZcMOC0tMLwVCnwmap0E= - secure: ZeFTHWwnpIKE9nAqs88ocmiQh7bKce84lilGm5J23nf3N6V4wNyLwqlkvsM008WGBCaOg9AUx7ZunasT0ANsR5gLP3eV2UUg7ILdRgV2Gy13eNRFheC4PHdN92RqQ3aKoqlIv2K999xlhVjod0NzhkQQXB6PddfQINbuU7ks6As= diff --git a/CHANGELOG.md b/CHANGELOG.md index 1a5e3a0e032e019be3728732e9a62ca9431ed009..826b4fb9e0000c6b445f28a7f1a0db2c58e2c678 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,19 +1,31 @@ # Python Buildpack Changelog -# 141 (2018-10-10) +# 146 (2018-15-08) + +Python 3.7.1, 3.6.7, 3.5.6 and 3.4.9 now available on all Heroku stacks. + +# 145 (2018-11-08) + +Testing and tooling expanded to better support new runtimes + +# 144 (2018-10-10) Switch to cautious upgrade for Pipenv install to ensure the pinned pip version is used with Pipenv -# 140 (2018-10-09) +# 143 (2018-10-09) Add support for detecting SLUGIFY_USES_TEXT_UNIDECODE, which is required to install Apache Airflow version 1.10 or higher. -# 139 (2018-10-08) +# 142 (2018-10-08) Improvements to Python install messaging +# 139, 140, 141 + +No user-facing changes, documenting for version clarity + # 138 (2018-08-01) Use stack image SQLite3 instead of vendoring diff --git a/Gemfile.lock b/Gemfile.lock index 621cd725af7a845fad9b193a293b6ef5bfe78976..6a6f314b6b78e926c6f60ed665984886619ab323 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -6,16 +6,16 @@ GEM i18n (>= 0.7, < 2) minitest (~> 5.1) tzinfo (~> 1.1) - concurrent-ruby (1.0.5) + concurrent-ruby (1.1.3) diff-lcs (1.3) erubis (2.7.0) excon (0.62.0) - heroics (0.0.24) + heroics (0.0.25) erubis (~> 2.0) excon moneta multi_json (>= 1.9.2) - heroku_hatchet (4.0.2) + heroku_hatchet (4.0.6) excon (~> 0) minitest-retry (~> 0.1.9) platform-api (~> 2) @@ -23,16 +23,16 @@ GEM rrrretry (~> 1) thor (~> 0) threaded (~> 0) - i18n (1.1.0) + i18n (1.1.1) concurrent-ruby (~> 1.0) minitest (5.11.3) minitest-retry (0.1.9) minitest (>= 5.0) - moneta (0.8.1) + moneta (1.0.0) multi_json (1.13.1) - platform-api (2.1.0) - heroics (~> 0.0.23) - moneta (~> 0.8.1) + platform-api (2.2.0) + heroics (~> 0.0.25) + moneta (~> 1.0.0) rake (12.3.1) repl_runner (0.0.3) activesupport @@ -52,7 +52,7 @@ GEM rspec-retry (0.6.1) rspec-core (> 3.3) rspec-support (3.8.0) - thor (0.20.0) + thor (0.20.3) thread_safe (0.3.6) threaded (0.0.4) tzinfo (1.2.5) diff --git a/Makefile b/Makefile index 6d6ac4c30b08a6d9581fd7e11d2dc6ed5e074341..43c2bbf8aef044f6ccf811d8a90b3570ce3344b0 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ # These targets are not files .PHONY: tests -test: test-heroku-16 +test: test-heroku-18 test-heroku-16 check: @shellcheck -x bin/compile bin/detect bin/release bin/test-compile bin/utils bin/warnings diff --git a/README.md b/README.md index a4a5bf962c754a35b2a72f13161181cf022f6de5..546e5ecd0c91a6955a490a3ec4761e5ac4aaf912 100644 --- a/README.md +++ b/README.md @@ -4,36 +4,54 @@ [](https://travis-ci.org/heroku/heroku-buildpack-python) -This is the official [Heroku buildpack](https://devcenter.heroku.com/articles/buildpacks) for Python apps, powered by [Pipenv](http://docs.pipenv.org/), [pip](https://pip.pypa.io/) and other excellent software. +This is the official [Heroku buildpack](https://devcenter.heroku.com/articles/buildpacks) for Python apps. -Recommended web frameworks include **Django** and **Flask**. The recommended webserver is **Gunicorn**. There are no restrictions around what software can be used (as long as it's pip-installable). Web processes must bind to `$PORT`, and only the HTTP protocol is permitted for incoming connections. +Recommended web frameworks include **Django** and **Flask**, among others. The recommended webserver is **Gunicorn**. There are no restrictions around what software can be used (as long as it's pip-installable). Web processes must bind to `$PORT`, and only the HTTP protocol is permitted for incoming connections. -Python packages with C dependencies that are not [available on the stack image](https://devcenter.heroku.com/articles/stack-packages) are generally not supported, unless `manylinux` wheels are provided by the package maintainers (common). For recommended solutions, check out [this article](https://devcenter.heroku.com/articles/python-c-deps) for more information. +Python packages with C dependencies that are not [available on the stack image](https://devcenter.heroku.com/articles/stack-packages) are generally not supported, unless `manylinux` wheels are provided by the package maintainers (common). For recommended solutions, check out [this article](https://devcenter.heroku.com/articles/python-c-deps) for more information. See it in Action ---------------- - -Deploying a Python application couldn't be easier: - - $ ls - Pipfile Pipfile.lock Procfile web.py - - $ heroku create --buildpack heroku/python - - $ git push heroku master - … - -----> Python app detected - -----> Installing python-3.6.6 - -----> Installing pip - -----> Installing requirements with Pipenv 2018.5.18… - ... - Installing dependencies from Pipfile… - -----> Discovering process types - Procfile declares types -> (none) - -A `Pipfile` or `requirements.txt` must be present at the root of your application's repository. - -You can also specify the latest production release of this buildpack for upcoming builds of an existing application: +``` +$ ls +my-application requirements.txt runtime.txt + +$ git push heroku master +Counting objects: 4, done. +Delta compression using up to 8 threads. +Compressing objects: 100% (2/2), done. +Writing objects: 100% (4/4), 276 bytes | 276.00 KiB/s, done. +Total 4 (delta 0), reused 0 (delta 0) +remote: Compressing source files... done. +remote: Building source: +remote: +remote: -----> Python app detected +remote: -----> Installing python-3.7.1 +remote: -----> Installing pip +remote: -----> Installing SQLite3 +remote: -----> Installing requirements with pip +remote: Collecting flask (from -r /tmp/build_c2c067ef79ff14c9bf1aed6796f9ed1f/requirements.txt (line 1)) +remote: Downloading ... +remote: Installing collected packages: Werkzeug, click, MarkupSafe, Jinja2, itsdangerous, flask +remote: Successfully installed Jinja2-2.10 MarkupSafe-1.1.0 Werkzeug-0.14.1 click-7.0 flask-1.0.2 itsdangerous-1.1.0 +remote: +remote: -----> Discovering process types +remote: Procfile declares types -> (none) +remote: +``` + +A `requirements.txt` must be present at the root of your application's repository to deploy. + +To specify your python version, you also need a `runtime.txt` file - unless you are using the default Python runtime version. + +Current default Python Runtime: Python 3.6.7 + +Alternatively, you can provide a `setup.py` file, or a `Pipfile`. Using `Pipenv` will generate `runtime.txt` based on `python-version` at build time. + +Specify a Buildpack Version +--------------------------- + +You can specify the latest production release of this buildpack for upcoming builds of an existing application: $ heroku buildpacks:set heroku/python @@ -41,23 +59,30 @@ You can also specify the latest production release of this buildpack for upcomin Specify a Python Runtime ------------------------ -Specific versions of the Python runtime can be specified in your `Pipfile`: +Supported runtime options include: + +- `python-3.7.1` +- `python-3.6.7` +- `python-2.7.15` - [requires] - python_version = "2.7" +## Tests -Or, more specifically: +The buildpack tests use [Docker](https://www.docker.com/) to simulate +Heroku's [stack images.](https://devcenter.heroku.com/articles/stack) - [requires] - python_full_version = "2.7.15" +To run the test suite: -Or, with a `runtime.txt` file: +``` +make test +``` - $ cat runtime.txt - python-2.7.15 +Or to test in a particular stack: -Runtime options include: +``` +make test-heroku-18 +make test-heroku-16 +``` -- `python-3.7.0` -- `python-3.6.6` -- `python-2.7.15` +The tests are run via the vendored +[shunit2](https://github.com/kward/shunit2) +test framework. diff --git a/bin/compile b/bin/compile index d97af680d5428c3abb0d5f72444608a72df2248e..2d7c661eb373d4505c0dfd006a67ba17be974409 100755 --- a/bin/compile +++ b/bin/compile @@ -49,17 +49,28 @@ export VENDOR_URL # These variables are used to specify which versions of Python to install by default, # as well as prompt the user to upgrade if they are using an un–supported version. # Note: When 3.7 lands, I recommend switching to LATEST_36 and LATEST_37. -DEFAULT_PYTHON_VERSION="python-3.6.6" -LATEST_36="python-3.6.6" -LATEST_37="python-3.7.0" -LATEST_2="python-2.7.15" +DEFAULT_PYTHON_VERSION="python-3.6.7" +LATEST_36="python-3.6.7" +LATEST_37="python-3.7.1" +LATEST_35="python-3.5.6" +LATEST_34="python-3.4.9" +LATEST_27="python-2.7.15" + +# Supported Python Branches +PY37="python-3.7" +PY36="python-3.6" +PY35="python-3.5" +PY34="python-3.4" +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 DEFAULT_PYTHON_VERSION DEFAULT_PYTHON_STACK PIP_UPDATE +export LATEST_27 LATEST_36 LATEST_37 LATEST_35 LATEST_34 +export PY37 PY36 PY35 PY27 PY34 # Common Problem Warnings: # This section creates a temporary file in which to stick the output of `pip install`. diff --git a/bin/steps/pipenv-python-version b/bin/steps/pipenv-python-version index c8ee06dba2266d1bb1b284f6e3486db48b2e443f..dcdf3c2617559689019f93f69ad62a626cb7a95a 100755 --- a/bin/steps/pipenv-python-version +++ b/bin/steps/pipenv-python-version @@ -19,7 +19,7 @@ if [[ -f $BUILD_DIR/Pipfile ]]; then if [[ "$PYTHON" == "null" ]]; then PYTHON=$(jq -r '._meta.requires.python_version' "$BUILD_DIR/Pipfile.lock") if [ "$PYTHON" = 2.7 ]; then - echo "$LATEST_2" > "$BUILD_DIR/runtime.txt" + echo "$LATEST_27" > "$BUILD_DIR/runtime.txt" fi if [ "$PYTHON" = 3.6 ]; then echo "$LATEST_36" > "$BUILD_DIR/runtime.txt" @@ -33,4 +33,3 @@ if [[ -f $BUILD_DIR/Pipfile ]]; then fi fi fi - diff --git a/bin/steps/python b/bin/steps/python index ea623b1bfdf72daef78dcb7c12bfa766f44e352a..d10eccf23463b56bcbe0d7c0252d9d2db43509ec 100755 --- a/bin/steps/python +++ b/bin/steps/python @@ -7,41 +7,49 @@ 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)" +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" == $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 [ "$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 diff --git a/bin/utils b/bin/utils index 2bbf82a32e59e33c84bc5be925e72f6437cb4e68..f625645dff0ddaf8b21e86e9cfe6e4b45e183fc8 100755 --- a/bin/utils +++ b/bin/utils @@ -89,10 +89,9 @@ python3_check() { # Check if Python version needs to install SQLite3 python_sqlite3_check() { VERSION="$1" - MIN_PYTHON_3="python-3.6.6" + MIN_PYTHON_3="python-3.5.6" MIN_PYTHON_2="python-2.7.15" ( python2_check "$VERSION" && version_gte "$VERSION" "$MIN_PYTHON_2" ) \ - || ( python3_check "$VERSION" && version_gte "$VERSION" "$MIN_PYTHON_3" ) \ - || ( version_gte "$VERSION" "3.7.0" ) + || ( python3_check "$VERSION" && version_gte "$VERSION" "$MIN_PYTHON_3" ) } 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/builds/runtimes/python-3.5.6 b/builds/runtimes/python-3.5.6 new file mode 100755 index 0000000000000000000000000000000000000000..0d179352b1f3c996b1003d0ba9d5999a5bbd8c7c --- /dev/null +++ b/builds/runtimes/python-3.5.6 @@ -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.5.6/Python-3.5.6.tgz' +curl -L $SOURCE_TARBALL | tar xz +mv Python-3.5.6 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/builds/runtimes/python-3.6.7 b/builds/runtimes/python-3.6.7 new file mode 100755 index 0000000000000000000000000000000000000000..052ee1e2fb0275ed9f5cf164f00951c61eda4e1e --- /dev/null +++ b/builds/runtimes/python-3.6.7 @@ -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.6.7/Python-3.6.7.tgz' +curl -L $SOURCE_TARBALL | tar xz +mv Python-3.6.7 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/builds/runtimes/python-3.7.1 b/builds/runtimes/python-3.7.1 new file mode 100755 index 0000000000000000000000000000000000000000..b8051393f22aaf95ac504c64ea082eb025c17ca0 --- /dev/null +++ b/builds/runtimes/python-3.7.1 @@ -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.7.1/Python-3.7.1.tgz' +curl -L $SOURCE_TARBALL | tar xz +mv Python-3.7.1 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/requirements.txt b/requirements.txt index 35bd16651cfbdf08820a00aff48aa38404248e7f..ad7e217efaeda0436f9d51e25a75837e7e102b3a 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,3 @@ docopt==0.6.2 -bob-builder==0.0.13 +bob-builder boto==2.48.0 diff --git a/spec/hatchet/python_spec.rb b/spec/hatchet/python_spec.rb index 5ae95ed1b24d51f0d979559f7640ddbe048edeb4..39c00269d990d6aabb2c5431c38993c7721f3c96 100644 --- a/spec/hatchet/python_spec.rb +++ b/spec/hatchet/python_spec.rb @@ -4,7 +4,7 @@ describe "Python!!!!!!!!!!!" do it "ðŸ" do Hatchet::Runner.new('python-getting-started', stack: DEFAULT_STACK).deploy do |app| expect(app.output).to match(/Installing pip/) - expect(app.run('python -V')).to match(/3.6.6/) + expect(app.run('python -V')).to match(/3.6.7/) end end end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index d8a55da7a3c99c51047a61a1d3fa327949539001..12a11b8899b3d51856398c7f4b359b97220318c4 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,4 +1,4 @@ -ENV['HATCHET_BUILDPACK_BASE'] = 'https://github.com/heroku/heroku-buildpack-python.git' +ENV['HATCHET_BUILDPACK_BASE'] = 'https://github.com/' + ENV['TRAVIS_REPO_SLUG'] + '.git' require 'rspec/core' require 'rspec/retry' diff --git a/test/fixtures/pipenv-version/Pipfile b/test/fixtures/pipenv-version/Pipfile index cd4e813138e32642c4c9979cf289d2b43241815c..91ec2539881bbcb249109cadc8ab078549398ae8 100644 --- a/test/fixtures/pipenv-version/Pipfile +++ b/test/fixtures/pipenv-version/Pipfile @@ -6,4 +6,4 @@ verify_ssl = true requests = "*" [requires] -python_version = "3.6" \ No newline at end of file +python_version = "3.6" diff --git a/test/fixtures/pipenv-version2/Pipfile b/test/fixtures/pipenv-version2/Pipfile new file mode 100644 index 0000000000000000000000000000000000000000..3026dd10ac2e152ac8062b762d116ebcbe084c81 --- /dev/null +++ b/test/fixtures/pipenv-version2/Pipfile @@ -0,0 +1,11 @@ +[[source]] +url = "https://pypi.org/simple" +verify_ssl = true +name = "pypi" + +[packages] + +[dev-packages] + +[requires] +python_version = "2.7" diff --git a/test/fixtures/pipenv-version2/Pipfile.lock b/test/fixtures/pipenv-version2/Pipfile.lock new file mode 100644 index 0000000000000000000000000000000000000000..637b90ff5ed18a03d96f67a6e125ff69b1a5d7d4 --- /dev/null +++ b/test/fixtures/pipenv-version2/Pipfile.lock @@ -0,0 +1,20 @@ +{ + "_meta": { + "hash": { + "sha256": "ae4bdd7d4157baab65ae9d0e8389a6011e6b640995372c45ec81fa5d1ddfae9f" + }, + "pipfile-spec": 6, + "requires": { + "python_version": "2.7" + }, + "sources": [ + { + "name": "pypi", + "url": "https://pypi.org/simple", + "verify_ssl": true + } + ] + }, + "default": {}, + "develop": {} +} diff --git a/test/fixtures/python3/requirements.txt b/test/fixtures/python2_fail/requirements.txt similarity index 100% rename from test/fixtures/python3/requirements.txt rename to test/fixtures/python2_fail/requirements.txt diff --git a/test/fixtures/python2_fail/runtime.txt b/test/fixtures/python2_fail/runtime.txt new file mode 100644 index 0000000000000000000000000000000000000000..d42956de9c4f2893134ed473cf17671343f4ee35 --- /dev/null +++ b/test/fixtures/python2_fail/runtime.txt @@ -0,0 +1 @@ +python-2.7.16 diff --git a/test/fixtures/python2_warn/requirements.txt b/test/fixtures/python2_warn/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..663bd1f6a2ae02f29df59fb4963c17934034f731 --- /dev/null +++ b/test/fixtures/python2_warn/requirements.txt @@ -0,0 +1 @@ +requests \ No newline at end of file diff --git a/test/fixtures/python2_warn/runtime.txt b/test/fixtures/python2_warn/runtime.txt new file mode 100644 index 0000000000000000000000000000000000000000..538568204a78b4e4ec20255b64fa25533b4edae3 --- /dev/null +++ b/test/fixtures/python2_warn/runtime.txt @@ -0,0 +1 @@ +python-2.7.14 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_4_fail/requirements.txt b/test/fixtures/python3_4_fail/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..7e1060246fd6746a14204539a72e199a25469a05 --- /dev/null +++ b/test/fixtures/python3_4_fail/requirements.txt @@ -0,0 +1 @@ +flask diff --git a/test/fixtures/python3_4_fail/runtime.txt b/test/fixtures/python3_4_fail/runtime.txt new file mode 100644 index 0000000000000000000000000000000000000000..3b5c63e5912725bc4dec2bfc3135db3470d14d8e --- /dev/null +++ b/test/fixtures/python3_4_fail/runtime.txt @@ -0,0 +1 @@ +python-3.4.10 diff --git a/test/fixtures/python3_4_warn/requirements.txt b/test/fixtures/python3_4_warn/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..7e1060246fd6746a14204539a72e199a25469a05 --- /dev/null +++ b/test/fixtures/python3_4_warn/requirements.txt @@ -0,0 +1 @@ +flask diff --git a/test/fixtures/python3_4_warn/runtime.txt b/test/fixtures/python3_4_warn/runtime.txt new file mode 100644 index 0000000000000000000000000000000000000000..fe5dcf7a3aeb68d0bb349ddd6f7d61ba731a1057 --- /dev/null +++ b/test/fixtures/python3_4_warn/runtime.txt @@ -0,0 +1 @@ +python-3.4.0 diff --git a/test/fixtures/python3_5/requirements.txt b/test/fixtures/python3_5/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..663bd1f6a2ae02f29df59fb4963c17934034f731 --- /dev/null +++ b/test/fixtures/python3_5/requirements.txt @@ -0,0 +1 @@ +requests \ No newline at end of file diff --git a/test/fixtures/python3_5/runtime.txt b/test/fixtures/python3_5/runtime.txt new file mode 100644 index 0000000000000000000000000000000000000000..e6391f4a68edd6f81269b05227977459a9fbd6a8 --- /dev/null +++ b/test/fixtures/python3_5/runtime.txt @@ -0,0 +1 @@ +python-3.5.6 diff --git a/test/fixtures/python3_5_fail/requirements.txt b/test/fixtures/python3_5_fail/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..7e1060246fd6746a14204539a72e199a25469a05 --- /dev/null +++ b/test/fixtures/python3_5_fail/requirements.txt @@ -0,0 +1 @@ +flask diff --git a/test/fixtures/python3_5_fail/runtime.txt b/test/fixtures/python3_5_fail/runtime.txt new file mode 100644 index 0000000000000000000000000000000000000000..df4118a6a06eb46538803009ef7a69291fca95dd --- /dev/null +++ b/test/fixtures/python3_5_fail/runtime.txt @@ -0,0 +1 @@ +python-3.5.7 diff --git a/test/fixtures/python3_5_warn/requirements.txt b/test/fixtures/python3_5_warn/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..7e1060246fd6746a14204539a72e199a25469a05 --- /dev/null +++ b/test/fixtures/python3_5_warn/requirements.txt @@ -0,0 +1 @@ +flask diff --git a/test/fixtures/python3_5_warn/runtime.txt b/test/fixtures/python3_5_warn/runtime.txt new file mode 100644 index 0000000000000000000000000000000000000000..5486d7adb9a188bcfc1d0d8844b4091b1c369ec9 --- /dev/null +++ b/test/fixtures/python3_5_warn/runtime.txt @@ -0,0 +1 @@ +python-3.5.3 diff --git a/test/fixtures/python3_6/requirements.txt b/test/fixtures/python3_6/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..663bd1f6a2ae02f29df59fb4963c17934034f731 --- /dev/null +++ b/test/fixtures/python3_6/requirements.txt @@ -0,0 +1 @@ +requests \ No newline at end of file diff --git a/test/fixtures/python3_6/runtime.txt b/test/fixtures/python3_6/runtime.txt new file mode 100644 index 0000000000000000000000000000000000000000..34b35b713f56868abc889d5798cab36939bec38f --- /dev/null +++ b/test/fixtures/python3_6/runtime.txt @@ -0,0 +1 @@ +python-3.6.7 diff --git a/test/fixtures/python3_6_fail/requirements.txt b/test/fixtures/python3_6_fail/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..7e1060246fd6746a14204539a72e199a25469a05 --- /dev/null +++ b/test/fixtures/python3_6_fail/requirements.txt @@ -0,0 +1 @@ +flask diff --git a/test/fixtures/python3_6_fail/runtime.txt b/test/fixtures/python3_6_fail/runtime.txt new file mode 100644 index 0000000000000000000000000000000000000000..9fbd3bf0a8cbd237fdc16f03556d84baf76522be --- /dev/null +++ b/test/fixtures/python3_6_fail/runtime.txt @@ -0,0 +1 @@ +python-3.6.8 diff --git a/test/fixtures/python3_6_warn/requirements.txt b/test/fixtures/python3_6_warn/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..663bd1f6a2ae02f29df59fb4963c17934034f731 --- /dev/null +++ b/test/fixtures/python3_6_warn/requirements.txt @@ -0,0 +1 @@ +requests \ No newline at end of file diff --git a/test/fixtures/python3_6_warn/runtime.txt b/test/fixtures/python3_6_warn/runtime.txt new file mode 100644 index 0000000000000000000000000000000000000000..486fcce127f00eba90a4096290b67c31adaef0bd --- /dev/null +++ b/test/fixtures/python3_6_warn/runtime.txt @@ -0,0 +1 @@ +python-3.6.5 diff --git a/test/fixtures/python3_7/requirements.txt b/test/fixtures/python3_7/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..663bd1f6a2ae02f29df59fb4963c17934034f731 --- /dev/null +++ b/test/fixtures/python3_7/requirements.txt @@ -0,0 +1 @@ +requests \ No newline at end of file diff --git a/test/fixtures/python3_7/runtime.txt b/test/fixtures/python3_7/runtime.txt new file mode 100644 index 0000000000000000000000000000000000000000..4255f73ae6037a2a4a5ddd6a1093c841fc339845 --- /dev/null +++ b/test/fixtures/python3_7/runtime.txt @@ -0,0 +1 @@ +python-3.7.1 diff --git a/test/fixtures/python3_7_fail/requirements.txt b/test/fixtures/python3_7_fail/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..7e1060246fd6746a14204539a72e199a25469a05 --- /dev/null +++ b/test/fixtures/python3_7_fail/requirements.txt @@ -0,0 +1 @@ +flask diff --git a/test/fixtures/python3_7_fail/runtime.txt b/test/fixtures/python3_7_fail/runtime.txt new file mode 100644 index 0000000000000000000000000000000000000000..a01373a365d95c1ab01706aadd1ff7376441ccfa --- /dev/null +++ b/test/fixtures/python3_7_fail/runtime.txt @@ -0,0 +1 @@ +python-3.7.2 diff --git a/test/fixtures/python3_7_warn/requirements.txt b/test/fixtures/python3_7_warn/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..663bd1f6a2ae02f29df59fb4963c17934034f731 --- /dev/null +++ b/test/fixtures/python3_7_warn/requirements.txt @@ -0,0 +1 @@ +requests \ No newline at end of file diff --git a/test/fixtures/python3_7_warn/runtime.txt b/test/fixtures/python3_7_warn/runtime.txt new file mode 100644 index 0000000000000000000000000000000000000000..881a2db1abd7719381d1925771e0d4208fb46fb5 --- /dev/null +++ b/test/fixtures/python3_7_warn/runtime.txt @@ -0,0 +1 @@ +python-3.7.0 diff --git a/test/fixtures/pythonDefault/requirements.txt b/test/fixtures/pythonDefault/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..7e1060246fd6746a14204539a72e199a25469a05 --- /dev/null +++ b/test/fixtures/pythonDefault/requirements.txt @@ -0,0 +1 @@ +flask diff --git a/test/run b/test/run index f6368161bae2719f3f75e8fa4d18febfe1fef5bd..ae200a11391be04303e8c424ce1cb26700cc2a3a 100755 --- a/test/run +++ b/test/run @@ -19,10 +19,15 @@ testPipenvLock() { testPipenvVersion() { compile "pipenv-version" - assertCaptured "3.6.6" + assertCaptured "3.6.7" assertCapturedSuccess } +testPipenvVersion2() { + compile "pipenv-version2" + assertCaptured "2.7.15" + assertCapturedSuccess +} testPipenvFullVersion() { compile "pipenv-full-version" assertCaptured "3.6.3" @@ -87,18 +92,127 @@ testPylibmc() { assertCapturedSuccess } +testPythonDefault() { + compile "pythonDefault" + assertCaptured "python-3.6.7" + assertCapturedSuccess +} + testPython2() { compile "python2" assertCaptured "python-2.7.15" assertCapturedSuccess } -testPython3() { - compile "python3" - assertCaptured "python-3.6.6" +testPython2_warn() { + compile "python2_warn" + if [[ $STACK = "heroku-18" ]]; then + assertCapturedError + else + assertCaptured "python-2.7.14" + assertCaptured "security update!" + assertCapturedSuccess + fi +} + +testPython2_fail() { + compile "python2_fail" + assertCaptured "Aborting" + assertCapturedError +} + +testPython3_4() { + compile "python3_4" + assertCaptured "python-3.4.9" + assertCapturedSuccess +} + +testPython3_4_warn() { + compile "python3_4_warn" + if [[ $STACK = "cedar-14" ]]; then + assertCaptured "python-3.4.0" + assertCaptured "security update!" + assertCapturedSuccess + else + assertCapturedError + fi +} + +testPython3_4_fail() { + compile "python3_4_fail" + assertCaptured "Aborting" + assertCapturedError +} + +testPython3_5() { + compile "python3_5" + assertCaptured "python-3.5.6" + assertCapturedSuccess +} + +testPython3_5_warn() { + compile "python3_5_warn" + if [[ $STACK = "cedar-14" ]]; then + assertCaptured "python-3.5.3" + assertCaptured "security update!" + assertCapturedError + else + assertCapturedError + fi +} + +testPython3_5_fail() { + compile "python3_5_fail" + assertCaptured "Aborting" + assertCapturedError +} + +testPython3_6() { + compile "python3_6" + assertCaptured "python-3.6.7" assertCapturedSuccess } +testPython3_6_warn() { + compile "python3_6_warn" + assertCaptured "python-3.6.5" + assertCaptured "security update!" + assertCapturedSuccess +} + +testPython3_6_fail() { + compile "python3_6_fail" + assertCaptured "Aborting" + assertCapturedError +} + +testPython3_7() { + compile "python3_7" + if [[ $STACK = "cedar-14" ]]; then + assertCapturedError + else + assertCaptured "python-3.7.1" + assertCapturedSuccess + fi +} + +testPython3_7_warn() { + compile "python3_7_warn" + if [[ $STACK = "cedar-14" ]]; then + assertCapturedError + else + assertCaptured "python-3.7.0" + assertCaptured "security update!" + assertCapturedSuccess + fi +} + +testPython3_7_fail() { + compile "python3_7_fail" + assertCaptured "Aborting" + assertCapturedError +} + testGitEgg() { compile "git-egg" assertCaptured "requests"