[PATCH b4] review-tui: Use review-signature-template for signature

Charlie Jenkins <[email protected]> Mon, 22 Jun 2026 23:56:52 -0700
Newsgroups org.kernel.linux.tools
Message-ID <[email protected]>
Follow the pattern of the other tools and use a template for the email
sent through the review-tui. This is a bit different from the other
templates because it is only for the signature and tries to only add the
signature if it is not already present.

Signed-off-by: Charlie Jenkins <[email protected]>
---
I felt like the review signature strayed away from how the other b4
commands worked so here's an implementation of how a template could be
used for the review tui flow. I tried to keep the spirit of the existing
code by checking if the signature already exists. I know this is still
in alpha but this change was easy enough for me to draft up in case you
were interested :)
---
 docs/config.rst                                    | 10 ++++++
 src/b4/__init__.py                                 |  2 ++
 src/b4/review/_review.py                           | 36 +++++++++++++++++++---
 src/b4/templates/review-signature-template.example |  6 ++++
 4 files changed, 50 insertions(+), 4 deletions(-)

diff --git a/docs/config.rst b/docs/config.rst
index 7b279e4..a304fb5 100644
--- a/docs/config.rst
+++ b/docs/config.rst
@@ -598,6 +598,16 @@ These settings control ``b4 review`` TUI behaviour.
 
      .. versionadded:: v0.15
 
+   :term:`b4.review-signature-template`
+     Path to the template to use for the review signature. The template supports the
+     following tokens:
+
+     * ``${signature}``: your signature, either from ``~/.signature`` if found, or from your Git config
+
+     Default: ``None``
+
+     .. versionadded:: v0.16
+
 .. _patchwork_settings:
 
 Patchwork integration settings
diff --git a/src/b4/__init__.py b/src/b4/__init__.py
index 4cb6e72..ba74417 100644
--- a/src/b4/__init__.py
+++ b/src/b4/__init__.py
@@ -183,6 +183,8 @@ DEFAULT_CONFIG: ConfigDictT = {
     # (review replies, follow-up replies, and thank-you notes). Series patches sent
     # with "b4 prep/send" keep their templated message-ids and are not affected.
     'custom-msgid-cmd': None,
+    # See review-signature-template.example
+    'review-signature-template': None,
 }
 
 # This is where we store actual config
diff --git a/src/b4/review/_review.py b/src/b4/review/_review.py
index 7a4e606..048c830 100644
--- a/src/b4/review/_review.py
+++ b/src/b4/review/_review.py
@@ -15,6 +15,7 @@ import re
 import shutil
 import sys
 import urllib.parse
+from string import Template
 from typing import Any, Callable, Dict, List, NamedTuple, Optional, Set, Tuple, Union
 
 import liblore.utils
@@ -35,6 +36,17 @@ COMMIT_MESSAGE_PATH = ':message'
 _REPLY_CONTEXT_LINES = 5
 
 
+DEFAULT_REVIEW_SIGNATURE_TEMPLATE = (
+    """
+Best regards,
+--"""
+    + ' '
+    + """
+${signature}
+"""
+)
+
+
 def _should_promote_waiting(newer_vers: List[int], previously_known: Set[int]) -> bool:
     """Decide whether a waiting series should be promoted to reviewing.
 
@@ -2647,10 +2659,26 @@ def _build_review_email(
     if not reply_text:
         body = _ensure_trailers_in_body(body, trailers)
 
-    # Append signature if not already present
-    if '\n-- \n' not in body:
-        signature = b4.get_email_signature()
-        body = body.rstrip('\n') + '\n\n-- \n' + signature
+    review_template = DEFAULT_REVIEW_SIGNATURE_TEMPLATE
+    config = b4.get_main_config()
+    _ctpr = config.get('review-signature-template')
+
+    if isinstance(_ctpr, str) and _ctpr:
+        # Try to load this template instead
+        try:
+            review_template = b4.read_template(_ctpr)
+        except FileNotFoundError:
+            logger.critical(
+                'ERROR: review-signature-template says to use %s, but it does not exist',
+                config['review-signature-template'],
+            )
+            sys.exit(2)
+
+    jsondata = {'signature': b4.get_email_signature()}
+    review_signature = Template(review_template).safe_substitute(jsondata)
+
+    if review_signature.strip('\n') not in body:
+        body = body.rstrip('\n') + '\n\n' + f"'{review_signature}'"
 
     # Construct the EmailMessage
     user_name, user_email = b4.get_mailfrom()
diff --git a/src/b4/templates/review-signature-template.example b/src/b4/templates/review-signature-template.example
new file mode 100644
index 0000000..dc45499
--- /dev/null
+++ b/src/b4/templates/review-signature-template.example
@@ -0,0 +1,6 @@
+# Lines starting with '#' will be removed
+Best regards,
+--
+# if ~/.signature exists, it will be put here, otherwise
+# the contents will be "user.name <user.email>" from gitconfig
+${signature}

---
base-commit: e7e48f19f7a553e80dea9c8dd267887cb3a3cf09
change-id: 20260622-review_tui_template-fb8460987a1a

Best regards,
--  
- Charlie