Sunday, 9 June 2013

Capistrano Gotchas: 401 http request failed


In my last post I covered the basics of deploying a simple Sinatra app to a hosted server using Capistrano.
Later that week I had occasion to use Capistrano for real.
A repo on Github was in a private repository owned by someone else.
I was a contributor to that repo and was using Capistrano to deploy it.

During that exercise I encountered a problem.
I kept getting:
error: The requested URL returned error: 401 while accessing 
# https://github.com/GITHUB_USER/GITHUB_REPO.git/info/refs?service=git-receive-pack 
# fatal: HTTP request failed 

What confused me was that because I wasn't using ssh keys, I was being asked to enter the username and password for the repo despite them being defined in the config/deploy.rb.
I struggled with this for some time running debugs, traces and what not.
In the end the answer dawned on me like a large incontinent beast.

The version of git on my local machine (OS-X) was 1.7.7 and on the server (Ubuntu 10.04) was 1.7.0.
Bugger.
So I downloaded the latest version of git source code which at the time I did it was 1.8.3.
Doing:
make prefix=/opt/git all doc info 

Caused a slew of missing components for generating documentation, and since I didn't need it on the server, I just did:
make prefix=/opt/git all 

After that completed, I did:
sudo make prefix=/opt/git install 

Which installed all the components into /opt/git.

I then adjusted the config/deploy.rb thus:
# Specify the EXACT locations of git 
set :scm_command, '/opt/git/bin/git' 
set :local_scm_command, '/usr/bin/git' 

And voila! The cap deploy worked as advertised.

For reference I did read: https://help.github.com/articles/https-cloning-errors

I have to say that Capistrano seems to have the 'growing like topsy' disease.
The options in the config/deploy.rb seem to be organic rather than structured.
What I mean by that is that the scm_username and scm_password are structured and give a clear indication of their purpose, while the remote server variables user and password do not.
I would have perhaps named variables in a hierarchical manner using yml for example:

application:
    name: [APP_NAME]
repositories:
    scm:
      uses: git
      username: [GIT_USER]
      password: [GIT_PASS]
      branch: master
local:
  command: /usr/bin/git
remotes:
  [SERVER_NAME]:
    web: www.somedomain.com
    app: www.somedomain.com
    db: www.somedomain.com
    username: [SERVER_USERNAME]
    password: [SERVER_PASSWORD]
    deploy_to: /path/to/site/folder
    command: /opt/git/bin/git
    keep_releases: 5
    use_sudo: false
    before:
      ...set of tasks...
    after:
      ...set of tasks...
    term_options: { pty: false } # or whatever
  [ANOTHER_SERVER]:
    ...etc...

Just a thought.

No comments:

Post a Comment