Cannot load configuration for Capistrano Receipe - ruby-on-rails

The thing is that I want to get parameters for my Capistrano recipe from the console, so after looking on Google I came up with this:
task :set_repo do
set :repository, "git#github.com:#{configuration[:repo]}/MyApp.git"
set :scm_user, configuration[:repo]
end
When trying to run the task, I come up with a "method missing" error for the configuration hash. And after another search on Google I found that I have to load the configuration from Capistrano, so I added this code:
configuration = Capistrano::Configuration.respond_to?(:instance) ?
Capistrano::Configuration.instance(true) :
Capistrano.configuration(:must_exist)
But that's throwing a LoadError with the message "Please require this file from within a Capistrano recipe". I have tried requiring the capistrano/configuration module, but I keep getting the same error.
Any help is greatly appreciated.

Well, I found a work around without using the configuration at all.
It seems that you can set a couple of tasks outside a namespace like this
desc "Use UserA's git repository"
task :usera do
set :repository, "git#github.com:UserA/MyApp.git"
set :scm_user, "UserA"
end
desc "Use UserB's git repository"
task :userb do
set :repository, "git#github.com:UserB/MyApp.git"
set :scm_user, "UserB"
end
and after doing this, you can simply call your deploy task prepending your repository task in the console. For example:
$ cap usera deploy
So this is going to call first your usera task and then your deploy task.

You can set capistano variables from the command line.
For example, the below invocation would set the capistrano variable scm_user to 'userA' and the capistrano variable repository to "http://myrepo.com/blah":
cap deploy -s scm_user="userA" -s repository="http://myrepo.com/blah"
This has the same effect as putting
set :scm_user, 'userA'
set :repository, 'http://myrepo.com/blah'
at the top of your deploy.rb file.

Related

Capistrano has incorrect default deploy location

I'm trying to deploy using Capistrano 3.1.0.
The file deploy.rb states:
# Default deploy_to directory is /var/www/my_app
However, when I run cap production deploy I get the following error:
mkdir: cannot create directory /var/www/shared
It appears to be ignoring my app name completely and trying to create directories in the wrong place. It should be trying to create /var/www/myapp/shared/. My deploy.rb file specifically has:
set :application, 'myapp'
Am I missing something here, or is this a bug?
UPDATE: The relevant line of the Capistrano source code appears to be:
set :deploy_to, "/var/www/#{fetch(:application)}"
in defaults.rb. If I print out the value of fetch(:application) it's nil, so something is stopping my application name from being set properly.
Turns out it's a bug with a fix that hasn't yet made it into a release.
Here's the change:
https://github.com/capistrano/capistrano/blob/master/lib/capistrano/defaults.rb#L3
Make sure you have the directory structure that Capistrano requires. You can use the Capistrano itself to create it with the command:
cap deploy:setup
Or you can create it directly with something like this:
# Capistrano will use /var/www/....... where ... is the value set in
# :application, you can override this by setting the ':deploy_to' variable
deploy_to=/var/www/:application
mkdir -p ${deploy_to}
mkdir ${deploy_to}/{releases,shared}
ref.: wiki deploy:setup and Authentication and Authorisation
edit: if you set the :deploy_to after the :application, you don't need the commit you mentioned.

Capistrano 3 pulling command line arguments

I'm in the process of upgrading from Capistrano 2 to Capistrano 3. In Cap 2 I was using the following to take a command line argument as the branch name (otherwise default to master)
set :branch, fetch(:branch, "master")
If I called cap deploy it would deploy the master branch. But it also let me do something like this:
cap deploy -S branch=foo
Which would deploy the foo branch.
Now, in Capistrano 3, if I try to run the above I get an error: invalid option: -S.
What's the proper way to pass an argument via the command line now?
What I ended up doing was setting an ENV variable.
So now I can call
cap production deploy branch=mybranch
And it will deploy mybranch. If I run a simple cap production deploy it will deploy the default branch (master if you don't set one, but I've changed mine below to default to demonstrate)
This is the code I put in my deploy.rb file:
set :branch, "default"
if ENV['branch']
set :branch, ENV['branch']
end
Rake tasks (which cap is using) are supporting arguments.
namespace :test do
desc "Test task"
task :test, :arg1 do |t, args|
arg1 = args[:arg1]
puts arg1
end
end
cap -T outputs:
cap yiic:test[arg1] # Test task
Example of invocation:
cap production yiic:test[test1]
Also, here is a helpful post
P.S.: you should use env vars for "global" settings. Like common values for multiple tasks.
To give an updated and working solution for Capistrano 3 (as it took me a while to find and too many tests to make it works).
My files are like:
config/
deploy/
staging.rb
production.rb
deploy.rb
...
Capfile
In staging.rb I have:
server 'staging', roles: %w(db)
set :branch, ENV.fetch('REVISION', 'master')
set :use_sudo, false
set :user, 'toto'
set :deploy_to, '/var/www'
(In server 'staging', staging is a SSH connexion, defined in my .ssh/config)
Then, to deploy a specific revision, I just need to call:
cap staging deploy REVISION=3b2d9ab
Where 3b2d9ab is the Git commit hash (short or long version).

Set default stage with Capistrano 3

Is there a way to set a default stage in Capistrano 3?
I've tried putting set :stage, :production inside deploy.rb but that didn't work, it gives the error:
Stage not set, please call something such as `cap production deploy`,
where production is a stage you have defined
I only have one stage right now so I want to be able to just run cap deploy and have it execute on the default.
Capistrano v3 is somewhat of a wrapper around Rake, so you need to realize that what's really happening is that a production task is getting run first, followed by a deploy task.
If you debug it a little, you'll find that deploy.rb doesn't get loaded when you don't type in a stage. This is because the stage's task is where deploy.rb gets loaded: Looking at lib/setup.rb, a task is defined for each stage. When run, the stage's task sets :stage, loads up the capistrano defaults, and then finally loads your deploy.rb file.
So, an easy trick would be to tell Capistrano to invoke the stage task every time you run cap by adding this to the end of your Capfile (not your deploy.rb):
Rake::Task[:production].invoke
or, using the invoke method from Capistrano's DSL:
invoke :production
This may have some unintended consequences if you actually do use multiple stages, but if you only ever use the production stage, it should work fine.
Another easy solution could be a simple shell alias, such as alias cap='cap production', but it might not work great if you have multiple projects with different stage names.
After I cd into the RAILS Root directory, issuing the command:
cap development deploy
seems to work. Earlier I was in the app/models folder and issuing the command came back with this error:
Stage not set, please call something such as cap production deploy, where production is a stage you have defined.
The old solution works for me in Capistrano 3:
cap --version
#=> Capistrano Version: 3.3.5 (Rake Version: 10.4.2)
At the very top of the Capfile after these lines
# Load DSL and Setup Up Stages
require 'capistrano/setup'
add:
set :stage, :production
and then run you task as usual without the stage specified:
cap foo:bar
New answer for capistrano 3.6+:
It's better to use invoke :production unless Rake.application.options.show_tasks to avoid the warning which you would otherwise get with cap -T
You can add the following line to your deploy.rb, which will prevent Capistrano from expecting a stage:
set :stages, ["production"]

Capistrano and Git, Ruining my life. "Unable to resolve revision for [HEAD] on repository ..."

I searched all of the relevant Capistrano issues, but couldn't find something that even elucidated anything here for me.
git version 1.6.4.2
Capistrano v2.5.10
Basically, when I run my cap deploy.rb script, it connects to the server, starts executing the deploy:update task, then in the deploy:update_code task:
*** [deploy:update_code] rolling back
* executing "rm -rf /home/user_name/public_html/project_name/releases/20091223094358; true"
servers: ["project_name.com"]
It fails with the following error:
/Library/Ruby/Gems/1.8/gems/capistrano-2.5.10/lib/capistrano/recipes/deploy/scm/git.rb:231:in `query_revision': Unable to resolve revision for 'master' on repository 'ssh://git#slice_ip:path_to_git_repository'. (RuntimeError)
Here's my deploy script, I've tried including and omitting:
set :branch 'master'
I also just thought my path to the repository was off, but i've tried just about every permutation (absolute, not absolute, .git suffix, no suffix). There's definitely a bare git repository at the path i'm pointing to.
**I do have multiple projects being hosted on one slice. The other projects is also a rails project, but is running SVN. Capistrano deployments work fine.
Any pointers in the right direction or any ideas would help reduce the amount of drinking I am planning on doing if I can't figure this out. (Paths / IPs obfuscated, dont hack me bro!)
set :application, "project1"
set :user, "username"
set :repository, "ssh://git#67.24.9.133/home/git/project1.git"
set :branch, "master"
set :port, 696969
set :deploy_to, "/home/username/public_html/#{application}"
set :scm, :git
role :app, application
role :web, application
role :db, application, :primary => true
# deployment via remote client (workstation)
set :deploy_via, :copy
set :runner, user
# mod_rails
namespace :deploy do
desc "Restarting mod_rails with restart.txt"
task :restart, :roles => :app, :except => { :no_release => true } do
run "touch #{current_path}/tmp/restart.txt"
end
[:start, :stop].each do |t|
desc "#{t} task is a no-op with mod_rails"
task t, :roles => :app do ; end
end
end
This was the most relevant post (extremely relevant even), but I couldn't really figure out what they were saying the fix is. I'm pretty new with git / capistrano configs.
https://capistrano.lighthouseapp.com/projects/8716/tickets/56-query_revision-unable-to-resolve-revision-for-head-on-repository
Ok I seemed to have fixed it.
Basically, since I have 2 separate repositories on the remote server, I think the "git" user was failing because I hadn't registered an ssh keypair for the git user. That explains why one of my deploy.rb scripts was working properly, while this one wasn't.
In the link I posted in the question, one of the commenters pointed out the issue:
https://capistrano.lighthouseapp.com/projects/8716/tickets/56-query%5Frevision-unable-to-resolve-revision-for-head-on-repository
Note this error is also displayed if
you are using multiple github keys per
http://capistrano.lighthouseapp....
and you do not have these keys and a
corresponding entry in your
.ssh/config on the workstation you're
running the deploy from. so the
ls-remote is run locally. is there a
way to reference the repository at
github.com for this request while the
remote deploy uses
git#github-project1:user/project1.git
Also, see the following link for more details, since the whole ssh issue would apply even if you're not using github.
http://github.com/guides/multiple-github-accounts
Both your workstation and your server must be able to reach the repository at the address specified, if not then you may have to set :local_repository to how you access it from your workstaion, and :repository to be how your servers should access it.
For me Capistrano deployments with Git only seem to work when setting set :copy_cache, true
I've only used capistrano with git once, but never used or seen the use of ssh:// in the repository definition.
Try using set :repository, "git#67.24.9.133/home/git/project1.git" instead
Make sure the branch you are deploying from exists.
set :branch, "upgrade-to-2013.4.3"
is not equal to
set :branch, "upgrade-to-2013.3.4"

Can a specify a particular server on the capistrano command line?

I just tried to run
cap deploy:setup
on the command line, but it wanted it to run on just one particular server instead of them all. Is there a way to run a task on just one server from the command line, or do I have to define it that way in the deploy.rb file?
Are you using capistrano-multistage? If not I recommend you do, I believe you can achieve the same with just the deploy.rb but personally I just find it easier this way and it makes this process much neater, especially if you start doing different things in production, staging or other stages.
Basically once you've installed the gem locally you can simply run commands like this:
cap staging deploy:setup
Where the 'staging' part matches one of you stage files (See below).
To get up and running change deploy.rb to something like this:
set :stages, %w(staging production)
set :default_stage, "staging"
require 'capistrano/ext/multistage'
after "deploy", "deploy:cleanup"
Then add a folder named deploy into the config directory of your rails app. In there you can place your separate deployment files, e.g staging.rb and production.rb.

Resources