Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add strip option to capture, reinstate stripping by default in the capture methods #249

Merged
merged 2 commits into from
May 18, 2015

Conversation

robd
Copy link
Contributor

@robd robd commented May 12, 2015

I am nervous about the decision we made over in #239, to no longer strip the output of capture. Having seen some of the issues that are raised, I think there might be quite a lot of fallout from this. I'm particularly worried that this may not fail in an easy-to-understand way, and that we may waste a lot of everyones time dealing with them. I also think that in many cases, eg the one liners in Capistrano, stripping is a reasonable default.

I do still think that we should make the API consistent between the Local and NetSSH backends. Therefore, I'd like to propose that we make stripping whitespace the default, but add an option to the capture method to turn off stripping.

@townsen Would you be OK with adding the strip: false option in the Local cases where you need full whitespace?

This PR also adds some docs for the basic SSHKit usage, which I believe were sort of missing from the README.

This reverses the decision made in capistrano#239. We now reinstate stripping by default to maintain backwards compatibility with the NetSSH backend, but support `strip: false` if full whitespace is needed.
@leehambley
Copy link
Member

I am nervous about the decision we made over in #239, to no longer strip the output of capture. Having seen some of the issues that are raised, I think there might be quite a lot of fallout from this.

Welcome to FOSS maintainer-ship of a popular project!

I also think that in many cases, eg the one liners in Capistrano, stripping is a reasonable default.

That's basically why I did it, although it's not a solid reason :) Capistrano could also be tweaked to strip the results of captures() to allow SSHKit to do the right thing, correctly whilst not breaking Cap, but I'd still keep the strip: {bool} option, just maybe leave the default as false and monkeypatch the method in Capistrano to keep the old behaviour, and send a deprecation warning, or something.

I do still think that we should make the API consistent between the Local and NetSSH backends. Therefore, I'd like to propose that we make stripping whitespace the default, but add an option to the capture method to turn off stripping.

Agreed, absolutely even though most people don't capture() locally, in my experience, consistent APIs are better, no doubt.

This PR also adds some docs for the basic SSHKit usage, which I believe were sort of missing from the README.

Cool, good catch.

@robd
Copy link
Contributor Author

robd commented May 13, 2015

Welcome to FOSS maintainer-ship of a popular project!

Yes - totally! :) I'm trying to focus now on having SSHKit behave in the least surprising way.

That's basically why I did it, although it's not a solid reason

I think this one is finely balanced, but I think your reasoning, to strip, makes sense in most situations, especially the trailing newline.

monkeypatch the method in Capistrano to keep the old behaviour, and send a deprecation warning, or something.

The thing about this is that it might make the documentation a bit confusing - if people read the SSHKit docs, Capistrano then does the opposite. I'm also thinking coding examples which work in Capistrano on Stack overflow etc, might not work in pure SSHKit.

@leehambley
Copy link
Member

I think this one is finely balanced, but I think your reasoning, to strip, makes sense in most situations, especially the trailing newline.

Looking back I think it would have been wiser to always document capture being used with capture(:athing) ~= /some string/ rather than in absolutes, but that ship has sailed.

The thing about this is that it might make the documentation a bit confusing

You're right… let's wait for some other feedback from others, and then we might merge this.

@robd
Copy link
Contributor Author

robd commented May 13, 2015

Looking back I think it would have been wiser to always document capture being used with capture(:athing) ~= /some string/ rather than in absolutes, but that ship has sailed.

Yeah I agree. The thing I'm most worried about is this sort of usage (untested example):

file_path = capture('ls -r1 | head -1')
execute("mv #{file_path} another_path")

It seems like having a newline on the end of file_path seems like it could be a pretty bad thing. I can imagine other much worse examples depending on what people are doing with the output. Especially, it could mean that command line switches aren't evaluated.

I agree would be good to get others' feelings - maybe @townsen, @mattbrictson if you have time?

@ghost
Copy link

ghost commented May 13, 2015

I agree with most of what has been said regarding the history of how this came to be, it was an understandable 'simplification', but I do feel that it was a mistake to strip any output. I have a few reasons for this:

  • Silently removing information that you have no way of getting back is always bad, and
  • If you really want it stripped then the fix is very simple - just add .strip to the capture call, and
  • I imagine the majority of Capistrano users understand that whitespace is significant - after all it is the command itself that outputs the newline (or whatever), not any framework. It's kind of a core Unix principle so that command pipelines and shell stuff work ok.

But I think the above is easy to agree on, the question is what to do next! My opinion on that is:

  • I'm always in favour of making things 'right', so that the future users don't learn 'bad' habits, or have to go through historical hoops, or have inconsistencies.
  • Breaking past behaviour is not a problem: People don't have to upgrade the Cap and SSHkit gems, and if they do then the effort of altering their captures strip behaviour is just part of the price.
  • Since fixing this 'properly' is a breaking change, we should honour Semantic Versioning and make it part of a major release, perhaps along with any other breaking changes we're collecting.
  • But if we are not ready for a major release, then the proposal of a boolean option to enable/disable stripping works well with the default true to preserve backwards compatibility. I would be happy to update my existing code with that.
  • Note that I don't think this is a 'clean' way of doing it for version 4 - as it is largely redundant: it takes more characters to use that feature than to add .strip to the end!

I know this is a long reply, I hope it helps!

Nick

@robd
Copy link
Contributor Author

robd commented May 13, 2015

I think the above is easy to agree on, the question is what to do next!

Yes, I agree with the points above too!

Since fixing this 'properly' is a breaking change, we should honour Semantic Versioning and make it part of a major release, perhaps along with any other breaking changes we're collecting.

I like this idea. Maybe we should add an API cleanup wishlist .md file (or a long running issue?) where we can keep a note of things we want to fix for the next major version API.

But if we are not ready for a major release, then the proposal of a boolean option to enable/disable stripping works well with the default true to preserve backwards compatibility.

I would appreciate that. I have made a number of other changes which should be backwards compatible, and if possible, I'd like to release them as a minor release and fix any problems I've introduced first.

@mattbrictson
Copy link
Member

I agree with the proposal to strip by default, with new support for a :strip => false option, and then change the behavior in a future major version.

As an anecdote, I tried doing a cap deploy using SSHKit master and was initially very confused by the resulting error. One of my tasks was doing something like this (similar to @robd's hypothetical example):

set :api_key, capture("grep ... awk ... etc etc")
...
execute "curl ... -F access_token=#{fetch(:api_key)} ..."

The curl failed because somehow a semicolon was mysteriously inserted into the command string. Apparently there is some magic in cap or sshkit that translates newlines into semicolons?

Anyway, it took me a while to finally trace the issue back to the fact that the capture output had changed to include the trailing newline.

Long story short: I think this change will cause confusion. 😉 Better save it for a major version number release.

Update to reflect new `strip: false` option on the capture method
@robd robd force-pushed the add-strip-option-to-capture branch from c242430 to c77b398 Compare May 17, 2015 17:14
@robd
Copy link
Contributor Author

robd commented May 17, 2015

OK, consensus seems to be that it would be good to leave the breaking API change until the next major release. I introduced a new file -BREAKING_API_WISHLIST.md - to keep notes on these type of changes.

@leehambley
Copy link
Member

Excellent thought @robd :)

@robd
Copy link
Contributor Author

robd commented May 17, 2015

Cool. I think we have agreement on this, so would it be possible to merge this?

leehambley added a commit that referenced this pull request May 18, 2015
Add strip option to capture, reinstate stripping by default in the capture methods
@leehambley leehambley merged commit deacbc6 into capistrano:master May 18, 2015
@leehambley
Copy link
Member

Thanks for the teamwork chaps.

robd added a commit to robd/capistrano that referenced this pull request May 26, 2015
This reverts commit ad8682d. The original change to SSHKit which made stripping necessary was reverted in capistrano/sshkit#249, so we no longer need to strip in capistrano.
robd added a commit to robd/capistrano that referenced this pull request May 26, 2015
This reverts commit ad8682d. The original change to SSHKit which made stripping necessary was reverted in capistrano/sshkit#249, so we no longer need to strip in capistrano.
jsonn pushed a commit to jsonn/pkgsrc that referenced this pull request Dec 14, 2015
## 1.8.1

  * Change license to MIT, thanks to all the patient contributors who gave
    their permissions.

## 1.8.0

  * add SSHKit::Backend::ConnectionPool#close_connections
    [PR #285](capistrano/sshkit#285)
    @akm
  * Clean up rubocop lint warnings
    [PR #275](capistrano/sshkit#275)
    @cshaffer
    * Prepend unused parameter names with an underscore
    * Prefer “safe assignment in condition”
    * Disambiguate regexp literals with parens
    * Prefer `sprintf` over `String#%`
    * No longer shadow `caller_line` variable in `DeprecationLogger`
    * Rescue `StandardError` instead of `Exception`
    * Remove useless `private` access modifier in `TestAbstract`
    * Disambiguate block operator with parens
    * Disambiguate between grouped expression and method params
    * Remove assertion in `TestHost#test_assert_hosts_compare_equal` that compares something with itself
  * Export environment variables and execute command in a subshell.
    [PR #273](capistrano/sshkit#273)
    @kuon
  * Introduce `log_command_start`, `log_command_data`, `log_command_exit` methods on `Formatter`
    [PR #257](capistrano/sshkit#257)
    @robd
    * Deprecate `@stdout` and `@stderr` accessors on `Command`
  * Add support for deprecation logging options.
    [README](README.md#deprecation-warnings),
    [PR #258](capistrano/sshkit#258)
    @robd
  * Quote environment variable values.
    [PR #250](capistrano/sshkit#250)
    @Sinjo - Chris Sinjakli
  * Simplified formatter hierarchy.
    [PR #248](capistrano/sshkit#248)
    @robd
    * `SimpleText` formatter now extends `Pretty`, rather than duplicating.
  * Hide ANSI color escape sequences when outputting to a file.
    [README](README.md#output-colors),
    [Issue #245](capistrano/sshkit#245),
    [PR #246](capistrano/sshkit#246)
    @robd
    * Now only color the output if it is associated with a tty,
      or the `SSHKIT_COLOR` environment variable is set.
  * Removed broken support for assigning an `IO` to the `output` config option.
    [Issue #243](capistrano/sshkit#243),
    [PR #244](capistrano/sshkit#244)
    @robd
    * Use `SSHKit.config.output = SSHKit::Formatter::SimpleText.new($stdin)` instead
  * Added support for `:interaction_handler` option on commands.
    [PR #234](capistrano/sshkit#234),
    [PR #242](capistrano/sshkit#242)
    @robd
  * Removed partially supported `TRACE` log level.
    [2aa7890](capistrano/sshkit@2aa7890)
    @robd
  * Add support for the `:strip` option to the `capture` method and strip by default on the `Local` backend.
    [PR #239](capistrano/sshkit#239),
    [PR #249](capistrano/sshkit#249)
    @robd
    * The `Local` backend now strips by default to be consistent with the `Netssh` one.
    * This reverses change [7d15a9a](capistrano/sshkit@7d15a9a) to the `Local` capture API to remove stripping by default.
    * If you require the raw, unstripped output, pass the `strip: false` option: `capture(:ls, strip: false)`
  * Simplified backend hierarchy.
    [PR #235](capistrano/sshkit#235),
    [PR #237](capistrano/sshkit#237)
    @robd
    * Moved duplicate implementations of `make`, `rake`, `test`, `capture`, `background` on to `Abstract` backend.
    * Backend implementations now only need to implement `execute_command`, `upload!` and `download!`
    * Removed `Printer` from backend hierarchy for `Local` and `Netssh` backends (they now just extend `Abstract`)
    * Removed unused `Net::SSH:LogLevelShim`
  * Removed dependency on the `colorize` gem. SSHKit now implements its own ANSI color logic, with no external dependencies. Note that SSHKit now only supports the `:bold` or plain modes. Other modes will be gracefully ignored. [#263](capistrano/sshkit#263)
  * New API for setting the formatter: `use_format`. This differs from `format=` in that it accepts options or arguments that will be passed to the formatter's constructor. The `format=` syntax will be deprecated in a future release. [#295](capistrano/sshkit#295)
  * SSHKit now immediately raises a `NameError` if you try to set a formatter that does not exist. [#295](capistrano/sshkit#295)
jsonn pushed a commit to jsonn/pkgsrc that referenced this pull request Dec 14, 2015
## 1.8.1

  * Change license to MIT, thanks to all the patient contributors who gave
    their permissions.

## 1.8.0

  * add SSHKit::Backend::ConnectionPool#close_connections
    [PR #285](capistrano/sshkit#285)
    @akm
  * Clean up rubocop lint warnings
    [PR #275](capistrano/sshkit#275)
    @cshaffer
    * Prepend unused parameter names with an underscore
    * Prefer “safe assignment in condition”
    * Disambiguate regexp literals with parens
    * Prefer `sprintf` over `String#%`
    * No longer shadow `caller_line` variable in `DeprecationLogger`
    * Rescue `StandardError` instead of `Exception`
    * Remove useless `private` access modifier in `TestAbstract`
    * Disambiguate block operator with parens
    * Disambiguate between grouped expression and method params
    * Remove assertion in `TestHost#test_assert_hosts_compare_equal` that compares something with itself
  * Export environment variables and execute command in a subshell.
    [PR #273](capistrano/sshkit#273)
    @kuon
  * Introduce `log_command_start`, `log_command_data`, `log_command_exit` methods on `Formatter`
    [PR #257](capistrano/sshkit#257)
    @robd
    * Deprecate `@stdout` and `@stderr` accessors on `Command`
  * Add support for deprecation logging options.
    [README](README.md#deprecation-warnings),
    [PR #258](capistrano/sshkit#258)
    @robd
  * Quote environment variable values.
    [PR #250](capistrano/sshkit#250)
    @Sinjo - Chris Sinjakli
  * Simplified formatter hierarchy.
    [PR #248](capistrano/sshkit#248)
    @robd
    * `SimpleText` formatter now extends `Pretty`, rather than duplicating.
  * Hide ANSI color escape sequences when outputting to a file.
    [README](README.md#output-colors),
    [Issue #245](capistrano/sshkit#245),
    [PR #246](capistrano/sshkit#246)
    @robd
    * Now only color the output if it is associated with a tty,
      or the `SSHKIT_COLOR` environment variable is set.
  * Removed broken support for assigning an `IO` to the `output` config option.
    [Issue #243](capistrano/sshkit#243),
    [PR #244](capistrano/sshkit#244)
    @robd
    * Use `SSHKit.config.output = SSHKit::Formatter::SimpleText.new($stdin)` instead
  * Added support for `:interaction_handler` option on commands.
    [PR #234](capistrano/sshkit#234),
    [PR #242](capistrano/sshkit#242)
    @robd
  * Removed partially supported `TRACE` log level.
    [2aa7890](capistrano/sshkit@2aa7890)
    @robd
  * Add support for the `:strip` option to the `capture` method and strip by default on the `Local` backend.
    [PR #239](capistrano/sshkit#239),
    [PR #249](capistrano/sshkit#249)
    @robd
    * The `Local` backend now strips by default to be consistent with the `Netssh` one.
    * This reverses change [7d15a9a](capistrano/sshkit@7d15a9a) to the `Local` capture API to remove stripping by default.
    * If you require the raw, unstripped output, pass the `strip: false` option: `capture(:ls, strip: false)`
  * Simplified backend hierarchy.
    [PR #235](capistrano/sshkit#235),
    [PR #237](capistrano/sshkit#237)
    @robd
    * Moved duplicate implementations of `make`, `rake`, `test`, `capture`, `background` on to `Abstract` backend.
    * Backend implementations now only need to implement `execute_command`, `upload!` and `download!`
    * Removed `Printer` from backend hierarchy for `Local` and `Netssh` backends (they now just extend `Abstract`)
    * Removed unused `Net::SSH:LogLevelShim`
  * Removed dependency on the `colorize` gem. SSHKit now implements its own ANSI color logic, with no external dependencies. Note that SSHKit now only supports the `:bold` or plain modes. Other modes will be gracefully ignored. [#263](capistrano/sshkit#263)
  * New API for setting the formatter: `use_format`. This differs from `format=` in that it accepts options or arguments that will be passed to the formatter's constructor. The `format=` syntax will be deprecated in a future release. [#295](capistrano/sshkit#295)
  * SSHKit now immediately raises a `NameError` if you try to set a formatter that does not exist. [#295](capistrano/sshkit#295)
mikejohn857 added a commit to mikejohn857/angular-capistrano-project that referenced this pull request Nov 25, 2022
This reverts commit ad8682de34ac78ba69da1569fe0fcdfa3014dc6d. The original change to SSHKit which made stripping necessary was reverted in capistrano/sshkit#249, so we no longer need to strip in capistrano.
dazralsky pushed a commit to dazralsky/capistrano that referenced this pull request Aug 21, 2023
This reverts commit ad8682de34ac78ba69da1569fe0fcdfa3014dc6d. The original change to SSHKit which made stripping necessary was reverted in capistrano/sshkit#249, so we no longer need to strip in capistrano.
Sign up for free to 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.

None yet

3 participants