Skip to content

Commit

Permalink
[Docker] Fix bug when a putative target address did not exist. (pants…
Browse files Browse the repository at this point in the history
…build#14125)

The issue was that we attempted to translate all inferred addresses for dependencies to targets, and if they didn't exist, boom.

This fix goes via all known addresses for the relevant directories, and filters the list of inferred addresses down to what is actually defined.

Fixes pantsbuild#14031.
  • Loading branch information
kaos authored Jan 10, 2022
1 parent 47fa4cb commit de987cd
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 4 deletions.
17 changes: 14 additions & 3 deletions src/python/pants/backend/docker/util_rules/dependencies.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

from pants.backend.docker.subsystems.dockerfile_parser import DockerfileInfo, DockerfileInfoRequest
from pants.backend.docker.target_types import DockerDependenciesField
from pants.base.specs import AddressSpecs, MaybeEmptySiblingAddresses
from pants.core.goals.package import PackageFieldSet
from pants.engine.addresses import Addresses, UnparsedAddressInputs
from pants.engine.rules import Get, collect_rules, rule
Expand All @@ -22,18 +23,28 @@ class InjectDockerDependencies(InjectDependenciesRequest):

@rule
async def inject_docker_dependencies(request: InjectDockerDependencies) -> InjectedDependencies:
"""Inspects COPY instructions in the Dockerfile for references to known targets."""
"""Inspects COPY instructions in the Dockerfile for references to known packagable targets."""
dockerfile_info = await Get(
DockerfileInfo, DockerfileInfoRequest(request.dependencies_field.address)
)

targets = await Get(
Targets,
# Parse all putative target addresses.
putative_addresses = await Get(
Addresses,
UnparsedAddressInputs(
dockerfile_info.putative_target_addresses,
owning_address=dockerfile_info.address,
),
)

# Get the target for those addresses that are known.
directories = {address.spec_path for address in putative_addresses}
all_addresses = await Get(Addresses, AddressSpecs(map(MaybeEmptySiblingAddresses, directories)))
targets = await Get(
Targets, Addresses((address for address in putative_addresses if address in all_addresses))
)

# Only keep those targets that we can "package".
package = await Get(FieldSetsPerTarget, FieldSetsPerTargetRequest(PackageFieldSet, targets))
referenced_targets = (
field_sets[0].address for field_sets in package.collection if len(field_sets) > 0
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,7 @@ def test_packaged_pex_path(rule_runner: RuleRunner) -> None:
rule_runner.write_files(
{
"src/docker/BUILD": """docker_image(dependencies=["src/python/proj/cli:bin"])""",
"src/docker/Dockerfile": """FROM python""",
"src/docker/Dockerfile": """FROM python:3.8""",
"src/python/proj/cli/BUILD": """pex_binary(name="bin", entry_point="main.py")""",
"src/python/proj/cli/main.py": """print("cli main")""",
}
Expand Down Expand Up @@ -593,3 +593,38 @@ def test_create_docker_build_context() -> None:
assert dict(context.build_env.environment) == {"ENVNAME": "value2"}
assert context.dockerfile == "test/Dockerfile"
assert context.stages == ("base", "dev", "prod")


def test_pex_custom_output_path_issue14031(rule_runner: RuleRunner) -> None:
rule_runner.write_files(
{
"project/test/BUILD": dedent(
"""\
pex_binary(
name="test",
entry_point="main.py",
output_path="project/test.pex",
)
docker_image(
name="test-image",
dependencies=[":test"],
)
"""
),
"project/test/main.py": "print('Hello')",
"project/test/Dockerfile": dedent(
"""\
FROM python:3.8
COPY project/test.pex .
CMD ["./test.pex"]
"""
),
}
)

assert_build_context(
rule_runner,
Address("project/test", target_name="test-image"),
expected_files=["project/test/Dockerfile", "project/test.pex"],
)

0 comments on commit de987cd

Please sign in to comment.