Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
ac9ac2c
feat(py_image_layer): support multiple binaries
tamird Jul 20, 2026
c144393
fix(py_image_layer): deduplicate shared sources
tamird Jul 20, 2026
23a9fd9
fix(py_image_layer): validate all runfile layers
tamird Jul 20, 2026
eccd864
fix(py_image_layer): validate interpreter layers
tamird Jul 20, 2026
de60b14
fix(py_image_layer): preserve aliased interpreters
tamird Jul 20, 2026
67495e9
fix(py_image_layer): namespace merged pip layers
tamird Jul 20, 2026
4a71d18
fix(py_image_layer): avoid helper collisions
tamird Jul 20, 2026
9afa9b7
fix(py_image_layer): handle ampersand paths
tamird Jul 20, 2026
23e16fb
fix(py_image_layer): parse mtree metadata fields
tamird Jul 20, 2026
372881d
refactor(py): simplify multi-binary image API
tamird Jul 20, 2026
f1c0de0
test(py): exercise image-layer validation fixtures
tamird Jul 20, 2026
40b1d69
test(py): tighten image-layer validation coverage
tamird Jul 20, 2026
f87e6da
refactor(py): narrow multi-binary image layering
tamird Jul 20, 2026
ae99786
fix(py): preserve scalar image-layer behavior
tamird Jul 20, 2026
f776568
fix(py): preserve image-layer destination semantics
tamird Jul 20, 2026
60d0cdd
fix(py): preserve scalar layer placement and ordering
tamird Jul 20, 2026
a23add5
fix(py): validate expanded image destinations
tamird Jul 20, 2026
a7c6a34
fix(py): align destination validation with emitted layers
tamird Jul 20, 2026
7d921a8
fix(py): use the deepest runfiles prefix
tamird Jul 20, 2026
a583e35
chore(py): align image-layer fixtures with typing checks
tamird Jul 20, 2026
41586fd
fix(py): drop unreachable nested runfiles handling
tamird Jul 20, 2026
da24ca0
fix(py): preserve nested runfiles on Bazel 8
tamird Jul 20, 2026
d731402
fix(py): preserve scalar image-layer mapping
tamird Jul 20, 2026
fd1ede5
refactor(py): simplify multi-binary image layering
tamird Jul 21, 2026
1508945
fix(py): default multi-binary launcher directory
tamird Jul 22, 2026
14b4201
fix(py): validate image file contents
tamird Jul 23, 2026
9657157
test(py): accept identical wheel destinations
tamird Jul 23, 2026
fb22e29
fix(py): exclude rule groups from sources
tamird Jul 23, 2026
0612c62
fix(py): preserve binary runfile launchers
tamird Jul 23, 2026
cb32061
fix(py): preserve multi-binary image metadata
tamird Jul 23, 2026
887d959
fix(py): preserve multi-binary runfiles
tamird Jul 23, 2026
cd83dc4
fix(py): stage scalar repository mappings
tamird Jul 23, 2026
c0e878e
fix(py): parse mtree mapping metadata fields
tamird Jul 23, 2026
b73ae52
fix(py): apply external launcher strip prefixes
tamird Jul 23, 2026
7adce7e
fix(py): preserve relocated launcher runfiles
tamird Jul 23, 2026
8869593
fix(py): preserve runfile and mtree paths
tamird Jul 23, 2026
bed76ba
fix(py): resolve grouped symlinks across layers
tamird Jul 23, 2026
a82c9dc
fix(py): resolve interpreter layer symlinks
tamird Jul 23, 2026
a2352e3
fix(py): unify image layer binary inputs
tamird Jul 23, 2026
b8db863
test(py): correct singleton source listing counts
tamird Jul 23, 2026
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

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

195 changes: 191 additions & 4 deletions e2e/cases/oci/py_image_layer/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
load("@aspect_rules_py//py:defs.bzl", "py_binary", "py_image_layer", "py_layer_tier", "py_test")
load("@aspect_rules_py//py:defs.bzl", "py_binary", "py_image_layer", "py_layer_tier", "py_library", "py_test")
load("@bazel_lib//lib:transitions.bzl", "platform_transition_filegroup")
load("@bazel_skylib//rules:build_test.bzl", "build_test")
load("@container_structure_test//:defs.bzl", "container_structure_test")
load("@rules_oci//oci:defs.bzl", "oci_image", "oci_load")
load("//tools:asserts.bzl", "assert_tar_listing")
load(":image_layer_analysis_tests.bzl", "image_layer_analysis_test_suite")

platform(
name = "aarch64_linux",
Expand Down Expand Up @@ -98,9 +99,9 @@ py_image_layer(
)

# Multi-member group coverage: two pip packages mapped to the same group name
# go through the _merge_aspect path (no per-package tars; single merged tar
# from both install_dirs). Binary also adds pyproject_hooks to make the
# closure non-trivial. Zstd-compressed to exercise _compression_ext.
# produce a single merged tar from both install_dirs. Binary also adds
# pyproject_hooks to make the closure non-trivial. Zstd-compressed to exercise
# _compression_ext.
py_binary(
name = "my_app_multi_bin",
srcs = ["__main__.py"],
Expand Down Expand Up @@ -131,6 +132,153 @@ py_image_layer(
layer_tier = ":my_app_multi_tier",
)

# Exercise the actual multi-launcher flow with separate lock universes and two
# interpreter versions. colorama has the same normalized label in both
# closures, but distinct 3.14/3.12 install trees; both launchers must resolve
# their own venv and the unioned dependency layers from the shared runfiles tree.
py_library(
name = "worker_support",
srcs = ["worker_support.py"],
imports = ["."],
)

py_binary(
name = "my_app_launcher_bin",
srcs = ["launcher.py"],
data = [":my_app_worker_bin"],
dep_group = "images",
python_version = "3.11",
deps = [
"@bazel_tools//tools/python/runfiles",
"@pypi_oci_py_image_layer//build",
"@pypi_oci_py_image_layer//colorama",
],
)

py_binary(
name = "my_app_worker_bin",
srcs = ["worker.py"],
dep_group = "venv_images",
python_version = "3.12",
deps = [
":worker_support",
"@pypi_oci_py_venv_image_layer//build",
"@pypi_oci_py_venv_image_layer//colorama",
"@pypi_oci_py_venv_image_layer//pyproject_hooks",
],
)

alias(
name = "my_app_worker_alias",
actual = ":my_app_worker_bin",
)

py_layer_tier(
name = "my_app_launchers_tier",
groups = {
"//oci/py_image_layer:worker_support": "worker_support",
"@pip//build": "third_party",
"@pip//colorama": "third_party",
"@pip//pyproject_hooks": "third_party",
},
interpreter_group = "interpreter",
strip_prefix = "oci/py_image_layer/my_app_bin",
)

py_image_layer(
name = "my_app_launchers_layers",
binaries = [
":my_app_launcher_bin",
":my_app_worker_alias",
],
layer_tier = ":my_app_launchers_tier",
)

genrule(
name = "my_app_launchers_sources_listing",
srcs = [":my_app_launchers_layers_only_src"],
outs = ["_my_app_launchers_sources.listing"],
cmd = "for f in $(SRCS); do $(BSDTAR_BIN) -tf $$f; done > $@",
toolchains = ["@bsd_tar_toolchains//:resolved_toolchain"],
)

# Default-tier source closures share the interpreter, branding source, and
# data. The listing test proves the unioned source tar ships each byte once.
py_binary(
name = "my_app_peer_bin",
srcs = ["server.py"],
data = ["my_app_peer_bin/config.json"],
dep_group = "images",
python_version = "3.11",
deps = ["//oci/py_image_layer/branding"],
)

py_image_layer(
name = "my_app_shared_layers",
binaries = [
":my_app_bin",
":my_app_peer_bin",
],
launcher_dir = "/custom/bin",
)

genrule(
name = "my_app_shared_sources_listing",
srcs = [":my_app_shared_layers_only_src"],
outs = ["_my_app_shared_sources.listing"],
cmd = "for f in $(SRCS); do $(BSDTAR_BIN) -tf $$f; done > $@",
toolchains = ["@bsd_tar_toolchains//:resolved_toolchain"],
)

py_image_layer(
name = "my_app_binaries_layers",
binaries = select({
":_python_3_11": [
":my_app_bin",
":my_app_peer_bin",
],
"//conditions:default": [
":my_app_peer_bin",
":my_app_bin",
],
}),
launcher_dir = "/app/bin",
)

build_test(
name = "my_app_binary_api_test",
targets = [
":_configured_wheel_collision_layers",
":my_app_binaries_layers",
":my_app_launchers_layers",
":_scalar_default_sources_listing",
],
)

oci_image(
name = "launchers_image",
base = "@ubuntu",
env = {"RUNFILES_DIR": "/app.runfiles"},
tars = [":my_app_launchers_layers"],
)

platform_transition_filegroup(
name = "amd64_launchers_image",
srcs = [":launchers_image"],
target_platform = ":x86_64_linux",
)

container_structure_test(
name = "launchers_image_command_test",
args = ["--verbosity=debug"],
configs = ["launchers_image_command_test.yaml"],
image = ":amd64_launchers_image",
platform = "linux/amd64",
tags = ["requires-docker"],
)

image_layer_analysis_test_suite()

platform_transition_filegroup(
name = "platform_layers",
srcs = [":my_app_layers"],
Expand Down Expand Up @@ -271,3 +419,42 @@ container_structure_test(
"requires-docker",
],
)

# Exercise scalar launcher relocation independently from the default `/app`
# regression above.
py_layer_tier(
name = "server_custom_tier",
strip_prefix = "does/not/match",
)

py_image_layer(
name = "server_custom_layers",
binary = ":server",
launcher_dir = "/custom/bin",
layer_tier = ":server_custom_tier",
)

oci_image(
name = "server_custom_image",
base = "@ubuntu",
entrypoint = ["/custom/bin/server"],
env = {"RUNFILES_DIR": "/app.runfiles"},
tars = [":server_custom_layers"],
)

platform_transition_filegroup(
name = "amd64_server_custom_image",
srcs = [":server_custom_image"],
target_platform = ":x86_64_linux",
)

container_structure_test(
name = "server_custom_image_command_test",
args = ["--verbosity=debug"],
configs = ["server_custom_image_command_test.yaml"],
image = ":amd64_server_custom_image",
platform = "linux/amd64",
tags = [
"requires-docker",
],
)
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
data
Loading
Loading