Skip to content

fix: sanitise newlines in integration PR titles to prevent GitHub 422 (PTFE-3249)#270

Open
matthiasL-scality wants to merge 1 commit into
mainfrom
PTFE-3249-fix-special-chars-integration-pr-title
Open

fix: sanitise newlines in integration PR titles to prevent GitHub 422 (PTFE-3249)#270
matthiasL-scality wants to merge 1 commit into
mainfrom
PTFE-3249-fix-special-chars-integration-pr-title

Conversation

@matthiasL-scality
Copy link
Copy Markdown
Contributor

Summary

  • A parent PR title containing newline characters (e.g. from a multi-line commit message like "My feature\n* fix something") caused bert-e to forward those newlines in the integration PR title string, triggering a 422 Unprocessable Entity from GitHub's API.
  • Fixed by stripping \r/\n via re.sub before composing the INTEGRATION [...] title in IntegrationBranch.get_or_create_pull_request.
  • Added helpers.FakeRepo as a shared test stub, and 7 unit tests covering the sanitisation behaviour.

Root cause

# before — newlines in parent_pr.title propagated directly to GitHub API
title = 'INTEGRATION [PR#%s > %s] %s' % (
    parent_pr.id, self.dst_branch.name, parent_pr.title
)

Fix

safe_title = re.sub(r'[\r\n]+', ' ', parent_pr.title).strip()
# outer strip handles edge case where safe_title is empty (all-newlines title)
title = ('INTEGRATION [PR#%s > %s] %s' % (
    parent_pr.id, self.dst_branch.name, safe_title
)).strip()

The inner .strip() prevents a leading \n (e.g. "\nfoo"" foo") from introducing a double space inside the formatted string. The outer .strip() handles the pathological case where the parent title consists entirely of newlines, which would otherwise leave a trailing space after the closing bracket.

Test plan

  • test_newline_in_parent_title_is_stripped — core regression case
  • test_carriage_return_in_parent_title_is_stripped — CRLF variant
  • test_asterisk_without_newline_is_preserved* alone is not stripped
  • test_clean_title_is_unchanged — happy path, no regression
  • test_integration_prefix_is_present — prefix always present
  • test_trailing_newline_does_not_produce_trailing_space — trailing \n
  • test_newlines_only_title_does_not_produce_trailing_space — pathological all-newlines title
  • flake8 passes on all changed files

🤖 Generated with Claude Code

…PTFE-3249)

A parent PR whose title contains newline characters (e.g. from a
multi-line commit message such as "My feature\n* fix something") caused
bert-e to forward those newlines in the integration PR title, which
GitHub's API rejects with a 422 Unprocessable Entity.

Strip \r and \n via re.sub before composing the INTEGRATION title.
The inner .strip() prevents a leading \n from causing a double space
inside the formatted string; the outer .strip() handles the edge case
where the parent title consists entirely of newlines (which would
otherwise leave a trailing space after the closing bracket).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@matthiasL-scality matthiasL-scality requested a review from a team as a code owner June 5, 2026 08:50
@codecov
Copy link
Copy Markdown

codecov Bot commented Jun 5, 2026

Codecov Report

❌ Patch coverage is 98.52941% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 89.60%. Comparing base (f88a30e) to head (58424e9).

Files with missing lines Patch % Lines
bert_e/tests/unit/helpers.py 83.33% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #270      +/-   ##
==========================================
+ Coverage   89.54%   89.60%   +0.05%     
==========================================
  Files          79       81       +2     
  Lines       10522    10589      +67     
==========================================
+ Hits         9422     9488      +66     
- Misses       1100     1101       +1     
Flag Coverage Δ
integration 87.19% <100.00%> (+<0.01%) ⬆️
tests 87.15% <100.00%> (+<0.01%) ⬆️
tests-BuildFailedTest 26.68% <0.00%> (-0.01%) ⬇️
tests-QuickTest 34.22% <0.00%> (-0.01%) ⬇️
tests-RepositoryTests 26.34% <0.00%> (-0.01%) ⬇️
tests-TaskQueueTests 51.47% <100.00%> (+<0.01%) ⬆️
tests-TestBertE 65.38% <100.00%> (+<0.01%) ⬆️
tests-TestQueueing 53.70% <100.00%> (+<0.01%) ⬆️
tests-api-mock 15.37% <0.00%> (-0.10%) ⬇️
tests-noqueue 77.36% <100.00%> (+<0.01%) ⬆️
tests-noqueue-BuildFailedTest 26.68% <0.00%> (-0.01%) ⬇️
tests-noqueue-QuickTest 34.22% <0.00%> (-0.01%) ⬇️
tests-noqueue-RepositoryTests 26.34% <0.00%> (-0.01%) ⬇️
tests-noqueue-TaskQueueTests 51.47% <100.00%> (+<0.01%) ⬆️
tests-noqueue-TestBertE 61.76% <100.00%> (+<0.01%) ⬆️
tests-noqueue-TestQueueing 26.36% <0.00%> (-0.01%) ⬇️
tests-server 28.31% <0.00%> (-0.19%) ⬇️
unittests 43.44% <98.52%> (+0.44%) ⬆️
utests 28.17% <98.52%> (+0.54%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants