Re: b4 v0.15.0 released

Jiri Slaby
2026-03-24T07:26:19Z

On 20. 03. 26, 21:47, Konstantin Ryabitsev wrote:
> Hi, all:
>
> B4 v0.15.0 is now available! Install or upgrade using your usual mechanism.

Hi,

the TUI tests fail for me (while packaging for openSUSE):

> FAILED src/tests/test_tui_tracking.py::TestTrackingAppStartup::test_empty_database - RuntimeError: Not inside a git repository
> FAILED src/tests/test_tui_tracking.py::TestTrackingAppStartup::test_series_listed - RuntimeError: Not inside a git repository
> FAILED src/tests/test_tui_tracking.py::TestTrackingAppStartup::test_title_shows_identifier_and_count - RuntimeError: Not inside a git repository
> FAILED src/tests/test_tui_tracking.py::TestTrackingAppStartup::test_series_sorted_by_added_at - RuntimeError: Not inside a git repository
> FAILED src/tests/test_tui_tracking.py::TestTrackingNavigation::test_jk_navigation - RuntimeError: Not inside a git repository
> FAILED src/tests/test_tui_tracking.py::TestTrackingNavigation::test_help_opens_and_closes - RuntimeError: Not inside a git repository
> FAILED src/tests/test_tui_tracking.py::TestTrackingLimit::test_limit_filters_by_subject - RuntimeError: Not inside a git repository
> FAILED src/tests/test_tui_tracking.py::TestTrackingLimit::test_limit_filters_by_sender - RuntimeError: Not inside a git repository
> FAILED src/tests/test_tui_tracking.py::TestTrackingLimit::test_clear_limit - RuntimeError: Not inside a git repository
> FAILED src/tests/test_tui_tracking.py::TestTrackingLimit::test_limit_title_shows_count - RuntimeError: Not inside a git repository
> FAILED src/tests/test_tui_tracking.py::TestTrackingLimitPrefixes::test_limit_by_status - RuntimeError: Not inside a git repository
> FAILED src/tests/test_tui_tracking.py::TestTrackingStatusGroups::test_actionable_before_non_actionable - RuntimeError: Not inside a git repository
> FAILED src/tests/test_tui_tracking.py::TestTrackingStatusGroups::test_archived_not_shown - RuntimeError: Not inside a git repository
> FAILED src/tests/test_tui_tracking.py::TestTrackingFocusChangeId::test_focus_on_specific_series - RuntimeError: Not inside a git repository
> FAILED src/tests/test_tui_tracking.py::TestTrackingQuit::test_q_exits - RuntimeError: Not inside a git repository
> FAILED src/tests/test_tui_tracking.py::TestTrackingActionMenu::test_action_menu_for_new_series - RuntimeError: Not inside a git repository
> FAILED src/tests/test_tui_tracking.py::TestTrackingActionMenu::test_action_menu_for_snoozed - RuntimeError: Not inside a git repository
> FAILED src/tests/test_tui_tracking.py::TestTrackingActionMenu::test_enter_on_new_opens_action_menu - RuntimeError: Not inside a git repository
> FAILED src/tests/test_tui_tracking.py::TestTrackingUpgradeNewSeries::test_action_menu_shows_upgrade_for_new_with_newer - RuntimeError: Not inside a git repository
> FAILED src/tests/test_tui_tracking.py::TestTrackingUpgradeNewSeries::test_action_menu_no_upgrade_without_newer - RuntimeError: Not inside a git repository
> FAILED src/tests/test_tui_tracking.py::TestTrackingUpgradeNewSeries::test_upgrade_switches_revision - RuntimeError: Not inside a git repository
> FAILED src/tests/test_tui_tracking.py::TestTrackingSnooze::test_snooze_new_series - RuntimeError: Not inside a git repository
> FAILED src/tests/test_tui_tracking.py::TestTrackingSnooze::test_snooze_cancel - RuntimeError: Not inside a git repository
> FAILED src/tests/test_tui_tracking.py::TestTrackingAbandon::test_abandon_new_series - RuntimeError: Not inside a git repository
> FAILED src/tests/test_tui_tracking.py::TestTrackingAbandon::test_abandon_cancel - RuntimeError: Not inside a git repository
> FAILED src/tests/test_tui_tracking.py::TestTrackingDetailPanel::test_detail_panel_shows_on_highlight - RuntimeError: Not inside a git repository
> FAILED src/tests/test_tui_tracking.py::TestTrackingDetailPanel::test_detail_panel_hides_on_escape - RuntimeError: Not inside a git repository
> FAILED src/tests/test_tui_tracking.py::TestTrackingDetailPanel::test_detail_panel_updates_on_navigation - RuntimeError: Not inside a git repository
> FAILED src/tests/test_tui_tracking.py::TestTrackingSnoozeRemembersChoice::test_snooze_remembers_last_input - RuntimeError: Not inside a git repository
> FAILED src/tests/test_tui_tracking.py::TestSeriesLifecycle::test_new_directly_to_snoozed - RuntimeError: Not inside a git repository
> FAILED src/tests/test_tui_tracking.py::TestSeriesLifecycle::test_gone_series_actions - RuntimeError: Not inside a git repository
> FAILED src/tests/test_tui_tracking.py::TestTargetBranch::test_target_branch_in_details - RuntimeError: Not inside a git repository
> FAILED src/tests/test_tui_tracking.py::TestUpdateRevisionWorkflow::test_prepared_none_is_noop - RuntimeError: Not inside a git repository
> FAILED src/tests/test_tui_tracking.py::TestUpdateRevisionWorkflow::test_prepared_pushes_base_selection - RuntimeError: Not inside a git repository
> FAILED src/tests/test_tui_tracking.py::TestUpdateRevisionWorkflow::test_base_selected_none_cancels - RuntimeError: Not inside a git repository

I use the released .tar, so there is indeed no .git. Doing:

--- a/src/b4/ty.py 2026-03-24 07:24:14.713405924 +0100
+++ b/src/b4/ty.py 2026-03-24 08:19:47.936368274 +0100
@@ -682,7 +681,7 @@
"""
gitdir = b4.git_get_common_dir()
if not gitdir:
- raise RuntimeError('Not inside a git repository')
+ gitdir = '.'
qdir = os.path.join(gitdir, 'b4-review', 'queue')
if dryrun:
qdir = os.path.join(qdir, 'dryrun')

makes this work -- whether this is correct, I don't know.

Then, there is one more failure:

> ____________________________________________________ TestTrackingAbandon.test_abandon_new_series _____________________________________________________
>
> self = <tests.test_tui_tracking.TestTrackingAbandon object at 0x7f2f1db36850>
> tmp_path = PosixPath('/tmp/pytest-of-abuild/pytest-18/test_abandon_new_series0')
>
> @pytest.mark.asyncio
> async def test_abandon_new_series(self, tmp_path: pathlib.Path) -> None:
> """Abandoning a new series should remove it from the DB."""
> identifier = 'test-abandon'
> _seed_db(identifier, [
> {
> 'change_id': 'keep-1',
> 'subject': '[PATCH] keep me',
> 'sent_at': '2026-03-10T11:00:00+00:00',
> 'message_id': 'keep@ex.com',
> },
> {
> 'change_id': 'abandon-1',
> 'subject': '[PATCH] abandon me',
> 'sent_at': '2026-03-10T12:00:00+00:00',
> 'message_id': 'abandon@ex.com',
> },
> ])
>
> app = TrackingApp(identifier)
> async with app.run_test(size=(120, 30)) as pilot:
> await pilot.pause()
> # First series is 'abandon-1' (last inserted, added_at desc)
> assert app._selected_series is not None
> assert app._selected_series['change_id'] == 'abandon-1'
>
> await pilot.press('a')
> await pilot.pause()
> assert isinstance(app.screen, ActionScreen)
>
> # Select 'abandon' from the menu
> await pilot.press('A') # shortcut for abandon
> await pilot.pause()
>
> # Should show confirm dialog
> assert isinstance(app.screen, ConfirmScreen)
>
> await pilot.press('y')
> await pilot.pause()
>
> # Verify the abandoned series is gone from DB
> conn = tracking.get_db(identifier)
> cursor = conn.execute('SELECT change_id FROM series')
> remaining = [row[0] for row in cursor.fetchall()]
> conn.close()
> assert 'keep-1' in remaining
>> assert 'abandon-1' not in remaining
> E AssertionError: assert 'abandon-1' not in ['abandon-1', 'keep-1']
>
> src/tests/test_tui_tracking.py:1076: AssertionError
> ----------------------------------------------------------------- Captured log setup -----------------------------------------------------------------
> DEBUG b4:__init__.py:3047 Running git --no-pager rev-parse --show-toplevel
> DEBUG asyncio:selector_events.py:64 Using selector: EpollSelector
> ----------------------------------------------------------------- Captured log call ------------------------------------------------------------------
> DEBUG b4:__init__.py:3047 Running git --no-pager rev-parse --git-common-dir
> DEBUG b4:__init__.py:3047 Running git --no-pager rev-parse --show-toplevel
> DEBUG b4:__init__.py:3047 Running git --no-pager rev-parse --show-toplevel
> DEBUG b4:__init__.py:3047 Running git --no-pager rev-parse b4/review/abandon-1
> DEBUG b4:__init__.py:3047 Running git --no-pager rev-parse b4/review/keep-1
> DEBUG b4:__init__.py:3047 Running git --no-pager rev-parse --git-common-dir
> DEBUG b4:__init__.py:3047 Running git --no-pager rev-parse --show-toplevel
> DEBUG b4:__init__.py:3047 Running git --no-pager rev-parse --show-toplevel
> DEBUG b4:__init__.py:3047 Running git --no-pager rev-parse --show-toplevel
> DEBUG b4:__init__.py:3047 Running git --no-pager rev-parse b4/review/abandon-1
> DEBUG b4:__init__.py:3047 Running git --no-pager rev-parse --show-toplevel
> ============================================================== short test summary info ===============================================================
> FAILED src/tests/test_tui_tracking.py::TestTrackingAbandon::test_abandon_new_series - AssertionError: assert 'abandon-1' not in ['abandon-1', 'keep-1']

thanks,
--
js
suse labs