From 1e595df20e9130f883f2f7edb74299cd2f572841 Mon Sep 17 00:00:00 2001 From: Martin Torp Date: Fri, 17 Apr 2026 07:47:46 +0200 Subject: [PATCH] fix: strip git name-rev suffix operators from detected branch name In detached-HEAD CI checkouts (common in Buildkite/CircleCI/Jenkins/etc. where none of the GitHub/GitLab/Bitbucket CI env vars are recognized), the Python CLI falls back to `git name-rev --name-only HEAD` to detect the current branch. When the checked-out SHA is not exactly at a branch tip (e.g. master moved forward after the pipeline started), name-rev returns strings like `remotes/origin/master~1` or `master^0`. The previous split('/')[-1] cleanup kept the `~N`/`^N` suffix, which the Socket API then rejected with "Invalid branch name". Strip anything from the first `~` or `^` onward before the prefix split. Both characters are forbidden in git ref names per check-ref-format(1), so truncating at them is always safe. Assisted-by: Claude Code:opus-4-7 --- CHANGELOG.md | 4 ++++ pyproject.toml | 2 +- socketsecurity/__init__.py | 2 +- socketsecurity/core/git_interface.py | 6 ++++++ 4 files changed, 12 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 683e0ad..e2ea6c0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +## 2.2.83 + +- Fixed branch detection in detached-HEAD CI checkouts. When `git name-rev --name-only HEAD` returned an output with a suffix operator (e.g. `remotes/origin/master~1`, `master^0`), the `~N`/`^N` was previously passed through as the branch name and rejected by the Socket API as an invalid Git ref. The suffix is now stripped before the prefix split, producing the bare branch name. + ## 2.2.71 - Added `strace` to the Docker image for debugging purposes. diff --git a/pyproject.toml b/pyproject.toml index a07a1f8..07501c5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -6,7 +6,7 @@ build-backend = "hatchling.build" [project] name = "socketsecurity" -version = "2.2.82" +version = "2.2.83" requires-python = ">= 3.11" license = {"file" = "LICENSE"} dependencies = [ diff --git a/socketsecurity/__init__.py b/socketsecurity/__init__.py index a9cab02..f233dd0 100644 --- a/socketsecurity/__init__.py +++ b/socketsecurity/__init__.py @@ -1,3 +1,3 @@ __author__ = 'socket.dev' -__version__ = '2.2.82' +__version__ = '2.2.83' USER_AGENT = f'SocketPythonCLI/{__version__}' diff --git a/socketsecurity/core/git_interface.py b/socketsecurity/core/git_interface.py index d750284..da61406 100644 --- a/socketsecurity/core/git_interface.py +++ b/socketsecurity/core/git_interface.py @@ -1,3 +1,4 @@ +import re import urllib.parse import os @@ -108,6 +109,11 @@ def __init__(self, path: str): # Try git name-rev first (most reliable for detached HEAD) result = self.repo.git.name_rev('--name-only', 'HEAD') if result and result != 'undefined': + # Strip name-rev suffix operators (~N, ^N, or combinations + # like master~3^2). These characters are forbidden in git + # ref names, so cutting at the first occurrence can never + # truncate a real branch name. + result = re.split(r'[~^]', result, maxsplit=1)[0] # Clean up the result (remove any prefixes like 'remotes/origin/') git_detected_branch = result.split('/')[-1] log.debug(f"Branch detected from git name-rev: {git_detected_branch}")