mirror of
https://github.com/capistrano/capistrano
synced 2023-03-27 23:21:18 -04:00
Commit this stuff before I lose it all
This commit is contained in:
commit
61aec364b2
26 changed files with 1094 additions and 0 deletions
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
_site
|
6
Gemfile
Normal file
6
Gemfile
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
source "https://rubygems.org"
|
||||||
|
|
||||||
|
gem "debugger"
|
||||||
|
gem "jekyll"
|
||||||
|
gem "redcarpet"
|
||||||
|
gem "git"
|
50
Gemfile.lock
Normal file
50
Gemfile.lock
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
GEM
|
||||||
|
remote: https://rubygems.org/
|
||||||
|
specs:
|
||||||
|
classifier (1.3.3)
|
||||||
|
fast-stemmer (>= 1.0.0)
|
||||||
|
colorator (0.1)
|
||||||
|
columnize (0.3.6)
|
||||||
|
commander (4.1.3)
|
||||||
|
highline (~> 1.6.11)
|
||||||
|
debugger (1.6.0)
|
||||||
|
columnize (>= 0.3.1)
|
||||||
|
debugger-linecache (~> 1.2.0)
|
||||||
|
debugger-ruby_core_source (~> 1.2.1)
|
||||||
|
debugger-linecache (1.2.0)
|
||||||
|
debugger-ruby_core_source (1.2.2)
|
||||||
|
directory_watcher (1.4.1)
|
||||||
|
fast-stemmer (1.0.2)
|
||||||
|
git (1.2.5)
|
||||||
|
highline (1.6.19)
|
||||||
|
jekyll (1.0.2)
|
||||||
|
classifier (~> 1.3)
|
||||||
|
colorator (~> 0.1)
|
||||||
|
commander (~> 4.1.3)
|
||||||
|
directory_watcher (~> 1.4.1)
|
||||||
|
kramdown (~> 1.0.2)
|
||||||
|
liquid (~> 2.3)
|
||||||
|
maruku (~> 0.5)
|
||||||
|
pygments.rb (~> 0.5.0)
|
||||||
|
safe_yaml (~> 0.7.0)
|
||||||
|
kramdown (1.0.2)
|
||||||
|
liquid (2.5.0)
|
||||||
|
maruku (0.6.1)
|
||||||
|
syntax (>= 1.0.0)
|
||||||
|
posix-spawn (0.3.6)
|
||||||
|
pygments.rb (0.5.0)
|
||||||
|
posix-spawn (~> 0.3.6)
|
||||||
|
yajl-ruby (~> 1.1.0)
|
||||||
|
redcarpet (2.2.2)
|
||||||
|
safe_yaml (0.7.1)
|
||||||
|
syntax (1.0.0)
|
||||||
|
yajl-ruby (1.1.0)
|
||||||
|
|
||||||
|
PLATFORMS
|
||||||
|
ruby
|
||||||
|
|
||||||
|
DEPENDENCIES
|
||||||
|
debugger
|
||||||
|
git
|
||||||
|
jekyll
|
||||||
|
redcarpet
|
7
_config.yml
Normal file
7
_config.yml
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
name: Capistrano
|
||||||
|
pygments: true
|
||||||
|
markdown: redcarpet
|
||||||
|
redcarpet:
|
||||||
|
extensions: ["no_intra_emphasis", "fenced_code_blocks", "autolink", "tables", "with_toc_data"]
|
||||||
|
table_of_contents:
|
||||||
|
dirs: [documentation]
|
28
_includes/footer.html
Normal file
28
_includes/footer.html
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
<div class="bottom-menu">
|
||||||
|
<div class="container">
|
||||||
|
<div class="row">
|
||||||
|
<div class="span2 brand">
|
||||||
|
<a href="http://capistranorb.com/" class="capistrano-logo"></a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="span8">
|
||||||
|
<ul class="bottom-links">
|
||||||
|
<li><a href="#fakelink">About Capistrano</a></li>
|
||||||
|
<li><a href="#fakelink">Contributing</a></li>
|
||||||
|
<li><a href="#fakelink">Releases</a></li>
|
||||||
|
<li><a href="#fakelink">Upgrading</a></li>
|
||||||
|
<li><a href="#fakelink">StackOverflow</a></li>
|
||||||
|
<li><a href="#fakelink">Mailing List</a></li>
|
||||||
|
<li><a href="#fakelink">Support</a></li>
|
||||||
|
<li><a href="#fakelink">Links</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="span2">
|
||||||
|
<ul class="bottom-icons">
|
||||||
|
<li><a href="#fakelink" class="fui-twitter"></a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
5
_includes/header.html
Normal file
5
_includes/header.html
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
<div class="header pure-u-1-1">
|
||||||
|
<a href="/" class="brand">
|
||||||
|
<img src="/images/CapistranoLogo.png" />
|
||||||
|
</a>
|
||||||
|
</div>
|
31
_includes/navigation.html
Normal file
31
_includes/navigation.html
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
<div class="pure-menu pure-menu-open">
|
||||||
|
<ul class="nav nav-list">
|
||||||
|
<li><a href="http://www.harrow.io/" class="advertisment"><span class="label label-important">New</span> Hosted Capistrano for Teams</a></li>
|
||||||
|
<li class="pure-menu-heading">Overview</li>
|
||||||
|
<li><a href="/documentation/overview/what-is-capistrano/">What is Capistrano?</a></li>
|
||||||
|
<li><a href="/documentation/overview/introductory-demo-video/">Introductory Demo Video</a></li>
|
||||||
|
<li class="pure-menu-heading">Getting Started</li>
|
||||||
|
<li><a href="/documentation/getting-started/installation/">Installation</a></li>
|
||||||
|
<li><a href="/documentation/getting-started/preparing-your-application/">Preparing Your Application</a></li>
|
||||||
|
<li><a href="/documentation/getting-started/authentication-and-authorisation/">Authentication & Authorisation</a></li>
|
||||||
|
<li><a href="/documentation/getting-started/cold-start/">Cold Start</a></li>
|
||||||
|
<li><a href="/documentation/getting-started/rollbacks/">Rollbacks</a></li>
|
||||||
|
<li class="pure-menu-heading">Troubleshooting</li>
|
||||||
|
<li><a href="/documentation/troubleshooting/authentication/">SCM (Git, SVN, etc) Authentication</a></li>
|
||||||
|
<li><a href="/documentation/troubleshooting/connectivity/">Connectivity</a></li>
|
||||||
|
<li><a href="/documentation/troubleshooting/gateway-servers/">Gateway Servers</a></li>
|
||||||
|
<li><a href="/documentation/troubleshooting/agent-forwarding/">Agent Forwarding</a></li>
|
||||||
|
<li><a href="/documentation/troubleshooting/sudo-password/">`sudo` Password</a></li>
|
||||||
|
<li><a href="/documentation/troubleshooting/rvm-rbenv-nvm/">RVM, `rbenv` And `nvm`</a></li>
|
||||||
|
<li class="pure-menu-heading">FAQ</li>
|
||||||
|
<li><a href="/documentation/faq/why-does-something-work-in-my-ssh-session-but-not-in-capistrano/">Why Does Something Work In An SSH Session, But Not In Capistrano</a></li>
|
||||||
|
<li><a href="/documentation/faq/should-i-use-capistrano-to-provision-my-servers/">Should I Use Capistrano To Provision My Servers?</a></li>
|
||||||
|
<li class="pure-menu-heading">Power Use-Cases</li>
|
||||||
|
<li><a href="/documentation/power-use-cases/integration-with-rake/">Integration With Rake</a></li>
|
||||||
|
<li><a href="/documentation/power-use-cases/driving-tools-such-as-chef-solo/">Driving Tools Such As <em>Chef Solo</em></a></li>
|
||||||
|
<li class="pure-menu-heading">Recent Announcements</li>
|
||||||
|
{% for post in site.posts %}
|
||||||
|
<li><a href="{{ post.url }}"><span class="post-date">{{ post.date | date_to_string }}</span> {{ post.title }}</a></li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
</div>
|
47
_layouts/default.html
Normal file
47
_layouts/default.html
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>{{ page.title }}</title>
|
||||||
|
<script type="text/javascript" src="//use.typekit.net/itm5ubu.js"></script>
|
||||||
|
<script type="text/javascript">try{Typekit.load();}catch(e){}</script>
|
||||||
|
<link href='http://fonts.googleapis.com/css?family=Open+Sans:400,300' rel='stylesheet' type='text/css'>
|
||||||
|
<link href='http://fonts.googleapis.com/css?family=Montserrat' rel='stylesheet' type='text/css'>
|
||||||
|
<link href='http://fonts.googleapis.com/css?family=Enriqueta' rel='stylesheet' type='text/css'>
|
||||||
|
<link href="http://vjs.zencdn.net/4.0.2/video-js.css" rel="stylesheet">
|
||||||
|
<script src="http://vjs.zencdn.net/4.0.2/video.js"></script>
|
||||||
|
<link rel="stylesheet" href="http://yui.yahooapis.com/pure/0.1.0/pure-min.css">
|
||||||
|
<link rel="stylesheet" href="/css/syntax.css">
|
||||||
|
<link rel="stylesheet" href="/css/capistrano.css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
{% include header.html %}
|
||||||
|
|
||||||
|
<div class="pure-g-r">
|
||||||
|
<div class="pure-u-1-3">
|
||||||
|
{% include navigation.html %}
|
||||||
|
</div>
|
||||||
|
<div class="pure-u-2-3">
|
||||||
|
<div class="content">
|
||||||
|
<h2>{{ page.title }}</h2>
|
||||||
|
{{ content }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!--<div class="container"> -->
|
||||||
|
<!-- <h1 class="title"><a href="/">{{ site.name }}</a></h1>-->
|
||||||
|
<!-- <a class="extra" href="/">home</a> -->
|
||||||
|
<!-- </div> -->
|
||||||
|
|
||||||
|
<!-- {{ content }} -->
|
||||||
|
|
||||||
|
<!--</div> [> /container <] -->
|
||||||
|
|
||||||
|
{% include footer.html %}
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
8
_layouts/post.html
Normal file
8
_layouts/post.html
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
---
|
||||||
|
layout: default
|
||||||
|
---
|
||||||
|
<p class="meta">{{ page.date | date_to_string }}</p>
|
||||||
|
|
||||||
|
<div id="post">
|
||||||
|
{{ content }}
|
||||||
|
</div>
|
1
_layouts/table_of_contents.html
Normal file
1
_layouts/table_of_contents.html
Normal file
|
@ -0,0 +1 @@
|
||||||
|
Why is this here?
|
32
_plugins/gitactivity.rb
Normal file
32
_plugins/gitactivity.rb
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
require 'git'
|
||||||
|
|
||||||
|
module Jekyll
|
||||||
|
class GitActivityTag < Liquid::Tag
|
||||||
|
|
||||||
|
def initialize(tag_name, text, tokens)
|
||||||
|
super
|
||||||
|
end
|
||||||
|
|
||||||
|
def render(context)
|
||||||
|
result = ""
|
||||||
|
g = Git.open(File.join(Dir.getwd, ".."))
|
||||||
|
|
||||||
|
index = 0
|
||||||
|
g.log.each do |log|
|
||||||
|
if(index < 10)
|
||||||
|
result << "<li>"
|
||||||
|
result << log.date.strftime("%d %b")
|
||||||
|
result << " - <a href='https://github.com/capistrano/capistrano-documentation/commit/"
|
||||||
|
result << log.sha
|
||||||
|
result << "/'>"
|
||||||
|
result << log.message
|
||||||
|
result << "</a></li>"
|
||||||
|
index += 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
"<ul>#{result}</ul>"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
Liquid::Template.register_tag('gitactivity', Jekyll::GitActivityTag)
|
30
_plugins/table_of_contents.rb
Normal file
30
_plugins/table_of_contents.rb
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
require 'git'
|
||||||
|
|
||||||
|
module Jekyll
|
||||||
|
class TableOfContentsTag < Liquid::Tag
|
||||||
|
def initialize(tag_name, text, tokens)
|
||||||
|
super
|
||||||
|
end
|
||||||
|
def render(context)
|
||||||
|
result = ""
|
||||||
|
g = Git.open(File.join(Dir.getwd, ".."))
|
||||||
|
|
||||||
|
index = 0
|
||||||
|
g.log.each do |log|
|
||||||
|
if(index < 10)
|
||||||
|
result << "<li>"
|
||||||
|
result << log.date.strftime("%d %b")
|
||||||
|
result << " - <a href='https://github.com/capistrano/capistrano-documentation/commit/"
|
||||||
|
result << log.sha
|
||||||
|
result << "/'>"
|
||||||
|
result << log.message
|
||||||
|
result << "</a></li>"
|
||||||
|
index += 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
"<ul>#{result}</ul>"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
Liquid::Template.register_tag('table_of_contents', Jekyll::TableOfContentsTag)
|
24
_posts/2013-05-18-welcome-to-jekyll.markdown
Normal file
24
_posts/2013-05-18-welcome-to-jekyll.markdown
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
---
|
||||||
|
layout: post
|
||||||
|
title: "Welcome to Jekyll!"
|
||||||
|
date: 2013-05-18 15:09:49
|
||||||
|
categories: jekyll update
|
||||||
|
---
|
||||||
|
|
||||||
|
You'll find this post in your `_posts` directory - edit this post and re-build (or run with the `-w` switch) to see your changes!
|
||||||
|
To add new posts, simply add a file in the `_posts` directory that follows the convention: YYYY-MM-DD-name-of-post.ext.
|
||||||
|
|
||||||
|
Jekyll also offers powerful support for code snippets:
|
||||||
|
|
||||||
|
{% highlight ruby %}
|
||||||
|
def print_hi(name)
|
||||||
|
puts "Hi, #{name}"
|
||||||
|
end
|
||||||
|
print_hi('Tom')
|
||||||
|
#=> prints 'Hi, Tom' to STDOUT.
|
||||||
|
{% endhighlight %}
|
||||||
|
|
||||||
|
Check out the [Jekyll docs][jekyll] for more info on how to get the most out of Jekyll. File all bugs/feature requests at [Jekyll's GitHub repo][jekyll-gh].
|
||||||
|
|
||||||
|
[jekyll-gh]: https://github.com/mojombo/jekyll
|
||||||
|
[jekyll]: http://jekyllrb.com
|
529
_posts/2013-06-01-release-announcement.markdown
Normal file
529
_posts/2013-06-01-release-announcement.markdown
Normal file
|
@ -0,0 +1,529 @@
|
||||||
|
---
|
||||||
|
layout: post
|
||||||
|
title: "Capistrano Version 3 Release Announcement"
|
||||||
|
date: 2013-06-01 00:00:00
|
||||||
|
---
|
||||||
|
|
||||||
|
After what seems like years of work, the Capistrano team (that's Tom and I)
|
||||||
|
are pleased to announce the first *major* release of Capistrano in almost 5
|
||||||
|
years.
|
||||||
|
|
||||||
|
The reasons behind the length of time between the last architectural overhaul
|
||||||
|
and this one are numerous, but it can be summrised to say that Capistrano is a
|
||||||
|
widely used tool, and when working around software deployment it's really a
|
||||||
|
question of downtime. If we had changed something significant in Capistrano we
|
||||||
|
could have taken a lot of sites offline, and made a lot of people very
|
||||||
|
unhappy. Until this point we haven't felt that the time has been ripe where
|
||||||
|
the benefits of a slightly rocky upgrade path are worth the risks of downtime.
|
||||||
|
|
||||||
|
It also hasn't helped historically that we've only just gotten to grips with
|
||||||
|
Ruby 1.9, and that Bundler's near ubuquity means that now it's trivial to lock
|
||||||
|
a Gem at a specific version. With other tools in the Ruby eco system it's
|
||||||
|
become easier for us to make significant changes to a tool upon which many
|
||||||
|
hundreds of thousands of people rely.
|
||||||
|
|
||||||
|
### Design Goals
|
||||||
|
|
||||||
|
We had a few goals for this release, in no particular order they were:
|
||||||
|
|
||||||
|
* **Get away from our own DSL solution.** Great DSL alternatives (Rake, Sake, Thor,
|
||||||
|
etc) are already widely used.
|
||||||
|
* **Better modularisation.** to enable people outside the Rails community to
|
||||||
|
benefit from Capistrano's *best-practice* workflow, and to enable people in
|
||||||
|
the Rails community to pick and choose support for components they use
|
||||||
|
(Database Migrations, Asset Pipeline, etc)
|
||||||
|
* **Easier Debugging.** A lot of problems with Capistrano come from weirdness
|
||||||
|
surrounding environmental issues around PTY vs non-TTY environments, login
|
||||||
|
and non-login shells not to mention *environment managers* such as rvm,
|
||||||
|
rbenv and nvm.
|
||||||
|
* **Speed.** We know that in a lot of environments speed of deploment is a
|
||||||
|
huge factor, since Rails introduced the *Asset Pipeline* it's not uncommon
|
||||||
|
for a deploy that formerly took 5 seconds now takes 5 minutes. This really
|
||||||
|
is mostly out of our control, but with improved support for parallelism,
|
||||||
|
rolling restarts we feel confident that things are bettwe not.
|
||||||
|
* **Applicability.** We've always maintained that Capistrano is a terrible
|
||||||
|
tool for system provisioning, and that more often than not servers are
|
||||||
|
better being setup with Chef, Puppet or similar, whilst we still agree with
|
||||||
|
that, the new features in Capistrano really lend themselves to integrating
|
||||||
|
with these kinds of tools.
|
||||||
|
|
||||||
|
### What's missing?
|
||||||
|
|
||||||
|
Before we get too carried away it's worth shortlisting the things that don't
|
||||||
|
exist in version three, *yet*.
|
||||||
|
|
||||||
|
* *Run Locally.* `run_locally` was always a bit of the poor relation in the
|
||||||
|
family, it didn't quite work the same way as other things, and I never liked
|
||||||
|
the idea that you were binding a tool that in principle should be cross
|
||||||
|
platform (Ruby, and Capistrano) to locally executing shell commands which
|
||||||
|
probably only work on POSIX-like operating systems. I hope that
|
||||||
|
`run_locally` will stay gone, and that as a community we can find better
|
||||||
|
ways of doing things that always relied on locally creating tarballs, or
|
||||||
|
writing configuration files, or similar.
|
||||||
|
* *SSH Gateway Support.* SSH Gateway support hasn't been implemented in
|
||||||
|
version three yet, I hope that this will be done soon. As I have no direct
|
||||||
|
need for it, I haven't the means to test it with a view to implementing it,
|
||||||
|
yet.
|
||||||
|
* *Mecurial, Subversion, and CVS Support.* These have been removed as we've
|
||||||
|
been able to implement the Git SCM in an incredibly neat way that isn't
|
||||||
|
compatible with the others. We wanted to break the cycle of always sticking
|
||||||
|
with the lowest common denominator, so we are **actively** looking for
|
||||||
|
people who are interested in contributing, or sharing expertise on the
|
||||||
|
*best-practice* way of speedily deploying from your respective choice of
|
||||||
|
source control.
|
||||||
|
* *`HOSTFILTER` ,`ROLEFILTER` and friends.* These have gone away because I
|
||||||
|
always felt they were indemic of a bad design desision about using
|
||||||
|
Environmental Variables. These will be coming back as flags passed to `cap`
|
||||||
|
on the CLI, and options that can be set on the Capistrano::Application Ruby
|
||||||
|
class.
|
||||||
|
* *Shell.* The shell has been removed temporarily pending a neater
|
||||||
|
implementation, we've got something that we are playing with internally, but
|
||||||
|
it needs better readline support, and some more controls around what to do
|
||||||
|
when things go badly on some servers, but not others.
|
||||||
|
* *Cold Deploy.* The `cap deploy:cold` is a really old legacy component,
|
||||||
|
orignally from the days of the `script/spinner` where deploying cold
|
||||||
|
(starting workers that weren't running), and deploying a *warm* system were
|
||||||
|
different (restarting existing worker pools, which wasn't fun!) By and large
|
||||||
|
these things have gone away, and it's time `deploy:cold` went away. It's
|
||||||
|
safe in every case we could find to call setup, and seed and other Rake
|
||||||
|
tasks without things blowing up, and that should be the approach we take.
|
||||||
|
Tasks on the server should be idempotent, and if something is called twice,
|
||||||
|
let it be.
|
||||||
|
* *Coloured Output.*✝ The capistrano-colours Gem was (fairly) recently merged
|
||||||
|
into Capistrano v2, this has gone away in favour of a IO streaming model
|
||||||
|
inspired by MiniTest/Pride. Read more below in new features.
|
||||||
|
|
||||||
|
### What's new?
|
||||||
|
|
||||||
|
Each section here really deserves it's own sub-heading as some of the new
|
||||||
|
features are awesome.
|
||||||
|
|
||||||
|
#### Rake Integration
|
||||||
|
|
||||||
|
We have moved away from our own DSL implemenation to implement Capistrano as a
|
||||||
|
Rake application.
|
||||||
|
|
||||||
|
Rake has always supported being sub-classed, so to speak as a
|
||||||
|
*sub-application*; it is however poorly documented. By subclassing
|
||||||
|
Rake::Application one can specify what the *Rakefile* should look like, where
|
||||||
|
to search for it, and how to load other *Rakefiles*.
|
||||||
|
|
||||||
|
The *Rake* DSL is widely used, well known and very powerful. As Rake is
|
||||||
|
essentially a dependency resolution system, it offers a lot of nice ways to,
|
||||||
|
for example build a tarball as a dependency of uploading it and deploying it.
|
||||||
|
|
||||||
|
This has allowed us to do away with the *copy* strategy all together, as it
|
||||||
|
can now be implemented from scratch in fewer than ten lines of code. You can
|
||||||
|
check out the [replicating the copy strategy][] screencast and acompanying
|
||||||
|
documentation if you want to explore that any further.
|
||||||
|
|
||||||
|
The guiding principle is dependency resolution, and interoperability with
|
||||||
|
other tools, for example:
|
||||||
|
|
||||||
|
{% highlight ruby %}
|
||||||
|
# No description, this is an internal method
|
||||||
|
task :notify do
|
||||||
|
this_release_tag = sh("git describe --abbrev=0 --tags")
|
||||||
|
last_ten_commits = sh("git log #{this_release_tag}~10..#{this_release_tag}")
|
||||||
|
Mail.deliver do
|
||||||
|
to "team@example.com"
|
||||||
|
subject "Releasing #{this_release_tag} Now!"
|
||||||
|
body last_ten_commits
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
namespace :deploy
|
||||||
|
task default: :notify
|
||||||
|
end
|
||||||
|
{% endhighlight %}
|
||||||
|
|
||||||
|
The last three lines rely on Rake's additive task declaration, by redefining the
|
||||||
|
`deploy:default` task by adding another dependency. Rake will automatically
|
||||||
|
resolve this dependency at Runtime, mailing the recent changelog to your team,
|
||||||
|
assuming everything is setup correctly.
|
||||||
|
|
||||||
|
#### Built In Stage Support
|
||||||
|
|
||||||
|
#### Parallelism
|
||||||
|
|
||||||
|
In former versions of Capistrano there was a *parallel* option to run
|
||||||
|
different tasks differently on groups of servers, it looked something like
|
||||||
|
this:
|
||||||
|
|
||||||
|
{% highlight ruby %}
|
||||||
|
task :restart do
|
||||||
|
parallel do |session|
|
||||||
|
session.when "in?(:app)", "/u/apps/social/script/restart-mongrel"
|
||||||
|
session.when "in?(:web)", "/u/apps/social/script/restart-apache"
|
||||||
|
session.else "echo nothing to do"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
{% endhighlight %}
|
||||||
|
|
||||||
|
This always felt a little unclean, and indeed it's a hack that was originally
|
||||||
|
implemeted to facilitate rolling deployments at a large German firm by a
|
||||||
|
couple of freelancers who were consulting with them. (Hint, one of those guys
|
||||||
|
went on to found Travis-CI!)
|
||||||
|
|
||||||
|
The equivilent code in under Capistrano v3 would look like this:
|
||||||
|
|
||||||
|
{% highlight ruby %}
|
||||||
|
task :restart do
|
||||||
|
on :all, in: :parallel do |host|
|
||||||
|
if host.roles.include?(:app)
|
||||||
|
execute "/u/apps/social/script/restart-mongrel"
|
||||||
|
elsif host.roles.include?(:web)
|
||||||
|
execute "/u/apps/social/script/restart-web"
|
||||||
|
else
|
||||||
|
info "Nothing to do for #{host} with roles #{host.properties.roles}."
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
{% endhighlight %}
|
||||||
|
|
||||||
|
The second block of code, that representing the new Rake derived DSL and
|
||||||
|
demonstrating how to use the parallel execution mode is a little longer, but I
|
||||||
|
think it's clearer, more idiomatic Ruby code which relies less on an intimate
|
||||||
|
knowledge of how the Capistrano DSL happens to work. It also hints at the
|
||||||
|
built-in logging subsystem, keep reading to learn more.
|
||||||
|
|
||||||
|
Other modes for parallelism include:
|
||||||
|
|
||||||
|
{% highlight ruby %}
|
||||||
|
on :all, in: :groups, max: 3, wait: 5 do
|
||||||
|
# Take all servers, in groups of three which execute in parallel
|
||||||
|
# wait five seconds between groups of servers.
|
||||||
|
# This is perfect for rolling restarts
|
||||||
|
end
|
||||||
|
|
||||||
|
on :all, in: :sequence, wait: 15 do
|
||||||
|
# This takes all servers, in sequence and waits 15 seconds between
|
||||||
|
# each server, this might be perfect if you are afraid about
|
||||||
|
# overloading a shared resource, or want to defer the asset compilation
|
||||||
|
# over your cluster owing to worries about load
|
||||||
|
end
|
||||||
|
|
||||||
|
on :all, in: :parallel do
|
||||||
|
# This will simply try and execute the commands contained within
|
||||||
|
# the block in parallel on all servers. This might be perfect for kicking
|
||||||
|
# off something like a Git checkout or similar.
|
||||||
|
end
|
||||||
|
{% endhighlight %}
|
||||||
|
|
||||||
|
The internal tasks, for standard deploy recipes make use of all of these as is
|
||||||
|
appropriate for the normal case, no need to be afraid of scary slow deploys
|
||||||
|
again!
|
||||||
|
|
||||||
|
#### Streaming IO
|
||||||
|
|
||||||
|
This IO streaming model means that results from commands, the commands
|
||||||
|
themselves and any other arbitrary output are sent as objects to a class with
|
||||||
|
an `IO`ish interface, the class knows what to do with these things. There's a
|
||||||
|
*progress* formatter which prints dots for each command that is called, as
|
||||||
|
well as a *pretty* formatter which prints the full command, it's output on
|
||||||
|
standard out and standard error, as well as the final return status. It would
|
||||||
|
be trivial to implement HTML formatters, or formatters that reported to your
|
||||||
|
IRC room, or to email. I look forward to seeing more of these cropping up in
|
||||||
|
the community.
|
||||||
|
|
||||||
|
#### Host Definition Access
|
||||||
|
|
||||||
|
If you didn't skim over the *Parallism* section above, you might have noticed we
|
||||||
|
did something clever that wasn't possible in Capistrano v2; we accessed the
|
||||||
|
`host` inside the execution block.
|
||||||
|
|
||||||
|
For a lot of reasons in Capistrano v2 is wasn't possible to do this, the block
|
||||||
|
was essentially evaluated once and called verbatim on each host. This lead to
|
||||||
|
disappointing missing features such as not being able to pull the host list
|
||||||
|
out of Capistrano and examine the roles to do something like controlling chef
|
||||||
|
solo, or similar.
|
||||||
|
|
||||||
|
In Capistrano v3 the `host` object is the same object that is created when a
|
||||||
|
server is defined, and is internally used, for example to pass to an ERB
|
||||||
|
template for rendering a last-deploy message that is dumped onto each server
|
||||||
|
after a successful deployment. The last deploy log includes everything
|
||||||
|
Capistrano knew about that server during the deployment.
|
||||||
|
|
||||||
|
> Users of Capistrano v2 may be familiar with the perenial `cap deploy:cleanup`
|
||||||
|
problem which came to light when servers differed in their old releases list,
|
||||||
|
imagine a scenario with two servers, one has been your bread-and-butter since
|
||||||
|
you launched, it has hundreds of old releases from all your wonderful deploys
|
||||||
|
over the months or years. The second server has been in the cluster for about
|
||||||
|
a month, it didn't quite slot-in cleanly, so the list of old releases looks a
|
||||||
|
bit weird, you deleted a few by hand, and anyway there might only be ten-or-so
|
||||||
|
releases there.
|
||||||
|
|
||||||
|
> Now imagine that you call `cap deploy:cleanup`, old `capture()`
|
||||||
|
implementations silently only ran on the first server that matched the
|
||||||
|
properties defined, so server one returned a list of ~95 old timestamped
|
||||||
|
release directories. Next Capistrano v2 would call `rm -rf
|
||||||
|
release1..release95` on **both** servers, causing server two to err our, and
|
||||||
|
leaving an undefined state on server one, as Capistrano would simply hang up
|
||||||
|
both connections.
|
||||||
|
|
||||||
|
This cleanup routine can now be better implemented as follows (which is
|
||||||
|
actually more or less the actual implenetation in the the new Gem):
|
||||||
|
|
||||||
|
{% highlight ruby %}
|
||||||
|
desc "Cleanup all old releases (keeps #{fetch(:releases_to_keeo_on_cleanup)}
|
||||||
|
old releases"
|
||||||
|
task :cleanup do
|
||||||
|
keep_releases = fetch(:releases_to_keeo_on_cleanup)
|
||||||
|
releases = capture(:ls, fetch(:releases_directory))
|
||||||
|
release_to_delete = releases.sort_by { |r| rn.to_i }.slice(1..-(keep_releases + 1))
|
||||||
|
releases_to_delete.each do |r|
|
||||||
|
execute :rm, fetch(:releases_directory).join(r)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
{% endhighlight %}
|
||||||
|
|
||||||
|
Some handy things to note here are that both server one and server two in our
|
||||||
|
contrived example will both evaluate that independently, and when both servers
|
||||||
|
are finished removing old releases the `task :cleanup` block will have
|
||||||
|
finished.
|
||||||
|
|
||||||
|
Also in Capistrano v3 most path varaibles are [`Pathname`] objects, so they natively
|
||||||
|
respond to things like `#basename`, `#expand_path`, `#join` and similar.
|
||||||
|
|
||||||
|
**Warning:** `#expand_path` probably won't do what you expect, it will execute
|
||||||
|
on your *workstation* machine, and not on the remote host, so it's possible
|
||||||
|
that it will return an error in the case of paths which exist remotely but not
|
||||||
|
locally.
|
||||||
|
|
||||||
|
#### Host Properties
|
||||||
|
|
||||||
|
As the `host` object is now available to the task blocks, it made sense to make
|
||||||
|
it possible to store arbitrarty values against them.
|
||||||
|
|
||||||
|
Enter `host.properties`. This is a simple [*OpenStruct*][] which can be used to
|
||||||
|
store any additional properties which are important for your application.
|
||||||
|
|
||||||
|
An example of it's usage might be:
|
||||||
|
|
||||||
|
{% highlight ruby %}
|
||||||
|
h = SSHKit::Host.new 'example.com'
|
||||||
|
h.properties.roles ||= %i{wep app}
|
||||||
|
{% endhighlight %}
|
||||||
|
|
||||||
|
#### More Expressive Command Language
|
||||||
|
|
||||||
|
In Capistrano v2, it wasn't uncommon to find commands such as:
|
||||||
|
|
||||||
|
{% highlight ruby %}
|
||||||
|
task :precompile, :roles => lambda { assets_role }, :except => { :no_release => true } do
|
||||||
|
run <<-CMD.compact
|
||||||
|
cd -- #{latest_release} &&
|
||||||
|
RAILS_ENV=#{rails_env.to_s.shellescape} #{asset_env} #{rake} assets:precompile
|
||||||
|
CMD
|
||||||
|
end
|
||||||
|
{% endhighlight %}
|
||||||
|
|
||||||
|
In Capistrano v3 this looks more like this:
|
||||||
|
|
||||||
|
{% highlight ruby %}
|
||||||
|
task :precompile do
|
||||||
|
on :sprockets_asset_host, reject: lambda { |h| h.properties.no_release } do
|
||||||
|
within fetch(:latest_release_directory)
|
||||||
|
with rails_env: fetch(:rails_env) do
|
||||||
|
execute :rake, 'assets:precompile'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
{% endhighlight %}
|
||||||
|
|
||||||
|
Again, with other examples this format is a little longer, but much more
|
||||||
|
expressive, and all the nightmare of shell escaping is handled interally for
|
||||||
|
you, environmental variables are capitalised and applied at the correct point
|
||||||
|
(i.e between the `cd` and `rake` calls in this case).
|
||||||
|
|
||||||
|
Other options here include `as :a_user` and
|
||||||
|
|
||||||
|
#### Better *magic* Variable Support
|
||||||
|
|
||||||
|
In Capistrano v2 there were certain bits of magic where if calling a variable
|
||||||
|
and NoMethodError would have been raised (for example the
|
||||||
|
`latest_release_directory` varaible). This variable never existed on the
|
||||||
|
global namespace, as a fall-back the list of `set()` variables would be
|
||||||
|
consulted.
|
||||||
|
|
||||||
|
This magic lead to times when people were not recognising that magic variables
|
||||||
|
were even being used. The magic variable system of Capistrano v2 did also
|
||||||
|
include a way to `fetch(:some_variable, 'with a default value')` incase the
|
||||||
|
variable might not be set already, but it wasn't widely used, and more often
|
||||||
|
than not people just used things like `latest_release_directory` never knowing
|
||||||
|
that behind the scenes an exception was raised, then rescued, and that
|
||||||
|
`:latest_release_directory` in the variable map was actually a continuation
|
||||||
|
that was evaluated the first time it was used, and the value then cached until
|
||||||
|
the end of the script.
|
||||||
|
|
||||||
|
The system has now 100% less magic. If you set a variable using `set()`, it
|
||||||
|
can be fetched with `fetch()`, if the value you set into the variable responds
|
||||||
|
to `#call` then it will be executed in the current context whenever it is
|
||||||
|
used, the values will not be cached, unless your continuation does some
|
||||||
|
explicit caching. *Again, we are favoring clarity over micro optimisation*.
|
||||||
|
|
||||||
|
#### SSHKit
|
||||||
|
|
||||||
|
Many of the new features in Capistrano whch relate to logging, formatting,
|
||||||
|
SSH, connection management and pooling, parallism, batch execution and more
|
||||||
|
are from a library that fell out of the Capistrano v3 development process.
|
||||||
|
|
||||||
|
[*SSHKit*][] is a lower level toolkit, a level higher than *Net::SSH*, still
|
||||||
|
but lacking the roles, environments, rollbacks and other higher level features
|
||||||
|
from Capistrano.
|
||||||
|
|
||||||
|
SSHkit is ideal for use if you need to just connect to a machine and run some
|
||||||
|
arbitrary command, for example:
|
||||||
|
|
||||||
|
{% highlight ruby %}
|
||||||
|
# Rakefile
|
||||||
|
require 'sshkit'
|
||||||
|
desc "Check the uptime of example.com"
|
||||||
|
task :uptime do |h|
|
||||||
|
execute :uptime
|
||||||
|
end
|
||||||
|
{% endhighlight %}
|
||||||
|
|
||||||
|
There is much more than can be done with SSHKit, and we have quite an
|
||||||
|
extensive [list of examples][]. For the most part with Capistrano v3, anything
|
||||||
|
that happens inside of an `on()` block is happening in SSHkit, and the
|
||||||
|
documentation from that library is the place to go to find more information.
|
||||||
|
|
||||||
|
#### Command Mapping
|
||||||
|
|
||||||
|
This is another feature from SSHKit, designed to remove a little ambiguity
|
||||||
|
from preceedings, there is a so-called command map for commands.
|
||||||
|
|
||||||
|
When executing something like:
|
||||||
|
|
||||||
|
{% highlight ruby %}
|
||||||
|
execute "git clone ........ ......."
|
||||||
|
{% endhighlight %}
|
||||||
|
|
||||||
|
The command is passed through to the remote server *completely unchanged*.
|
||||||
|
This includes the options which might be set, such as user, directory, and
|
||||||
|
environmental variables. **This is by design.** This feature is designed to
|
||||||
|
allow people to write non-trivial commands in [heredocs][] when the need
|
||||||
|
arises.
|
||||||
|
|
||||||
|
The idiomatic way to write that command in Capistrano v3 is to use the
|
||||||
|
separated variadaric method to specify the command:
|
||||||
|
|
||||||
|
{% highlight ruby %}
|
||||||
|
execute :git, :clone, "........", "......."
|
||||||
|
{% endhighlight %}
|
||||||
|
|
||||||
|
In this way the *command map* is consulted, the command map maps all unknown
|
||||||
|
commands (which in this case is `git`, the rest of the line are *arguments* to
|
||||||
|
`git` ) are mapped to `/usr/bin/env ...`. Meaning that this command would be
|
||||||
|
expanded to `/usr/bin/env git clone ...... ......` which is what happens when
|
||||||
|
`git` is called without a full path, the `env` program is consulted (perhaps
|
||||||
|
indirectly) to determine which `git` to run.
|
||||||
|
|
||||||
|
Commands such as `rake` and `rails` are often better prefixed by `bundle
|
||||||
|
exec`, and in this case could be mapped to:
|
||||||
|
|
||||||
|
{% highlight ruby %}
|
||||||
|
SSHKit.config.command_map[:rake] = "bundle exec rake"
|
||||||
|
SSHKit.config.command_map[:rails] = "bundle exec rails"
|
||||||
|
{% endhighlight %}
|
||||||
|
|
||||||
|
There can also be a lamda or Proc applied in place of the mapping like so:
|
||||||
|
|
||||||
|
{% highlight ruby %}
|
||||||
|
SSHKit.config.command_map = Hash.new do |hash, key|
|
||||||
|
if %i{rails rake bundle clockwork heroku}.include?(key.to_sym)
|
||||||
|
hash[key] = "/usr/bin/env bundle exec #{key}"
|
||||||
|
else
|
||||||
|
hash[key] = "/usr/bin/env #{key}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
{% endhighlight %}
|
||||||
|
|
||||||
|
Between these two options there should be quite powerful options to map
|
||||||
|
commands in your environment without having to override internal tasks from
|
||||||
|
Capistrano just because a path is different, or a binary has a different name.
|
||||||
|
|
||||||
|
This can also be *slightly* abused in environments where *shim* executables
|
||||||
|
are used, for example `rbenv` *wrappers*:
|
||||||
|
|
||||||
|
{% highlight ruby %}
|
||||||
|
SSHKit.config.command_map = Hash.new do |hash, key|
|
||||||
|
if %i{rails rake bundle clockwork heroku}.include?(key.to_sym)
|
||||||
|
hash[key] = "/usr/bin/env myproject_bundle exec myproject_#{key}"
|
||||||
|
else
|
||||||
|
hash[key] = "/usr/bin/env #{key}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
{% endhighlight %}
|
||||||
|
|
||||||
|
The above assumes that you have done something like `rbenv wrapper default
|
||||||
|
myproject` which creates wrapper binaries which correctly set up the Ruby
|
||||||
|
environment without requiring an interactive login shell.
|
||||||
|
|
||||||
|
#### Testing
|
||||||
|
|
||||||
|
The old test suite for Capistrano was purely unit tests, and didn't cover a
|
||||||
|
wide varity of problem cases, specifically nothing in the `deploy.rb` (that is
|
||||||
|
the actual *deployment* code) was tested at all; because of having our own DSL
|
||||||
|
implementation, and other slightly odd design points, it was painful to test
|
||||||
|
the actual *recipes*.
|
||||||
|
|
||||||
|
Testing has been a focus of Capistrano v3. The *integration* test suite uses
|
||||||
|
Vagrant to boot a machine, configures certain scenarios using portable shell
|
||||||
|
script, and then executes commands against them, deploying common
|
||||||
|
configurations to typical Linux systems. This is slow to execute, but offers
|
||||||
|
stronger guarantees that nothing is broken that we've ever been able to give
|
||||||
|
before.
|
||||||
|
|
||||||
|
Capistrano v3 also offers a possibility to swap out backend implementations.
|
||||||
|
This is interesting because for the purpose of testing your *own* recipes you
|
||||||
|
can use a *printer* backend, and verify that the output matched what you
|
||||||
|
expected, or use a stubbed backend upon which you can verify that calls were
|
||||||
|
made, or not made as expected.
|
||||||
|
|
||||||
|
#### Arbitrary Logging
|
||||||
|
|
||||||
|
Capistrano exposes the methods `debug()`, `info()`, `warn()`, `error()` and
|
||||||
|
`fatal()` inside of `on()` blocks which can be used to log using the existing
|
||||||
|
logging infrastructure and streaming IO formatters:
|
||||||
|
|
||||||
|
{% highlight ruby %}
|
||||||
|
on hosts do |host|
|
||||||
|
f = '/some/file'
|
||||||
|
if test("[ -d #{f} ]")
|
||||||
|
execute :touch, f
|
||||||
|
else
|
||||||
|
info "#{f} already exists on #{host}!"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
{% endhighlight %}
|
||||||
|
|
||||||
|
### Upgrading
|
||||||
|
|
||||||
|
The best place to go here is the [upgrading documentation][] to get deeper
|
||||||
|
into the specifics.
|
||||||
|
|
||||||
|
The simple version is to say that there is *no **direct** upgrade path*,
|
||||||
|
versions two and three are incompatible.
|
||||||
|
|
||||||
|
This is partly by design, the old DSL was imprecise in places that would have
|
||||||
|
made doing the right thing in most cases tricky, we opted to invest in more
|
||||||
|
features and better reliability than investing in keeping a backwards
|
||||||
|
compatible API.
|
||||||
|
|
||||||
|
There are a number of *gotchas* listed below, but the main points are the new
|
||||||
|
names of the built-in roles, as well as that by default Capistrano v3 is
|
||||||
|
platform agnostic, if you need Rails support, for migrations, asset pipeline
|
||||||
|
and such like, then it's required to `require` the support files.
|
||||||
|
|
||||||
|
### Gotchas
|
||||||
|
|
||||||
|
#### Rake DSL Is Additive
|
||||||
|
|
||||||
|
In Capistrano v2 if you re-define a task then it replaces the original
|
||||||
|
implemetation, this has been used by people to replace internal tasks
|
||||||
|
piecemeal with their own implementations
|
||||||
|
|
||||||
|
#### `sudo` Behaviour
|
4
changes.html
Normal file
4
changes.html
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
---
|
||||||
|
layout: default
|
||||||
|
title: "Recent Site Changes"
|
||||||
|
---
|
66
css/capistrano.css
Normal file
66
css/capistrano.css
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
a {
|
||||||
|
text-decoration: none;
|
||||||
|
color: #52C1DB;
|
||||||
|
}
|
||||||
|
|
||||||
|
body, p, a {
|
||||||
|
font-family: 'Open-Sans', sans-serif;
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
}
|
||||||
|
|
||||||
|
p, h1, h2, h3, h4, h5, h6 {
|
||||||
|
color: #1C1B39;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header {
|
||||||
|
height: 195px;
|
||||||
|
background-color: #1C1B39;
|
||||||
|
background-image: url('/images/CapistranoGraphicWireframe.png');
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-size: 275px;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header a {
|
||||||
|
color: #52C1DB;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre {
|
||||||
|
margin: 1.3em 0 1em;
|
||||||
|
padding: 1.3em;
|
||||||
|
}
|
||||||
|
|
||||||
|
code, kbd, pre, samp {
|
||||||
|
font-family: 'droid-sans-mono', monospace, serif;
|
||||||
|
background-color: rgb(250, 250, 250);
|
||||||
|
}
|
||||||
|
|
||||||
|
.header a.brand img {
|
||||||
|
margin: 6.5em auto auto 7em;
|
||||||
|
width: 300px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1, h2, h3, h4, h5 h6 {
|
||||||
|
font-family: 'Enriqueta', serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
.post-date {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 36pt;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
font-size: 18pt;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav.nav-list {
|
||||||
|
border-top: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content {
|
||||||
|
margin: 1.3em 0 1em;
|
||||||
|
padding: 1.3em;
|
||||||
|
}
|
60
css/syntax.css
Normal file
60
css/syntax.css
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
.highlight { background: #ffffff; }
|
||||||
|
.highlight .c { color: #999988; font-style: italic } /* Comment */
|
||||||
|
.highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */
|
||||||
|
.highlight .k { font-weight: bold } /* Keyword */
|
||||||
|
.highlight .o { font-weight: bold } /* Operator */
|
||||||
|
.highlight .cm { color: #999988; font-style: italic } /* Comment.Multiline */
|
||||||
|
.highlight .cp { color: #999999; font-weight: bold } /* Comment.Preproc */
|
||||||
|
.highlight .c1 { color: #999988; font-style: italic } /* Comment.Single */
|
||||||
|
.highlight .cs { color: #999999; font-weight: bold; font-style: italic } /* Comment.Special */
|
||||||
|
.highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */
|
||||||
|
.highlight .gd .x { color: #000000; background-color: #ffaaaa } /* Generic.Deleted.Specific */
|
||||||
|
.highlight .ge { font-style: italic } /* Generic.Emph */
|
||||||
|
.highlight .gr { color: #aa0000 } /* Generic.Error */
|
||||||
|
.highlight .gh { color: #999999 } /* Generic.Heading */
|
||||||
|
.highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */
|
||||||
|
.highlight .gi .x { color: #000000; background-color: #aaffaa } /* Generic.Inserted.Specific */
|
||||||
|
.highlight .go { color: #888888 } /* Generic.Output */
|
||||||
|
.highlight .gp { color: #555555 } /* Generic.Prompt */
|
||||||
|
.highlight .gs { font-weight: bold } /* Generic.Strong */
|
||||||
|
.highlight .gu { color: #aaaaaa } /* Generic.Subheading */
|
||||||
|
.highlight .gt { color: #aa0000 } /* Generic.Traceback */
|
||||||
|
.highlight .kc { font-weight: bold } /* Keyword.Constant */
|
||||||
|
.highlight .kd { font-weight: bold } /* Keyword.Declaration */
|
||||||
|
.highlight .kp { font-weight: bold } /* Keyword.Pseudo */
|
||||||
|
.highlight .kr { font-weight: bold } /* Keyword.Reserved */
|
||||||
|
.highlight .kt { color: #445588; font-weight: bold } /* Keyword.Type */
|
||||||
|
.highlight .m { color: #009999 } /* Literal.Number */
|
||||||
|
.highlight .s { color: #d14 } /* Literal.String */
|
||||||
|
.highlight .na { color: #008080 } /* Name.Attribute */
|
||||||
|
.highlight .nb { color: #0086B3 } /* Name.Builtin */
|
||||||
|
.highlight .nc { color: #445588; font-weight: bold } /* Name.Class */
|
||||||
|
.highlight .no { color: #008080 } /* Name.Constant */
|
||||||
|
.highlight .ni { color: #800080 } /* Name.Entity */
|
||||||
|
.highlight .ne { color: #990000; font-weight: bold } /* Name.Exception */
|
||||||
|
.highlight .nf { color: #990000; font-weight: bold } /* Name.Function */
|
||||||
|
.highlight .nn { color: #555555 } /* Name.Namespace */
|
||||||
|
.highlight .nt { color: #000080 } /* Name.Tag */
|
||||||
|
.highlight .nv { color: #008080 } /* Name.Variable */
|
||||||
|
.highlight .ow { font-weight: bold } /* Operator.Word */
|
||||||
|
.highlight .w { color: #bbbbbb } /* Text.Whitespace */
|
||||||
|
.highlight .mf { color: #009999 } /* Literal.Number.Float */
|
||||||
|
.highlight .mh { color: #009999 } /* Literal.Number.Hex */
|
||||||
|
.highlight .mi { color: #009999 } /* Literal.Number.Integer */
|
||||||
|
.highlight .mo { color: #009999 } /* Literal.Number.Oct */
|
||||||
|
.highlight .sb { color: #d14 } /* Literal.String.Backtick */
|
||||||
|
.highlight .sc { color: #d14 } /* Literal.String.Char */
|
||||||
|
.highlight .sd { color: #d14 } /* Literal.String.Doc */
|
||||||
|
.highlight .s2 { color: #d14 } /* Literal.String.Double */
|
||||||
|
.highlight .se { color: #d14 } /* Literal.String.Escape */
|
||||||
|
.highlight .sh { color: #d14 } /* Literal.String.Heredoc */
|
||||||
|
.highlight .si { color: #d14 } /* Literal.String.Interpol */
|
||||||
|
.highlight .sx { color: #d14 } /* Literal.String.Other */
|
||||||
|
.highlight .sr { color: #009926 } /* Literal.String.Regex */
|
||||||
|
.highlight .s1 { color: #d14 } /* Literal.String.Single */
|
||||||
|
.highlight .ss { color: #990073 } /* Literal.String.Symbol */
|
||||||
|
.highlight .bp { color: #999999 } /* Name.Builtin.Pseudo */
|
||||||
|
.highlight .vc { color: #008080 } /* Name.Variable.Class */
|
||||||
|
.highlight .vg { color: #008080 } /* Name.Variable.Global */
|
||||||
|
.highlight .vi { color: #008080 } /* Name.Variable.Instance */
|
||||||
|
.highlight .il { color: #009999 } /* Literal.Number.Integer.Long */
|
86
documentation/getting-started/installation/index.markdown
Normal file
86
documentation/getting-started/installation/index.markdown
Normal file
|
@ -0,0 +1,86 @@
|
||||||
|
---
|
||||||
|
title: Installation
|
||||||
|
layout: default
|
||||||
|
---
|
||||||
|
|
||||||
|
Capistrano is bundled as a Ruby Gem. **It requires Ruby 1.9 or newer.**
|
||||||
|
|
||||||
|
Capistrano can be installed as a standalone Gem, or bundled into your
|
||||||
|
application.
|
||||||
|
|
||||||
|
<div class="alert">
|
||||||
|
It is recommended to fix the version number when using Capistrano, and is
|
||||||
|
therefore recommended to use an appropriate bundler.
|
||||||
|
</div>
|
||||||
|
|
||||||
|
### General Usage
|
||||||
|
|
||||||
|
The following commands will clone Capistrano at the latest `v3` revision, and
|
||||||
|
will build the gem and install it locally. **The Gem is not yet availalble via
|
||||||
|
Rubygems.org.**
|
||||||
|
|
||||||
|
{% highlight bash %}
|
||||||
|
$ git clone -b v3 https://github.com/capistrano/capistrano.git
|
||||||
|
$ cd capistrano
|
||||||
|
$ gem build *.gemspec
|
||||||
|
$ gem install *.gem
|
||||||
|
{% endhighlight %}
|
||||||
|
|
||||||
|
### Usage in a Rails project
|
||||||
|
|
||||||
|
Add the following lines to the Gemfile, to the group `:development` ideally.
|
||||||
|
|
||||||
|
{% highlight ruby %}
|
||||||
|
group :development do
|
||||||
|
gem 'capistrano-rails', github: 'capistrano/capistrano-rails', branch: 'v3'
|
||||||
|
end
|
||||||
|
{% endhighlight %}
|
||||||
|
|
||||||
|
There will be a Gem released via [rubygems.org][rubygems], but as most people
|
||||||
|
are still using Capistrano v2.x, the v3 release will not be pushed to
|
||||||
|
[rubygems.org][rubygems] just yet give people a chance to lock their version
|
||||||
|
in their `Gemfile`.
|
||||||
|
|
||||||
|
The *Capistrano-Rails* Gem includes extras specifically designed for Ruby on
|
||||||
|
Rails, specifically:
|
||||||
|
|
||||||
|
* Asset Pipeline Support
|
||||||
|
* Gem Bundler Support
|
||||||
|
* Database Migration Support
|
||||||
|
|
||||||
|
The documentation for these components can be found in
|
||||||
|
[their][capistrano-rails-asset-pipeline-readme],
|
||||||
|
[respective][capistrano-rails-gem-bundler-readme],
|
||||||
|
[READMEs][capistrano-rails-database-migrations-readme]. However for the most
|
||||||
|
part, to get the best, and most sensible results, simply `require` these
|
||||||
|
files:
|
||||||
|
|
||||||
|
{% highlight ruby %}
|
||||||
|
require 'capistrano/rails/assets'
|
||||||
|
require 'capistrano/rails/gem-bundler'
|
||||||
|
require 'capistrano/rails/database-migrations'
|
||||||
|
{% endhighlight %}
|
||||||
|
|
||||||
|
<div class="alert alert-info">
|
||||||
|
<h5>Help! I was using Capistrano `v2.x` and I didn't want to upgrade!</h5>
|
||||||
|
|
||||||
|
If you are using Capistrano `v2.x.x` and have also installed Capistrano `v3`
|
||||||
|
by mistake, then you can lock your Gem version for Capistrano at something
|
||||||
|
like:
|
||||||
|
|
||||||
|
{% highlight ruby %}
|
||||||
|
gem 'capistrano', '~> 2.15' # Or whatever patch release you are using
|
||||||
|
{% endhighlight %}
|
||||||
|
|
||||||
|
This is the [pessimistic operator][rubygems-pessimistic-operator] which
|
||||||
|
installs the closest matching version, at the time of writing this would
|
||||||
|
install `2.15.4`, and any other point-release in the `2.15.x` family without
|
||||||
|
the risk of accidentally upgrading to `v3`.
|
||||||
|
</div>
|
||||||
|
|
||||||
|
--
|
||||||
|
[rubygems]: http://rubygems.org/
|
||||||
|
[rubygems-pessimistic-operator]: http://docs.rubygems.org/read/chapter/16#page74
|
||||||
|
[capistrano-rails-asset-pipeline-readme]: https://www.github.com/capistrano/asset-pipeline/bundler/README.md
|
||||||
|
[capistrano-rails-database-migrations-readme]: https://www.github.com/capistrano/migrations/bundler/README.md
|
||||||
|
[capistrano-rails-gem-bundler-readme]: https://www.github.com/capistrano/capistrano-rails/bundler/README.md
|
1
documentation/index.html
Normal file
1
documentation/index.html
Normal file
|
@ -0,0 +1 @@
|
||||||
|
FUCK YOU JEKYLL
|
|
@ -0,0 +1,38 @@
|
||||||
|
---
|
||||||
|
title: Introductory Demo Video
|
||||||
|
layout: default
|
||||||
|
---
|
||||||
|
|
||||||
|
The video below was filmed on Mac OSX 10.8 using a more-or-less standard shell
|
||||||
|
without much previous setup.
|
||||||
|
|
||||||
|
It covers using Capistrano to install an example Rails project on a previously
|
||||||
|
unprepared server, covering all aspects of Github access, as well as
|
||||||
|
privisioning the server using *Chef Solo* and Capistrano with *Rake*.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#### Show Notes
|
||||||
|
|
||||||
|
The *Chef Solo* recipes can be reached at [this repository at
|
||||||
|
Github][capistrano-chef-solo-example-recipes], they rely on a fairly new
|
||||||
|
version of *Chef Solo*, spefically any including the results of [this
|
||||||
|
ticket][chef-issue-3365]. The aforementioned *Chef* issue adds environment
|
||||||
|
support to *Chef Solo*.
|
||||||
|
|
||||||
|
The provisioning can also be done using any other mechanism, it's generally
|
||||||
|
accepted however that there's not much point in automising your deploys,
|
||||||
|
unless you are also automating provisioning of your servers for a known,
|
||||||
|
consistent state.
|
||||||
|
|
||||||
|
Using `sudo` with any deployment can be tricky, so it's better to avoid it.
|
||||||
|
Rebooting services without `sudo` is typically the first place people run into
|
||||||
|
trouble using Capistrano. The [trouble shooting page for `sudo`
|
||||||
|
problems][troubleshooting-sudo-password] may help.
|
||||||
|
|
||||||
|
**Note:** Some long sequences have been shortened (nobody needs to sit and watch me
|
||||||
|
sitting and watching Ruby compile, for example!)
|
||||||
|
|
||||||
|
--
|
||||||
|
[chef-issue-3365]: https://github.com/opscode/chef/pull/359
|
||||||
|
[troubleshooting-sudo-password]: /troubleshooting/sudo-password/
|
5
documentation/upgrading/index.html
Normal file
5
documentation/upgrading/index.html
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
title: "Upgrading from v2.x.x"
|
||||||
|
---
|
||||||
|
|
||||||
|
Lorem Ipsum
|
BIN
images/CapistranoAvatar.png
Normal file
BIN
images/CapistranoAvatar.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 9 KiB |
BIN
images/CapistranoGraphic.png
Normal file
BIN
images/CapistranoGraphic.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 26 KiB |
BIN
images/CapistranoGraphicWireframe.png
Normal file
BIN
images/CapistranoGraphicWireframe.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 65 KiB |
BIN
images/CapistranoLogo.png
Normal file
BIN
images/CapistranoLogo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 9.6 KiB |
35
index.markdown
Normal file
35
index.markdown
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
---
|
||||||
|
layout: default
|
||||||
|
title: A remote server automation and deployment tool written in Ruby.
|
||||||
|
---
|
||||||
|
|
||||||
|
### A Simple Task
|
||||||
|
|
||||||
|
{% highlight ruby %}
|
||||||
|
role :demo, %{example.com example.org, example.net}
|
||||||
|
task :uptime do |host|
|
||||||
|
on :demo, in: :parallel do
|
||||||
|
uptime = capture(:uptime)
|
||||||
|
puts "#{host.hostname} reports: #{uptime}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
{% endhighlight %}
|
||||||
|
|
||||||
|
Capistrano extends the *Rake* DSL with methods specific to running commands
|
||||||
|
`on()` servers.
|
||||||
|
|
||||||
|
### For Any Language
|
||||||
|
|
||||||
|
Capistrano is written in Ruby, but it can easily be used to deploy any
|
||||||
|
language. Popular extensions add support for *Wordpress* blogs as well as
|
||||||
|
*Symfony* and *Node.js* applications.
|
||||||
|
|
||||||
|
If your language has special deployment requirements, Capistrano can easily be
|
||||||
|
extended to support them.
|
||||||
|
|
||||||
|
### Demo Video
|
||||||
|
|
||||||
|
<video id="demo" class="video-js vjs-default-skin" controls preload="auto" width="640" height="400" data-setup="{}">
|
||||||
|
<source src="http://capistrano-screencasts.s3.amazonaws.com/Capistrano%20Introduction%20Video.mp4" type='video/mp4'>
|
||||||
|
</video>
|
||||||
|
|
Loading…
Reference in a new issue