From 619bcc01a8443fb5c00166a015f5816ef70ac83a Mon Sep 17 00:00:00 2001 From: Pantani Date: Thu, 5 Mar 2026 20:03:24 -0300 Subject: [PATCH 1/3] fix: enable automatic switching to daemon mode when not a terminal --- ignite/cmd/chain_serve.go | 41 ++++++++++++++++++++++++- ignite/cmd/chain_serve_test.go | 56 ++++++++++++++++++++++++++++++++++ 2 files changed, 96 insertions(+), 1 deletion(-) create mode 100644 ignite/cmd/chain_serve_test.go diff --git a/ignite/cmd/chain_serve.go b/ignite/cmd/chain_serve.go index 650c6c5740..10bda3f22a 100644 --- a/ignite/cmd/chain_serve.go +++ b/ignite/cmd/chain_serve.go @@ -2,12 +2,14 @@ package ignitecmd import ( "context" + "io" "os" "os/signal" "syscall" tea "github.com/charmbracelet/bubbletea" "github.com/spf13/cobra" + "golang.org/x/term" cmdmodel "github.com/ignite/cli/v29/ignite/cmd/bubblemodel" "github.com/ignite/cli/v29/ignite/pkg/cliui" @@ -28,6 +30,8 @@ const ( flagOutputFile = "output-file" ) +var isTerminal = term.IsTerminal + // NewChainServe creates a new serve command to serve a blockchain. func NewChainServe() *cobra.Command { c := &cobra.Command{ @@ -88,7 +92,7 @@ production, you may want to run "appd start" manually. } func chainServeHandler(cmd *cobra.Command, _ []string) error { - if cmd.Flags().Changed(flagOutputFile) { + if shouldRunServeInDaemonMode(cmd) { return daemonMode(cmd) } @@ -124,6 +128,41 @@ func chainServeHandler(cmd *cobra.Command, _ []string) error { return chainServe(cmd, session) } +func shouldRunServeInDaemonMode(cmd *cobra.Command) bool { + if cmd.Flags().Changed(flagOutputFile) { + return true + } + + return !hasTerminalInputAndOutput(cmd.InOrStdin(), cmd.OutOrStdout()) +} + +func hasTerminalInputAndOutput(stdin io.Reader, stdout io.Writer) bool { + stdinFD, ok := fileDescriptor(stdin) + if !ok { + return false + } + + stdoutFD, ok := fileDescriptor(stdout) + if !ok { + return false + } + + return isTerminal(stdinFD) && isTerminal(stdoutFD) +} + +type fileDescriptorProvider interface { + Fd() uintptr +} + +func fileDescriptor(v any) (int, bool) { + provider, ok := v.(fileDescriptorProvider) + if !ok { + return 0, false + } + + return int(provider.Fd()), true +} + // daemonMode runs the chain serve command without user interaction, UI in verbose mode. Useful to be used as daemon. func daemonMode(cmd *cobra.Command) error { // always yes, no user interaction diff --git a/ignite/cmd/chain_serve_test.go b/ignite/cmd/chain_serve_test.go new file mode 100644 index 0000000000..67307ed7de --- /dev/null +++ b/ignite/cmd/chain_serve_test.go @@ -0,0 +1,56 @@ +package ignitecmd + +import ( + "bytes" + "os" + "testing" + + "github.com/stretchr/testify/require" +) + +func TestShouldRunServeInDaemonMode(t *testing.T) { + cmd := NewChainServe() + + require.NoError(t, cmd.Flags().Set(flagOutputFile, "/tmp/serve.log")) + require.True(t, shouldRunServeInDaemonMode(cmd)) +} + +func TestShouldRunServeInDaemonModeNoTerminal(t *testing.T) { + cmd := NewChainServe() + cmd.SetIn(bytes.NewBufferString("")) + cmd.SetOut(bytes.NewBuffer(nil)) + + require.True(t, shouldRunServeInDaemonMode(cmd)) +} + +func TestShouldRunServeInDaemonModeInteractiveTerminal(t *testing.T) { + cmd := NewChainServe() + cmd.SetIn(os.Stdin) + cmd.SetOut(os.Stdout) + + originalIsTerminal := isTerminal + t.Cleanup(func() { + isTerminal = originalIsTerminal + }) + isTerminal = func(_ int) bool { return true } + + require.False(t, shouldRunServeInDaemonMode(cmd)) +} + +func TestShouldRunServeInDaemonModeMixedTerminal(t *testing.T) { + cmd := NewChainServe() + cmd.SetIn(os.Stdin) + cmd.SetOut(os.Stdout) + + originalIsTerminal := isTerminal + t.Cleanup(func() { + isTerminal = originalIsTerminal + }) + calls := 0 + isTerminal = func(_ int) bool { + calls++ + return calls == 1 + } + + require.True(t, shouldRunServeInDaemonMode(cmd)) +} From 96ef699c460456de22069255c512a2df3c3fd9bb Mon Sep 17 00:00:00 2001 From: Pantani Date: Tue, 10 Mar 2026 19:28:04 -0300 Subject: [PATCH 2/3] add changelog --- changelog.md | 1 + 1 file changed, 1 insertion(+) diff --git a/changelog.md b/changelog.md index 071a41103d..7a9a408a21 100644 --- a/changelog.md +++ b/changelog.md @@ -15,6 +15,7 @@ - [#4878](https://github.com/ignite/cli/pull/4878) Improve the `xast` package readability. - [#4883](https://github.com/ignite/cli/pull/4883) Remove ibc keys placeholders. - [#4884](https://github.com/ignite/cli/pull/4884) Remove autocli placeholders. +- [#4901](https://github.com/ignite/cli/pull/4901) Enable automatic switching to daemon mode when not a terminal. ### Fixes From 4d86b94659ab966cb4a8bc0a182cdc6c4a23dfd9 Mon Sep 17 00:00:00 2001 From: Pantani Date: Tue, 10 Mar 2026 19:28:51 -0300 Subject: [PATCH 3/3] fix changelog --- changelog.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/changelog.md b/changelog.md index 7a9a408a21..d87244018f 100644 --- a/changelog.md +++ b/changelog.md @@ -2,6 +2,10 @@ ## Unreleased +### Changes + +- [#4901](https://github.com/ignite/cli/pull/4901) Enable automatic switching to daemon mode when not a terminal. + ## [`v29.9.0`](https://github.com/ignite/cli/releases/tag/v29.9.0) ## Features @@ -15,7 +19,6 @@ - [#4878](https://github.com/ignite/cli/pull/4878) Improve the `xast` package readability. - [#4883](https://github.com/ignite/cli/pull/4883) Remove ibc keys placeholders. - [#4884](https://github.com/ignite/cli/pull/4884) Remove autocli placeholders. -- [#4901](https://github.com/ignite/cli/pull/4901) Enable automatic switching to daemon mode when not a terminal. ### Fixes