Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Remove the deploy:web:{disable, enable} tasks

  • Loading branch information...
commit 4ece7902d5058c3c0222fe4d198c33b4eaf7110b 1 parent 4d53eaf
@carsomyr carsomyr authored
Showing with 0 additions and 69 deletions.
  1. +0 −69 lib/capistrano/recipes/deploy.rb
View
69 lib/capistrano/recipes/deploy.rb
@@ -529,73 +529,4 @@ def try_runner(*args)
system(source.local.log(from))
end
end
-
- namespace :web do
- desc <<-DESC
- Present a maintenance page to visitors. Disables your application's web \
- interface by writing a "#{maintenance_basename}.html" file to each web server. The \
- servers must be configured to detect the presence of this file, and if \
- it is present, always display it instead of performing the request.
-
- By default, the maintenance page will just say the site is down for \
- "maintenance", and will be back "shortly", but you can customize the \
- page by specifying the REASON and UNTIL environment variables:
-
- $ cap deploy:web:disable \\
- REASON="hardware upgrade" \\
- UNTIL="12pm Central Time"
-
- You can use a different template for the maintenance page by setting the \
- :maintenance_template_path variable in your deploy.rb file. The template file \
- should either be a plaintext or an erb file.
-
- Further customization will require that you write your own task.
- DESC
- task :disable, :roles => :web, :except => { :no_release => true } do
- require 'erb'
- on_rollback { run "rm -f #{shared_path}/system/#{maintenance_basename}.html" }
-
- warn <<-EOHTACCESS
-
- # Please add something like this to your site's Apache htaccess to redirect users to the maintenance page.
- # More Info: http://www.shiftcommathree.com/articles/make-your-rails-maintenance-page-respond-with-a-503
-
- ErrorDocument 503 /system/#{maintenance_basename}.html
- RewriteEngine On
- RewriteCond %{REQUEST_URI} !\.(css|gif|jpg|png)$
- RewriteCond %{DOCUMENT_ROOT}/system/#{maintenance_basename}.html -f
- RewriteCond %{SCRIPT_FILENAME} !#{maintenance_basename}.html
- RewriteRule ^.*$ - [redirect=503,last]
-
- # Or if you are using Nginx add this to your server config:
-
- if (-f $document_root/system/maintenance.html) {
- return 503;
- }
- error_page 503 @maintenance;
- location @maintenance {
- rewrite ^(.*)$ /system/maintenance.html last;
- break;
- }
- EOHTACCESS
-
- reason = ENV['REASON']
- deadline = ENV['UNTIL']
-
- template = File.read(maintenance_template_path)
- result = ERB.new(template).result(binding)
-
- put result, "#{shared_path}/system/#{maintenance_basename}.html", :mode => 0644
- end
-
- desc <<-DESC
- Makes the application web-accessible again. Removes the \
- "#{maintenance_basename}.html" page generated by deploy:web:disable, which (if your \
- web servers are configured correctly) will make your application \
- web-accessible again.
- DESC
- task :enable, :roles => :web, :except => { :no_release => true } do
- run "rm -f #{shared_path}/system/#{maintenance_basename}.html"
- end
- end
end

52 comments on commit 4ece790

@christophermanning

Why was this removed?

@carsomyr

@christophermanning It's too specific.

  1. Apache is assumed.
  2. It has too many dependencies like system_maintenance_path and maintenance_basename.
  3. This is just one interpretation of what it means to take a server down for maintenance.
  4. It caused issue #73. I decided to take it out and let people maintain their own versions.
@mreinsch

thanks for the warnings and stuff, just cost me 15 minutes or so to figure out why those tasks went missing. And I only found that here in the commit history. Way to go. Some people use this stuff you know.

@tvdeyen

@carsomyr Apache is not assumed. You can achieve this with nginx and all other webservers that support rewriting. Removing this without any possibility to get this back, like moving it into a gem or something ist not very pleasant to developers that rely on that widely used feature. Why didn't you made it deprecated for at least 2-3 versions?

You should really consider to revert this.

@tvdeyen

btw: @leehambley in #73:

... (and move it to an extension)...

So?

@carsomyr

@tvdeyen Excellent, great work!

@wlipa

I agree with the comment about having a deprecation period. These tasks have been around for a long time.

@wlipa

Or, now that the tasks have been moved to another gem, add a stub task that points developers in the right direction with a log message if they use these tasks.

@mnarayan01

It would be nice to at least put something in the change log about this.

Edit: nevermind - reading is hard

@jrochkind

I hadn't noticed this was removed either. It is still documented in your online docs might want to update them to match.

A backwards incompatible chagne for people using this feature ideally should have gotten better announcement or not be done unless a major version number update (semver).

@leehambley
Owner

:+1: This was a bit of an oversight, and has caused a bit of a stir. Who wants to step up and take responsibility for:

  • Docs
  • Changelog/deprecation
  • Recommending an alternative (probably in the docs?)
@jrochkind

It's hard for someone who is not intimately involved with the changes to take responsibility for that stuff -- you can't doc what you
don't know about, and you can't coordinate doc release with code release without knowing about release schedules.

Personally, I think that docs are analagous to writing tests. We've all come to learn that you can't do a commit without tests.
I think you also shouldn't do a commit without considering what doc changes are needed, and either doing them or finding
someone to do them (for the particular commits), and making sure they get done as the release gets done. I think this is
a developer's responsibility, just like writing tests is. If the developer is terrible at writing docs, then the responsibility
can be discharged by finding someone else to do it and making sure it gets done, but docs have to be integrated into
writing code, accepting pull requests, and making releases, just like writing tests (or making sure someone else writes
tests) is.

I also think that in general it would be good for Cap developers to remember that backwards compat is
really important for Cap. People set up cap (on possibly multiple of their own local projects) and expect
it to just keep working. Perhaps some additional official guidance or policies for cap development
would be good. Ideally if there's anything you know is going to be backwards incompat, you woudn't
do it until a cap major release (semver). This may not be possible, but it should be possible to at least
only do it on minor (not patch!) releases, and to consider if there can be a deprecation period (measured
in calendar, not in number of release-increments) before making the backwards-incompat change -- with
some thought on how to advertise the upcoming deprecation. Many cap features are used infrequently
or used in such a way that developer may not see a deprecation notice output in a large text dump of
stdout/stderr. (And one's local automated tests seldom include actually putting cap through it's paces)

This isn't just a docs issue, it's also an issue of -- why was a backwards compat change made
in a patch release?

@leehambley
Owner

Those are questions best directed at @ndbroadbent and @carsomyr.

It's a terminal problem that you can't really have docs in a Ruby project in any way that makes sense, having a gh-pages branch ala-Jekyll doesn't even really help, since they're out of sight, and thus out of mind.

It's something I need to regain control of, and something I will raise privately with you @jrochkind, @carsomyr and @ndbroadbent. ( Topic: how to put Capistrano back on track )

@carsomyr

@jrochkind That was a mistake on my part. I published to the patch release without realizing that the task removal commit was in there. In retrospect, it would have been better to create a separate branch with patches cherry picked in.

@carsomyr

@leehambley I've removed those tasks from the wiki, and @tvdeyen has been kind enough to create a gem for the removed tasks. Perhaps they should be added back in as stubs. As for the changelog, it will be updated to reflect the task removal more prominently in the next (full) release.

@jrochkind
@leehambley
Owner

(Incase I wasn't clear, I wasn't trying to blame anyone, just to get everyone on the same page, I'm happy everyone's talking now, though)

I've set aside 2 hours on Sunday for smashing Cap issues, I'll resolve this if it's still open, and address the documentation problems, and see what I can do to smooth the whole thing out.

@tvdeyen

I vote for depending on my gem until the next mayor version. Do not put it back into the core.

@leehambley
Owner

I absolutely agree, I'm a bit confused by the inclusion of capistrano_colors as a core feature too, that's something I personally would never have wanted in the core, as it breaks some of my automated scripts, another team miscommunication I suppose.

@carsomyr

@leehambley How does it break your scripts?

@jrochkind
@ndbroadbent

@leehambley - Apologies for that, the capistrano_colors merge was my initiative. FWIW, I posted a blog post about it to Reddit and only received positive comments. It shouldn't break any of your scripts if the output device is detected as non-TTY, since the formatting will just be disabled.

@leehambley
Owner
@ndbroadbent
@jrochkind
@ndbroadbent

Agree, so the capistrano gem would definitely have a dependency on capistrano-rails.

I spent a year rewriting parts of the Fat Free CRM project, so I'm pretty jaded when it comes to discussions about rewrites. At the end, we actually hadn't added much value for our users, and the community didn't really notice any changes either.

However, every project needs to be considered separately, and the pros can sometimes outweigh the cons. So I'd love to hear more about the v3 plans first. Capistrano is a developer's tool first and foremost, so perhaps making it nicer to contribute to is a worthy goal.

@carsomyr

Hi All,

Since GitHub doesn't really have forums, I'm going to post my Capistrano v3 wishlist/manifesto right here. It's quite opinionated, so let's discuss. Maybe we can start a document somewhere else.

  1. We need a shell scripting DSL. From what I can tell, most issues stem from the fact that Capistrano doesn't have one, and that task writers are forced to drop down into (usually awful) shell scripts.
    • Using shell scripts has a variety of problems.
      • Escaping: The shell escaping in Capistrano is a nightmare. I've been causing @ndbroadbent no small amount of grief by insisting that his changes be shell escaped. Hopefully we can put a stop to sloppy escaping in v2 with better practices, but a DSL wouldn't suffer from such a problem.
      • Lack of transparency: It's all about control. If we want to see Capistrano used widely by big guys, each deployment command needs to potentially take reporting hooks. It's no wonder that Chef has this feature and is completely DSL driven. Right now, fine-grained control over consecutive shell commands strung together by && is impossible.
      • Portability: Using a scripting DSL means we can do whatever under the hood. For remote sessions, it can be shell commands. For local operations, it could be pure Ruby.
    • Here's what I would expect to see from a shell scripting DSL.
      • It should be able to stand on its own as a useful library: There would be DSL constructs and the Backend abstraction. Capistrano v3 would then provide an implementation of the Backend class with CommandChannelBackend. That would be a sign that everything has been architected in a clean way. I read somewhere in a forum that Chef is a "glorified script runner". Let's strive to be somewhere in the middle: More formal than Bash scripts and less formal than full-blown Chef resources that experience compile/converge steps.
      • A basic DSL-based command set should be offered. That would include basic commands like find, ln, mv, and cp. I believe that @leehambley already has a large part of this spec'd out.
      • Maybe a rollback infrastructure that records well-known commands and attempts to undo them if a transaction block fails.
  2. The SSH command execution backend should be decoupled from constructs like run. We should insert a layer of indirection like CommandChannelBackend that would allow users to send commands and receive return values. This approach has a view advantages.
    • We can have a LocalCommandChannelBackend class that bypasses SSH and just issues commands directly to a shell.
    • Easy local execution means integration/unit testing that extends to the deploy recipe. No more gaping holes in our testing infrastructure.
    • Command channels themselves need not be implemented in the style of SSH. They could be pure Ruby system calls like Pathname#delete and Dir.chdir.
  3. Namespace DSL rewrite. I don't think that using Rake for task and DSL management is a good idea, since Rake is really just the Ruby version of Make. You get the Make language in Ruby, no more, no less. I've been working in this area and thinking about the problems, and there are a few avenues of improvement.
    • Namespace-scoped variables. Capistrano has a myriad of variables, and it would be nice if they were isolated according to namespace.
    • Parameterized task execution. I want to be able to insert my project name as part of a namespace and have deploy_to set to that project's name.
    • Namespace refactoring. There are multiple aspects of Capistrano's namespace DSL implementation that are broken (i.e., lack of a top-level namespace). If these get refactored, we can remove much of the ambiguity associated with the extensive use of method_missing?.
    • Tasks should be able to specify depends and provides hooks. These are different from before and after hooks in that they're part of a dependency graph and execute only once. Thus, before, after, depends, and provides would provide more flexibility than the pure dependency engine of Rake.
  4. Parallelization and improved I/O throughput. We need to understand where Capistrano can be parallelized. At the very least, when run is being executed, it should execute in parallel for all matching servers and the results should be collected. This is something I'll have to investigate further. In particular, I'll have to take stock of what I/O framework Net:SSH can run over. Perhaps someone has come up with something better than EventMachine by now.
@leehambley
Owner

Roy, I only disagree with §1.2.3 and §3.4.

I'll elaborate more, in the coming week I'm planning to write a rather deep analysis of my perceived problems, analyse why they are not really solvable, and pitch a plan for resolving them.

In a short way, I can at least say that I want to take the runner style from MiniTest, I want to take the IO/formatting from them as well (which also leads to tasks being able to fire instrumentation events, as they do in MiniTest). I want to parallelize everywhere using the actor pattern (Tom already dove into that) and I want to make a toolkit for "defining things to be done on collections of hosts" -- that naturally leads to a widely usable toolkit for deployments, provisioning, and general maintenance.

Shell escaping is challenging, in Cap right now because of the weird hybrid bastard mix of shell scripting and ruby scripting, I've toyed with the idea of providing something like:

on application_servers do
  in release_directory do
    if File.exists?('tmp/restart.txt')
      File.unlink('tmp/restart.txt')
    end
  end
end

In this example the File wouldn't be ::File but an instance of some Capistrano class that is working on remote files. This isn't unlike other libraries such as Rake which overload the File/Dir classes in such a way that it "does the right thing", of course one could always offer LocalFile = ::File, or allow people to reach out of the local namespace to reach ::File with just that natural syntax.

@carsomyr

@leehambley Per the DSL, here's what I think: Create it in a way that "bridges" the shell and Ruby worlds. I mean constructs like:

cd "foo" do
  do_stuff
end

... or alternatively:

cd "foo"

A syntax like this is familiar to Bash scripters because they pretty much know which commands are available. On the other hand, Rubyists know what it means when cd takes a block (the directory change will be reverted at the end), as opposed to when it doesn't. As for file tests, we can use the test command instead of overloading File. This would ensure a consistent shell script-like look and feel. What do you think?

@leehambley
Owner

@carsomyr I'm in total agreement, it might not be until the weekend before I can focus on writing my plans for Cap clearly, but I will summarise problems and planned solutions, and whatever else!

@rrichards

Juar curious, what is the plan for capistrano 3? Any ideas on when development will start and if it has already started is there a branch for this yet?

thanks!
Ryan

@leehambley
Owner

Ryan, watch this space, I'm finally in a position to work on that, and to take it in the direction that I want to. Vaporware no more. I'm finishing my last major, time-destroying project this week, then I'm out for vacation for a week (first time in 4 years!) and then I'll be back to focus on that more dilligently.

In the meantime I've started a mailing list at Mailchimp to collect the email addresses of those who may wish to follow the development in a more structured way, sign up here and I'll keep you all in the loop to the best of my ability.

@carsomyr

Hi non-diverse white male commenters, if there's one thing that I learned from the Brit Ruby fiasco, it's that you can co-opt the Gist mechanism to have long-running discussions! Shall I create one so that we can move the Cap v3 discussion there? Public or private?

@carsomyr

@leehambley Per your disagreement with my point §3.4, I was throwing it out there as an illustration of the difference between two well-known, similar projects: Chef and Puppet. The former uses a notification mechanism not unlike our before and after hooks, while the latter is a more formal DAG walking model to "bring a system into compliance". I wasn't necessarily recommending that we support both paradigms; however, we should decide on one and go with it in v3.

@leehambley
Owner
@mpalenciano

I'm just amazed and very disappointed that the deploy:web:{disable, enable} tasks were removed this way, just because somebody decides to do it (?). We have being using this for ages in our staging and production environments. What's gonna be next?

@tvdeyen, thanks for the gem.

amazing :(

@gicappa

I can live without this tasks but a warning and a proper deprecation time would have been appreciated.

@ghazel

It's been 6 months since the initial commit, and I was still bitten by this today. eycap calls enable, still: engineyard/eycap#38

Why hasn't this been reverted yet?

@leehambley
Owner
@Confusion

So you do not subscribe to semantic versioning and we can expect a minor release to contain backwards incompatibilities?

@leehambley
Owner

There will be no more releases in the 2.x branch. There is a gem which replaces this functionality, it has been broken long enough that many people have already worked around. There's nothing I can do about it now without upsetting at least 50% of the users.

@jrochkind
@tvdeyen
@Confusion

It seems you interpreted my question as a rhetorical one, to which I would expect the answer 'no'. I should have been clearer and have hedged the question a bit: I meant it as an honest question. I think it is entirely reasonable for a project not to subscribe to semantic versioning and to allow backwards incompatibilities in minor releases.

From the discussion above it isn't clear to me whether capistrano intends to adhere to semantic versioning. On the one hand releasing this commit is deemed a mistake, on the other hand it wasn't reverted, even though there was plenty of time to do that, starting from the first complaint, up to the moment the new gem was released. Hardly anyone depends on the HEAD of a project, as bundler and pinning projects to specific released gem versions has become the standard. Almost everyone will thus have been using the previous released gem. It thus seems to me a conscious decision to release a new gem with a different minor version that contained a backwards incompatibility. So as a result I don't have an entirely consistent picture of the intended versioning scheme and because I consider either way is reasonable, I have to ask which one it is. The only thing it changes is how closely we need to read the CHANGELOG between minor releases.

@leehambley
Owner

Alright, I'll capitulate I'll fix it this weekend. By way of some kind of fix it'd help me if between you, you could let me know precisely which versions should be yanked (if any) from Rubygems, and what it seems to be missing. I notice the last two dot-releases also weren't tagged, or at least the tags weren't pushed to GH.

I'll sort this out as soon as I can. I had a day to think about it, and I realised just because someone broke something, doesn't mean it shouldn't be fixed.

@tvdeyen (nice to run in to you on here, since we met in real life!) do you predict any problems with your gem tasks colliding with the original tasks?

Any other thoughts/feedback welcome, I'm going to give cap 2.x a day at the weekend to try and undo all the problems that have recently been introduced. Please, make make issues for anything else, this commit comment is already getting out of hand!

@tvdeyen

Hi @leehambley :)

No, I don't see any problems, since I just plucked the tasks out of capistrano and put them into a separate gem. The gem is a 1:1 replacement of the original tasks.

You should be able to include it in your gemspec, require it per default and everything should be fine. I'll craft you a little PR in a minute. Then this incidence should be gone in no time :)

Best Thomas

@leehambley
Owner
@tvdeyen
@leehambley
Owner
@tvdeyen
Please sign in to comment.
Something went wrong with that request. Please try again.