Skip to content

Commit 90415cb

Browse files
committed
fix: ignore GitHub virtual merge commits in PR events
- Skip GITHUB_SHA for pull_request events to avoid virtual merge commits - GitHub Actions creates virtual merge commits for PRs that don't exist as real commits - CLI now uses HEAD commit for PR events, GITHUB_SHA for push events - Added comprehensive tests for both PR and push event scenarios - Resolves issue with confusing merge messages like 'Merge abc123 into def456 (virtual)'
1 parent 5437697 commit 90415cb

File tree

2 files changed

+63
-4
lines changed

2 files changed

+63
-4
lines changed

socketsecurity/core/git_interface.py

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,19 +54,28 @@ def __init__(self, path: str):
5454

5555
# Use CI environment SHA if available, otherwise fall back to current HEAD commit
5656
github_sha = os.getenv('GITHUB_SHA')
57+
github_event_name = os.getenv('GITHUB_EVENT_NAME')
5758
gitlab_sha = os.getenv('CI_COMMIT_SHA')
5859
bitbucket_sha = os.getenv('BITBUCKET_COMMIT')
59-
ci_sha = github_sha or gitlab_sha or bitbucket_sha
60+
61+
# For GitHub PR events, ignore GITHUB_SHA (virtual merge commit) and use HEAD
62+
if github_event_name == 'pull_request':
63+
ci_sha = gitlab_sha or bitbucket_sha # Skip github_sha
64+
log.debug("GitHub PR event detected - ignoring GITHUB_SHA (virtual merge commit)")
65+
else:
66+
ci_sha = github_sha or gitlab_sha or bitbucket_sha
6067

6168
if ci_sha:
6269
try:
6370
self.commit = self.repo.commit(ci_sha)
64-
if github_sha:
71+
if ci_sha == github_sha and github_event_name != 'pull_request':
6572
env_source = "GITHUB_SHA"
66-
elif gitlab_sha:
73+
elif ci_sha == gitlab_sha:
6774
env_source = "CI_COMMIT_SHA"
68-
else:
75+
elif ci_sha == bitbucket_sha:
6976
env_source = "BITBUCKET_COMMIT"
77+
else:
78+
env_source = "UNKNOWN_CI_SOURCE"
7079
log.debug(f"Using commit from {env_source}: {ci_sha}")
7180
except Exception as error:
7281
log.debug(f"Failed to get commit from CI environment: {error}")

tests/core/test_git_interface.py

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -762,3 +762,53 @@ def test_environment_variable_parsing(self, git_instance):
762762
}):
763763
assert os.getenv('BITBUCKET_BRANCH') == 'feature'
764764
assert os.getenv('BITBUCKET_PR_DESTINATION_BRANCH') == 'main'
765+
766+
def test_github_virtual_merge_commit_ignored(self, git_instance, caplog):
767+
"""
768+
Test that GitHub virtual merge commits are ignored for pull_request events.
769+
770+
GitHub Actions sets GITHUB_SHA to a virtual merge commit for PR events,
771+
which should be ignored to avoid scanning non-existent commits.
772+
"""
773+
with caplog.at_level(logging.DEBUG):
774+
# Simulate GitHub PR environment with virtual merge commit
775+
with patch.dict(os.environ, {
776+
'GITHUB_EVENT_NAME': 'pull_request',
777+
'GITHUB_SHA': 'abc123virtual', # Virtual merge commit
778+
'CI_COMMIT_SHA': '', # No GitLab SHA
779+
'BITBUCKET_COMMIT': '' # No Bitbucket SHA
780+
}, clear=True):
781+
# Create new Git instance to trigger commit selection logic
782+
git_instance_new = Git(git_instance.path)
783+
784+
# Should log that GITHUB_SHA is being ignored
785+
debug_messages = [record.message for record in caplog.records if record.levelname == "DEBUG"]
786+
virtual_commit_logs = [msg for msg in debug_messages if "ignoring GITHUB_SHA (virtual merge commit)" in msg]
787+
assert len(virtual_commit_logs) >= 1, f"Expected virtual merge commit log, got: {debug_messages}"
788+
789+
# Should use HEAD commit instead of GITHUB_SHA
790+
assert git_instance_new.commit.hexsha != 'abc123virtual'
791+
assert git_instance_new.commit.hexsha == git_instance.commit.hexsha # Should match original HEAD
792+
793+
def test_github_push_event_uses_github_sha(self, git_instance, caplog):
794+
"""
795+
Test that GitHub push events still use GITHUB_SHA (not virtual merge commits).
796+
"""
797+
with caplog.at_level(logging.DEBUG):
798+
# Simulate GitHub push environment with real commit
799+
with patch.dict(os.environ, {
800+
'GITHUB_EVENT_NAME': 'push',
801+
'GITHUB_SHA': git_instance.commit.hexsha, # Real commit
802+
'CI_COMMIT_SHA': '',
803+
'BITBUCKET_COMMIT': ''
804+
}, clear=True):
805+
# Create new Git instance to trigger commit selection logic
806+
git_instance_new = Git(git_instance.path)
807+
808+
# Should use GITHUB_SHA for push events
809+
assert git_instance_new.commit.hexsha == git_instance.commit.hexsha
810+
811+
# Should NOT log virtual merge commit message
812+
debug_messages = [record.message for record in caplog.records if record.levelname == "DEBUG"]
813+
virtual_commit_logs = [msg for msg in debug_messages if "ignoring GITHUB_SHA (virtual merge commit)" in msg]
814+
assert len(virtual_commit_logs) == 0, f"Should not ignore GITHUB_SHA for push events: {debug_messages}"

0 commit comments

Comments
 (0)