Skip to content
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# Change log

## [Unreleased]

### Added
* Add :tag option to add custom tags to command output

## [v0.10.1] - 2021-02-14

### Fixed
Expand Down
27 changes: 23 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,9 @@ Or install it yourself as:
* [2.3. Logging](#23-logging)
* [2.3.1. Color](#231-color)
* [2.3.2. UUID](#232-uuid)
* [2.3.3. Only output on error](#233-only-output-on-error)
* [2.3.4. Verbose](#234-verbose)
* [2.3.3. Tag](#233-tag)
* [2.3.4. Only output on error](#234-only-output-on-error)
* [2.3.5. Verbose](#235-verbose)
* [2.4. Dry run](#24-dry-run)
* [2.5. Wait](#25-wait)
* [2.6. Test](#26-test)
Expand Down Expand Up @@ -221,7 +222,25 @@ cmd.run("echo hello", uuid: false)
# Finished in 0.003 seconds with exit status 0 (successful)
```

#### 2.3.3 Only output on error
#### 2.3.3 Tag

You can add custom tags to command output using the `:tag` option. This is useful for categorizing or identifying a specific instance or run of a command:

```ruby
cmd = TTY::Command.new(tag: "deploy")
cmd.run("echo hello")

# or individually per command run:
cmd = TTY::Command.new
cmd.run("echo hello", tag: "deploy")

# =>
# [deploy] Running echo hello
# hello
# [deploy] Finished in 0.003 seconds with exit status 0 (successful)
```

#### 2.3.4 Only output on error

When using a command that can fail, setting `:only_output_on_error` option to `true` hides the output if the command succeeds:

Expand Down Expand Up @@ -254,7 +273,7 @@ will also print the output.

*Setting this option will cause the output to show at once, at the end of the command.*

#### 2.3.4 Verbose
#### 2.3.5 Verbose

By default commands will produce warnings when, for example `pty` option is not supported on a given platform. You can switch off such warnings with `:verbose` option set to `false`.

Expand Down
4 changes: 3 additions & 1 deletion lib/tty/command.rb
Original file line number Diff line number Diff line change
Expand Up @@ -55,14 +55,16 @@ def initialize(**options)
@output = options.fetch(:output) { $stdout }
@color = options.fetch(:color) { true }
@uuid = options.fetch(:uuid) { true }
@tag = options[:tag]
@printer_name = options.fetch(:printer) { :pretty }
@dry_run = options.fetch(:dry_run) { false }
@printer = use_printer(@printer_name, color: @color, uuid: @uuid)
@printer = use_printer(@printer_name, color: @color, uuid: @uuid, tag: @tag)
@cmd_options = {}
@cmd_options[:verbose] = options.fetch(:verbose, true)
@cmd_options[:pty] = true if options[:pty]
@cmd_options[:binmode] = true if options[:binmode]
@cmd_options[:timeout] = options[:timeout] if options[:timeout]
@cmd_options[:tag] = @tag if @tag
end

# Start external executable in a child process
Expand Down
9 changes: 8 additions & 1 deletion lib/tty/command/cmd.rb
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,12 @@ def group(value)
def with_clean_env
end

# The command tag
# @api public
def tag
@options[:tag]
end

# Assemble full command
#
# @api public
Expand All @@ -140,7 +146,8 @@ def to_hash
{
command: command,
argv: argv,
uuid: uuid
uuid: uuid,
tag: @options[:tag]
}
end

Expand Down
7 changes: 4 additions & 3 deletions lib/tty/command/printers/pretty.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ class Pretty < Abstract
def initialize(*)
super
@uuid = options.fetch(:uuid, true)
@tag = options[:tag]
end

def print_command_start(cmd, *args)
Expand Down Expand Up @@ -46,10 +47,10 @@ def print_command_exit(cmd, status, runtime, *args)
def write(cmd, message, data = nil)
cmd_set_uuid = cmd.options.fetch(:uuid, true)
uuid_needed = cmd.options[:uuid].nil? ? @uuid : cmd_set_uuid
prefix = cmd.tag || @tag || (uuid_needed ? cmd.uuid : nil)

out = []
if uuid_needed
out << "[#{decorate(cmd.uuid, :green)}] " unless cmd.uuid.nil?
end
out << "[#{decorate(prefix, :green)}] " if prefix
out << "#{message}\n"
target = (cmd.only_output_on_error && !data.nil?) ? data : output
target << out.join
Expand Down
135 changes: 99 additions & 36 deletions spec/unit/run_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
"[\e[32m#{uuid}\e[0m] Running \e[33;1mecho hello\e[0m\n",
"[\e[32m#{uuid}\e[0m] \thello\n",
"[\e[32m#{uuid}\e[0m] Finished in x seconds with exit status 0 " \
"(\e[32;1msuccessful\e[0m)\n"
"(\e[32;1msuccessful\e[0m)\n"
])
end

Expand All @@ -48,38 +48,6 @@
])
end

it "runs command successfully with logging without uuid set globally" do
output = StringIO.new
command = TTY::Command.new(output: output, uuid: false)

command.run(:echo, "hello")
output.rewind

lines = output.readlines
lines.last.gsub!(/\d+\.\d+/, "x")
expect(lines).to eq([
"Running \e[33;1mecho hello\e[0m\n",
"\thello\n",
"Finished in x seconds with exit status 0 (\e[32;1msuccessful\e[0m)\n"
])
end

it "runs command successfully with logging without uuid set locally" do
output = StringIO.new
command = TTY::Command.new(output: output)

command.run(:echo, "hello", uuid: false)
output.rewind

lines = output.readlines
lines.last.gsub!(/\d+\.\d+/, "x")
expect(lines).to eq([
"Running \e[33;1mecho hello\e[0m\n",
"\thello\n",
"Finished in x seconds with exit status 0 (\e[32;1msuccessful\e[0m)\n"
])
end

it "runs command and fails with logging" do
non_zero_exit = fixtures_path("non_zero_exit")
output = StringIO.new
Expand All @@ -96,7 +64,7 @@
"[\e[32m#{uuid}\e[0m] Running \e[33;1mruby #{non_zero_exit}\e[0m\n",
"[\e[32m#{uuid}\e[0m] \tnooo\n",
"[\e[32m#{uuid}\e[0m] Finished in x seconds with exit status 1 " \
"(\e[31;1mfailed\e[0m)\n"
"(\e[31;1mfailed\e[0m)\n"
])
end

Expand Down Expand Up @@ -160,12 +128,12 @@
"[\e[32m#{uuid}\e[0m] Running \e[33;1mruby #{phased_output}\e[0m\n",
"[\e[32m#{uuid}\e[0m] \t..........\n",
"[\e[32m#{uuid}\e[0m] Finished in x seconds with exit status 0 " \
"(\e[32;1msuccessful\e[0m)\n"
"(\e[32;1msuccessful\e[0m)\n"
])
end

it "does not persist environment variables",
unless: RSpec::Support::OS.windows? do
unless: RSpec::Support::OS.windows? do
output = StringIO.new
command = TTY::Command.new(output: output)

Expand All @@ -184,4 +152,99 @@
lines = output.readlines
expect(lines[0]).to include("Running \e[33;1mecho hello\e[0m\n")
end

context "with uuid option" do
it "runs command successfully with logging without uuid set globally" do
output = StringIO.new
command = TTY::Command.new(output: output, uuid: false)

command.run(:echo, "hello")
output.rewind

lines = output.readlines
lines.last.gsub!(/\d+\.\d+/, "x")
expect(lines).to eq(
generic_colored_log_lines(prefix: nil)
)
end

it "runs command successfully with logging without uuid set locally" do
output = StringIO.new
command = TTY::Command.new(output: output)

command.run(:echo, "hello", uuid: false)
output.rewind

lines = output.readlines
lines.last.gsub!(/\d+\.\d+/, "x")
expect(lines).to eq(
generic_colored_log_lines(prefix: nil)
)
end
end

context "with tag option" do
it "prints the tag set globally" do
output = StringIO.new
tag = "task"
command = TTY::Command.new(output: output, tag: tag)

command.run(:echo, "hello")

output.rewind
lines = output.readlines
lines.last.gsub!(/\d+\.\d+/, "x")
expect(lines).to eq(
generic_colored_log_lines(prefix: tag)
)
end

it "prints the tag set locally" do
output = StringIO.new
tag = "task"
command = TTY::Command.new(output: output)

command.run(:echo, "hello", tag: tag)

output.rewind
lines = output.readlines
lines.last.gsub!(/\d+\.\d+/, "x")
expect(lines).to eq(
generic_colored_log_lines(prefix: tag)
)
end

it "prints the tag even if uuid is set to false" do
output = StringIO.new
tag = "task"
command = TTY::Command.new(output: output, tag: tag, uuid: false)

command.run(:echo, "hello")

output.rewind
lines = output.readlines
lines.last.gsub!(/\d+\.\d+/, "x")
expect(lines).to eq(
generic_colored_log_lines(prefix: tag)
)
end
end

# Generates the expected log lines in colored mode, with/without `[prefix]`
def generic_colored_log_lines(prefix: nil)
if prefix
[
"[\e[32m#{prefix}\e[0m] Running \e[33;1mecho hello\e[0m\n",
"[\e[32m#{prefix}\e[0m] \thello\n",
"[\e[32m#{prefix}\e[0m] Finished in x seconds with exit status 0 " \
"(\e[32;1msuccessful\e[0m)\n"
]
else
[
"Running \e[33;1mecho hello\e[0m\n",
"\thello\n",
"Finished in x seconds with exit status 0 (\e[32;1msuccessful\e[0m)\n"
]
end
end
end