@@ -46,8 +46,9 @@ def test_no_redis_expose(self, dockerfile):
4646 stripped = line .strip ()
4747 if stripped .startswith ("#" ):
4848 continue
49- assert not re .match (r"EXPOSE\s+.*\b6379\b" , stripped ), \
50- "redis port 6379 must not be EXPOSEd"
49+ assert not re .match (
50+ r"EXPOSE\s+.*\b6379\b" , stripped
51+ ), "redis port 6379 must not be EXPOSEd"
5152
5253 def test_app_dir_root_owned_readonly (self , dockerfile ):
5354 assert "chown -R root:root ${APP_HOME}" in dockerfile
@@ -66,10 +67,27 @@ def test_playwright_headless_shell_is_copied_to_runtime_cache(self, dockerfile):
6667 dockerfile ,
6768 re .DOTALL ,
6869 )
69- assert cache_copy , "Dockerfile must copy Playwright artifacts into appuser's cache"
70+ assert (
71+ cache_copy
72+ ), "Dockerfile must copy Playwright artifacts into appuser's cache"
7073 assert "chromium-*" in cache_copy .group ("artifacts" )
7174 assert "chromium_headless_shell-*" in cache_copy .group ("artifacts" )
7275
76+ def test_build_artifacts_removed_before_layer_commit (self , dockerfile ):
77+ for command , cleanup in (
78+ ("playwright install --with-deps" , "rm -rf /root/.cache/ms-playwright" ),
79+ ("crawl4ai-doctor" , "-name '*.core' -delete" ),
80+ ):
81+ layer = re .search (
82+ rf"^RUN { re .escape (command )} (?P<body>(?:(?!^[A-Z]+\s).)*)" ,
83+ dockerfile ,
84+ re .MULTILINE | re .DOTALL ,
85+ )
86+ assert layer , f"Dockerfile must run { command } "
87+ assert cleanup in layer .group (
88+ "body"
89+ ), f"{ cleanup } must run in the { command } layer"
90+
7391 def test_runs_as_non_root (self , dockerfile ):
7492 assert re .search (r"^USER\s+appuser" , dockerfile , re .MULTILINE )
7593
0 commit comments