Skip to content

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

Open
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
Open

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 deployed to Mergify Merge Protections August 7, 2026 16:06 Active
@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

🟢 All 6 merge protections satisfied — ready to merge.

Show 6 satisfied protections

🟢 🤖 Continuous Integration

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

🟢 👀 Review Requirements

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

🟢 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)(?:\(.+\))?!?:

🟢 🔎 Reviews

  • #changes-requested-reviews-by = 0
  • #review-requested = 0
  • #review-threads-unresolved = 0

🟢 📕 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
@jd
jd marked this pull request as ready for review August 10, 2026 11:44
@mergify
mergify Bot requested a review from a team August 10, 2026 12:04
@mergify

mergify Bot commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

Merge Queue Status

Waiting for
  • check-success=ci-gate
All merge conditions
Required conditions to stay in the queue
  • -closed [📌 queue requirement]
  • -conflict [📌 queue requirement]
  • -draft [📌 queue requirement]
  • deployment-success = Mergify Merge Protections [📌 queue requirement]
  • any of [📌 queue -> configuration change requirements]:
    • -mergify-configuration-changed
    • check-success = Configuration changed
  • any of [🔀 queue conditions]:
    • all of [📌 queue conditions of queue rule default]:
      • base=main
      • github-review-approved [🛡 GitHub branch protection]
      • github-review-approved [🛡 GitHub repository ruleset rule Require pull request for default branch]
      • label!=manual merge
      • all of [🛡 Merge Protections rule Enforce conventional commit]:
        • title ~= ^(fix|feat|internal|docs|style|refactor|perf|test|build|ci|chore|revert|ui)(?:\(.+\))?!?:
      • all of [🛡 Merge Protections rule 👀 Review Requirements]:
        • any of:
          • #approved-reviews-by>=2
          • author = dependabot[bot]
          • author = mergify-ci-bot
          • author = renovate[bot]
      • all of [🛡 Merge Protections rule 📕 PR description]:
        • body ~= (?ms:.{48,})
      • all of [🛡 Merge Protections rule 🔎 Reviews]:
        • #changes-requested-reviews-by = 0
        • #review-requested = 0
        • #review-threads-unresolved = 0
      • all of [🛡 Merge Protections rule 🤖 Continuous Integration]:
        • all of:
          • check-success=ci-gate
    • all of [📌 queue conditions of queue rule dependencies]:
      • any of:
        • author = dependabot[bot]
        • author = renovate[bot]
      • base=main
      • github-review-approved [🛡 GitHub branch protection]
      • github-review-approved [🛡 GitHub repository ruleset rule Require pull request for default branch]
      • label!=manual merge
      • all of [🛡 Merge Protections rule Enforce conventional commit]:
        • title ~= ^(fix|feat|internal|docs|style|refactor|perf|test|build|ci|chore|revert|ui)(?:\(.+\))?!?:
      • all of [🛡 Merge Protections rule 👀 Review Requirements]:
        • any of:
          • #approved-reviews-by>=2
          • author = dependabot[bot]
          • author = mergify-ci-bot
          • author = renovate[bot]
      • all of [🛡 Merge Protections rule 📕 PR description]:
        • body ~= (?ms:.{48,})
      • all of [🛡 Merge Protections rule 🔎 Reviews]:
        • #changes-requested-reviews-by = 0
        • #review-requested = 0
        • #review-threads-unresolved = 0
      • all of [🛡 Merge Protections rule 🤖 Continuous Integration]:
        • all of:
          • check-success=ci-gate

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Development

Successfully merging this pull request may close these issues.

4 participants