Skip to content

Commit

Permalink
Tests: Add additional coverage of editable package installation
Browse files Browse the repository at this point in the history
Previously the editable installation mode test only checked whether
the build completed successfully, not whether the installed editable
packages worked.

Now the packages are tested via their entrypoints in the following scenarios:
1. During the `bin/post_compile` hook
2. By a later buildpack in the build
3. At runtime

In particular, (2) catches the issue described in #1006 when setuptools is upgraded,
and (1) + (3) will be useful to verify the solution to #1006 hasn't broken the other cases.

GUS-W-10047026.

[skip-changelog]
  • Loading branch information
edmorley committed Oct 18, 2021
1 parent 2514526 commit 686a6e0
Show file tree
Hide file tree
Showing 9 changed files with 102 additions and 10 deletions.
10 changes: 10 additions & 0 deletions spec/fixtures/requirements_editable/bin/compile
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#!/usr/bin/env bash

# This file is run by the inline buildpack, and tests that editable reqirements are
# usable by buildpacks that run after the Python buildpack during the build.

set -euo pipefail

BUILD_DIR="${1}"

exec "${BUILD_DIR}/bin/test-entrypoints"
7 changes: 7 additions & 0 deletions spec/fixtures/requirements_editable/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"
5 changes: 5 additions & 0 deletions spec/fixtures/requirements_editable/bin/post_compile
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#!/usr/bin/env bash

set -euo pipefail

exec bin/test-entrypoints
9 changes: 9 additions & 0 deletions spec/fixtures/requirements_editable/bin/test-entrypoints
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#!/usr/bin/env bash

set -euo pipefail

echo -n "Running entrypoint for the local package: "
local_package

echo -n "Running entrypoint for the VCS package: "
gunicorn --version
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
def hello():
print("Hello!")
10 changes: 10 additions & 0 deletions spec/fixtures/requirements_editable/local_package/setup.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
[metadata]
name = local_package
version = 0.0.1

[options]
packages = local_package

[options.entry_points]
console_scripts =
local_package = local_package:hello
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
from setuptools import setup

setup(
name='test',
)
setup()
4 changes: 2 additions & 2 deletions spec/fixtures/requirements_editable/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
-e git+https://github.com/certifi/python-certifi#egg=certifi
-e .
-e ./local_package
-e git+https://github.com/benoitc/[email protected]#egg=gunicorn
61 changes: 56 additions & 5 deletions spec/hatchet/pip_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -88,12 +88,63 @@
end

context 'when requirements.txt contains editable requirements' do
let(:app) { Hatchet::Runner.new('spec/fixtures/requirements_editable') }
let(:buildpacks) { [:default, 'heroku-community/inline'] }
let(:app) { Hatchet::Runner.new('spec/fixtures/requirements_editable', buildpacks: buildpacks) }

# TODO: Make this test the path rewriting, and --src directory handling,
# and that the packages work during all of hooks, later buildpacks, runtime,
# and on subsequent builds (where the paths have to be migrated back).
include_examples 'installs successfully using pip'
it 'rewrites .pth paths correctly for hooks, later buildpacks, runtime and cached builds' do
app.deploy do |app|
expect(clean_output(app.output)).to match(Regexp.new(<<~REGEX))
remote: -----> Installing requirements with pip
remote: Obtaining file:///tmp/build_.*/local_package \\(from -r /tmp/build_.*/requirements.txt \\(line 1\\)\\)
remote: Obtaining gunicorn from git\\+https://github.com/benoitc/[email protected]#egg=gunicorn \\(from -r /tmp/build_.*/requirements.txt \\(line 2\\)\\)
remote: Cloning https://github.com/benoitc/gunicorn \\(to revision 20.1.0\\) to /app/.heroku/src/gunicorn
remote: Installing collected packages: gunicorn, local-package
remote: Running setup.py develop for gunicorn
remote: Running setup.py develop for local-package
remote: Successfully installed gunicorn local-package
remote: -----> Running post-compile hook
remote: Running entrypoint for the local package: Hello!
remote: Running entrypoint for the VCS package: gunicorn \\(version 20.1.0\\)
remote: -----> Inline app detected
remote: Running entrypoint for the local package: Hello!
remote: Running entrypoint for the VCS package: gunicorn \\(version 20.1.0\\)
REGEX

# Test rewritten paths work at runtime.
expect(app.run('bin/test-entrypoints')).to include(<<~OUTPUT)
Running entrypoint for the local package: Hello!
Running entrypoint for the VCS package: gunicorn (version 20.1.0)
OUTPUT

# Test restoring paths in the cached .pth files works correctly.
app.commit!
app.push!
expect(clean_output(app.output)).to match(Regexp.new(<<~REGEX))
remote: -----> No change in requirements detected, installing from cache
remote: -----> Using cached install of python-#{DEFAULT_PYTHON_VERSION}
remote: -----> Installing pip 20.2.4, setuptools 47.1.1 and wheel 0.36.2
remote: -----> Installing SQLite3
remote: -----> Installing requirements with pip
remote: Obtaining file:///tmp/build_.*/local_package \\(from -r /tmp/build_.*/requirements.txt \\(line 1\\)\\)
remote: Obtaining gunicorn from git\\+https://github.com/benoitc/[email protected]#egg=gunicorn \\(from -r /tmp/build_.*/requirements.txt \\(line 2\\)\\)
remote: Cloning https://github.com/benoitc/gunicorn \\(to revision 20.1.0\\) to /app/.heroku/src/gunicorn
remote: Installing collected packages: gunicorn, local-package
remote: Attempting uninstall: gunicorn
remote: Found existing installation: gunicorn 20.1.0
remote: Uninstalling gunicorn-20.1.0:
remote: Successfully uninstalled gunicorn-20.1.0
remote: Running setup.py develop for gunicorn
remote: Running setup.py develop for local-package
remote: Successfully installed gunicorn local-package
remote: -----> Running post-compile hook
remote: Running entrypoint for the local package: Hello!
remote: Running entrypoint for the VCS package: gunicorn \\(version 20.1.0\\)
remote: -----> Inline app detected
remote: Running entrypoint for the local package: Hello!
remote: Running entrypoint for the VCS package: gunicorn \\(version 20.1.0\\)
REGEX
end
end
end

context 'when there is only a setup.py' do
Expand Down

0 comments on commit 686a6e0

Please sign in to comment.