From: Christian Brauner <brauner@kernel.org>
To: "Kernel.org Tools" <tools@kernel.org>
Cc: Konstantin Ryabitsev <konstantin@linuxfoundation.org>,
"Christian Brauner (Amutable)" <brauner@kernel.org>,
"str = 'test"@example.com'
Subject: [PATCH b4 2/2] tests: guard the test-apply probes against gpg signing
Date: Thu, 23 Jul 2026 10:33:36 +0200 [thread overview]
Message-ID: <20260723-work-b4-testapply-nosign-v1-2-a7cb7105e06f@kernel.org> (raw)
In-Reply-To: <20260723-work-b4-testapply-nosign-v1-0-a7cb7105e06f@kernel.org>
Test gpg override as best as possible. The tests force
commit.gpgsign=true with gpg.program=/bin/false through appended
GIT_CONFIG_* environment entries so a probe that regresses into signing
fails the apply and the test.
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
---
src/tests/test_tui_tracking.py | 113 +++++++++++++++++++++++++++++++++++++++--
1 file changed, 109 insertions(+), 4 deletions(-)
diff --git a/src/tests/test_tui_tracking.py b/src/tests/test_tui_tracking.py
index c987022..a809037 100644
--- a/src/tests/test_tui_tracking.py
+++ b/src/tests/test_tui_tracking.py
@@ -36,12 +36,15 @@ from b4 import (
from b4.review_tui._modals import (
ActionItem,
ActionScreen,
+ BaseSelectionScreen,
CherryPickScreen,
ConfirmScreen,
HelpScreen,
LimitScreen,
LinkRevisionScreen,
+ RebaseScreen,
SnoozeScreen,
+ TakeConfirmScreen,
TargetBranchScreen,
)
from b4.review_tui._tracking_app import (
@@ -121,10 +124,13 @@ def _create_review_branch(
subject: str = 'Test series',
sender_name: str = 'Test Author',
sender_email: str = 'test@example.com',
+ with_patch: bool = False,
) -> str:
"""Create a fake b4 review branch with a proper tracking commit.
- Returns the branch name.
+ With ``with_patch``, a real patch commit modifying file1.txt sits
+ between the base and the tracking commit, and the tracking metadata
+ describes it. Returns the branch name.
"""
branch_name = f'b4/review/{change_id}'
# Get current HEAD as base
@@ -134,6 +140,24 @@ def _create_review_branch(
# Create the branch at HEAD
ecode, _ = b4.git_run_command(gitdir, ['branch', branch_name, base_sha])
assert ecode == 0
+ parent_sha = base_sha
+ patches: List[Dict[str, Any]] = []
+ if with_patch:
+ ecode, _ = b4.git_run_command(gitdir, ['checkout', branch_name])
+ assert ecode == 0
+ with open(os.path.join(gitdir, 'file1.txt'), 'a') as fh:
+ fh.write(f'{change_id} tweak\n')
+ b4.git_run_command(gitdir, ['add', 'file1.txt'])
+ ecode, _ = b4.git_run_command(
+ gitdir, ['commit', '-m', f'{change_id}: tweak file1']
+ )
+ assert ecode == 0
+ ecode, parent_sha = b4.git_run_command(gitdir, ['rev-parse', 'HEAD'])
+ assert ecode == 0
+ parent_sha = parent_sha.strip()
+ ecode, _ = b4.git_run_command(gitdir, ['checkout', 'master'])
+ assert ecode == 0
+ patches = [{'title': f'{change_id}: tweak file1', 'link': ''}]
# Build tracking metadata
trk = {
'series': {
@@ -148,11 +172,11 @@ def _create_review_branch(
'complete': True,
'base-commit': base_sha,
'prerequisite-commits': [],
- 'first-patch-commit': base_sha,
+ 'first-patch-commit': parent_sha,
'header-info': {},
},
'followups': [],
- 'patches': [],
+ 'patches': patches,
}
commit_msg = f'{subject}\n\n{b4.review.make_review_magic_json(trk)}'
# Create an empty tracking commit on the branch
@@ -161,7 +185,7 @@ def _create_review_branch(
tree = tree.strip()
ecode, new_sha = b4.git_run_command(
gitdir,
- ['commit-tree', tree, '-p', base_sha],
+ ['commit-tree', tree, '-p', parent_sha],
stdin=commit_msg.encode(),
)
assert ecode == 0
@@ -4140,3 +4164,84 @@ class TestDoTakeMergeConflict:
common_dir = b4.git_get_common_dir(gitdir)
assert common_dir is not None
assert not os.path.isdir(os.path.join(common_dir, 'b4-take-worktree'))
+
+
+def _poison_gpg_signing(monkeypatch: pytest.MonkeyPatch) -> None:
+ """Force commit.gpgsign=true with a signing backend that always fails.
+
+ The appended entries override conftest's gpgsign=false injection, so
+ any git command that tries to sign fails outright; only a command
+ that explicitly disables signing (git -c commit.gpgsign=false, which
+ outranks environment config) can create commits.
+
+ gpg.format is pinned because the suite does not isolate the global
+ git config: under gpg.format=ssh git signs through gpg.ssh.program
+ and never looks at gpg.program, so the probes would sign happily and
+ these tests would pass with the fix reverted.
+
+ Build fixtures before poisoning -- they commit normally.
+ """
+ entries = [
+ ('commit.gpgsign', 'true'),
+ ('gpg.format', 'openpgp'),
+ ('gpg.program', '/bin/false'),
+ ]
+ count = int(os.environ.get('GIT_CONFIG_COUNT', '0'))
+ monkeypatch.setenv('GIT_CONFIG_COUNT', str(count + len(entries)))
+ for idx, (key, value) in enumerate(entries, start=count):
+ monkeypatch.setenv(f'GIT_CONFIG_KEY_{idx}', key)
+ monkeypatch.setenv(f'GIT_CONFIG_VALUE_{idx}', value)
+
+
+def _one_patch_mbox(gitdir: str) -> bytes:
+ """Build mbox bytes for one patch that applies cleanly to master."""
+ ecode, _ = b4.git_run_command(gitdir, ['checkout', '-b', 'sign-tweak'])
+ assert ecode == 0
+ with open(os.path.join(gitdir, 'file1.txt'), 'a') as fh:
+ fh.write('sign-tweak\n')
+ b4.git_run_command(gitdir, ['add', 'file1.txt'])
+ ecode, _ = b4.git_run_command(gitdir, ['commit', '-m', 'sign-tweak file1'])
+ assert ecode == 0
+ ecode, mbox = b4.git_run_command(
+ gitdir, ['format-patch', '-1', '--stdout'], decode=False
+ )
+ assert ecode == 0
+ b4.git_run_command(gitdir, ['checkout', 'master'])
+ b4.git_run_command(gitdir, ['branch', '-D', 'sign-tweak'])
+ return mbox
+
+
+class TestTestApplyNoSigning:
+ """Throwaway test-applies must never gpg-sign their commits.
+
+ With commit.gpgsign=true and a card-backed key, a signing git-am in a
+ modal worker pops pinentry on the tty the live TUI owns -- the TUI
+ repaints over the prompt and swallows the PIN, hanging the apply.
+ With gpg poisoned to always fail, these pass only if the test-apply
+ disables signing.
+ """
+
+ @pytest.mark.parametrize(
+ 'screen_cls',
+ [RebaseScreen, TargetBranchScreen, BaseSelectionScreen],
+ ids=lambda c: c.__name__,
+ )
+ def test_static_test_apply_does_not_sign(
+ self,
+ gitdir: str,
+ monkeypatch: pytest.MonkeyPatch,
+ screen_cls: Any,
+ ) -> None:
+ ambytes = _one_patch_mbox(gitdir)
+ _poison_gpg_signing(monkeypatch)
+ ok, detail = screen_cls._test_apply_at(ambytes, 'master')
+ assert ok, f'{screen_cls.__name__} test-apply tried to sign: {detail}'
+
+ def test_take_confirm_test_apply_does_not_sign(
+ self, gitdir: str, monkeypatch: pytest.MonkeyPatch
+ ) -> None:
+ branch = _create_review_branch(gitdir, 'sign-take', with_patch=True)
+ _poison_gpg_signing(monkeypatch)
+ screen = TakeConfirmScreen('linear', 'master', branch)
+ ok, detail = screen._test_take()
+ assert ok, f'take test-apply tried to sign: {detail}'
--
2.53.0
next prev parent reply other threads:[~2026-07-23 8:33 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-23 8:33 [PATCH b4 0/2] review-tui: don't gpg-sign throwaway test-apply commits Christian Brauner
2026-07-23 8:33 ` [PATCH b4 1/2] " Christian Brauner
2026-07-23 8:33 ` Christian Brauner [this message]
2026-07-23 15:33 ` [PATCH b4 0/2] " Nicolas Schier
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260723-work-b4-testapply-nosign-v1-2-a7cb7105e06f@kernel.org \
--to=brauner@kernel.org \
--cc="str = 'test"@example.com' \
--cc=konstantin@linuxfoundation.org \
--cc=tools@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox