Skip to content

Commit 355bd45

Browse files
committed
fix path mangling in config docs
Signed-off-by: Alex Goodman <[email protected]>
1 parent e303d6e commit 355bd45

File tree

7 files changed

+221
-11
lines changed

7 files changed

+221
-11
lines changed

content/docs/reference/grype/configuration.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,7 @@ timestamp: true
235235

236236
db:
237237
# location to write the vulnerability database cache (env: GRYPE_DB_CACHE_DIR)
238-
cache-dir: "~.cache~grype~db"
238+
cache-dir: "~/.cache/grype/db"
239239

240240
# URL of the vulnerability database (env: GRYPE_DB_UPDATE_URL)
241241
update-url: "https://grype.anchore.io/databases"

content/docs/reference/syft/configuration.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,7 @@ golang:
206206
search-local-mod-cache-licenses:
207207

208208
# specify an explicit go mod cache directory, if unset this defaults to $GOPATH/pkg/mod or $HOME/go/pkg/mod (env: SYFT_GOLANG_LOCAL_MOD_CACHE_DIR)
209-
local-mod-cache-dir: "~go~pkg~mod"
209+
local-mod-cache-dir: "~/go/pkg/mod"
210210

211211
# search for go package licences in the vendor folder on the system running Syft, note that this is outside the
212212
# container filesystem and potentially outside the root of a local directory scan (env: SYFT_GOLANG_SEARCH_LOCAL_VENDOR_LICENSES)
@@ -253,7 +253,7 @@ java:
253253

254254
# override the default location of the local Maven repository.
255255
# the default is the subdirectory '.m2/repository' in your home directory (env: SYFT_JAVA_MAVEN_LOCAL_REPOSITORY_DIR)
256-
maven-local-repository-dir: "~.m2~repository"
256+
maven-local-repository-dir: "~/.m2/repository"
257257

258258
# maven repository to use, defaults to Maven central (env: SYFT_JAVA_MAVEN_URL)
259259
maven-url: "https://repo1.maven.org/maven2"
@@ -358,7 +358,7 @@ unknowns:
358358

359359
cache:
360360
# root directory to cache any downloaded content; empty string will use an in-memory cache (env: SYFT_CACHE_DIR)
361-
dir: "~.cache~syft"
361+
dir: "~/.cache/syft"
362362

363363
# time to live for cached data; setting this to 0 will disable caching entirely (env: SYFT_CACHE_TTL)
364364
ttl: "7d"

data/grype/config/output.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,7 @@ timestamp: true
207207

208208
db:
209209
# location to write the vulnerability database cache (env: GRYPE_DB_CACHE_DIR)
210-
cache-dir: '~.cache~grype~db'
210+
cache-dir: '~/.cache/grype/db'
211211

212212
# URL of the vulnerability database (env: GRYPE_DB_UPDATE_URL)
213213
update-url: 'https://grype.anchore.io/databases'

data/syft/config/output.txt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ golang:
178178
search-local-mod-cache-licenses:
179179

180180
# specify an explicit go mod cache directory, if unset this defaults to $GOPATH/pkg/mod or $HOME/go/pkg/mod (env: SYFT_GOLANG_LOCAL_MOD_CACHE_DIR)
181-
local-mod-cache-dir: '~go~pkg~mod'
181+
local-mod-cache-dir: '~/go/pkg/mod'
182182

183183
# search for go package licences in the vendor folder on the system running Syft, note that this is outside the
184184
# container filesystem and potentially outside the root of a local directory scan (env: SYFT_GOLANG_SEARCH_LOCAL_VENDOR_LICENSES)
@@ -225,7 +225,7 @@ java:
225225

226226
# override the default location of the local Maven repository.
227227
# the default is the subdirectory '.m2/repository' in your home directory (env: SYFT_JAVA_MAVEN_LOCAL_REPOSITORY_DIR)
228-
maven-local-repository-dir: '~.m2~repository'
228+
maven-local-repository-dir: '~/.m2/repository'
229229

230230
# maven repository to use, defaults to Maven central (env: SYFT_JAVA_MAVEN_URL)
231231
maven-url: 'https://repo1.maven.org/maven2'
@@ -330,7 +330,7 @@ unknowns:
330330

331331
cache:
332332
# root directory to cache any downloaded content; empty string will use an in-memory cache (env: SYFT_CACHE_DIR)
333-
dir: '~.cache~syft'
333+
dir: '~/.cache/syft'
334334

335335
# time to live for cached data; setting this to 0 will disable caching entirely (env: SYFT_CACHE_TTL)
336336
ttl: '7d'

src/generate_reference_config_docs.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,7 @@ def get_config_output(image: str, tool_name: str, update: bool = False) -> str |
234234
return cached.strip()
235235

236236
# run command
237+
# note: HOME is set by default in syft.run() to avoid path mangling
237238
stdout, stderr, returncode = syft.run(
238239
syft_image=image,
239240
args=["config"],

src/utils/syft.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,10 +49,15 @@ def run(
4949
"""
5050
docker_cmd = ["docker", "run", "--pull", "always", "--rm"]
5151

52-
# add environment variables
52+
# always set HOME to avoid path mangling in config output
53+
# (e.g., ~/go/pkg/mod becomes ~go~pkg~mod without HOME set)
54+
default_env_vars = {"HOME": "/root"}
5355
if env_vars:
54-
for key, value in env_vars.items():
55-
docker_cmd.extend(["-e", f"{key}={value}"])
56+
default_env_vars.update(env_vars)
57+
58+
# add environment variables
59+
for key, value in default_env_vars.items():
60+
docker_cmd.extend(["-e", f"{key}={value}"])
5661

5762
# add volume mounts
5863
if volumes:
Lines changed: 204 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,204 @@
1+
import re
2+
from dataclasses import replace
3+
from pathlib import Path
4+
5+
import pytest
6+
7+
from generate_reference_config_docs import generate_markdown_content
8+
from utils.config import paths
9+
10+
11+
@pytest.fixture
12+
def syft_config_cache(tmp_path: Path, monkeypatch) -> Path:
13+
"""Create a mock cache directory with sample syft config output."""
14+
cache_dir = tmp_path / "data" / "syft" / "config"
15+
cache_dir.mkdir(parents=True)
16+
17+
# sample config output with correct paths (as would be generated with HOME=/root)
18+
config_output = """log:
19+
quiet: false
20+
level: 'warn'
21+
22+
golang:
23+
local-mod-cache-dir: '~/go/pkg/mod'
24+
25+
java:
26+
maven-local-repository-dir: '~/.m2/repository'
27+
28+
cache:
29+
dir: '~/.cache/syft'
30+
"""
31+
(cache_dir / "output.txt").write_text(config_output)
32+
33+
# create version cache
34+
version_dir = tmp_path / "data" / "syft" / "version"
35+
version_dir.mkdir(parents=True)
36+
(version_dir / "output.txt").write_text("1.0.0\n")
37+
38+
# create a new Paths instance with modified reference_cache_dir
39+
new_paths = replace(paths, reference_cache_dir=tmp_path / "data")
40+
monkeypatch.setattr("utils.config.paths", new_paths)
41+
monkeypatch.setattr("generate_reference_config_docs.config.paths", new_paths)
42+
43+
return cache_dir
44+
45+
46+
@pytest.fixture
47+
def grype_config_cache(tmp_path: Path, monkeypatch) -> Path:
48+
"""Create a mock cache directory with sample grype config output."""
49+
cache_dir = tmp_path / "data" / "grype" / "config"
50+
cache_dir.mkdir(parents=True)
51+
52+
# sample config output with correct paths
53+
config_output = """log:
54+
quiet: false
55+
level: 'warn'
56+
57+
db:
58+
cache-dir: '~/.cache/grype/db'
59+
"""
60+
(cache_dir / "output.txt").write_text(config_output)
61+
62+
# create version cache
63+
version_dir = tmp_path / "data" / "grype" / "version"
64+
version_dir.mkdir(parents=True)
65+
(version_dir / "output.txt").write_text("0.80.0\n")
66+
67+
# create a new Paths instance with modified reference_cache_dir
68+
new_paths = replace(paths, reference_cache_dir=tmp_path / "data")
69+
monkeypatch.setattr("utils.config.paths", new_paths)
70+
monkeypatch.setattr("generate_reference_config_docs.config.paths", new_paths)
71+
72+
return cache_dir
73+
74+
75+
class TestPathMangling:
76+
"""Tests to ensure configuration paths are not mangled."""
77+
78+
def test_syft_config_paths_not_mangled(self, syft_config_cache: Path) -> None:
79+
"""Verify syft config output contains properly formatted paths."""
80+
content = generate_markdown_content(
81+
image="anchore/syft:latest",
82+
app_name="syft",
83+
tool_name="syft",
84+
update=False,
85+
)
86+
87+
# check that proper paths are present
88+
assert "~/go/pkg/mod" in content, "Go module cache path should use ~/ not ~"
89+
assert "~/.m2/repository" in content, "Maven repository path should use ~/."
90+
assert "~/.cache/syft" in content, "Cache dir path should use ~/."
91+
92+
# check that mangled paths are NOT present
93+
assert "~go~pkg~mod" not in content, "Go path should not be mangled"
94+
assert "~.m2~repository" not in content, "Maven path should not be mangled"
95+
assert "~.cache~syft" not in content, "Cache path should not be mangled"
96+
97+
def test_grype_config_paths_not_mangled(self, grype_config_cache: Path) -> None:
98+
"""Verify grype config output contains properly formatted paths."""
99+
content = generate_markdown_content(
100+
image="anchore/grype:latest",
101+
app_name="grype",
102+
tool_name="grype",
103+
update=False,
104+
)
105+
106+
# check that proper paths are present
107+
assert "~/.cache/grype/db" in content, "Cache dir path should use ~/."
108+
109+
# check that mangled paths are NOT present
110+
assert "~.cache~grype~db" not in content, "Cache path should not be mangled"
111+
112+
@pytest.mark.parametrize(
113+
"mangled_pattern,description",
114+
[
115+
(
116+
r"~[^/\s]+~[^/\s]+~",
117+
"tilde-separated path components (like ~.cache~syft)",
118+
),
119+
(r"'~[a-z0-9]+~", "path starting with tilde followed by word and tilde"),
120+
],
121+
)
122+
def test_no_mangled_path_patterns(
123+
self, syft_config_cache: Path, mangled_pattern: str, description: str
124+
) -> None:
125+
"""Check for common mangled path patterns in syft config output."""
126+
content = generate_markdown_content(
127+
image="anchore/syft:latest",
128+
app_name="syft",
129+
tool_name="syft",
130+
update=False,
131+
)
132+
133+
matches = re.findall(mangled_pattern, content)
134+
assert not matches, f"Found {description}: {matches}"
135+
136+
137+
class TestConfigGeneration:
138+
"""Tests for config generation functionality."""
139+
140+
def test_syft_config_contains_yaml_block(self, syft_config_cache: Path) -> None:
141+
"""Verify generated content contains YAML code block."""
142+
content = generate_markdown_content(
143+
image="anchore/syft:latest",
144+
app_name="syft",
145+
tool_name="syft",
146+
update=False,
147+
)
148+
149+
assert "```yaml" in content
150+
assert "```" in content
151+
assert "log:" in content
152+
153+
def test_grype_config_contains_yaml_block(self, grype_config_cache: Path) -> None:
154+
"""Verify generated content contains YAML code block."""
155+
content = generate_markdown_content(
156+
image="anchore/grype:latest",
157+
app_name="grype",
158+
tool_name="grype",
159+
update=False,
160+
)
161+
162+
assert "```yaml" in content
163+
assert "```" in content
164+
assert "log:" in content
165+
166+
def test_syft_config_contains_version_info(self, syft_config_cache: Path) -> None:
167+
"""Verify generated content includes version information."""
168+
content = generate_markdown_content(
169+
image="anchore/syft:latest",
170+
app_name="syft",
171+
tool_name="syft",
172+
update=False,
173+
)
174+
175+
# version info is included even if it's "unknown" from cache miss
176+
assert "Syft version" in content
177+
assert "{{< alert" in content
178+
179+
def test_grype_config_contains_version_info(self, grype_config_cache: Path) -> None:
180+
"""Verify generated content includes version information."""
181+
content = generate_markdown_content(
182+
image="anchore/grype:latest",
183+
app_name="grype",
184+
tool_name="grype",
185+
update=False,
186+
)
187+
188+
# version info is included even if it's "unknown" from cache miss
189+
assert "Grype version" in content
190+
assert "{{< alert" in content
191+
192+
def test_config_contains_search_locations(self, syft_config_cache: Path) -> None:
193+
"""Verify generated content includes config search locations."""
194+
content = generate_markdown_content(
195+
image="anchore/syft:latest",
196+
app_name="syft",
197+
tool_name="syft",
198+
update=False,
199+
)
200+
201+
assert "./.syft.yaml" in content
202+
assert "./.syft/config.yaml" in content
203+
assert "~/.syft.yaml" in content
204+
assert "$XDG_CONFIG_HOME/syft/config.yaml" in content

0 commit comments

Comments
 (0)