From 6972b71f22dada9c214d2d55e2a5e31b7ef3c91a Mon Sep 17 00:00:00 2001 From: matthiasL-scality Date: Fri, 22 May 2026 13:47:11 +0200 Subject: [PATCH 1/3] Fix robot-authored feature branch PRs being misrouted as integration PRs bert-e was crashing with 404 when processing CID bump PRs (authored by the robot but on feature/... branches): handle_pull_request routed all robot-authored PRs to handle_parent_pull_request, which extracted the first number from the description and tried to fetch a non-existent parent PR. Fix by also checking that the source branch matches IntegrationBranch pattern (w/...) before routing to handle_parent_pull_request. Closes PTFE-3261 Co-Authored-By: Claude Sonnet 4.6 --- bert_e/tests/unit/test_handle_pull_request.py | 61 +++++++++++++++++++ bert_e/workflow/gitwaterflow/__init__.py | 3 +- 2 files changed, 63 insertions(+), 1 deletion(-) create mode 100644 bert_e/tests/unit/test_handle_pull_request.py diff --git a/bert_e/tests/unit/test_handle_pull_request.py b/bert_e/tests/unit/test_handle_pull_request.py new file mode 100644 index 00000000..3a89f670 --- /dev/null +++ b/bert_e/tests/unit/test_handle_pull_request.py @@ -0,0 +1,61 @@ +"""Unit tests for gitwaterflow.handle_pull_request routing.""" +from types import SimpleNamespace +from unittest.mock import patch + +from bert_e.workflow.gitwaterflow import handle_pull_request + + +class _FakeRepo: + def __init__(self): + self._url = '' + self._remote_branches = {} + + def cmd(self, *args, **kwargs): + return '' + + +def _make_job(author, src_branch): + """Return a minimal PullRequestJob stub.""" + pull_request = SimpleNamespace( + author=author, + src_branch=src_branch, + id=5171, + ) + settings = SimpleNamespace(robot=author) + bert_e = SimpleNamespace(settings=settings) + git = SimpleNamespace(cascade=None, repo=_FakeRepo()) + return SimpleNamespace( + pull_request=pull_request, + settings=settings, + bert_e=bert_e, + git=git, + ) + + +def test_robot_authored_integration_branch_routes_to_parent(): + """A PR authored by the robot on a w/... branch must be routed to + handle_parent_pull_request — it's an integration PR.""" + job = _make_job(author='bert-e', + src_branch='w/4.2/improvement/ARTESCA-17563-something') + + with patch('bert_e.workflow.gitwaterflow.handle_parent_pull_request') as mock_parent: + handle_pull_request(job) + mock_parent.assert_called_once_with(job, job.pull_request) + + +def test_robot_authored_feature_branch_does_not_route_to_parent(): + """A PR authored by the robot on a feature/... branch (e.g. a CID bump) + must NOT be routed to handle_parent_pull_request. + + Regression: bert-e was crashing with 404 on bump PRs because it extracted + the first number in the description (a Jira ticket ID) and tried to fetch + a non-existent parent PR. + """ + job = _make_job(author='bert-e', + src_branch='feature/ARTESCA-17576-bump-identity-ui-0.41.0') + + with patch('bert_e.workflow.gitwaterflow.handle_parent_pull_request') as mock_parent, \ + patch('bert_e.workflow.gitwaterflow._handle_pull_request') as mock_handle: + handle_pull_request(job) + mock_parent.assert_not_called() + mock_handle.assert_called_once_with(job) diff --git a/bert_e/workflow/gitwaterflow/__init__.py b/bert_e/workflow/gitwaterflow/__init__.py index 33fcf69b..f875c379 100644 --- a/bert_e/workflow/gitwaterflow/__init__.py +++ b/bert_e/workflow/gitwaterflow/__init__.py @@ -50,7 +50,8 @@ @handler(PullRequestJob) def handle_pull_request(job: PullRequestJob): """Analyse and handle a pull request that has just been updated.""" - if job.pull_request.author == job.settings.robot: + if job.pull_request.author == job.settings.robot and re.match( + IntegrationBranch.pattern, job.pull_request.src_branch): return handle_parent_pull_request(job, job.pull_request) try: _handle_pull_request(job) From 7acfcb8a6fcfec801f3e9a842ca1b959baaa393f Mon Sep 17 00:00:00 2001 From: matthiasL-scality Date: Fri, 22 May 2026 14:06:35 +0200 Subject: [PATCH 2/3] Fix flake8 E501 line-too-long violations in test_handle_pull_request Co-Authored-By: Claude Sonnet 4.6 --- bert_e/tests/unit/test_handle_pull_request.py | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/bert_e/tests/unit/test_handle_pull_request.py b/bert_e/tests/unit/test_handle_pull_request.py index 3a89f670..34d0f723 100644 --- a/bert_e/tests/unit/test_handle_pull_request.py +++ b/bert_e/tests/unit/test_handle_pull_request.py @@ -38,7 +38,8 @@ def test_robot_authored_integration_branch_routes_to_parent(): job = _make_job(author='bert-e', src_branch='w/4.2/improvement/ARTESCA-17563-something') - with patch('bert_e.workflow.gitwaterflow.handle_parent_pull_request') as mock_parent: + parent_path = 'bert_e.workflow.gitwaterflow.handle_parent_pull_request' + with patch(parent_path) as mock_parent: handle_pull_request(job) mock_parent.assert_called_once_with(job, job.pull_request) @@ -51,11 +52,14 @@ def test_robot_authored_feature_branch_does_not_route_to_parent(): the first number in the description (a Jira ticket ID) and tried to fetch a non-existent parent PR. """ - job = _make_job(author='bert-e', - src_branch='feature/ARTESCA-17576-bump-identity-ui-0.41.0') + job = _make_job( + author='bert-e', + src_branch='feature/ARTESCA-17576-bump-identity-ui-0.41.0', + ) - with patch('bert_e.workflow.gitwaterflow.handle_parent_pull_request') as mock_parent, \ - patch('bert_e.workflow.gitwaterflow._handle_pull_request') as mock_handle: + parent_path = 'bert_e.workflow.gitwaterflow.handle_parent_pull_request' + handle_path = 'bert_e.workflow.gitwaterflow._handle_pull_request' + with patch(parent_path) as mock_parent, patch(handle_path) as mock_handle: handle_pull_request(job) mock_parent.assert_not_called() mock_handle.assert_called_once_with(job) From 53a3420cc8f2adac574eff25f776a3af2492ab20 Mon Sep 17 00:00:00 2001 From: matthiasL-scality Date: Fri, 22 May 2026 14:08:09 +0200 Subject: [PATCH 3/3] Address code review: tighten unit tests, remove unused _FakeRepo.cmd - Add mock_handle.assert_not_called() to positive routing test - Simplify docstrings to single line - Remove unused _FakeRepo.cmd method Co-Authored-By: Claude Sonnet 4.6 --- bert_e/tests/unit/test_handle_pull_request.py | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/bert_e/tests/unit/test_handle_pull_request.py b/bert_e/tests/unit/test_handle_pull_request.py index 34d0f723..fd6b8d32 100644 --- a/bert_e/tests/unit/test_handle_pull_request.py +++ b/bert_e/tests/unit/test_handle_pull_request.py @@ -10,9 +10,6 @@ def __init__(self): self._url = '' self._remote_branches = {} - def cmd(self, *args, **kwargs): - return '' - def _make_job(author, src_branch): """Return a minimal PullRequestJob stub.""" @@ -33,25 +30,20 @@ def _make_job(author, src_branch): def test_robot_authored_integration_branch_routes_to_parent(): - """A PR authored by the robot on a w/... branch must be routed to - handle_parent_pull_request — it's an integration PR.""" + """Robot PR on w/... branch routes to handle_parent_pull_request.""" job = _make_job(author='bert-e', src_branch='w/4.2/improvement/ARTESCA-17563-something') parent_path = 'bert_e.workflow.gitwaterflow.handle_parent_pull_request' - with patch(parent_path) as mock_parent: + handle_path = 'bert_e.workflow.gitwaterflow._handle_pull_request' + with patch(parent_path) as mock_parent, patch(handle_path) as mock_handle: handle_pull_request(job) mock_parent.assert_called_once_with(job, job.pull_request) + mock_handle.assert_not_called() def test_robot_authored_feature_branch_does_not_route_to_parent(): - """A PR authored by the robot on a feature/... branch (e.g. a CID bump) - must NOT be routed to handle_parent_pull_request. - - Regression: bert-e was crashing with 404 on bump PRs because it extracted - the first number in the description (a Jira ticket ID) and tried to fetch - a non-existent parent PR. - """ + """Robot PR on feature/... branch (CID bump) is not an integration PR.""" job = _make_job( author='bert-e', src_branch='feature/ARTESCA-17576-bump-identity-ui-0.41.0',