Skip to content

ci: quiet buildkite log noise from hk/mise progress output#5

Merged
jdx merged 4 commits intomainfrom
claude/thirsty-kirch-b33cbb
Apr 18, 2026
Merged

ci: quiet buildkite log noise from hk/mise progress output#5
jdx merged 4 commits intomainfrom
claude/thirsty-kirch-b33cbb

Conversation

@jdx
Copy link
Copy Markdown
Contributor

@jdx jdx commented Apr 18, 2026

Summary

  • Pipe hk check / hk fix through cat in mise.toml so hk drops its spinner UI under Buildkite's PTY. Kills ~10k progress-frame rows per linux / test run.
  • Drop -v from mise install in .buildkite/bootstrap.sh. Kills ~15k DEBUG-level rows from bootstrap; --locked and INFO output remain.

Why

Buildkite agents run commands under a PTY so cargo/clippy emit colors. From hk and aube's perspective isatty(stderr) == true, so they render spinners. Buildkite's log capturer strips cursor-up/clear-line escapes but keeps the text, so each animation frame becomes its own log line.

Concrete evidence from build #4's linux / test step:

  • Total log rows: 28,432 for a single step
  • mise install -v bootstrap alone: ~15,900 rows (DEBUG log flood)
  • hk check --all --slow: ~10,200 rows (spinner-frame flood)
  • Wall-clock breakdown unchanged — compile/lint time is ~3 minutes on a warm cache, it was just hard to see through the noise.

Verified on warm-cache build #6 that the cache path itself is healthy (4.4G restored, zero Compiling messages in cargo test), so the 5-minute wall clock on the cold-start build #4 wasn't a cache bug — just a cold cargo target dir on pipeline init.

Test plan

  • Next Buildkite run on this branch: linux / test log rows drop from ~28k to ~3k
  • hk check --all --slow still runs to completion and surfaces real lint errors (spinner gone, but the final error summary is what actually matters)
  • mise install still installs all tools; only the DEBUG chatter is gone

🤖 Generated with Claude Code


Note

Medium Risk
Changes how progress output is rendered in CI and modifies the Buildkite lint command pipeline; mistakes could hide failures (mitigated via set -o pipefail) or degrade progress UX.

Overview
Reduces Buildkite log noise by making aube prefer CI-style (append-only) progress output when running in a detected CI environment even if stderr is a TTY (via new is_ci dependency).

Buildkite’s linux / test step now runs mise run lint through cat with pipefail to prevent hk spinner frames from exploding log rows while still failing the step on lint errors, and .buildkite/bootstrap.sh drops verbose mise install -v to avoid DEBUG-level bootstrap spam.

Reviewed by Cursor Bugbot for commit 5cc91ed. Bugbot is set up for automated code reviews on this repo. Configure here.

Buildkite allocates a PTY for each job so tools emit colors. hk's
spinner and mise's -v DEBUG stream both detect the TTY and flood the
log — we counted 28,432 rows on build #4's `linux / test` step, most
of them progress frames captured as newline-separated lines after
Buildkite strips the cursor-control escapes.

- mise.toml: pipe `hk check`/`hk fix` through `cat`, which breaks the
  PTY on both stdout and stderr and forces hk into its non-interactive
  path. ~10k spinner-frame rows per run go away.
- .buildkite/bootstrap.sh: drop `-v` from `mise install`. `--locked`
  stays, INFO-level output stays; the ~15k DEBUG rows from the initial
  bootstrap go away.

No wall-clock change — this is purely log hygiene so failures are
findable and the Buildkite UI loads quickly.
@greptile-apps
Copy link
Copy Markdown

greptile-apps Bot commented Apr 18, 2026

Greptile Summary

This PR makes two targeted CI noise-reduction changes: pipes hk check/hk fix through cat in mise.toml to strip hk's spinner UI under Buildkite's PTY, and drops -v from mise install in .buildkite/bootstrap.sh to eliminate ~15k DEBUG log rows from bootstrap. The changes are purely cosmetic for log output — compile times, lint results, and tool installations are unaffected.

Key changes:

  • mise.toml lint/lint-fix tasks: 2>&1 | cat forces non-TTY mode on hk's stderr/stdout, preventing spinner-frame flooding (~10k rows removed). Since mise runs pipelines with pipefail by default, hk's exit code is correctly propagated — lint failures still break CI.
  • .buildkite/bootstrap.sh: mise install --locked (dropped -v) removes verbose DEBUG-level output (~15k rows) while retaining --locked for reproducibility and INFO-level progress.

Confidence Score: 5/5

Safe to merge — two clean, well-scoped CI noise-reduction changes with no impact on build correctness or lint enforcement.

Both changes are mechanical and low-risk: dropping a verbosity flag and piping output through cat. Mise's default pipefail shell args ensure hk's exit code is preserved, so lint failures still break CI. The PR description includes concrete build evidence validating the row-count impact.

No files require special attention.

Important Files Changed

Filename Overview
mise.toml Pipes hk check/fix through cat with 2>&1 to suppress spinner output in Buildkite's PTY; exit codes correctly preserved via mise's default pipefail shell args.
.buildkite/bootstrap.sh Drops -v from mise install --locked, eliminating ~15k DEBUG log rows; --locked flag and INFO output remain intact.

Sequence Diagram

sequenceDiagram
    participant BK as Buildkite Agent (PTY)
    participant BS as bootstrap.sh
    participant Mise as mise
    participant HK as hk
    participant Cat as cat

    BK->>BS: run bootstrap
    BS->>Mise: mise install --locked
    Note over Mise: INFO output only<br/>(no -v DEBUG flood)
    Mise-->>BS: tools installed

    BK->>Mise: mise run lint
    Mise->>HK: hk check --all --slow
    Note over HK: isatty(stderr)==true<br/>(Buildkite PTY)
    HK->>Cat: stdout+stderr piped via 2>&1
    Note over Cat: cat has no TTY →<br/>hk drops spinner
    Cat-->>BK: clean text output
    Note over BK: exit code = hk's exit code<br/>(mise uses pipefail by default)
Loading

Reviews (2): Last reviewed commit: "ci: quiet buildkite log noise from hk/mi..." | Re-trigger Greptile

jdx added 2 commits April 18, 2026 14:06
Most CI runners (Buildkite, GitHub Actions, …) allocate a PTY for the
job so tools emit colors, which makes std::io::stderr().is_terminal()
return true. Their log capturers then strip cursor-control escapes and
each animation frame lands as its own log line, flooding the build log
with thousands of near-duplicate spinner rows.

Add is_ci = "1" and prefer CI mode whenever is_ci::cached() says we're
in a known CI environment, even on a TTY. is_ci checks CI,
CONTINUOUS_INTEGRATION, BUILDKITE, GITHUB_ACTIONS, and friends — so
aube now automatically switches to its 2s-heartbeat output there
without callers needing to set any env var or pipe through cat.

Also relocate the hk `| cat` workaround from mise.toml into
.buildkite/pipeline.sh so local `mise run lint` / `mise run lint-fix`
keep their animated UI. hk doesn't do this CI detection itself yet,
so the pipeline-layer pipe remains necessary for it; aube no longer
needs it because is_ci handles it natively.
…stitution

shfmt's normalization rewrote the markdown-style backticks around
\`mise run lint\` into $(mise run lint). That lives inside an
unquoted <<YAML heredoc, so bash would actually execute the
substitution whenever pipeline.sh runs — harmless here since mise run
lint doesn't print anything to stdout, but still a bad shape to leave
in. Plain prose in the comment avoids both backticks and $() so the
next shfmt pass has nothing to rewrite.
Copy link
Copy Markdown

@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.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit f021e4a. Configure here.

Comment thread .buildkite/pipeline.sh Outdated
…ures

Caught by cursor bugbot on PR #5: `mise run lint 2>&1 | cat` returns
cat's exit code (always 0), so a failing hk check would look green
in CI.

bootstrap.sh sets `set -euo pipefail`, but Buildkite runs each entry
in a \`commands:\` list in its own shell invocation — only environment
variables carry forward, not shell options. So pipefail inherited by
the source call in the first command doesn't apply to the lint
command two steps later.

Prepend `set -o pipefail;` to the single piped command instead. The
option now applies to exactly the shell running the pipe, independent
of what came before. Verified locally that `bash -c 'false' 2>&1 | cat`
exits 0 without pipefail and 1 with it.
@jdx jdx merged commit 6bbaa13 into main Apr 18, 2026
16 of 17 checks passed
@jdx jdx deleted the claude/thirsty-kirch-b33cbb branch April 18, 2026 19:19
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.

1 participant