Skip to content

fix(logs): bypass pager when --tail is active#253

Merged
jdx merged 2 commits intomainfrom
fix/logs-tail-pager
Feb 24, 2026
Merged

fix(logs): bypass pager when --tail is active#253
jdx merged 2 commits intomainfrom
fix/logs-tail-pager

Conversation

@jdx
Copy link
Owner

@jdx jdx commented Feb 23, 2026

Summary

  • When using pitchfork logs <daemon> --tail, the pager (less) would open and block with (END), requiring the user to press q before tailing actually started. Now --tail skips the pager and streams directly to stdout so tail_logs() runs immediately.
  • Adds bats test infrastructure (mirroring garni's pattern) with tests for --tail, -n, and --follow

Closes #252

Test plan

  • cargo nextest run — all 164 tests pass
  • test/bats/bin/bats test/logs.bats — all 3 new bats tests pass
  • Manual: pitchfork logs <daemon> --tail streams without opening pager

🤖 Generated with Claude Code


Note

Low Risk
Small, isolated CLI behavior change plus test/CI plumbing; main risk is altered pager behavior for interactive users when tailing.

Overview
Fixes pitchfork logs --tail/--follow to skip the pager even in an interactive terminal, streaming logs directly to stdout so tailing starts immediately.

Adds bats integration test infrastructure via git submodules and a shared common_setup, introduces new test/logs.bats coverage for --tail, --follow, and -n/--raw, and updates mise/GitHub Actions CI to fetch submodules and run the bats test suite.

Written by Cursor Bugbot for commit 3b14a2e. This will update automatically on new commits. Configure here.

Copilot AI review requested due to automatic review settings February 23, 2026 21:04
@gemini-code-assist
Copy link

Summary of Changes

Hello @jdx, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request enhances the pitchfork logs command by ensuring that when the --tail option is active, logs are streamed directly to standard output, preventing the pager from blocking the output. Additionally, it introduces a new Bats testing framework and a suite of tests to validate the correct functionality of the logs command's streaming and line-limiting features.

Highlights

  • Log Pager Bypass: The pitchfork logs --tail command now directly streams logs to stdout, bypassing the less pager. This resolves an issue where the pager would block, requiring user interaction before log tailing began.
  • Bats Test Infrastructure: New Bats test infrastructure has been integrated into the project, mirroring existing patterns, to enable robust shell script testing.
  • New Log Command Tests: Dedicated Bats tests were added to verify the correct behavior of pitchfork logs with --tail, -n (number of lines), and --follow options, ensuring they function as expected without opening a pager.
Changelog
  • .gitmodules
    • Added submodules for bats-core, bats-support, bats-assert, and bats-file to integrate the Bats testing framework.
  • src/cli/logs.rs
    • Modified the condition for direct log streaming to include the self.tail flag, ensuring the pager is bypassed when tailing logs.
  • test/bats
    • Added the bats-core submodule.
  • test/logs.bats
    • Added new Bats tests to verify that pitchfork logs --tail, -n, and --follow commands stream logs directly without invoking a pager and correctly handle line limits.
  • test/test_helper/bats-assert
    • Added the bats-assert submodule.
  • test/test_helper/bats-file
    • Added the bats-file submodule.
  • test/test_helper/bats-support
    • Added the bats-support submodule.
  • test/test_helper/common_setup.bash
    • Added a common setup and teardown script for Bats tests, including environment setup, loading Bats libraries, and helper functions for creating pitchfork.toml and waiting for daemon status or log lines.
Activity
  • The author provided a detailed summary of the changes and a comprehensive test plan.
  • The author indicated that all existing Rust tests (cargo nextest run) passed.
  • The author confirmed that all new Bats tests (test/bats/bin/bats test/logs.bats) passed.
  • The author included a manual test step for verifying the --tail functionality.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request correctly fixes an issue where the pager would block when using pitchfork logs --tail. The change to bypass the pager is simple and effective. The addition of a bats testing framework with integration tests for the logs command is a great improvement for the project's stability. The new tests cover the fix and related functionality well. I've pointed out a minor potential issue in one of the new test scripts to make it more robust. Overall, this is a solid contribution.

assert_output --partial "tick"
# Should have at most 3 lines
local line_count
line_count="$(echo "$output" | wc -l | tr -d ' ')"

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Using echo "$output" can be problematic for counting lines, as echo may add an extra newline character depending on its implementation and the content of $output. This can cause wc -l to report an incorrect line count. Using printf '%s' is a more reliable way to print the exact content of the variable without modifications, ensuring the line count is accurate.

  line_count="$(printf '%s' "$output" | wc -l | tr -d ' ')"

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes pitchfork logs --tail by bypassing the pager so streaming starts immediately, and adds Bats-based integration tests to validate --tail, -n, and --follow.

Changes:

  • Skip pager when --tail is active by streaming logs directly to stdout.
  • Add Bats submodules and shared test setup helpers.
  • Add integration tests covering --tail, -n, and --follow behavior.

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
src/cli/logs.rs Ensures --tail bypasses the pager by streaming directly.
test/logs.bats Adds Bats tests validating tail/follow behavior and -n output.
test/test_helper/common_setup.bash Introduces shared Bats setup/teardown and helper wait functions.
.gitmodules Adds Bats + helper libraries as git submodules.
test/bats Pins bats-core submodule revision.
test/test_helper/bats-support Pins bats-support submodule revision.
test/test_helper/bats-assert Pins bats-assert submodule revision.
test/test_helper/bats-file Pins bats-file submodule revision.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

test/logs.bats Outdated
Comment on lines +24 to +27
run timeout 3 pitchfork logs ticker --tail --raw
# timeout exits 124 when it kills the child — that's expected
assert_output --partial "tick"
refute_output --partial "(END)"
Copy link

Copilot AI Feb 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These timeout-based tests can produce false positives because they never assert the expected timeout exit status (typically 124). If pitchfork logs ... --tail unexpectedly exits early after printing a line, the test would still pass. Consider asserting the exit status explicitly (and/or assert_failure) so the test guarantees the command was still running when killed by timeout.

Copilot uses AI. Check for mistakes.
test/logs.bats Outdated
# --tail should stream directly to stdout without spawning a pager.
# If it opens a pager (less), the process will block waiting for input and
# timeout will kill it, producing no output (or "(END)" from less).
run timeout 3 pitchfork logs ticker --tail --raw
Copy link

Copilot AI Feb 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Relying on the external timeout command can make the test suite less portable (e.g., environments where GNU timeout isn’t available, or it’s named differently). Consider adding a small helper in common_setup.bash that provides a consistent cross-platform timeout wrapper (e.g., detect timeout vs gtimeout, or implement a simple alarm-based wrapper) and use that helper in these tests.

Copilot uses AI. Check for mistakes.
test/logs.bats Outdated
pitchfork start ticker
wait_for_log_lines ticker 3

run timeout 3 pitchfork logs ticker --follow --raw
Copy link

Copilot AI Feb 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Relying on the external timeout command can make the test suite less portable (e.g., environments where GNU timeout isn’t available, or it’s named differently). Consider adding a small helper in common_setup.bash that provides a consistent cross-platform timeout wrapper (e.g., detect timeout vs gtimeout, or implement a simple alarm-based wrapper) and use that helper in these tests.

Copilot uses AI. Check for mistakes.
local daemon="$1"
local expected="$2"
for _ in $(seq 1 50); do
if pitchfork status "$daemon" 2>/dev/null | grep -q "$expected"; then
Copy link

Copilot AI Feb 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using grep -q \"$expected\" treats expected as a regular expression, which can lead to unintended matches if the expected status contains regex metacharacters. Using fixed-string matching (e.g., grep -Fq -- \"$expected\") makes the helper more robust and avoids regex-related surprises.

Suggested change
if pitchfork status "$daemon" 2>/dev/null | grep -q "$expected"; then
if pitchfork status "$daemon" 2>/dev/null | grep -Fq -- "$expected"; then

Copilot uses AI. Check for mistakes.
When using `pitchfork logs <daemon> --tail`, the pager (less) would open
and block with "(END)", requiring the user to press q before tailing
actually started. Now --tail skips the pager and streams directly to
stdout so tail_logs() runs immediately.

Also adds bats test infrastructure (mirroring garni's pattern) with
PTY-based tests that verify the pager is actually bypassed. Tests use
`script` to allocate a PTY so is_terminal() returns true, ensuring
the pager code path is exercised. Bats tests run in CI via mise.

Closes #252

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@jdx jdx force-pushed the fix/logs-tail-pager branch from 8dfd1d9 to c109cc7 Compare February 23, 2026 21:24
Copilot AI review requested due to automatic review settings February 23, 2026 21:25
@jdx jdx review requested due to automatic review settings February 23, 2026 21:25
@jdx
Copy link
Owner Author

jdx commented Feb 24, 2026

bugbot run

Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

@jdx jdx merged commit cc2ac94 into main Feb 24, 2026
5 checks passed
@jdx jdx deleted the fix/logs-tail-pager branch February 24, 2026 02:19
@jdx jdx mentioned this pull request Feb 24, 2026
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