Skip to content

Commit

Permalink
Misc integration test improvements
Browse files Browse the repository at this point in the history
As part of adding Poetry + `.python-version` file support, a fair
amount of buildpack refactoring will be required.

This backports some of the additional test scenarios we now have
in the new Python CNB, along with some test general improvements.

It's been split out of later PRs for easier review.
  • Loading branch information
edmorley committed Sep 20, 2024
1 parent d13fbbd commit 6230534
Show file tree
Hide file tree
Showing 29 changed files with 343 additions and 100 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,14 @@ jobs:
matrix:
stack: ["heroku-20", "heroku-22", "heroku-24"]
env:
HATCHET_APP_LIMIT: 200
HATCHET_APP_LIMIT: 300
HATCHET_DEFAULT_STACK: ${{ matrix.stack }}
HATCHET_EXPENSIVE_MODE: 1
HEROKU_API_KEY: ${{ secrets.HEROKU_API_KEY }}
HEROKU_API_USER: ${{ secrets.HEROKU_API_USER }}
HEROKU_DISABLE_AUTOUPDATE: 1
PARALLEL_SPLIT_TEST_PROCESSES: 60
RSPEC_RETRY_RETRY_COUNT: 3
PARALLEL_SPLIT_TEST_PROCESSES: 70
RSPEC_RETRY_RETRY_COUNT: 2
steps:
- name: Checkout
uses: actions/checkout@v4
Expand Down
24 changes: 12 additions & 12 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ GEM
base64 (0.2.0)
diff-lcs (1.5.1)
erubis (2.7.0)
excon (0.110.0)
excon (0.111.0)
heroics (0.1.3)
base64
erubis (~> 2.0)
Expand All @@ -27,7 +27,7 @@ GEM
parallel_split_test (0.10.0)
parallel (>= 0.5.13)
rspec-core (>= 3.9.0)
parser (3.3.4.2)
parser (3.3.5.0)
ast (~> 2.4.1)
racc
platform-api (3.7.0)
Expand All @@ -39,32 +39,32 @@ GEM
rate_throttle_client (0.1.2)
regexp_parser (2.9.2)
rrrretry (1.0.0)
rspec-core (3.13.0)
rspec-core (3.13.1)
rspec-support (~> 3.13.0)
rspec-expectations (3.13.2)
rspec-expectations (3.13.3)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.13.0)
rspec-retry (0.6.2)
rspec-core (> 3.3)
rspec-support (3.13.1)
rubocop (1.66.0)
rubocop (1.66.1)
json (~> 2.3)
language_server-protocol (>= 3.17.0)
parallel (~> 1.10)
parser (>= 3.3.0.2)
rainbow (>= 2.2.2, < 4.0)
regexp_parser (>= 2.4, < 3.0)
rubocop-ast (>= 1.32.1, < 2.0)
rubocop-ast (>= 1.32.2, < 2.0)
ruby-progressbar (~> 1.7)
unicode-display_width (>= 2.4.0, < 3.0)
rubocop-ast (1.32.1)
rubocop-ast (1.32.3)
parser (>= 3.3.1.0)
rubocop-rspec (3.0.4)
rubocop-rspec (3.0.5)
rubocop (~> 1.61)
ruby-progressbar (1.13.0)
thor (1.3.1)
thor (1.3.2)
threaded (0.0.4)
unicode-display_width (2.5.0)
unicode-display_width (2.6.0)
webrick (1.8.1)

PLATFORMS
Expand All @@ -80,7 +80,7 @@ DEPENDENCIES
rubocop-rspec

RUBY VERSION
ruby 3.3.2p78
ruby 3.3.5p100

BUNDLED WITH
2.5.11
2.5.18
5 changes: 3 additions & 2 deletions spec/fixtures/hooks/bin/post_compile
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,6 @@

set -euo pipefail

echo 'post_compile ran with env vars:'
printenv | cut -d '=' -f 1 | sort
echo '~ post_compile ran with env vars:'
bin/print-env-vars.sh
echo '~ post_compile complete'
5 changes: 3 additions & 2 deletions spec/fixtures/hooks/bin/pre_compile
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,6 @@

set -euo pipefail

echo 'pre_compile ran with env vars:'
printenv | cut -d '=' -f 1 | sort
echo '~ pre_compile ran with env vars:'
bin/print-env-vars.sh
echo '~ pre_compile complete'
10 changes: 10 additions & 0 deletions spec/fixtures/hooks/bin/print-env-vars.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#!/usr/bin/env bash

set -euo pipefail

printenv | sort \
| grep -vE '^(_|BUILDPACK_LOG_FILE|DYNO|OLDPWD|REQUEST_ID|SHLVL)=' \
| sed --regexp-extended \
--expression 's#(=/tmp/build_)[^:/]+#\1<hash>#' \
--expression 's#^(ENV_DIR=/tmp/).*#\1...#' \
--expression 's#^(SOURCE_VERSION=).*#\1...#'
2 changes: 1 addition & 1 deletion spec/fixtures/pipenv_editable/bin/compile
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,4 @@ BUILD_DIR="${1}"

cd "${BUILD_DIR}"

exec bin/test-entrypoints
exec bin/test-entrypoints.sh
2 changes: 1 addition & 1 deletion spec/fixtures/pipenv_editable/bin/post_compile
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@

set -euo pipefail

exec bin/test-entrypoints
exec bin/test-entrypoints.sh
2 changes: 1 addition & 1 deletion spec/fixtures/pipenv_python_version_unspecified/Pipfile
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@ verify_ssl = true
name = "pypi"

[packages]
urllib3 = "*"
typing-extensions = "*"

[dev-packages]
10 changes: 5 additions & 5 deletions spec/fixtures/pipenv_python_version_unspecified/Pipfile.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

19 changes: 19 additions & 0 deletions spec/fixtures/pipenv_python_version_unspecified/bin/compile
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#!/usr/bin/env bash

# This file is run by the inline buildpack, and tests that the environment is
# configured as expected for buildpacks that run after the Python buildpack.

set -euo pipefail

printenv | sort | grep -vE '^(_|BUILDPACK_LOG_FILE|DYNO|HOME|PWD|REQUEST_ID|SHLVL|SOURCE_VERSION|STACK)='
echo

python -c 'import pprint, sys; pprint.pp(sys.path)'
echo

# TODO: Investigate why 'pipenv graph' doesn't work here.
# TODO: Remove --disable-pip-version-check in favour of exporting PIP_DISABLE_PIP_VERSION_CHECK
pip list --disable-pip-version-check
echo

python -c 'import typing_extensions; print(typing_extensions)'
7 changes: 7 additions & 0 deletions spec/fixtures/pipenv_python_version_unspecified/bin/detect
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#!/usr/bin/env bash

# This file is run by the inline buildpack.

set -euo pipefail

echo "Inline"
9 changes: 9 additions & 0 deletions spec/fixtures/pipenv_python_version_unspecified/setup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# This file is here to confirm we don't try and create the fallback requirements
# file containing '-e .' when using Pipenv.

from setuptools import setup

setup(
name='test',
install_requires=['six'],
)
18 changes: 18 additions & 0 deletions spec/fixtures/requirements_basic/bin/compile
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#!/usr/bin/env bash

# This file is run by the inline buildpack, and tests that the environment is
# configured as expected for buildpacks that run after the Python buildpack.

set -euo pipefail

printenv | sort | grep -vE '^(_|BUILDPACK_LOG_FILE|DYNO|HOME|PWD|REQUEST_ID|SHLVL|SOURCE_VERSION|STACK)='
echo

python -c 'import pprint, sys; pprint.pp(sys.path)'
echo

# TODO: Remove --disable-pip-version-check in favour of exporting PIP_DISABLE_PIP_VERSION_CHECK
pip list --disable-pip-version-check
echo

python -c 'import typing_extensions; print(typing_extensions)'
7 changes: 7 additions & 0 deletions spec/fixtures/requirements_basic/bin/detect
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#!/usr/bin/env bash

# This file is run by the inline buildpack.

set -euo pipefail

echo "Inline"
2 changes: 2 additions & 0 deletions spec/fixtures/requirements_basic/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# This package has been picked since it has no dependencies and is small/fast to install.
typing-extensions==4.12.2
2 changes: 1 addition & 1 deletion spec/fixtures/requirements_editable/bin/compile
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,4 @@ BUILD_DIR="${1}"

cd "${BUILD_DIR}"

exec bin/test-entrypoints
exec bin/test-entrypoints.sh
2 changes: 1 addition & 1 deletion spec/fixtures/requirements_editable/bin/post_compile
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@

set -euo pipefail

exec bin/test-entrypoints
exec bin/test-entrypoints.sh
2 changes: 0 additions & 2 deletions spec/fixtures/requirements_git/requirements.txt

This file was deleted.

1 change: 1 addition & 0 deletions spec/fixtures/requirements_invalid/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
an-invalid-requirement!
11 changes: 10 additions & 1 deletion spec/hatchet/django_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -97,10 +97,19 @@
expect(clean_output(app.output)).to match(Regexp.new(<<~REGEX, Regexp::MULTILINE))
remote: -----> \\$ python manage.py collectstatic --noinput
remote: Traceback \\(most recent call last\\):
remote: .*
remote: .+
remote: ModuleNotFoundError: No module named 'gettingstarted'
remote:
remote: ! Error while running '\\$ python manage.py collectstatic --noinput'.
remote: See traceback above for details.
remote:
remote: You may need to update application code to resolve this error.
remote: Or, you can disable collectstatic for this application:
remote:
remote: \\$ heroku config:set DISABLE_COLLECTSTATIC=1
remote:
remote: https://devcenter.heroku.com/articles/django-assets
remote: ! Push rejected, failed to compile Python app.
REGEX
end
end
Expand Down
83 changes: 48 additions & 35 deletions spec/hatchet/hooks_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,49 +3,62 @@
require_relative '../spec_helper'

RSpec.describe 'Compile hooks' do
context 'when an app has bin/pre_compile and bin/post_compile scripts' do
# TODO: Run this on Heroku-22 too, once it has also migrated to the new build infrastructure.
# (Currently the test fails on the old infrastructure due to subtle differences in system PATH elements.)
context 'when an app has bin/pre_compile and bin/post_compile scripts', stacks: %w[heroku-20 heroku-24] do
let(:app) { Hatchet::Runner.new('spec/fixtures/hooks', config: { 'SOME_APP_CONFIG_VAR' => '1' }) }

it 'runs the hooks with the correct environment' do
expected_env_vars = %w[
_
BUILD_DIR
BUILDPACK_LOG_FILE
CACHE_DIR
C_INCLUDE_PATH
CPLUS_INCLUDE_PATH
DYNO
ENV_DIR
HOME
LANG
LD_LIBRARY_PATH
LIBRARY_PATH
OLDPWD
PATH
PIP_NO_PYTHON_VERSION_WARNING
PKG_CONFIG_PATH
PWD
PYTHONUNBUFFERED
REQUEST_ID
SHLVL
SOME_APP_CONFIG_VAR
SOURCE_VERSION
STACK
]

app.deploy do |app|
expect(clean_output(app.output)).to match(Regexp.new(<<~REGEX, Regexp::MULTILINE))
output = clean_output(app.output)

expect(output).to include(<<~OUTPUT)
remote: -----> Python app detected
remote: -----> Running pre-compile hook
remote: pre_compile ran with env vars:
remote: #{expected_env_vars.join("\nremote: ")}
remote: -----> No Python version was specified. Using the buildpack default: python-#{DEFAULT_PYTHON_VERSION}
remote: .*
remote: ~ pre_compile ran with env vars:
remote: BUILD_DIR=/tmp/build_<hash>
remote: CACHE_DIR=/tmp/codon/tmp/cache
remote: C_INCLUDE_PATH=/app/.heroku/vendor/include:/app/.heroku/python/include:
remote: CPLUS_INCLUDE_PATH=/app/.heroku/vendor/include:/app/.heroku/python/include:
remote: ENV_DIR=/tmp/...
remote: HOME=/app
remote: LANG=en_US.UTF-8
remote: LD_LIBRARY_PATH=/app/.heroku/vendor/lib:/app/.heroku/python/lib:
remote: LIBRARY_PATH=/app/.heroku/vendor/lib:/app/.heroku/python/lib:
remote: PATH=/app/.heroku/python/bin:/app/.heroku/vendor/bin::/usr/local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
remote: PIP_NO_PYTHON_VERSION_WARNING=1
remote: PKG_CONFIG_PATH=/app/.heroku/vendor/lib/pkg-config:/app/.heroku/python/lib/pkg-config:
remote: PWD=/tmp/build_<hash>
remote: PYTHONUNBUFFERED=1
remote: SOME_APP_CONFIG_VAR=1
remote: SOURCE_VERSION=...
remote: STACK=#{app.stack}
remote: ~ pre_compile complete
OUTPUT

expect(output).to include(<<~OUTPUT)
remote: -----> Installing requirements with pip
remote: -----> Running post-compile hook
remote: post_compile ran with env vars:
remote: #{expected_env_vars.join("\nremote: ")}
REGEX
remote: ~ post_compile ran with env vars:
remote: BUILD_DIR=/tmp/build_<hash>
remote: CACHE_DIR=/tmp/codon/tmp/cache
remote: C_INCLUDE_PATH=/app/.heroku/vendor/include:/app/.heroku/python/include:
remote: CPLUS_INCLUDE_PATH=/app/.heroku/vendor/include:/app/.heroku/python/include:
remote: ENV_DIR=/tmp/...
remote: HOME=/app
remote: LANG=en_US.UTF-8
remote: LD_LIBRARY_PATH=/app/.heroku/vendor/lib:/app/.heroku/python/lib:
remote: LIBRARY_PATH=/app/.heroku/vendor/lib:/app/.heroku/python/lib:
remote: PATH=/app/.heroku/python/bin:/app/.heroku/vendor/bin::/usr/local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
remote: PIP_NO_PYTHON_VERSION_WARNING=1
remote: PKG_CONFIG_PATH=/app/.heroku/vendor/lib/pkg-config:/app/.heroku/python/lib/pkg-config:
remote: PWD=/tmp/build_<hash>
remote: PYTHONUNBUFFERED=1
remote: SOME_APP_CONFIG_VAR=1
remote: SOURCE_VERSION=...
remote: STACK=#{app.stack}
remote: ~ post_compile complete
OUTPUT
end
end
end
Expand Down
1 change: 1 addition & 0 deletions spec/hatchet/package_manager_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
remote: ! https://devcenter.heroku.com/articles/getting-started-with-python
remote: ! https://devcenter.heroku.com/articles/python-support
remote: !
remote: ! Push rejected, failed to compile Python app.
OUTPUT
end
end
Expand Down
Loading

0 comments on commit 6230534

Please sign in to comment.