capistrano / bundler

Bundler support for Capistrano 3.x
MIT License
219 stars 83 forks source link

verifying the non-interactive server environment -- help me help you #116

Open mustmodify opened 4 years ago

mustmodify commented 4 years ago

I tend to only dislike capistrano when I'm setting up a new server. :) Non-interactive things environment issues are someone out of my normal workflow, though I admit I can see how they could be considered superior in many situations.

One issue I ran into during this deploy was that nvm was in .bashrc hidden behind a "don't load if non-interactive" instructions. And as much as I appreciate your logs, obviously there's quite a bit going on there and I'm sad to say I was distracted by things like this for over an hour:

rake exit status: 1 (SSHKit::Runner::ExecuteError)
rake stdout: Nothing written
rake stderr: Yarn requires Node.js 4.0 or higher to be installed.
(Backtrace restricted to imported tasks)
cap aborted!
SSHKit::Runner::ExecuteError: Exception while executing as myuser:myserver.museium rake exit status: 1
rake stdout: Nothing written

I'd like to add the ability to assert that the environment is as expected... like "assert that ruby -v is 5.3.1" or "assert that node -v is 15.17.1024" etc. Is that something you'd be open to considering to help neophytes out and what kind of api should we use? Would it be as simple as this in config/deploy.rb?

   assert_equal "ruby -v", "8.5.2"
   assert_equal "node -v", "15.16.17"

or would you imagine hooking it into chruby, rvm, etc and saying "Once a version is set, those should assert it worked".

Alternately, something like:

expect_ruby_version '3.14159' expect_node_version '2.71828`

The first would work with more situations. But the second one could be required, which would help newer users who might not think to set up the assertions. In that situation, you could even consider running it AFTER a failure to say "Look, after this failed, in the same directory as the failure, Ruby isn't right. Fix that first."

So, if you're open to this, please let me know how you would like to see it presented and I'll try to work up a PR. I appreciate your time and this fantastic tool, which has certainly helped me deploy in a more professional way.

mattbrictson commented 4 years ago

Hi @mustmodify 👋 thanks for the writeup!

I agree these sort of .bashrc issues are some of the most frustrating to troubleshoot.

In this case I think the exact error is already being surfaced; i.e.:

Yarn requires Node.js 4.0 or higher to be installed.

So to me the problem is actually that the format of the logs is obscuring the error message. Would you agree?

I don't want to layer code into Capistrano for explicitly dealing with Ruby or Node versions when those underlying tools already have ways of enforcing those things. For example in a Ruby app you can specify the required Ruby version in the Gemfile. In Node you can specify the required Node or Yarn version in the "engines" section of package.json.

However I can see a case for some more general-purpose improvements to Capistrano that might help troubleshoot these problems:

  1. Introduce some sort of assertion DSL, like you suggest, that would check: "assert that when I run this command I get this output, if not then output a easy-to-read error."
  2. Improve Capistrano's log output so that when a remote script fails, the error is easily seen and not buried inside SSHKit::Runner::ExecuteError noise.

Do either of those sound worthwhile?

I'd also like to plug an alternative to Capistrano that is more limited, but beginner-friendly, and you might find interesting. It sets up .bashrc for you and is bundled with best-practices for installing Ruby and Node: https://github.com/mattbrictson/tomo