diff --git a/.github/workflows/build_python_runtime.yml b/.github/workflows/build_python_runtime.yml index f61f1d876..ab62a5548 100644 --- a/.github/workflows/build_python_runtime.yml +++ b/.github/workflows/build_python_runtime.yml @@ -26,21 +26,6 @@ env: # Unfortunately these jobs cannot be easily written as a matrix since `matrix.exclude` does not # support expression syntax, and the `inputs` context is not available inside the job `if` key. jobs: - build-and-upload-heroku-18: - runs-on: pub-hk-ubuntu-22.04-xlarge - env: - STACK_VERSION: "18" - steps: - - name: Checkout - uses: actions/checkout@v3 - - name: Build Docker image - run: docker build --pull --tag buildenv --build-arg=STACK_VERSION builds/ - - name: Build and package Python runtime - run: docker run --rm --platform="linux/amd64" --volume="${PWD}/upload:/tmp/upload" buildenv ./build_python_runtime.sh "${{ inputs.python_version }}" - - name: Upload Python runtime archive to S3 - if: (!inputs.dry_run) - run: aws s3 sync ./upload "s3://${S3_BUCKET}" - build-and-upload-heroku-20: runs-on: pub-hk-ubuntu-22.04-xlarge env: diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7fe348cf9..3cd6ff440 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -31,7 +31,7 @@ jobs: strategy: fail-fast: false matrix: - stack: ["heroku-18", "heroku-20", "heroku-22"] + stack: ["heroku-20", "heroku-22"] env: HATCHET_APP_LIMIT: 200 HATCHET_DEFAULT_STACK: ${{ matrix.stack }} diff --git a/CHANGELOG.md b/CHANGELOG.md index 7ac1c2a3d..f4b975518 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ## Unreleased +- Remove support for Heroku-18. ([#1449](https://github.com/heroku/heroku-buildpack-python/pull/1449)) ## v232 (2023-04-27) diff --git a/README.md b/README.md index 827731db0..65792d3f3 100644 --- a/README.md +++ b/README.md @@ -63,5 +63,5 @@ Supported runtime options include: - `python-3.11.3` on all [supported stacks](https://devcenter.heroku.com/articles/stack#stack-support-details) - `python-3.10.11` on all [supported stacks](https://devcenter.heroku.com/articles/stack#stack-support-details) - `python-3.9.16` on all [supported stacks](https://devcenter.heroku.com/articles/stack#stack-support-details) -- `python-3.8.16` on Heroku-18 and Heroku-20 only -- `python-3.7.16` on Heroku-18 and Heroku-20 only +- `python-3.8.16` on Heroku-20 only +- `python-3.7.16` on Heroku-20 only diff --git a/bin/steps/python b/bin/steps/python index e00b142da..6c2e14ffa 100755 --- a/bin/steps/python +++ b/bin/steps/python @@ -71,35 +71,6 @@ case "${PYTHON_VERSION}" in python-3.6.*) eol_python_version_error "3.6" "December 23rd, 2021" ;; - python-3.5.*) - eol_python_version_error "3.5" "September 30th, 2020" - ;; - python-3.4.*) - eol_python_version_error "3.4" "March 18th, 2019" - ;; - python-2.7.*) - puts-warn - puts-warn "Python 2 reached upstream end-of-life on January 1st, 2020, and is" - puts-warn "therefore no longer receiving security updates. Apps still using it" - puts-warn "contain potential security vulnerabilities and should be upgraded to" - puts-warn "Python 3 as soon as possible." - puts-warn - puts-warn "In addition, Python 2 is only supported on our oldest stack, Heroku-18," - puts-warn "which is deprecated and reaches end-of-life on April 30th, 2023." - puts-warn - puts-warn "As such, it is no longer supported by the latest version of this buildpack:" - puts-warn "https://devcenter.heroku.com/changelog-items/2473" - puts-warn - puts-warn "You must either:" - puts-warn " - Upgrade to Python 3 (recommended)" - puts-warn " - Switch to the container stack and use the upstream legacy 'python:2.7' Docker images" - puts-warn " - Switch to an older version of the Python buildpack (short term workaround only)" - puts-warn - puts-warn "For more details, see:" - puts-warn "https://devcenter.heroku.com/articles/python-2-7-eol-faq" - puts-warn - exit 1 - ;; pypy*) puts-warn puts-warn "PyPy is no longer supported by the latest version of this buildpack." diff --git a/builds/build_python_runtime.sh b/builds/build_python_runtime.sh index c1200f6ee..a04e065c0 100755 --- a/builds/build_python_runtime.sh +++ b/builds/build_python_runtime.sh @@ -9,10 +9,31 @@ INSTALL_DIR="/app/.heroku/python" SRC_DIR="/tmp/src" ARCHIVES_DIR="/tmp/upload/${STACK}/runtimes" -echo "Building Python ${PYTHON_VERSION} for ${STACK}..." +case "${STACK}" in + heroku-22) + SUPPORTED_PYTHON_VERSIONS=( + "3.9" + "3.10" + "3.11" + ) + ;; + heroku-20) + SUPPORTED_PYTHON_VERSIONS=( + "3.7" + "3.8" + "3.9" + "3.10" + "3.11" + ) + ;; + *) + echo "Error: Unsupported stack '${STACK}'!" >&2 + exit 1 + ;; +esac -if [[ "${STACK}" != "heroku-18" && "${STACK}" != "heroku-20" && "${PYTHON_MAJOR_VERSION}" == 3.[7-8] ]]; then - echo "Error: Python ${PYTHON_MAJOR_VERSION} is only supported on Heroku-20 and older!" >&2 +if [[ ! " ${SUPPORTED_PYTHON_VERSIONS[*]} " == *" ${PYTHON_MAJOR_VERSION} "* ]]; then + echo "Error: Python ${PYTHON_MAJOR_VERSION} is not supported on ${STACK}!" >&2 exit 1 fi @@ -36,6 +57,8 @@ case "${PYTHON_MAJOR_VERSION}" in ;; esac +echo "Building Python ${PYTHON_VERSION} for ${STACK}..." + SOURCE_URL="https://www.python.org/ftp/python/${PYTHON_VERSION}/Python-${PYTHON_VERSION}.tgz" SIGNATURE_URL="${SOURCE_URL}.asc" @@ -46,12 +69,8 @@ mkdir -p "${SRC_DIR}" "${INSTALL_DIR}" "${ARCHIVES_DIR}" curl --fail --retry 3 --retry-connrefused --connect-timeout 10 --max-time 60 -o python.tgz "${SOURCE_URL}" curl --fail --retry 3 --retry-connrefused --connect-timeout 10 --max-time 60 -o python.tgz.asc "${SIGNATURE_URL}" -# Skip GPG verification on Heroku-18 since it fails to fetch keys: -# `gpg: keyserver receive failed: Server indicated a failure` -if [[ "${STACK}" != "heroku-18" ]]; then - gpg --batch --verbose --recv-keys "${GPG_KEY_FINGERPRINT}" - gpg --batch --verify python.tgz.asc python.tgz -fi +gpg --batch --verbose --recv-keys "${GPG_KEY_FINGERPRINT}" +gpg --batch --verify python.tgz.asc python.tgz tar --extract --file python.tgz --strip-components=1 --directory "${SRC_DIR}" cd "${SRC_DIR}" diff --git a/spec/fixtures/pipenv_python_2.7/Pipfile b/spec/fixtures/pipenv_python_2.7/Pipfile deleted file mode 100644 index df91063cd..000000000 --- a/spec/fixtures/pipenv_python_2.7/Pipfile +++ /dev/null @@ -1,12 +0,0 @@ -[[source]] -url = "https://pypi.org/simple" -verify_ssl = true -name = "pypi" - -[packages] -urllib3 = "*" - -[dev-packages] - -[requires] -python_version = "2.7" diff --git a/spec/fixtures/pipenv_python_2.7/Pipfile.lock b/spec/fixtures/pipenv_python_2.7/Pipfile.lock deleted file mode 100644 index 009e23b42..000000000 --- a/spec/fixtures/pipenv_python_2.7/Pipfile.lock +++ /dev/null @@ -1,29 +0,0 @@ -{ - "_meta": { - "hash": { - "sha256": "76bbc9cda0ef0576bfaac66930845fc9f994ca85ed19a19bc8c6f4f3a0b8efa9" - }, - "pipfile-spec": 6, - "requires": { - "python_version": "2.7" - }, - "sources": [ - { - "name": "pypi", - "url": "https://pypi.org/simple", - "verify_ssl": true - } - ] - }, - "default": { - "urllib3": { - "hashes": [ - "sha256:076907bf8fd355cde77728471316625a4d2f7e713c125f51953bb5b3eecf4f72", - "sha256:75edcdc2f7d85b137124a6c3c9fc3933cdeaa12ecb9a6a959f22797a0feca7e1" - ], - "index": "pypi", - "version": "==1.26.14" - } - }, - "develop": {} -} diff --git a/spec/fixtures/pipenv_python_3.5/Pipfile b/spec/fixtures/pipenv_python_3.5/Pipfile deleted file mode 100644 index a7d73d1a8..000000000 --- a/spec/fixtures/pipenv_python_3.5/Pipfile +++ /dev/null @@ -1,12 +0,0 @@ -[[source]] -url = "https://pypi.org/simple" -verify_ssl = true -name = "pypi" - -[packages] -urllib3 = "*" - -[dev-packages] - -[requires] -python_version = "3.5" diff --git a/spec/fixtures/pipenv_python_3.5/Pipfile.lock b/spec/fixtures/pipenv_python_3.5/Pipfile.lock deleted file mode 100644 index e04abed7b..000000000 --- a/spec/fixtures/pipenv_python_3.5/Pipfile.lock +++ /dev/null @@ -1,29 +0,0 @@ -{ - "_meta": { - "hash": { - "sha256": "3a6323e6bc490e3ff501914a1a029cf76c96bfdf86cf8a48cd0d163a8cce4cb4" - }, - "pipfile-spec": 6, - "requires": { - "python_version": "3.5" - }, - "sources": [ - { - "name": "pypi", - "url": "https://pypi.org/simple", - "verify_ssl": true - } - ] - }, - "default": { - "urllib3": { - "hashes": [ - "sha256:076907bf8fd355cde77728471316625a4d2f7e713c125f51953bb5b3eecf4f72", - "sha256:75edcdc2f7d85b137124a6c3c9fc3933cdeaa12ecb9a6a959f22797a0feca7e1" - ], - "index": "pypi", - "version": "==1.26.14" - } - }, - "develop": {} -} diff --git a/spec/fixtures/python_2.7/requirements.txt b/spec/fixtures/python_2.7/requirements.txt deleted file mode 100644 index a42590beb..000000000 --- a/spec/fixtures/python_2.7/requirements.txt +++ /dev/null @@ -1 +0,0 @@ -urllib3 diff --git a/spec/fixtures/python_2.7/runtime.txt b/spec/fixtures/python_2.7/runtime.txt deleted file mode 100644 index 586b67310..000000000 --- a/spec/fixtures/python_2.7/runtime.txt +++ /dev/null @@ -1 +0,0 @@ -python-2.7.18 diff --git a/spec/fixtures/python_3.4/requirements.txt b/spec/fixtures/python_3.4/requirements.txt deleted file mode 100644 index a42590beb..000000000 --- a/spec/fixtures/python_3.4/requirements.txt +++ /dev/null @@ -1 +0,0 @@ -urllib3 diff --git a/spec/fixtures/python_3.4/runtime.txt b/spec/fixtures/python_3.4/runtime.txt deleted file mode 100644 index 3b5c63e59..000000000 --- a/spec/fixtures/python_3.4/runtime.txt +++ /dev/null @@ -1 +0,0 @@ -python-3.4.10 diff --git a/spec/fixtures/python_3.5/requirements.txt b/spec/fixtures/python_3.5/requirements.txt deleted file mode 100644 index a42590beb..000000000 --- a/spec/fixtures/python_3.5/requirements.txt +++ /dev/null @@ -1 +0,0 @@ -urllib3 diff --git a/spec/fixtures/python_3.5/runtime.txt b/spec/fixtures/python_3.5/runtime.txt deleted file mode 100644 index 51777184a..000000000 --- a/spec/fixtures/python_3.5/runtime.txt +++ /dev/null @@ -1 +0,0 @@ -python-3.5.10 diff --git a/spec/hatchet/pipenv_spec.rb b/spec/hatchet/pipenv_spec.rb index f10733893..35d720d8f 100644 --- a/spec/hatchet/pipenv_spec.rb +++ b/spec/hatchet/pipenv_spec.rb @@ -73,80 +73,10 @@ end end - context 'with a Pipfile.lock containing python_version 2.7' do - let(:app) { Hatchet::Runner.new('spec/fixtures/pipenv_python_2.7', allow_failure: true) } - - context 'when using Heroku-18', stacks: %w[heroku-18] do - it 'aborts the build with an EOL message' do - app.deploy do |app| - expect(clean_output(app.output)).to include(<<~OUTPUT) - remote: -----> Python app detected - remote: -----> Using Python version specified in Pipfile.lock - remote: ! - remote: ! Python 2 reached upstream end-of-life on January 1st, 2020, and is - remote: ! therefore no longer receiving security updates. Apps still using it - remote: ! contain potential security vulnerabilities and should be upgraded to - remote: ! Python 3 as soon as possible. - remote: ! - remote: ! In addition, Python 2 is only supported on our oldest stack, Heroku-18, - remote: ! which is deprecated and reaches end-of-life on April 30th, 2023. - remote: ! - remote: ! As such, it is no longer supported by the latest version of this buildpack: - remote: ! https://devcenter.heroku.com/changelog-items/2473 - remote: ! - remote: ! You must either: - remote: ! - Upgrade to Python 3 (recommended) - remote: ! - Switch to the container stack and use the upstream legacy 'python:2.7' Docker images - remote: ! - Switch to an older version of the Python buildpack (short term workaround only) - remote: ! - remote: ! For more details, see: - remote: ! https://devcenter.heroku.com/articles/python-2-7-eol-faq - remote: ! - OUTPUT - end - end - end - - context 'when using Heroku-20 or newer', stacks: %w[heroku-20 heroku-22] do - # Python 2.7 is EOL, so has not been built for newer stacks. - include_examples 'aborts the build with a runtime not available message (Pipenv)', '2.7.18' - end - end - - context 'with a Pipfile.lock containing python_version 3.5' do - let(:app) { Hatchet::Runner.new('spec/fixtures/pipenv_python_3.5', allow_failure: true) } - - context 'when using Heroku-18', stacks: %w[heroku-18] do - it 'aborts the build with an EOL message' do - app.deploy do |app| - expect(clean_output(app.output)).to include(<<~OUTPUT) - remote: -----> Python app detected - remote: -----> Using Python version specified in Pipfile.lock - remote: ! - remote: ! Python 3.5 reached upstream end-of-life on September 30th, 2020, and is - remote: ! therefore no longer receiving security updates: - remote: ! https://devguide.python.org/versions/#supported-versions - remote: ! - remote: ! As such, it is no longer supported by the latest version of this buildpack. - remote: ! - remote: ! Please upgrade to a newer Python version. See: - remote: ! https://devcenter.heroku.com/articles/python-runtimes - remote: ! - OUTPUT - end - end - end - - context 'when using Heroku-20 or newer', stacks: %w[heroku-20 heroku-22] do - # Python 3.5 is EOL, so has not been built for newer stacks. - include_examples 'aborts the build with a runtime not available message (Pipenv)', '3.5.10' - end - end - context 'with a Pipfile.lock containing python_version 3.6' do let(:app) { Hatchet::Runner.new('spec/fixtures/pipenv_python_3.6', allow_failure: true) } - context 'when using Heroku-18 or Heroku-20', stacks: %w[heroku-18 heroku-20] do + context 'when using Heroku-20', stacks: %w[heroku-20] do it 'aborts the build with an EOL message' do app.deploy do |app| expect(clean_output(app.output)).to match(Regexp.new(<<~OUTPUT)) @@ -177,7 +107,7 @@ let(:allow_failure) { false } let(:app) { Hatchet::Runner.new('spec/fixtures/pipenv_python_3.7', allow_failure:) } - context 'when using Heroku-18 or Heroku-20', stacks: %w[heroku-18 heroku-20] do + context 'when using Heroku-20', stacks: %w[heroku-20] do it 'builds with the latest Python 3.7 but shows a deprecation warning' do app.deploy do |app| expect(clean_output(app.output)).to match(Regexp.new(<<~REGEX)) @@ -213,7 +143,7 @@ let(:allow_failure) { false } let(:app) { Hatchet::Runner.new('spec/fixtures/pipenv_python_3.8', allow_failure:) } - context 'when using Heroku-18 or Heroku-20', stacks: %w[heroku-18 heroku-20] do + context 'when using Heroku-20', stacks: %w[heroku-20] do include_examples 'builds using Pipenv with the requested Python version', LATEST_PYTHON_3_8 end diff --git a/spec/hatchet/python_update_warning_spec.rb b/spec/hatchet/python_update_warning_spec.rb index 8533372ca..d3c10b71e 100644 --- a/spec/hatchet/python_update_warning_spec.rb +++ b/spec/hatchet/python_update_warning_spec.rb @@ -60,7 +60,7 @@ let(:allow_failure) { false } let(:app) { Hatchet::Runner.new('spec/fixtures/python_3.7_outdated', allow_failure:) } - context 'when using Heroku-18 or Heroku-20', stacks: %w[heroku-18 heroku-20] do + context 'when using Heroku-20', stacks: %w[heroku-20] do it 'warns about both the deprecated major version and the patch update' do app.deploy do |app| expect(clean_output(app.output)).to match(Regexp.new(<<~REGEX)) @@ -95,7 +95,7 @@ let(:allow_failure) { false } let(:app) { Hatchet::Runner.new('spec/fixtures/python_3.8_outdated', allow_failure:) } - context 'when using Heroku-18 or Heroku-20', stacks: %w[heroku-18 heroku-20] do + context 'when using Heroku-20', stacks: %w[heroku-20] do include_examples 'warns there is a Python update available', '3.8.12', LATEST_PYTHON_3_8 end diff --git a/spec/hatchet/python_version_spec.rb b/spec/hatchet/python_version_spec.rb index 80f586e90..3f92899e7 100644 --- a/spec/hatchet/python_version_spec.rb +++ b/spec/hatchet/python_version_spec.rb @@ -78,110 +78,10 @@ end end - context 'when runtime.txt contains python-2.7.18' do - let(:app) { Hatchet::Runner.new('spec/fixtures/python_2.7', allow_failure: true) } - - context 'when using Heroku-18', stacks: %w[heroku-18] do - it 'aborts the build with an EOL message' do - app.deploy do |app| - expect(clean_output(app.output)).to include(<<~OUTPUT) - remote: -----> Python app detected - remote: -----> Using Python version specified in runtime.txt - remote: ! - remote: ! Python 2 reached upstream end-of-life on January 1st, 2020, and is - remote: ! therefore no longer receiving security updates. Apps still using it - remote: ! contain potential security vulnerabilities and should be upgraded to - remote: ! Python 3 as soon as possible. - remote: ! - remote: ! In addition, Python 2 is only supported on our oldest stack, Heroku-18, - remote: ! which is deprecated and reaches end-of-life on April 30th, 2023. - remote: ! - remote: ! As such, it is no longer supported by the latest version of this buildpack: - remote: ! https://devcenter.heroku.com/changelog-items/2473 - remote: ! - remote: ! You must either: - remote: ! - Upgrade to Python 3 (recommended) - remote: ! - Switch to the container stack and use the upstream legacy 'python:2.7' Docker images - remote: ! - Switch to an older version of the Python buildpack (short term workaround only) - remote: ! - remote: ! For more details, see: - remote: ! https://devcenter.heroku.com/articles/python-2-7-eol-faq - remote: ! - OUTPUT - end - end - end - - context 'when using Heroku-20 or newer', stacks: %w[heroku-20 heroku-22] do - # Python 2.7 is EOL, so has not been built for newer stacks. - include_examples 'aborts the build with a runtime not available message', 'python-2.7.18' - end - end - - context 'when runtime.txt contains python-3.4.10' do - let(:app) { Hatchet::Runner.new('spec/fixtures/python_3.4', allow_failure: true) } - - context 'when using Heroku-18', stacks: %w[heroku-18] do - it 'aborts the build with an EOL message' do - app.deploy do |app| - expect(clean_output(app.output)).to include(<<~OUTPUT) - remote: -----> Python app detected - remote: -----> Using Python version specified in runtime.txt - remote: ! - remote: ! Python 3.4 reached upstream end-of-life on March 18th, 2019, and is - remote: ! therefore no longer receiving security updates: - remote: ! https://devguide.python.org/versions/#supported-versions - remote: ! - remote: ! As such, it is no longer supported by the latest version of this buildpack. - remote: ! - remote: ! Please upgrade to a newer Python version. See: - remote: ! https://devcenter.heroku.com/articles/python-runtimes - remote: ! - OUTPUT - end - end - end - - context 'when using Heroku-20 or newer', stacks: %w[heroku-20 heroku-22] do - # Python 3.4 is EOL, so has not been built for newer stacks. - include_examples 'aborts the build with a runtime not available message', 'python-3.4.10' - end - end - - context 'when runtime.txt contains python-3.5.10' do - let(:app) { Hatchet::Runner.new('spec/fixtures/python_3.5', allow_failure: true) } - - context 'when using Heroku-18', stacks: %w[heroku-18] do - it 'aborts the build with an EOL message' do - app.deploy do |app| - expect(clean_output(app.output)).to include(<<~OUTPUT) - remote: -----> Python app detected - remote: -----> Using Python version specified in runtime.txt - remote: ! - remote: ! Python 3.5 reached upstream end-of-life on September 30th, 2020, and is - remote: ! therefore no longer receiving security updates: - remote: ! https://devguide.python.org/versions/#supported-versions - remote: ! - remote: ! As such, it is no longer supported by the latest version of this buildpack. - remote: ! - remote: ! Please upgrade to a newer Python version. See: - remote: ! https://devcenter.heroku.com/articles/python-runtimes - remote: ! - OUTPUT - end - end - end - - context 'when using Heroku-20 or newer', stacks: %w[heroku-20 heroku-22] do - # Python 3.5 is EOL, so has not been built for newer stacks. - include_examples 'aborts the build with a runtime not available message', 'python-3.5.10' - end - end - context 'when runtime.txt contains python-3.6.15' do let(:app) { Hatchet::Runner.new('spec/fixtures/python_3.6', allow_failure: true) } - context 'when using Heroku-18 or Heroku-20', stacks: %w[heroku-18 heroku-20] do + context 'when using Heroku-20', stacks: %w[heroku-20] do it 'aborts the build with an EOL message' do app.deploy do |app| expect(clean_output(app.output)).to include(<<~OUTPUT) @@ -212,7 +112,7 @@ let(:allow_failure) { false } let(:app) { Hatchet::Runner.new('spec/fixtures/python_3.7', allow_failure:) } - context 'when using Heroku-18 or Heroku-20', stacks: %w[heroku-18 heroku-20] do + context 'when using Heroku-20', stacks: %w[heroku-20] do it 'builds with Python 3.7.16 but shows a deprecation warning' do app.deploy do |app| expect(clean_output(app.output)).to include(<<~OUTPUT) @@ -249,7 +149,7 @@ let(:allow_failure) { false } let(:app) { Hatchet::Runner.new('spec/fixtures/python_3.8', allow_failure:) } - context 'when using Heroku-18 or Heroku-20', stacks: %w[heroku-18 heroku-20] do + context 'when using Heroku-20', stacks: %w[heroku-20] do include_examples 'builds with the requested Python version', LATEST_PYTHON_3_8 end @@ -282,7 +182,7 @@ context 'when runtime.txt contains pypy3.6-7.3.2' do let(:app) { Hatchet::Runner.new('spec/fixtures/pypy_3.6', allow_failure: true) } - context 'when using Heroku-18 or Heroku-20', stacks: %w[heroku-18 heroku-20] do + context 'when using Heroku-20', stacks: %w[heroku-20] do it 'aborts the build with a sunset message' do app.deploy do |app| expect(clean_output(app.output)).to include(<<~OUTPUT)