diff --git a/src/devx/ci/auto_merge.py b/src/devx/ci/auto_merge.py index 7e700b5..0fb4ea0 100644 --- a/src/devx/ci/auto_merge.py +++ b/src/devx/ci/auto_merge.py @@ -41,6 +41,9 @@ from devx.config import ( from devx.exceptions import APIError from devx.i18n import _ +# Strip leading task ID prefix (e.g. "DEVX-12: " or "OBL-INFRA-364: ") from commit subjects. +_TASK_ID_PREFIX_RE = re.compile(rf"^{TASK_PREFIX}-\d+:\s*") + TASKID_FILE = ".taskid" # Deprecated, kept for backward-compat warnings PR_TITLE_RE = re.compile(rf"^{TASK_PREFIX}-\d+:\s+.+") @@ -168,19 +171,23 @@ def extract_conventional_msg(commits: list[dict[str, Any]]) -> str: for commit in reversed(commits): commit_info = commit.get("commit", {}) message = str(commit_info.get("message", "") if isinstance(commit_info, dict) else "").split("\n")[0] - m = CONVENTIONAL_RE.match(message) + # Strip any leading task ID prefix (e.g. "OBL-INFRA-364: fix: ...") so + # conventional commit matching works on the remainder. + stripped = _TASK_ID_PREFIX_RE.sub("", message) + m = CONVENTIONAL_RE.match(stripped) if m: prefix = m.group(1).split("(")[0].strip() # e.g. "feat" from "feat(scope)" score = priority.get(prefix, 0) if score > best_score: best_score = score - best_msg = message + best_msg = stripped if best_msg: return best_msg - # Fallback: use the newest commit's first line + # Fallback: use the newest commit's first line (strip task ID prefix if present) if commits: commit_info = commits[-1].get("commit", {}) - return str(commit_info.get("message", "") if isinstance(commit_info, dict) else "").split("\n")[0] + raw = str(commit_info.get("message", "") if isinstance(commit_info, dict) else "").split("\n")[0] + return _TASK_ID_PREFIX_RE.sub("", raw) return "" diff --git a/tests/unit/test_auto_merge.py b/tests/unit/test_auto_merge.py index 0e3352d..6c7db6e 100644 --- a/tests/unit/test_auto_merge.py +++ b/tests/unit/test_auto_merge.py @@ -218,6 +218,20 @@ class TestExtractConventionalMsg: ] assert extract_conventional_msg(commits) == "feat(api): add endpoint" + def test_strips_task_id_prefix(self) -> None: + """Commit messages with a task ID prefix should have it stripped.""" + commits = [ + {"commit": {"message": "DEVX-12: fix: resolve timeout"}}, + ] + assert extract_conventional_msg(commits) == "fix: resolve timeout" + + def test_strips_task_id_prefix_fallback(self) -> None: + """Fallback to newest commit should also strip task ID prefix.""" + commits = [ + {"commit": {"message": "DEVX-12: random message"}}, + ] + assert extract_conventional_msg(commits) == "random message" + # -- run_cmd --