Skip to content

Commit d53ca7a

Browse files
committed
Add support for the Heroku-22 stack
Adds binary generation and testing support for Heroku-22. Runtime version support for Heroku-22 is as follows: * Python 3.6 and older: Not supported since EOL. * Python 3.7/3.8: Not supported since: - they are in the security-fix-only phase of their lifecycle - they reach EOL in 2023-06 and 2024-10 respectively, which is well before the EOL date of Heroku-22 - upgrading from 3.7/3.9 to 3.9 is in most cases trivial, and so we should be encouraging users to upgrade. * Python 3.9: Only the current latest patch release (3.9.12) supported (plus any future 3.9 releases). * Python 3.10: Only the current latest patch release (3.10.4) supported (plus any future 3.10 releases). * PyPy: Not supported, since is deprecated, was only ever a beta feature, the PyPy versions available for Heroku-18/20 are significantly out of date, and usage is virtually non-existent. GUS-W-10343718.
1 parent 38afb77 commit d53ca7a

File tree

12 files changed

+319
-135
lines changed

12 files changed

+319
-135
lines changed

.circleci/config.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ jobs:
4747
parameters:
4848
stack:
4949
type: enum
50-
enum: ["heroku-18", "heroku-20"]
50+
enum: ["heroku-18", "heroku-20", "heroku-22"]
5151
docker:
5252
- image: cimg/ruby:2.7
5353
working_directory: /mnt/ramdisk/project
@@ -87,4 +87,4 @@ workflows:
8787
- hatchet:
8888
matrix:
8989
parameters:
90-
stack: ["heroku-18", "heroku-20"]
90+
stack: ["heroku-18", "heroku-20", "heroku-22"]

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
## Unreleased
44

5+
- Add support for Heroku-22 ([#1299](https://github.com/heroku/heroku-buildpack-python/pull/1299)).
56
- Use shared builds + LTO when building Python 3.10 binaries ([#1320](https://github.com/heroku/heroku-buildpack-python/pull/1320)).
67
Note: This and the other Python binary changes below will only take effect for future Python
78
version releases (or future Heroku stacks) - existing Python binaries are not being recompiled.

Makefile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
# These targets are not files
22
.PHONY: lint lint-scripts lint-ruby compile builder-image buildenv deploy-runtimes publish
33

4-
STACK ?= heroku-20
5-
STACKS ?= heroku-18 heroku-20
4+
STACK ?= heroku-22
5+
STACKS ?= heroku-18 heroku-20 heroku-22
66
PLATFORM := linux/amd64
77
FIXTURE ?= spec/fixtures/python_version_unspecified
88
ENV_FILE ?= builds/dockerenv.default

README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ Specify a Python Runtime
6060

6161
Supported runtime options include:
6262

63-
- `python-3.10.4`
64-
- `python-3.9.12`
65-
- `python-3.8.13`
66-
- `python-3.7.13`
63+
- `python-3.10.4` on all [supported stacks](https://devcenter.heroku.com/articles/stack#stack-support-details)
64+
- `python-3.9.12` on all [supported stacks](https://devcenter.heroku.com/articles/stack#stack-support-details)
65+
- `python-3.8.13` on Heroku-18 and Heroku-20 only
66+
- `python-3.7.13` on Heroku-18 and Heroku-20 only

builds/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ make deploy-runtimes RUNTIMES='python-X.Y.Z' STACKS='heroku-18'
7474
Multiple runtimes can also be specified (useful for when adding a new stack), like so:
7575

7676
```bash
77-
make deploy-runtimes RUNTIMES='python-A.B.C python-X.Y.Z' STACKS='heroku-20'
77+
make deploy-runtimes RUNTIMES='python-A.B.C python-X.Y.Z' STACKS='heroku-22'
7878
```
7979

8080
Note: Both `RUNTIMES` and `STACKS` are space delimited.

builds/heroku-22.Dockerfile

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
FROM heroku/heroku:22-build
2+
3+
ENV WORKSPACE_DIR="/app/builds" \
4+
S3_BUCKET="heroku-buildpack-python" \
5+
S3_PREFIX="heroku-22/" \
6+
STACK="heroku-22"
7+
8+
RUN apt-get update \
9+
&& DEBIAN_FRONTEND=noninteractive apt-get install --no-install-recommends -y \
10+
libsqlite3-dev \
11+
python3-pip \
12+
python3-setuptools \
13+
&& rm -rf /var/lib/apt/lists/*
14+
15+
WORKDIR /app
16+
17+
COPY requirements.txt /app/
18+
RUN pip3 install --disable-pip-version-check --no-cache-dir -r /app/requirements.txt
19+
20+
COPY . /app

builds/runtimes/python

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,12 @@ VERSION=$(echo "${FORMULA_FILENAME}" | cut --delimiter '-' --fields 2)
1212

1313
echo "Building Python ${VERSION}..."
1414

15+
if [[ "${STACK}" != "heroku-18" && "${STACK}" != "heroku-20" && "${VERSION}" == 3.[7-8].* ]]; then
16+
echo "Python 3.7 and 3.8 are only supported on Heroku-20 and older!" >&2
17+
echo "Override the default stacks list using: STACKS='heroku-18 heroku-20'" >&2
18+
exit 1
19+
fi
20+
1521
# See: https://www.python.org/downloads/ -> "OpenPGP Public Keys"
1622
case "${VERSION}" in
1723
3.10.*)

spec/hatchet/pipenv_spec.rb

Lines changed: 63 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,19 @@
2020
end
2121
end
2222

23+
RSpec.shared_examples 'aborts the build with a runtime not available message (Pipenv)' do |requested_version|
24+
it 'aborts the build with a runtime not available message' do
25+
app.deploy do |app|
26+
expect(clean_output(app.output)).to include(<<~OUTPUT)
27+
remote: -----> Python app detected
28+
remote: -----> Using Python version specified in Pipfile.lock
29+
remote: ! Requested runtime (python-#{requested_version}) is not available for this stack (#{app.stack}).
30+
remote: ! Aborting. More info: https://devcenter.heroku.com/articles/python-support
31+
OUTPUT
32+
end
33+
end
34+
end
35+
2336
RSpec.describe 'Pipenv support' do
2437
context 'without a Pipfile.lock' do
2538
let(:app) { Hatchet::Runner.new('spec/fixtures/pipenv_no_lockfile') }
@@ -85,20 +98,11 @@
8598
end
8699
end
87100

88-
context 'when using Heroku-20', stacks: %w[heroku-20] do
101+
context 'when using Heroku-20 or newer', stacks: %w[heroku-20 heroku-22] do
89102
let(:allow_failure) { true }
90103

91-
it 'fails the build' do
92-
# Python 2.7 is EOL, so it has not been built for Heroku-20.
93-
app.deploy do |app|
94-
expect(clean_output(app.output)).to include(<<~OUTPUT)
95-
remote: -----> Python app detected
96-
remote: -----> Using Python version specified in Pipfile.lock
97-
remote: ! Requested runtime (python-#{LATEST_PYTHON_2_7}) is not available for this stack (#{app.stack}).
98-
remote: ! Aborting. More info: https://devcenter.heroku.com/articles/python-support
99-
OUTPUT
100-
end
101-
end
104+
# Python 2.7 is EOL, so has not been built for newer stacks.
105+
include_examples 'aborts the build with a runtime not available message (Pipenv)', LATEST_PYTHON_2_7
102106
end
103107
end
104108

@@ -112,34 +116,64 @@
112116
end
113117

114118
context 'with a Pipfile.lock containing python_version 3.6' do
115-
let(:app) { Hatchet::Runner.new('spec/fixtures/pipenv_python_3.6') }
119+
let(:allow_failure) { false }
120+
let(:app) { Hatchet::Runner.new('spec/fixtures/pipenv_python_3.6', allow_failure: allow_failure) }
116121

117-
it 'builds with the latest Python 3.6' do
118-
app.deploy do |app|
119-
expect(clean_output(app.output)).to match(Regexp.new(<<~REGEX))
120-
remote: -----> Python app detected
121-
remote: -----> Using Python version specified in Pipfile.lock
122-
remote: cp: cannot stat '/tmp/build_.*/requirements.txt': No such file or directory
123-
remote: -----> Installing python-#{LATEST_PYTHON_3_6}
124-
remote: -----> Installing pip 21.3.1, setuptools 59.6.0 and wheel 0.37.1
125-
remote: -----> Installing dependencies with Pipenv 2020.11.15
126-
remote: Installing dependencies from Pipfile.lock \\(.*\\)...
127-
remote: -----> Installing SQLite3
128-
REGEX
122+
context 'when using Heroku-18 or Heroku-20', stacks: %w[heroku-18 heroku-20] do
123+
it 'builds with the latest Python 3.6' do
124+
app.deploy do |app|
125+
expect(clean_output(app.output)).to match(Regexp.new(<<~REGEX))
126+
remote: -----> Python app detected
127+
remote: -----> Using Python version specified in Pipfile.lock
128+
remote: cp: cannot stat '/tmp/build_.*/requirements.txt': No such file or directory
129+
remote: -----> Installing python-#{LATEST_PYTHON_3_6}
130+
remote: -----> Installing pip 21.3.1, setuptools 59.6.0 and wheel 0.37.1
131+
remote: -----> Installing dependencies with Pipenv 2020.11.15
132+
remote: Installing dependencies from Pipfile.lock \\(.*\\)...
133+
remote: -----> Installing SQLite3
134+
REGEX
135+
end
129136
end
130137
end
138+
139+
context 'when using Heroku-22', stacks: %w[heroku-22] do
140+
let(:allow_failure) { true }
141+
142+
# Python 3.6 is EOL, so has not been built for newer stacks.
143+
include_examples 'aborts the build with a runtime not available message (Pipenv)', LATEST_PYTHON_3_6
144+
end
131145
end
132146

133147
context 'with a Pipfile.lock containing python_version 3.7' do
134-
let(:app) { Hatchet::Runner.new('spec/fixtures/pipenv_python_3.7') }
148+
let(:allow_failure) { false }
149+
let(:app) { Hatchet::Runner.new('spec/fixtures/pipenv_python_3.7', allow_failure: allow_failure) }
135150

136-
include_examples 'builds using Pipenv with the requested Python version', LATEST_PYTHON_3_7
151+
context 'when using Heroku-18 or Heroku-20', stacks: %w[heroku-18 heroku-20] do
152+
include_examples 'builds using Pipenv with the requested Python version', LATEST_PYTHON_3_7
153+
end
154+
155+
context 'when using Heroku-22', stacks: %w[heroku-22] do
156+
let(:allow_failure) { true }
157+
158+
# Python 3.7 is in the security fix only stage of its lifecycle, so has not been built for newer stacks.
159+
include_examples 'aborts the build with a runtime not available message (Pipenv)', LATEST_PYTHON_3_7
160+
end
137161
end
138162

139163
context 'with a Pipfile.lock containing python_version 3.8' do
140-
let(:app) { Hatchet::Runner.new('spec/fixtures/pipenv_python_3.8') }
164+
let(:allow_failure) { false }
165+
let(:app) { Hatchet::Runner.new('spec/fixtures/pipenv_python_3.8', allow_failure: allow_failure) }
141166

142-
include_examples 'builds using Pipenv with the requested Python version', LATEST_PYTHON_3_8
167+
context 'when using Heroku-18 or Heroku-20', stacks: %w[heroku-18 heroku-20] do
168+
include_examples 'builds using Pipenv with the requested Python version', LATEST_PYTHON_3_8
169+
end
170+
171+
context 'when using Heroku-22', stacks: %w[heroku-22] do
172+
let(:allow_failure) { true }
173+
174+
# Python 3.8 is in the security fix only stage of its lifecycle, so has not been built for newer stacks.
175+
include_examples 'aborts the build with a runtime not available message (Pipenv)', LATEST_PYTHON_3_8
176+
end
143177
end
144178

145179
context 'with a Pipfile.lock containing python_version 3.9' do

0 commit comments

Comments
 (0)