Skip to content

fix(tui): gate color on the CLI entry point, not cfg!(test) - #1765

Draft
jd wants to merge 1 commit into
mainfrom
devs/jd/jd/mrgfy-8533-mergify-cli-mergify-events-has-no-default-limit-so-the/gate-color-cli-entry-point-cfg-test--d7eb12b9
Draft

fix(tui): gate color on the CLI entry point, not cfg!(test)#1765
jd wants to merge 1 commit into
mainfrom
devs/jd/jd/mrgfy-8533-mergify-cli-mergify-events-has-no-default-limit-so-the/gate-color-cli-entry-point-cfg-test--d7eb12b9

Conversation

@jd

@jd jd commented Aug 7, 2026

Copy link
Copy Markdown
Member

colors_enabled() opened with if cfg!(test) { return false }, whose
comment claims tests "never depend on the dev's TTY". It cannot do
that: cfg!(test) is false whenever mergify-tui is compiled as a
dependency, so the guard only ever covered mergify-tui's own tests.
Every consumer crate's tests fell through to the real policy and read
the developer's environment — FORCE_COLOR=1 cargo test -p mergify-events fails on main today, on escape sequences injected into
asserted output.

Gate on the recorded --color choice instead. set_color_choice() is
called from exactly one place, detect_dispatch() in main, so an unset
choice means the process did not come through the CLI: a test harness,
a doctest, an embedder. Colors stay off there, in any environment,
across every crate.

resolve_enabled() takes the Option<ColorChoice> so the new case is
covered by the existing precedence unit test rather than by global
state.

Refs MRGFY-8533.

`colors_enabled()` opened with `if cfg!(test) { return false }`, whose
comment claims tests "never depend on the dev's TTY". It cannot do
that: `cfg!(test)` is false whenever mergify-tui is compiled as a
dependency, so the guard only ever covered mergify-tui's own tests.
Every *consumer* crate's tests fell through to the real policy and read
the developer's environment — `FORCE_COLOR=1 cargo test -p
mergify-events` fails on main today, on escape sequences injected into
asserted output.

Gate on the recorded `--color` choice instead. `set_color_choice()` is
called from exactly one place, `detect_dispatch()` in main, so an unset
choice means the process did not come through the CLI: a test harness,
a doctest, an embedder. Colors stay off there, in any environment,
across every crate.

`resolve_enabled()` takes the `Option<ColorChoice>` so the new case is
covered by the existing precedence unit test rather than by global
state.

Refs MRGFY-8533.

Change-Id: Id7eb12b906409122000a14722e5ce172ab93cb4c
Copilot AI lite review requested due to automatic review settings August 7, 2026 16:06
@jd

jd commented Aug 7, 2026

Copy link
Copy Markdown
Member Author

This pull request is part of a Mergify stack:

# Pull Request Link
1 fix(tui): gate color on the CLI entry point, not cfg!(test) #1765 👈
2 feat(events): make the default page fast and readable #1766

@mergify
mergify Bot had a problem deploying to Mergify Merge Protections August 7, 2026 16:06 Failure
@jd
jd temporarily deployed to func-tests-live August 7, 2026 16:06 — with GitHub Actions Inactive
@mergify

mergify Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Merge Protections

🔴 2 of 6 protections blocking · waiting on 👀 reviews

Protection Waiting on
🔴 👀 Review Requirements 👀 reviews
🔴 🔎 Reviews 👀 reviews
🟢 🤖 Continuous Integration
🟢 Enforce conventional commit
🟢 📕 PR description
🟢 🚦 Auto-queue

🔴 👀 Review Requirements

Waiting for

  • #approved-reviews-by>=2
This rule is failing.
  • any of:
    • #approved-reviews-by>=2
    • author = dependabot[bot]
    • author = mergify-ci-bot
    • author = renovate[bot]

🔴 🔎 Reviews

Waiting for

  • #review-requested = 0
This rule is failing.
  • #review-requested = 0
  • #changes-requested-reviews-by = 0
  • #review-threads-unresolved = 0

Show 4 satisfied protections

🟢 🤖 Continuous Integration

  • all of:
    • check-success=ci-gate

🟢 Enforce conventional commit

Make sure that we follow https://www.conventionalcommits.org/en/v1.0.0/

  • title ~= ^(fix|feat|internal|docs|style|refactor|perf|test|build|ci|chore|revert|ui)(?:\(.+\))?!?:

🟢 📕 PR description

  • body ~= (?ms:.{48,})

🟢 🚦 Auto-queue

When all merge protections are satisfied, this pull request will be queued automatically.

Copilot AI left a comment

Copy link
Copy Markdown

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 color-detection in mergify-tui by removing an ineffective cfg!(test) gate (which only applied to mergify-tui’s own unit tests) and instead disabling colors unless the CLI entry point explicitly records a --color preference via set_color_choice().

Changes:

  • Make color enablement depend on whether set_color_choice() has been called (i.e., whether execution came through the CLI entry point).
  • Refactor resolve_enabled to accept Option<ColorChoice> so the “no recorded choice” case is explicitly modeled and unit-tested.
  • Update documentation/comments and expand unit test coverage for the new precedence behavior.
Suppressed comments (1)

crates/mergify-tui/src/theme.rs:165

  • colors_enabled() already treats an unset COLOR_CHOICE as “colors off”, but it still reads NO_COLOR/FORCE_COLOR and probes stdout().is_terminal() even though those values can’t affect the result when choice is None. Returning early when the choice is unset better matches the stated policy (“must not take a dependency on the developer's terminal or environment”) and avoids unnecessary syscalls in test/embedded contexts.
pub(crate) fn colors_enabled() -> bool {
    // An unset choice means we are not the CLI: colors off. This
    // used to be `cfg!(test)`, which cannot do the job — it is false
    // whenever this crate is compiled as a dependency, so every
    // *consumer* crate's tests were reading the developer's
    // environment after all. `FORCE_COLOR=1 cargo test` failed on the
    // escape sequences that leaked into asserted output.
    let choice = COLOR_CHOICE.get().copied();
    let no_color = std::env::var_os("NO_COLOR").is_some();
    let force_color =
        std::env::var_os("FORCE_COLOR").is_some() || std::env::var_os("CLICOLOR_FORCE").is_some();
    resolve_enabled(
        choice,
        no_color,
        force_color,
        std::io::stdout().is_terminal(),
    )

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

@mergify
mergify Bot requested a review from a team August 7, 2026 16:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants