Skip to content

Commit 79c140d

Browse files
committed
Add more messaging to the build log recommending uv
The package manager uv offers many benefits for users over the alternatives, such as it: - Supporting lockfiles (unlike pip) - Being much faster - Giving more helpful error messages - Being actively maintained by a full time team As such we want to encourage users who may not have heard of it (or be aware that the buildpack now supports it) to try it out - and so now mention uv at the env of the build log for successful builds. GUS-W-19124925.
1 parent d668dbe commit 79c140d

File tree

9 files changed

+117
-16
lines changed

9 files changed

+117
-16
lines changed

CHANGELOG.md

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

55
- Deprecated support for Python 3.10. ([#1972](https://github.com/heroku/heroku-buildpack-python/pull/1972))
66
- Updated uv from 0.9.9 to 0.9.11. ([#1973](https://github.com/heroku/heroku-buildpack-python/pull/1973))
7+
- Added more messaging to the build log recommending uv. ([#1975](https://github.com/heroku/heroku-buildpack-python/pull/1975))
78
- Switched from using `--disable-pip-version-check` to the env var `PIP_DISABLE_PIP_VERSION_CHECK=1` when using pip. ([#1974](https://github.com/heroku/heroku-buildpack-python/pull/1974))
89

910
## [v320] - 2025-11-20

bin/compile

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -290,4 +290,18 @@ hooks::run_hook "post_compile"
290290

291291
cache::save "${BUILD_DIR}" "${CACHE_DIR}" "${STACK}" "${python_full_version}" "${package_manager}"
292292

293+
if [[ "${package_manager}" != "uv" ]]; then
294+
output::notice <<-EOF
295+
Note: We recently added support for the package manager uv:
296+
https://devcenter.heroku.com/changelog-items/3238
297+
298+
It's now our recommended Python package manager, since it
299+
supports lockfiles, is faster, gives more helpful error
300+
messages, and is actively maintained by a full-time team.
301+
302+
If you haven't tried it yet, we suggest you take a look!
303+
https://docs.astral.sh/uv/
304+
EOF
305+
fi
306+
293307
build_data::set_duration "total_duration" "${compile_start_time}"

bin/detect

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,11 @@ If your app already has a package manager file, check that it:
8686
Otherwise, add a package manager file to your app. If your app has
8787
no dependencies, then create an empty 'requirements.txt' file.
8888
89+
If you aren't sure which package manager to use, we recommend
90+
trying uv, since it supports lockfiles, is extremely fast, and
91+
is actively maintained by a full-time team:
92+
https://docs.astral.sh/uv/
93+
8994
For help with using Python on Heroku, see:
9095
https://devcenter.heroku.com/articles/getting-started-with-python
9196
https://devcenter.heroku.com/articles/python-support

lib/package_manager.sh

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,10 @@ function package_manager::determine_package_manager() {
3030
delete your 'Pipfile' and then add either a 'requirements.txt',
3131
'poetry.lock' or 'uv.lock' file.
3232
33-
Note: This error replaces the warning which was displayed in
34-
build logs starting 12th November 2024.
33+
If you aren't sure which package manager to use, we recommend
34+
trying uv, since it supports lockfiles, is extremely fast, and
35+
is actively maintained by a full-time team:
36+
https://docs.astral.sh/uv/
3537
EOF
3638
build_data::set_string "failure_reason" "package-manager::pipenv-missing-lockfile"
3739
exit 1

spec/hatchet/ci_spec.rb

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,17 @@
3737
PKG_CONFIG_PATH=/app/.heroku/python/lib/pkg-config
3838
PYTHONUNBUFFERED=1
3939
-----> Saving cache
40+
41+
! Note: We recently added support for the package manager uv:
42+
! https://devcenter.heroku.com/changelog-items/3238
43+
!
44+
! It's now our recommended Python package manager, since it
45+
! supports lockfiles, is faster, gives more helpful error
46+
! messages, and is actively maintained by a full-time team.
47+
!
48+
! If you haven't tried it yet, we suggest you take a look!
49+
! https://docs.astral.sh/uv/
50+
4051
-----> Inline app detected
4152
LANG=en_US.UTF-8
4253
LD_LIBRARY_PATH=/app/.heroku/python/lib
@@ -117,6 +128,17 @@
117128
PYTHONUNBUFFERED=1
118129
VIRTUAL_ENV=/app/.heroku/python
119130
-----> Saving cache
131+
132+
! Note: We recently added support for the package manager uv:
133+
! https://devcenter.heroku.com/changelog-items/3238
134+
!
135+
! It's now our recommended Python package manager, since it
136+
! supports lockfiles, is faster, gives more helpful error
137+
! messages, and is actively maintained by a full-time team.
138+
!
139+
! If you haven't tried it yet, we suggest you take a look!
140+
! https://docs.astral.sh/uv/
141+
120142
-----> Inline app detected
121143
LANG=en_US.UTF-8
122144
LD_LIBRARY_PATH=/app/.heroku/python/lib
@@ -205,6 +227,17 @@
205227
POETRY_VIRTUALENVS_USE_POETRY_PYTHON=true
206228
PYTHONUNBUFFERED=1
207229
-----> Saving cache
230+
231+
! Note: We recently added support for the package manager uv:
232+
! https://devcenter.heroku.com/changelog-items/3238
233+
!
234+
! It's now our recommended Python package manager, since it
235+
! supports lockfiles, is faster, gives more helpful error
236+
! messages, and is actively maintained by a full-time team.
237+
!
238+
! If you haven't tried it yet, we suggest you take a look!
239+
! https://docs.astral.sh/uv/
240+
208241
-----> Inline app detected
209242
LANG=en_US.UTF-8
210243
LD_LIBRARY_PATH=/app/.heroku/python/lib

spec/hatchet/detect_spec.rb

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,11 @@
3838
remote: ! Otherwise, add a package manager file to your app. If your app has
3939
remote: ! no dependencies, then create an empty 'requirements.txt' file.
4040
remote: !
41+
remote: ! If you aren't sure which package manager to use, we recommend
42+
remote: ! trying uv, since it supports lockfiles, is extremely fast, and
43+
remote: ! is actively maintained by a full-time team:
44+
remote: ! https://docs.astral.sh/uv/
45+
remote: !
4146
remote: ! For help with using Python on Heroku, see:
4247
remote: ! https://devcenter.heroku.com/articles/getting-started-with-python
4348
remote: ! https://devcenter.heroku.com/articles/python-support

spec/hatchet/pip_spec.rb

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,17 @@
3434
remote: PKG_CONFIG_PATH=/app/.heroku/python/lib/pkg-config
3535
remote: PYTHONUNBUFFERED=1
3636
remote: -----> Saving cache
37+
remote:
38+
remote: ! Note: We recently added support for the package manager uv:
39+
remote: ! https://devcenter.heroku.com/changelog-items/3238
40+
remote: !
41+
remote: ! It's now our recommended Python package manager, since it
42+
remote: ! supports lockfiles, is faster, gives more helpful error
43+
remote: ! messages, and is actively maintained by a full-time team.
44+
remote: !
45+
remote: ! If you haven't tried it yet, we suggest you take a look!
46+
remote: ! https://docs.astral.sh/uv/
47+
remote:
3748
remote: -----> Inline app detected
3849
remote: LANG=en_US.UTF-8
3950
remote: LD_LIBRARY_PATH=/app/.heroku/python/lib
@@ -96,7 +107,7 @@
96107
remote: -----> Running bin/post_compile hook
97108
remote: .+
98109
remote: -----> Saving cache
99-
remote: -----> Inline app detected
110+
remote:
100111
REGEX
101112

102113
# For historical reasons pip is made available at run-time too, unlike some of the other package managers.
@@ -162,7 +173,7 @@
162173

163174
it 'rewrites .pth, .egg-link and finder paths correctly for hooks, later buildpacks, runtime and cached builds' do
164175
app.deploy do |app|
165-
expect(clean_output(app.output)).to match(Regexp.new(<<~REGEX))
176+
expect(clean_output(app.output)).to match(Regexp.new(<<~REGEX, Regexp::MULTILINE))
166177
remote: -----> Running bin/post_compile hook
167178
remote: easy-install.pth:/app/.heroku/python/src/gunicorn
168179
remote: easy-install.pth:/tmp/build_.+/packages/local_package_setup_py
@@ -174,6 +185,7 @@
174185
remote: Running entrypoint for the setup.py-based local package: Hello from setup.py!
175186
remote: Running entrypoint for the VCS package: gunicorn \\(version 20.1.0\\)
176187
remote: -----> Saving cache
188+
.+
177189
remote: -----> Inline app detected
178190
remote: easy-install.pth:/app/.heroku/python/src/gunicorn
179191
remote: easy-install.pth:/tmp/build_.+/packages/local_package_setup_py
@@ -202,7 +214,7 @@
202214
# Test that the cached .pth files work correctly.
203215
app.commit!
204216
app.push!
205-
expect(clean_output(app.output)).to match(Regexp.new(<<~REGEX))
217+
expect(clean_output(app.output)).to match(Regexp.new(<<~REGEX, Regexp::MULTILINE))
206218
remote: -----> Running bin/post_compile hook
207219
remote: easy-install.pth:/app/.heroku/python/src/gunicorn
208220
remote: easy-install.pth:/tmp/build_.+/packages/local_package_setup_py
@@ -214,6 +226,7 @@
214226
remote: Running entrypoint for the setup.py-based local package: Hello from setup.py!
215227
remote: Running entrypoint for the VCS package: gunicorn \\(version 20.1.0\\)
216228
remote: -----> Saving cache
229+
.+
217230
remote: -----> Inline app detected
218231
remote: easy-install.pth:/app/.heroku/python/src/gunicorn
219232
remote: easy-install.pth:/tmp/build_.+/packages/local_package_setup_py

spec/hatchet/pipenv_spec.rb

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,17 @@
3232
remote: PYTHONUNBUFFERED=1
3333
remote: VIRTUAL_ENV=/app/.heroku/python
3434
remote: -----> Saving cache
35+
remote:
36+
remote: ! Note: We recently added support for the package manager uv:
37+
remote: ! https://devcenter.heroku.com/changelog-items/3238
38+
remote: !
39+
remote: ! It's now our recommended Python package manager, since it
40+
remote: ! supports lockfiles, is faster, gives more helpful error
41+
remote: ! messages, and is actively maintained by a full-time team.
42+
remote: !
43+
remote: ! If you haven't tried it yet, we suggest you take a look!
44+
remote: ! https://docs.astral.sh/uv/
45+
remote:
3546
remote: -----> Inline app detected
3647
remote: LANG=en_US.UTF-8
3748
remote: LD_LIBRARY_PATH=/app/.heroku/python/lib
@@ -96,7 +107,7 @@
96107
remote: -----> Running bin/post_compile hook
97108
remote: .+
98109
remote: -----> Saving cache
99-
remote: -----> Inline app detected
110+
remote:
100111
REGEX
101112

102113
# For historical reasons Pipenv is made available at run-time too, unlike some of the other package managers.
@@ -141,7 +152,7 @@
141152
remote: -----> Installing dependencies using 'pipenv install --deploy'
142153
remote: Installing dependencies from Pipfile.lock \\(.+\\)...
143154
remote: -----> Saving cache
144-
remote: -----> Discovering process types
155+
remote:
145156
REGEX
146157
end
147158
end
@@ -303,8 +314,10 @@
303314
remote: ! delete your 'Pipfile' and then add either a 'requirements.txt',
304315
remote: ! 'poetry.lock' or 'uv.lock' file.
305316
remote: !
306-
remote: ! Note: This error replaces the warning which was displayed in
307-
remote: ! build logs starting 12th November 2024.
317+
remote: ! If you aren't sure which package manager to use, we recommend
318+
remote: ! trying uv, since it supports lockfiles, is extremely fast, and
319+
remote: ! is actively maintained by a full-time team:
320+
remote: ! https://docs.astral.sh/uv/
308321
remote:
309322
remote: ! Push rejected, failed to compile Python app.
310323
REGEX
@@ -465,7 +478,7 @@
465478
remote: -----> Installing dependencies using 'pipenv install --deploy'
466479
remote: Installing dependencies from Pipfile.lock \\(.+\\)...
467480
remote: -----> Saving cache
468-
remote: -----> Discovering process types
481+
remote:
469482
REGEX
470483
end
471484
end
@@ -477,7 +490,7 @@
477490

478491
it 'rewrites .pth and finder paths correctly for hooks, later buildpacks, runtime and cached builds' do
479492
app.deploy do |app|
480-
expect(clean_output(app.output)).to match(Regexp.new(<<~REGEX))
493+
expect(clean_output(app.output)).to match(Regexp.new(<<~REGEX, Regexp::MULTILINE))
481494
remote: -----> Installing dependencies using 'pipenv install --deploy'
482495
remote: Installing dependencies from Pipfile.lock \\(.+\\)...
483496
remote: -----> Running bin/post_compile hook
@@ -491,6 +504,7 @@
491504
remote: Running entrypoint for the setup.py-based local package: Hello from setup.py!
492505
remote: Running entrypoint for the VCS package: gunicorn \\(version 23.0.0\\)
493506
remote: -----> Saving cache
507+
.+
494508
remote: -----> Inline app detected
495509
remote: __editable___gunicorn_23_0_0_finder.py:/app/.heroku/python/src/gunicorn/gunicorn'}
496510
remote: __editable___local_package_pyproject_toml_0_0_1_finder.py:/tmp/build_.+/packages/local_package_pyproject_toml/local_package_pyproject_toml'}
@@ -519,7 +533,7 @@
519533
# Test that the cached .pth files work correctly.
520534
app.commit!
521535
app.push!
522-
expect(clean_output(app.output)).to match(Regexp.new(<<~REGEX))
536+
expect(clean_output(app.output)).to match(Regexp.new(<<~REGEX, Regexp::MULTILINE))
523537
remote: -----> Installing dependencies using 'pipenv install --deploy'
524538
remote: Installing dependencies from Pipfile.lock \\(.+\\)...
525539
remote: -----> Running bin/post_compile hook
@@ -533,6 +547,7 @@
533547
remote: Running entrypoint for the setup.py-based local package: Hello from setup.py!
534548
remote: Running entrypoint for the VCS package: gunicorn \\(version 23.0.0\\)
535549
remote: -----> Saving cache
550+
.+
536551
remote: -----> Inline app detected
537552
remote: __editable___gunicorn_23_0_0_finder.py:/app/.heroku/python/src/gunicorn/gunicorn'}
538553
remote: __editable___local_package_pyproject_toml_0_0_1_finder.py:/tmp/build_.+/packages/local_package_pyproject_toml/local_package_pyproject_toml'}

spec/hatchet/poetry_spec.rb

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,17 @@
3535
remote: POETRY_VIRTUALENVS_USE_POETRY_PYTHON=true
3636
remote: PYTHONUNBUFFERED=1
3737
remote: -----> Saving cache
38+
remote:
39+
remote: ! Note: We recently added support for the package manager uv:
40+
remote: ! https://devcenter.heroku.com/changelog-items/3238
41+
remote: !
42+
remote: ! It's now our recommended Python package manager, since it
43+
remote: ! supports lockfiles, is faster, gives more helpful error
44+
remote: ! messages, and is actively maintained by a full-time team.
45+
remote: !
46+
remote: ! If you haven't tried it yet, we suggest you take a look!
47+
remote: ! https://docs.astral.sh/uv/
48+
remote:
3849
remote: -----> Inline app detected
3950
remote: LANG=en_US.UTF-8
4051
remote: LD_LIBRARY_PATH=/app/.heroku/python/lib
@@ -98,7 +109,7 @@
98109
remote: -----> Running bin/post_compile hook
99110
remote: .+
100111
remote: -----> Saving cache
101-
remote: -----> Inline app detected
112+
remote:
102113
REGEX
103114

104115
command = 'bin/print-env-vars.sh && if command -v poetry; then echo "Poetry unexpectedly found!" && exit 1; fi'
@@ -145,7 +156,7 @@
145156
remote:
146157
remote: - Installing typing-extensions (4.12.2)
147158
remote: -----> Saving cache
148-
remote: -----> Discovering process types
159+
remote:
149160
OUTPUT
150161
end
151162
end
@@ -157,7 +168,7 @@
157168

158169
it 'rewrites .pth and finder paths correctly for hooks, later buildpacks, runtime and cached builds' do
159170
app.deploy do |app|
160-
expect(clean_output(app.output)).to match(Regexp.new(<<~REGEX))
171+
expect(clean_output(app.output)).to match(Regexp.new(<<~REGEX, Regexp::MULTILINE))
161172
remote: -----> Installing dependencies using 'poetry sync --only main'
162173
remote: Installing dependencies from lock file
163174
remote:
@@ -180,6 +191,7 @@
180191
remote: Running entrypoint for the setup.py-based local package: Hello from setup.py!
181192
remote: Running entrypoint for the VCS package: gunicorn \\(version 23.0.0\\)
182193
remote: -----> Saving cache
194+
.+
183195
remote: -----> Inline app detected
184196
remote: __editable___gunicorn_23_0_0_finder.py:/app/.heroku/python/src/gunicorn/gunicorn'}
185197
remote: __editable___local_package_pyproject_toml_0_0_1_finder.py:/tmp/build_.+/packages/local_package_pyproject_toml/local_package_pyproject_toml'}
@@ -208,7 +220,7 @@
208220
# Test that the cached .pth files work correctly.
209221
app.commit!
210222
app.push!
211-
expect(clean_output(app.output)).to match(Regexp.new(<<~REGEX))
223+
expect(clean_output(app.output)).to match(Regexp.new(<<~REGEX, Regexp::MULTILINE))
212224
remote: -----> Installing dependencies using 'poetry sync --only main'
213225
remote: Installing dependencies from lock file
214226
remote:
@@ -230,6 +242,7 @@
230242
remote: Running entrypoint for the setup.py-based local package: Hello from setup.py!
231243
remote: Running entrypoint for the VCS package: gunicorn \\(version 23.0.0\\)
232244
remote: -----> Saving cache
245+
.+
233246
remote: -----> Inline app detected
234247
remote: __editable___gunicorn_23_0_0_finder.py:/app/.heroku/python/src/gunicorn/gunicorn'}
235248
remote: __editable___local_package_pyproject_toml_0_0_1_finder.py:/tmp/build_.+/packages/local_package_pyproject_toml/local_package_pyproject_toml'}

0 commit comments

Comments
 (0)