Skip to content

Commit 413174b

Browse files
committed
fix: strip common CI workspace prefixes from filepaths before matching
Signed-off-by: lelia <2418071+lelia@users.noreply.github.com>
1 parent 050425a commit 413174b

1 file changed

Lines changed: 56 additions & 3 deletions

File tree

socket_basics/core/config.py

Lines changed: 56 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,15 @@
1515
logger = logging.getLogger(__name__)
1616

1717

18-
def normalize_repo_relative_path(path_value: str | None) -> str | None:
19-
"""Normalize a repo-relative path to the POSIX form emitted by SAST alerts."""
18+
def _normalize_path_parts(path_value: str | None) -> List[str] | None:
19+
"""Normalize a path-like string into comparable POSIX-style path segments."""
2020
if path_value is None:
2121
return None
2222

2323
path_str = str(path_value).strip()
2424
if not path_str:
2525
return None
2626

27-
# Accept common local input styles but keep the final format strict.
2827
path_str = path_str.replace('\\', '/')
2928
while path_str.startswith('./'):
3029
path_str = path_str[2:]
@@ -38,6 +37,60 @@ def normalize_repo_relative_path(path_value: str | None) -> str | None:
3837
return None
3938
normalized_parts.append(part)
4039

40+
return normalized_parts or None
41+
42+
43+
def _get_workspace_prefix_candidates() -> List[List[str]]:
44+
"""Return normalized workspace roots from common CI systems and local cwd."""
45+
candidate_values: List[str] = []
46+
for env_var in (
47+
'BITBUCKET_CLONE_DIR',
48+
'BUILD_SOURCESDIRECTORY',
49+
'BUILDKITE_BUILD_CHECKOUT_PATH',
50+
'CI_PROJECT_DIR',
51+
'CIRCLE_WORKING_DIRECTORY',
52+
'DRONE_WORKSPACE',
53+
'GITHUB_WORKSPACE',
54+
'SYSTEM_DEFAULTWORKINGDIRECTORY',
55+
'WORKSPACE',
56+
):
57+
env_value = os.getenv(env_var)
58+
if env_value:
59+
candidate_values.append(env_value)
60+
61+
try:
62+
candidate_values.append(os.getcwd())
63+
except Exception:
64+
pass
65+
66+
normalized_candidates: List[List[str]] = []
67+
seen: set[tuple[str, ...]] = set()
68+
for value in candidate_values:
69+
parts = _normalize_path_parts(value)
70+
if not parts:
71+
continue
72+
parts_key = tuple(parts)
73+
if parts_key in seen:
74+
continue
75+
seen.add(parts_key)
76+
normalized_candidates.append(parts)
77+
78+
# Check longer, more specific prefixes first.
79+
normalized_candidates.sort(key=len, reverse=True)
80+
return normalized_candidates
81+
82+
83+
def normalize_repo_relative_path(path_value: str | None) -> str | None:
84+
"""Normalize a repo-relative path to the POSIX form emitted by SAST alerts."""
85+
normalized_parts = _normalize_path_parts(path_value)
86+
if not normalized_parts:
87+
return None
88+
89+
for workspace_parts in _get_workspace_prefix_candidates():
90+
if len(normalized_parts) > len(workspace_parts) and normalized_parts[:len(workspace_parts)] == workspace_parts:
91+
normalized_parts = normalized_parts[len(workspace_parts):]
92+
break
93+
4194
normalized = '/'.join(normalized_parts)
4295
return normalized or None
4396

0 commit comments

Comments
 (0)