Skip to content

Consolidate cmdio capability detection into capabilities struct - #4298

Merged
pietern merged 4 commits into
mainfrom
cmdio-capabilities
Jan 16, 2026
Merged

Consolidate cmdio capability detection into capabilities struct#4298
pietern merged 4 commits into
mainfrom
cmdio-capabilities

Conversation

@pietern

@pieternpietern commented Jan 16, 2026

Copy link
Copy Markdown
Contributor

Changes

Replace scattered interactive/prompt booleans in libs/cmdio with a single capabilities struct that encapsulates all terminal capability detection (TTY status, color support, prompt support, Git Bash detection).

Changes:

  • Add Capabilities struct with methods SupportsInteractive(), SupportsPrompt(), SupportsColor()
  • Move IsTTY to tty.go with FakeTTY test helper
  • Replace cmdio.IsTTY(w) with cmdio.SupportsColor(ctx, w) for color decisions
  • Replace stdin TTY check with IsPromptSupported() in aitools install

No behavioral changes. Respects NO_COLOR and TERM=dumb throughout.

Tests

All tests pass.

Manually confirmed that I still see prompts and colors.

pieternand others added 3 commits January 15, 2026 20:32
Replace scattered interactive/prompt booleans in cmdIO with a single
Capabilities struct that encapsulates all terminal capability detection
(TTY status, color support, prompt support, Git Bash detection).
Changes:
- Add Capabilities struct with methods SupportsInteractive(), SupportsPrompt(), SupportsColor()
- Move IsTTY to tty.go with FakeTTY test helper
- Replace cmdio.IsTTY(w) with cmdio.SupportsColor(ctx, w) for color decisions
- Replace stdin TTY check with IsPromptSupported() in aitools install
No behavioral changes. Respects NO_COLOR and TERM=dumb throughout.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
@eng-dev-ecosystem-bot

eng-dev-ecosystem-bot commented Jan 16, 2026

Copy link
Copy Markdown
Collaborator

Commit: dea0180

Run: 21063093460

Env🟨​KNOWN🔄​flaky💚​RECOVERED🙈​SKIP✅​pass🙈​skipTime
🟨​aws linux314241169529:49
🟨​aws windows611241369335:59
🟨​aws-ucws linux3214258456862:38
🟨​aws-ucws windows611258856666:10
💚​azure linux12341369429:22
🟨​azure windows417341569237:17
💚​azure-ucws linux12358456760:36
🟨​azure-ucws windows48358656562:08
💚​gcp linux12340270037:56
🟨​gcp windows48340469844:52
21 interesting tests: 11 RECOVERED, 6 KNOWN, 3 flaky, 1 SKIP
Test Nameaws linuxaws windowsaws-ucws linuxaws-ucws windowsazure linuxazure windowsazure-ucws linuxazure-ucws windowsgcp linuxgcp windows
🟨​TestAccept🟨​K🟨​K🟨​K🟨​K💚​R🟨​K💚​R🟨​K💚​R🟨​K
💚​TestAccept/bundle/deployment/bind/alert🙈​S🙈​S🙈​S🙈​S💚​R💚​R💚​R💚​R💚​R💚​R
🟨​TestAccept/bundle/generate/alert💚​R🟨​K💚​R🟨​K💚​R🟨​K💚​R🟨​K💚​R🟨​K
🟨​TestAccept/bundle/generate/alert/DATABRICKS_BUNDLE_ENGINE=direct💚​R🟨​K💚​R🟨​K💚​R🟨​K💚​R🟨​K💚​R🟨​K
🟨​TestAccept/bundle/generate/alert/DATABRICKS_BUNDLE_ENGINE=terraform💚​R🟨​K💚​R🟨​K💚​R🟨​K💚​R🟨​K💚​R🟨​K
💚​TestAccept/bundle/resources/alerts/basic💚​R💚​R💚​R💚​R💚​R💚​R💚​R💚​R💚​R💚​R
💚​TestAccept/bundle/resources/alerts/basic/DATABRICKS_BUNDLE_ENGINE=direct💚​R💚​R💚​R💚​R💚​R💚​R💚​R💚​R💚​R💚​R
💚​TestAccept/bundle/resources/alerts/basic/DATABRICKS_BUNDLE_ENGINE=terraform💚​R💚​R💚​R💚​R💚​R💚​R💚​R💚​R💚​R💚​R
💚​TestAccept/bundle/resources/alerts/with_file💚​R💚​R💚​R💚​R💚​R💚​R💚​R💚​R💚​R💚​R
💚​TestAccept/bundle/resources/alerts/with_file/DATABRICKS_BUNDLE_ENGINE=direct💚​R💚​R💚​R💚​R💚​R💚​R💚​R💚​R💚​R💚​R
💚​TestAccept/bundle/resources/alerts/with_file/DATABRICKS_BUNDLE_ENGINE=terraform💚​R💚​R💚​R💚​R💚​R💚​R💚​R💚​R💚​R💚​R
🙈​TestAccept/bundle/resources/permissions🙈​S🙈​S🙈​S🙈​S🙈​S🙈​S🙈​S🙈​S🙈​S🙈​S
🟨​TestAccept/bundle/resources/permissions/jobs/destroy_without_mgmtperms/with_permissions🟨​K🟨​K🟨​K🟨​K🙈​S🙈​S🙈​S🙈​S🙈​S🙈​S
🟨​TestAccept/bundle/resources/permissions/jobs/destroy_without_mgmtperms/with_permissions/DATABRICKS_BUNDLE_ENGINE=direct🟨​K🟨​K🟨​K🟨​K
💚​TestAccept/bundle/resources/permissions/jobs/destroy_without_mgmtperms/with_permissions/DATABRICKS_BUNDLE_ENGINE=terraform💚​R💚​R💚​R💚​R
💚​TestAccept/bundle/resources/permissions/jobs/destroy_without_mgmtperms/without_permissions💚​R💚​R💚​R💚​R🙈​S🙈​S🙈​S🙈​S🙈​S🙈​S
💚​TestAccept/bundle/resources/permissions/jobs/destroy_without_mgmtperms/without_permissions/DATABRICKS_BUNDLE_ENGINE=direct💚​R💚​R💚​R💚​R
💚​TestAccept/bundle/resources/permissions/jobs/destroy_without_mgmtperms/without_permissions/DATABRICKS_BUNDLE_ENGINE=terraform💚​R💚​R💚​R💚​R
🔄​TestAccept/bundle/resources/quality_monitors/change_assets_dir🙈​s🙈​s🔄​f✅​p🙈​s🙈​s✅​p✅​p🙈​s🙈​s
🔄​TestAccept/bundle/resources/quality_monitors/change_assets_dir/DATABRICKS_BUNDLE_ENGINE=terraform🔄​f✅​p✅​p✅​p
🔄​TestAccept/ssh/connection💚​R💚​R💚​R💚​R💚​R🔄​f💚​R💚​R💚​R💚​R
Top 50 slowest tests (at least 2 minutes):
durationenvtestname
10:48azure windowsTestAccept/bundle/resources/clusters/deploy/update-after-create/DATABRICKS_BUNDLE_ENGINE=direct
9:48azure windowsTestAccept/bundle/resources/clusters/deploy/update-after-create/DATABRICKS_BUNDLE_ENGINE=terraform
7:55azure linuxTestAccept/bundle/resources/clusters/deploy/update-after-create/DATABRICKS_BUNDLE_ENGINE=direct
7:50aws-ucws linuxTestAccept/bundle/resources/synced_database_tables/basic/DATABRICKS_BUNDLE_ENGINE=terraform
6:50aws-ucws windowsTestAccept/bundle/resources/synced_database_tables/basic/DATABRICKS_BUNDLE_ENGINE=direct
6:30aws-ucws linuxTestAccept/bundle/resources/synced_database_tables/basic/DATABRICKS_BUNDLE_ENGINE=direct
6:13aws-ucws windowsTestAccept/bundle/resources/synced_database_tables/basic/DATABRICKS_BUNDLE_ENGINE=terraform
6:01aws windowsTestAccept/bundle/resources/clusters/deploy/update-after-create/DATABRICKS_BUNDLE_ENGINE=terraform
5:56aws-ucws windowsTestAccept/bundle/resources/clusters/deploy/update-after-create/DATABRICKS_BUNDLE_ENGINE=terraform
5:55aws-ucws linuxTestAccept/bundle/resources/clusters/deploy/update-after-create/DATABRICKS_BUNDLE_ENGINE=direct
5:47aws windowsTestAccept/bundle/resources/clusters/deploy/update-after-create/DATABRICKS_BUNDLE_ENGINE=direct
5:28aws-ucws linuxTestAccept/bundle/resources/clusters/deploy/update-after-create/DATABRICKS_BUNDLE_ENGINE=terraform
5:26aws-ucws windowsTestAccept/bundle/resources/clusters/deploy/update-after-create/DATABRICKS_BUNDLE_ENGINE=direct
5:19gcp linuxTestAccept/bundle/resources/clusters/deploy/update-after-create/DATABRICKS_BUNDLE_ENGINE=terraform
5:11gcp windowsTestAccept/bundle/resources/clusters/deploy/update-after-create/DATABRICKS_BUNDLE_ENGINE=terraform
5:06gcp linuxTestAccept/bundle/resources/clusters/deploy/update-after-create/DATABRICKS_BUNDLE_ENGINE=direct
5:01gcp windowsTestAccept/bundle/resources/clusters/deploy/update-after-create/DATABRICKS_BUNDLE_ENGINE=direct
4:31gcp linuxTestAccept/bundle/resources/models/basic/DATABRICKS_BUNDLE_ENGINE=terraform
4:04azure-ucws linuxTestAccept/bundle/resources/synced_database_tables/basic/DATABRICKS_BUNDLE_ENGINE=terraform
3:54aws-ucws windowsTestAccept/bundle/resources/registered_models/basic/DATABRICKS_BUNDLE_ENGINE=direct
3:51gcp windowsTestAccept/bundle/resources/models/basic/DATABRICKS_BUNDLE_ENGINE=terraform
3:50gcp linuxTestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=terraform
3:48gcp windowsTestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=terraform
3:44azure-ucws linuxTestAccept/bundle/resources/clusters/deploy/update-after-create/DATABRICKS_BUNDLE_ENGINE=direct
3:32azure-ucws windowsTestAccept/bundle/resources/clusters/deploy/update-after-create/DATABRICKS_BUNDLE_ENGINE=terraform
3:32azure-ucws windowsTestAccept/bundle/resources/synced_database_tables/basic/DATABRICKS_BUNDLE_ENGINE=terraform
3:30azure-ucws windowsTestAccept/bundle/templates/default-python/combinations/classic/DATABRICKS_BUNDLE_ENGINE=direct/DLT=yes/NBOOK=yes/PY=yes/READPLAN=1
3:27aws-ucws windowsTestAccept/bundle/templates/default-python/integration_classic/DATABRICKS_BUNDLE_ENGINE=direct/UV_PYTHON=3.10
3:26azure-ucws windowsTestAccept/bundle/templates/default-python/combinations/classic/DATABRICKS_BUNDLE_ENGINE=direct/DLT=no/NBOOK=no/PY=yes/READPLAN=1
3:25aws-ucws windowsTestAccept/bundle/templates/default-python/combinations/classic/DATABRICKS_BUNDLE_ENGINE=terraform/DLT=no/NBOOK=no/PY=no/READPLAN=
3:25aws-ucws windowsTestAccept/bundle/templates/default-python/combinations/serverless/DATABRICKS_BUNDLE_ENGINE=terraform/DLT=no/NBOOK=yes/PY=no/READPLAN=
3:24gcp linuxTestAccept/bundle/templates/default-python/combinations/classic/DATABRICKS_BUNDLE_ENGINE=direct/DLT=yes/NBOOK=yes/PY=no/READPLAN=
3:23gcp windowsTestAccept/bundle/templates/default-python/combinations/classic/DATABRICKS_BUNDLE_ENGINE=terraform/DLT=no/NBOOK=no/PY=yes/READPLAN=
3:21gcp linuxTestAccept/bundle/templates/default-python/integration_classic/DATABRICKS_BUNDLE_ENGINE=terraform/UV_PYTHON=3.13
3:19azure-ucws windowsTestAccept/bundle/resources/registered_models/basic/DATABRICKS_BUNDLE_ENGINE=terraform
3:18aws windowsTestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=direct
3:14aws-ucws windowsTestAccept/bundle/resources/registered_models/basic/DATABRICKS_BUNDLE_ENGINE=terraform
3:13azure-ucws linuxTestAccept/bundle/templates/default-python/combinations/classic/DATABRICKS_BUNDLE_ENGINE=terraform/DLT=no/NBOOK=yes/PY=yes/READPLAN=
3:12azure-ucws linuxTestAccept/bundle/resources/registered_models/basic/DATABRICKS_BUNDLE_ENGINE=direct
3:12azure-ucws windowsTestAccept/bundle/resources/synced_database_tables/basic/DATABRICKS_BUNDLE_ENGINE=direct
3:10azure-ucws linuxTestAccept/bundle/templates/default-python/combinations/classic/DATABRICKS_BUNDLE_ENGINE=direct/DLT=yes/NBOOK=no/PY=yes/READPLAN=
3:10aws-ucws linuxTestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=terraform
3:09azure-ucws linuxTestAccept/bundle/templates/default-python/integration_classic/DATABRICKS_BUNDLE_ENGINE=direct/UV_PYTHON=3.12
3:08azure-ucws linuxTestAccept/bundle/resources/experiments/basic/DATABRICKS_BUNDLE_ENGINE=terraform
3:07aws-ucws windowsTestAccept/bundle/templates/default-python/combinations/classic/DATABRICKS_BUNDLE_ENGINE=terraform/DLT=no/NBOOK=yes/PY=yes/READPLAN=
3:07gcp windowsTestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=direct
3:06azure-ucws windowsTestAccept/bundle/resources/registered_models/basic/DATABRICKS_BUNDLE_ENGINE=direct
3:06azure windowsTestAccept/bundle/resources/experiments/basic/DATABRICKS_BUNDLE_ENGINE=terraform
3:06aws-ucws windowsTestAccept/bundle/templates/default-python/combinations/serverless/DATABRICKS_BUNDLE_ENGINE=terraform/DLT=no/NBOOK=yes/PY=yes/READPLAN=
3:05gcp linuxTestAccept/bundle/resources/apps/inline_config/DATABRICKS_BUNDLE_ENGINE=direct

w := f.file.Writer()
return handler.NewFriendlyHandler(w, &handler.Options{
Color: cmdio.IsTTY(w),
Color: cmdio.SupportsColor(ctx, w),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Why let commands configure color if there is only right way to do it? Why not make NewFriendlyHandler select color automatically?

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

Whether or not to log with color depends on the target io.Writer. Agree it can be moved into the function.

Comment threadlibs/cmdio/io.go
stdoutIsTTY: false,
stderrIsTTY: false,
color: false,
isGitBash: false,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

why do we have this here? It's not a "capability", it's environment, which may have some but not others capabilities? (I personally would be okay with saying if "git bash" disable all fancy stuff especially if alternative is that I have to sprinkle my code with gitbash-specific code).

Copy link
Copy Markdown
ContributorAuthor

Choose a reason for hiding this comment

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

The field isn't, but the outcome (does this term prompts, etc), is an outcome of Git Bash or not.

Once we switch to better fancy stuff this will disappear; Git Bash must be supported.

@pietern
pietern added this pull request to the merge queueJan 16, 2026
Merged via the queue into main with commit fa62e53Jan 16, 2026
21 checks passed
@pietern
pietern deleted the cmdio-capabilities branch January 16, 2026 15:10
@eng-dev-ecosystem-bot

Copy link
Copy Markdown
Collaborator

Commit: fa62e53

Run: 21071183032

pietern added a commit that referenced this pull request Jan 19, 2026
## Changes
All prompt functions now consistently write to stderr, removing the need
to check if stdout is a TTY for prompt support.
Depends on #4298.
## Why
This simplifies the logic and follows Unix conventions: keep stdout
clean for data/piping, use stderr for interactive UI elements. Now
prompts work even when stdout is redirected (e.g., `databricks cmd | tee
output.txt`).
---------
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
pietern added a commit that referenced this pull request Jan 19, 2026
## Changes
Configure forbidigo to prevent direct use of term.IsTerminal and isatty
functions outside libs/cmdio.
Depends on #4298 and #4301.
## Why
Use cmdio.IsPromptSupported() instead for consistent capability
detection.
---------
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
denik pushed a commit that referenced this pull request May 20, 2026
## Changes
Replace scattered interactive/prompt booleans in libs/cmdio with a
single capabilities struct that encapsulates all terminal capability
detection (TTY status, color support, prompt support, Git Bash
detection).
Changes:
- Add Capabilities struct with methods SupportsInteractive(),
SupportsPrompt(), SupportsColor()
- Move IsTTY to tty.go with FakeTTY test helper
- Replace cmdio.IsTTY(w) with cmdio.SupportsColor(ctx, w) for color
decisions
- Replace stdin TTY check with IsPromptSupported() in aitools install
No behavioral changes. Respects NO_COLOR and TERM=dumb throughout.
## Tests
All tests pass.
Manually confirmed that I still see prompts and colors.
---------
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
denik pushed a commit that referenced this pull request May 20, 2026
## Changes
All prompt functions now consistently write to stderr, removing the need
to check if stdout is a TTY for prompt support.
Depends on #4298.
## Why
This simplifies the logic and follows Unix conventions: keep stdout
clean for data/piping, use stderr for interactive UI elements. Now
prompts work even when stdout is redirected (e.g., `databricks cmd | tee
output.txt`).
---------
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
denik pushed a commit that referenced this pull request May 20, 2026
## Changes
Configure forbidigo to prevent direct use of term.IsTerminal and isatty
functions outside libs/cmdio.
Depends on #4298 and #4301.
## Why
Use cmdio.IsPromptSupported() instead for consistent capability
detection.
---------
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
Sign up for freeto 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.

3 participants

@pietern@eng-dev-ecosystem-bot@denik