Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ jobs:
strategy:
fail-fast: false
matrix:
stack: ["heroku-22", "heroku-24"]
stack: ["heroku-22", "heroku-24", "heroku-26"]
env:
HATCHET_APP_LIMIT: 300
HATCHET_DEFAULT_STACK: ${{ matrix.stack }}
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

## [Unreleased]

- Added support for Heroku-26. ([#2073](https://github.com/heroku/heroku-buildpack-python/pull/2073))

## [v341] - 2026-04-07

Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# These targets are not files
.PHONY: lint lint-scripts lint-ruby check-format format run publish

STACK ?= heroku-24
STACK ?= heroku-26
FIXTURE ?= spec/fixtures/python_version_unspecified
# Allow overriding the exit code in CI, so we can test bin/report works for failing builds.
COMPILE_FAILURE_EXIT_CODE ?= 1
Expand Down
2 changes: 1 addition & 1 deletion lib/checks.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ function checks::ensure_supported_stack() {
local stack="${1}"

case "${stack}" in
heroku-22 | heroku-24)
heroku-22 | heroku-24 | heroku-26)
return 0
;;
cedar* | heroku-16 | heroku-18 | heroku-20)
Expand Down
2 changes: 1 addition & 1 deletion spec/fixtures/python_version_outdated/.python-version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
3.13.2
3.14.0
5 changes: 4 additions & 1 deletion spec/hatchet/pipenv_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -455,7 +455,10 @@
end
end

context 'when the Pipenv and Python versions have changed since the last build' do
# TODO: Enable on Heroku-26 after the Pipenv and default Python versions next change,
# since for now there isn't a historic buildpack version we can use in this test whose
# stack check permits Heroku-26 and that also uses older Pipenv/Python versions.
context 'when the Pipenv and Python versions have changed since the last build', stacks: %w[heroku-22 heroku-24] do
let(:buildpacks) { ['https://github.com/heroku/heroku-buildpack-python#v313'] }
let(:app) { Hatchet::Runner.new('spec/fixtures/pipenv_basic', buildpacks:) }

Expand Down
5 changes: 4 additions & 1 deletion spec/hatchet/poetry_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,10 @@
end
end

context 'when the Poetry and Python versions have changed since the last build' do
# TODO: Enable on Heroku-26 after the Poetry and default Python versions next change,
# since for now there isn't a historic buildpack version we can use in this test whose
# stack check permits Heroku-26 and that also uses older Poetry/Python versions.
context 'when the Poetry and Python versions have changed since the last build', stacks: %w[heroku-22 heroku-24] do
let(:buildpacks) { ['https://github.com/heroku/heroku-buildpack-python#v313'] }
let(:app) { Hatchet::Runner.new('spec/fixtures/poetry_basic', buildpacks:) }

Expand Down
22 changes: 13 additions & 9 deletions spec/hatchet/python_version_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -88,17 +88,21 @@
end
end

context 'with an app last built using an older default Python version' do
# TODO: Enable on Heroku-26 after the default Python version next changes (for the 3.14.5
# release), since for now there isn't a historic buildpack version we can use in this test
# whose stack check permits Heroku-26 and also has a different default Python version so
# that we can test the sticky versions feature.
context 'with an app last built using an older default Python version', stacks: %w[heroku-22 heroku-24] do
# This test performs an initial build using an older buildpack version, followed
# by a build using the current version. This ensures that:
# - The current buildpack can successfully read the version metadata
# written to the build cache by older buildpack versions.
# - If no Python version is specified, the same major version as the
# last build is used (sticky versioning).
# last build is used (sticky major versioning).
# - Changes in the pip version are handled correctly.
let(:buildpacks) { ['https://github.com/heroku/heroku-buildpack-python#v267'] }

it 'builds with the same Python version as the last build' do
it 'builds with the same major Python version as the last build' do
app.deploy do |app|
update_buildpacks(app, [:default])
app.commit!
Expand Down Expand Up @@ -566,25 +570,25 @@
app.deploy do |app|
expect(clean_output(app.output)).to include(<<~OUTPUT)
remote: -----> Python app detected
remote: -----> Using Python 3.13.2 specified in .python-version
remote: -----> Using Python 3.14.0 specified in .python-version
remote:
remote: ! Warning: A Python patch update is available!
remote: !
remote: ! Your app is using Python 3.13.2, however, there is a newer
remote: ! patch release of Python 3.13 available: #{LATEST_PYTHON_3_13}
remote: ! Your app is using Python 3.14.0, however, there is a newer
remote: ! patch release of Python 3.14 available: #{LATEST_PYTHON_3_14}
remote: !
remote: ! It is important to always use the latest patch version of
remote: ! Python to keep your app secure.
remote: !
remote: ! Update your .python-version file to use the new version.
remote: !
remote: ! We strongly recommend that you don't pin your app to an
remote: ! exact Python version such as 3.13.2, and instead only specify
remote: ! the major Python version of 3.13 in your .python-version file.
remote: ! exact Python version such as 3.14.0, and instead only specify
remote: ! the major Python version of 3.14 in your .python-version file.
remote: ! This will allow your app to receive the latest available Python
remote: ! patch version automatically and prevent this warning.
remote:
remote: -----> Installing Python 3.13.2
remote: -----> Installing Python 3.14.0
remote: -----> Installing pip #{PIP_VERSION}
OUTPUT
end
Expand Down
16 changes: 8 additions & 8 deletions spec/hatchet/stack_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
require_relative '../spec_helper'

RSpec.describe 'Stack changes' do
context 'when the stack is upgraded from Heroku-22 to Heroku-24', stacks: %w[heroku-22] do
context 'when the stack is upgraded from Heroku-24 to Heroku-26', stacks: %w[heroku-24] do
# This test performs an initial build using an older buildpack version, followed by a build
# using the current version. This ensures that the current buildpack can successfully read
# the stack metadata written to the build cache in the past. The buildpack version chosen is
Expand All @@ -14,8 +14,8 @@

it 'clears the cache before installing again whilst preserving the sticky Python version' do
app.deploy do |app|
expect(app.output).to include('Building on the Heroku-22 stack')
app.update_stack('heroku-24')
expect(app.output).to include('Building on the Heroku-24 stack')
app.update_stack('heroku-26')
update_buildpacks(app, [:default])
app.commit!
app.push!
Expand Down Expand Up @@ -64,7 +64,7 @@
remote: ! file and this warning will be made an error.
remote:
remote: -----> Discarding cache since:
remote: - The stack has changed from heroku-22 to heroku-24
remote: - The stack has changed from heroku-24 to heroku-26
remote: - The Python version has changed from 3.12.3 to #{LATEST_PYTHON_3_12}
remote: - The buildpack cache format has changed
remote: - The legacy SQLite3 headers and CLI binary need to be uninstalled
Expand All @@ -77,20 +77,20 @@
end
end

context 'when the stack is downgraded from Heroku-24 to Heroku-22', stacks: %w[heroku-24] do
context 'when the stack is downgraded from Heroku-26 to Heroku-24', stacks: %w[heroku-26] do
let(:app) { Hatchet::Runner.new('spec/fixtures/python_3.14') }

it 'clears the cache before installing again' do
app.deploy do |app|
expect(app.output).to include('Building on the Heroku-24 stack')
app.update_stack('heroku-22')
expect(app.output).to include('Building on the Heroku-26 stack')
app.update_stack('heroku-24')
app.commit!
app.push!
expect(clean_output(app.output)).to include(<<~OUTPUT)
remote: -----> Python app detected
remote: -----> Using Python 3.14 specified in .python-version
remote: -----> Discarding cache since:
remote: - The stack has changed from heroku-24 to heroku-22
remote: - The stack has changed from heroku-26 to heroku-24
remote: -----> Installing Python #{LATEST_PYTHON_3_14}
remote: -----> Installing pip #{PIP_VERSION}
remote: -----> Installing dependencies using 'pip install -r requirements.txt'
Expand Down
5 changes: 4 additions & 1 deletion spec/hatchet/uv_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,10 @@
end
end

context 'when the uv and Python versions have changed since the last build' do
# TODO: Enable on Heroku-26 after the uv and default Python versions next change,
# since for now there isn't a historic buildpack version we can use in this test
# whose stack check permits Heroku-26 and that also uses older uv/Python versions.
context 'when the uv and Python versions have changed since the last build', stacks: %w[heroku-22 heroku-24] do
let(:buildpacks) { ['https://github.com/heroku/heroku-buildpack-python#v313'] }
let(:app) { Hatchet::Runner.new('spec/fixtures/uv_basic', buildpacks:) }

Expand Down
2 changes: 1 addition & 1 deletion spec/spec_helper.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# frozen_string_literal: true

ENV['HATCHET_BUILDPACK_BASE'] ||= 'https://github.com/heroku/heroku-buildpack-python.git'
ENV['HATCHET_DEFAULT_STACK'] ||= 'heroku-24'
ENV['HATCHET_DEFAULT_STACK'] ||= 'heroku-26'

require 'English' # for $CHILD_STATUS
require 'rspec/core'
Expand Down