Capistrano is a great tool for remote server automation and deployment. The standard practice is to have a single Capistrano setup per application, but if you are working on a complex project that consists of several applications or services, managing deployment configuration can become a daunting task.
There are two approaches for tackling deployment of larger projects with multiple applications.
Decentralized multi-deployment approach
This happens by default. With decentralized multi-deployment approach the deployment configuration is located in each application.
~/projects/my-app/my-app-base$ cap production deploy
~/projects/my-app/my-app-billing$ cap production deploy
~/projects/my-app/my-app-importer$ cap production deploy
Drawbacks:
– No separation of concerns: application code is mixed with deployment code.
– Duplication of code: code is duplicated across applications.
– Difficult workflow: multiple directories require more effort to navigate etc.
Centralized multi-deployment approach
With centralized multi-deployment approach the deployment configuration for each application is located in a single repository.
~/projects/my-app-deployment$ cap base:production deploy
~/projects/my-app-deployment$ cap billing:production deploy
~/projects/my-app-deployment$ cap importer:production deploy
Advantages:
– Separation of concerns: deployment code is located in a single dedicated repository, separate from application code.
– DRY: configuration can be shared between applications.
– Increased security: ability to restrict deployment access to authorized team members.
Drawbacks:
– Having the deployment script outside application code makes continuous delivery a bit more difficult to set up.
CapHub
CapHub is a tool which can help you set up a central deployment repository by generating a Capistrano skeleton suited for deploying to multiple applications.
$ gem install caphub
$ caphub my-app-deployment
$ tree --dirsfirst my-app-deployment my-app-deployment
├── config
│ ├── deploy
│ └── deploy.rb
├── recipes
├── Capfile
├── Gemfile
└── Gemfile.lock
Using centralized deployment on Semaphore
When adding a new server on Semaphore, select deployment option “Using a deploy script” and adapt the following deploy commands:
echo {SERVER_PUBLIC_KEY} >> ~/.ssh/known_hosts
cd /tmp
git clone https://{GITHUB_TOKEN}:x-oauth-basic@github.com/my-company/my-app-deployment.git
cd ./my-app-deployment
bundle install --path vendor/bundle
bundle exec cap base:production deploy:migrations
What we are doing here is pulling and initializing the central deployment repository before calling the deploy task. More information on the GITHUB_TOKEN mentioned above can be found on our documentation site.