Skip to content

Commit 0546fab

Browse files
authored
fix: robust changed file detection for PRs/MRs in GitHub, GitLab, and… (#106)
* fix: robust changed file detection for PRs/MRs in GitHub, GitLab, and Bitbucket - Use git diff with appropriate refs and environment variables to detect changed files in pull/merge requests across GitHub Actions, GitLab CI, and Bitbucket Pipelines. - Fallback to git show for single commit detection. - Ensures manifest and other file changes are correctly picked up in all major * Fixing logic for Github changed files * Add fetch of previous commit * Fix file names for changed files to work with globbing * Fixed detection for files in the commit files change
1 parent 20110b3 commit 0546fab

File tree

5 files changed

+107
-12
lines changed

5 files changed

+107
-12
lines changed

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ build-backend = "hatchling.build"
66

77
[project]
88
name = "socketsecurity"
9-
version = "2.1.28"
9+
version = "2.1.33"
1010
requires-python = ">= 3.10"
1111
license = {"file" = "LICENSE"}
1212
dependencies = [

socketsecurity/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
__author__ = 'socket.dev'
2-
__version__ = '2.1.28'
2+
__version__ = '2.1.33'

socketsecurity/core/__init__.py

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -389,15 +389,20 @@ def has_manifest_files(self, files: list) -> bool:
389389
from .utils import socket_globs as fallback_patterns
390390
patterns = fallback_patterns
391391

392+
# Normalize all file paths for matching
393+
norm_files = [f.replace('\\', '/').lstrip('./') for f in files]
394+
392395
for ecosystem in patterns:
393396
ecosystem_patterns = patterns[ecosystem]
394397
for file_name in ecosystem_patterns:
395398
pattern_str = ecosystem_patterns[file_name]["pattern"]
396-
for file in files:
397-
if "\\" in file:
398-
file = file.replace("\\", "/")
399-
if PurePath(file).match(pattern_str):
400-
return True
399+
# Expand brace patterns for each manifest pattern
400+
expanded_patterns = Core.expand_brace_pattern(pattern_str)
401+
for exp_pat in expanded_patterns:
402+
for file in norm_files:
403+
# Use PurePath.match for glob-like matching
404+
if PurePath(file).match(exp_pat):
405+
return True
401406
return False
402407

403408
def check_file_count_limit(self, file_count: int) -> dict:

socketsecurity/core/git_interface.py

Lines changed: 93 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,13 @@ def __init__(self, path: str):
1515
self.repo = Repo(path)
1616
assert self.repo
1717
self.head = self.repo.head
18+
19+
# Always fetch all remote refs to ensure branches exist for diffing
20+
try:
21+
self.repo.git.fetch('--all')
22+
log.debug("Fetched all remote refs for diffing.")
23+
except Exception as fetch_error:
24+
log.debug(f"Failed to fetch all remote refs: {fetch_error}")
1825

1926
# Use CI environment SHA if available, otherwise fall back to current HEAD commit
2027
github_sha = os.getenv('GITHUB_SHA')
@@ -128,12 +135,95 @@ def __init__(self, path: str):
128135
self.commit_sha = self.commit.binsha
129136
self.commit_message = self.commit.message
130137
self.committer = self.commit.committer
131-
self.show_files = self.repo.git.show(self.commit, name_only=True, format="%n").splitlines()
138+
# Detect changed files in PR/MR context for GitHub, GitLab, Bitbucket; fallback to git show
139+
self.show_files = []
140+
detected = False
141+
# GitHub Actions PR context
142+
github_base_ref = os.getenv('GITHUB_BASE_REF')
143+
github_head_ref = os.getenv('GITHUB_HEAD_REF')
144+
github_event_name = os.getenv('GITHUB_EVENT_NAME')
145+
github_before_sha = os.getenv('GITHUB_EVENT_BEFORE') # previous commit for push
146+
github_sha = os.getenv('GITHUB_SHA') # current commit
147+
if github_event_name == 'pull_request' and github_base_ref and github_head_ref:
148+
try:
149+
# Fetch both branches individually
150+
self.repo.git.fetch('origin', github_base_ref)
151+
self.repo.git.fetch('origin', github_head_ref)
152+
# Try remote diff first
153+
diff_range = f"origin/{github_base_ref}...origin/{github_head_ref}"
154+
try:
155+
diff_files = self.repo.git.diff('--name-only', diff_range)
156+
self.show_files = diff_files.splitlines()
157+
log.debug(f"Changed files detected via git diff (GitHub PR remote): {self.show_files}")
158+
detected = True
159+
except Exception as remote_error:
160+
log.debug(f"Remote diff failed: {remote_error}")
161+
# Try local branch diff
162+
local_diff_range = f"{github_base_ref}...{github_head_ref}"
163+
try:
164+
diff_files = self.repo.git.diff('--name-only', local_diff_range)
165+
self.show_files = diff_files.splitlines()
166+
log.debug(f"Changed files detected via git diff (GitHub PR local): {self.show_files}")
167+
detected = True
168+
except Exception as local_error:
169+
log.debug(f"Local diff failed: {local_error}")
170+
except Exception as error:
171+
log.debug(f"Failed to fetch branches or diff for GitHub PR: {error}")
172+
# Commits to default branch (push events)
173+
elif github_event_name == 'push' and github_before_sha and github_sha:
174+
try:
175+
diff_files = self.repo.git.diff('--name-only', f'{github_before_sha}..{github_sha}')
176+
self.show_files = diff_files.splitlines()
177+
log.debug(f"Changed files detected via git diff (GitHub push): {self.show_files}")
178+
detected = True
179+
except Exception as error:
180+
log.debug(f"Failed to get changed files via git diff (GitHub push): {error}")
181+
elif github_event_name == 'push':
182+
try:
183+
self.show_files = self.repo.git.show(self.commit, name_only=True, format="%n").splitlines()
184+
log.debug(f"Changed files detected via git show (GitHub push fallback): {self.show_files}")
185+
detected = True
186+
except Exception as error:
187+
log.debug(f"Failed to get changed files via git show (GitHub push fallback): {error}")
188+
# GitLab CI Merge Request context
189+
if not detected:
190+
gitlab_target = os.getenv('CI_MERGE_REQUEST_TARGET_BRANCH_NAME')
191+
gitlab_source = os.getenv('CI_MERGE_REQUEST_SOURCE_BRANCH_NAME')
192+
if gitlab_target and gitlab_source:
193+
try:
194+
self.repo.git.fetch('origin', gitlab_target, gitlab_source)
195+
diff_range = f"origin/{gitlab_target}...origin/{gitlab_source}"
196+
diff_files = self.repo.git.diff('--name-only', diff_range)
197+
self.show_files = diff_files.splitlines()
198+
log.debug(f"Changed files detected via git diff (GitLab): {self.show_files}")
199+
detected = True
200+
except Exception as error:
201+
log.debug(f"Failed to get changed files via git diff (GitLab): {error}")
202+
# Bitbucket Pipelines PR context
203+
if not detected:
204+
bitbucket_pr_id = os.getenv('BITBUCKET_PR_ID')
205+
bitbucket_source = os.getenv('BITBUCKET_BRANCH')
206+
bitbucket_dest = os.getenv('BITBUCKET_PR_DESTINATION_BRANCH')
207+
# BITBUCKET_BRANCH is the source branch in PR builds
208+
if bitbucket_pr_id and bitbucket_source and bitbucket_dest:
209+
try:
210+
self.repo.git.fetch('origin', bitbucket_dest, bitbucket_source)
211+
diff_range = f"origin/{bitbucket_dest}...origin/{bitbucket_source}"
212+
diff_files = self.repo.git.diff('--name-only', diff_range)
213+
self.show_files = diff_files.splitlines()
214+
log.debug(f"Changed files detected via git diff (Bitbucket): {self.show_files}")
215+
detected = True
216+
except Exception as error:
217+
log.debug(f"Failed to get changed files via git diff (Bitbucket): {error}")
218+
# Fallback to git show for single commit
219+
if not detected:
220+
self.show_files = self.repo.git.show(self.commit, name_only=True, format="%n").splitlines()
221+
log.debug(f"Changed files detected via git show: {self.show_files}")
132222
self.changed_files = []
133223
for item in self.show_files:
134224
if item != "":
135-
full_path = f"{self.path}/{item}"
136-
self.changed_files.append(full_path)
225+
# Use relative path for glob matching
226+
self.changed_files.append(item)
137227

138228
# Determine if this commit is on the default branch
139229
# This considers both GitHub Actions detached HEAD and regular branch situations

workflows/github-actions.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ on:
1515

1616
# Prevent concurrent runs for the same commit
1717
concurrency:
18-
group: socket-scan-${{ github.ref }}-${{ github.sha }}
18+
group: socket-scan-${{ github.sha }}
1919
cancel-in-progress: true
2020

2121
jobs:
@@ -33,7 +33,7 @@ jobs:
3333
- uses: actions/checkout@v4
3434
with:
3535
# For PRs, fetch one additional commit for proper diff analysis
36-
fetch-depth: ${{ github.event_name == 'pull_request' && 2 || 0 }}
36+
fetch-depth: 0
3737

3838
- name: Run Socket Security Scan
3939
env:

0 commit comments

Comments
 (0)