Minimalistic deployment tool
MIT License
Shuttle is a minimalistic application deployment tool designed for small applications and one-server deployments. Configuration is stored as YAML-encoded file, no need to use ruby code. Operations are performed on SSH connection with target server.
Install from Rubygems:
gem install shuttle-deploy
Or install manually (clone repo first):
rake install
Supported ruby versions:
Deployment structure is very similar to capistrano.
Application files will be stored in deploy_to
path that you specify in config.
Directory structure:
releases
- Main directory to store all application releasescurrent
- Symbolic link to the latest releaseshared
- Shared directory to store assets, configs, etcscm
- Code repository directoryversion
- File that contains current release numberShared directory structure:
tmp
- Temporary filespids
- Shared process IDs fileslog
- Shared log filesDeployment flow consists of steps:
Available deployment strategies:
static
wordpress
ruby
rails
nodejs
This is a default strategy that does not perform any application-related tasks. Example configuration:
app:
name: my-application
git: [email protected]:my-site.git
target:
host: my-host.com
user: username
password: password
deploy_to: /home/deployer/www
This strategy is designed to deploy wordpress sites developed as a separate theme.
It requires subversion
installed on the server (will be automatically installed).
Define strategy:
app:
strategy: wordpress
Wordpress applications are configured and deployed with wp
cli utility. On a clean setup
shuttle will attempt to install wp-cli and wordpress core first. CLI is installed from
main github repository and latest stable tag. Wordpress core will install latest version.
To specify required versions, use wordpress section:
wordpress:
core: 3.5.1
cli: 0.9.1
Then, you'll need to define theme and wp related options:
wordpress:
theme: my-theme
site:
title: "Site Title"
url: "http://sample-site.com"
admin_name: "admin"
admin_email: "[email protected]"
admin_password: "password"
Database options:
wordpress:
mysql:
host: 127.0.0.1
user: mysql-user
password: mysql-password
database: mysql-database
You can also provide a list of required plugins:
wordpress:
plugins:
- acf
- acf: git://github.com/elliotcondon/acf.git
- acf: http://my-site.com/acf.zip
- acf: http://my-site.com/acf.tar.gz
For more detailed example, check examples/wordpress.yml
Rails deployment strategy will deploy your basic application: install dependencies, migrate database, precompile assets and start web server. Most of the steps are automatic.
Define strategy first:
app:
name: myapp
strategy: rails
Then add a separate section:
rails:
environment: production
precompile_assets: true
start_server: true
If using start_server
, shuttle will try to start thin server.
You can modify settings for thin:
thin:
host: 127.0.0.1
port: 9000
servers: 5
You can also use foreman
to run application:
rails:
start_server: false
hooks:
before_link_release:
- "sudo bundle exec foreman export upstart /etc/init -a $DEPLOY_APP -u $DEPLOY_USER -p 9000 -l $DEPLOY_SHARED_PATH/log"
- "sudo start $DEPLOY_APP || sudo restart $DEPLOY_APP"
Deployment config has a few main sections: app
and target
.
Application section defines deployment strategy, source code location and other options:
app:
name: my-app
strategy: static
git: https://site-url.com/repo.git
branch: master
keep_releases: 5
Options:
name
- Your application namestrategy
- Deployment strategy. Defaults to static
git
- Git repository urlbranch
- Git repository branch. Defaults to master
keep_releases
- Number of releases to keep. Defaults to 10
You can also use Subversion as a main source:
app:
svn: http://site-url.com/repo.git
If your repository requires authentication, use url in the following format:
http://username:[email protected]/project
Target is a set of remote machine credentials:
target:
host: yourdomain.com
user: deployer
password: password
deploy_to: /home/deployer/myapp
Options:
host
- Remote server host or ipuser
- Remote server user accountpassword
- Optional password. Use passwordless authentication if possible.deploy_to
- Primary directory where all releases will be storedYou can also define multiple targets per config if environments does not have any specific configuration settings:
targets:
production:
host: mydomain.com
user: deployer
deploy_to: /home/production/myapp
staging:
host: mydomain.com
user: deployer
deploy_to: /home/staging/myapp
During deployment shuttle sets a few environment variables:
DEPLOY_APP
- Application nameDEPLOY_USER
- Current deployment userDEPLOY_PATH
- Path to application releasesDEPLOY_RELEASE
- New release numberDEPLOY_RELEASE_PATH
- Path to currently executing releaseDEPLOY_CURRENT_PATH
- Path to current release (symlinked)DEPLOY_SHARED_PATH
- Path to shared resourcesDEPLOY_SCM_PATH
- Path to code repositoryThese could be used in hooks. Example:
hooks:
before_link_release:
- "cp $DEPLOY_SHARED_PATH/myconfig $DEPLOY_RELEASE_PATH/myconfig"
To execute a new deploy, simply type (in your project folder):
shuttle deploy
Output will look like this:
Shuttle v0.2.0
-----> Connected to [email protected]
-----> Preparing application structure
-----> Fetching latest code
-----> Using branch 'master'
-----> Linking release
-----> Release v35 has been deployed
Execution time: 2s
If using multiple targets in config, you can specify which target to use with:
shuttle staging deploy
Specify a path to config with -f
flag:
shuttle -f /path/to/config.yml deploy
To run in debug mode, add -d
flag:
shuttle deploy -d
List of all available hooks that you can use to run custom commands:
before_setup
- Before base application directories are createdafter_setup
- After application directories are createdbefore_checkout_code
- Before code update (git pull, etc)after_checkout_code
- After code has been updatedbefore_link_release
- Before linking releaseafter_link_release
- After release has been linkedbefore_rollback
- Before rollback operationafter_rolback
- After rollback operationEach hook could include one or many bash commands.
Tasks are user-defined commands or a set of multiple commands that could be integrated into hooks. The benefit of having tasks defined separate from the hooks is to make deployment steps more readable.
Here's an example a task:
tasks:
flush_cache:
- bundle exec cache:clear
reset_counters:
- bundle exec counters:submit
- bundle exec counters:reset
hooks:
before_link_release:
- task=flush_cache
- task=reset_counters
Tasks could only be invoked from a hook, invoking a task from within another task does not work and intended to keep things simple.
Commands in tasks are treated in the same way as commands in a hook, thus any failure
of a command within a hook that does not allow any failures will trigger a deployment
rollback. The only hook that allows failures is after_link_release
, basically
release is already symlinked and if something goes wrong it will not affect anything.
Tasks are also a great way to split up groups of steps into smaller, more logical chunks.
In case if you want to revert latest deploy, run:
shuttle rollback
Last release will be permanently destroyed and previous release will be symlinked as current. If you wish to run some commands on rollback, you can specify a hook:
hooks:
before_rollback:
- bash commands
after_rollback:
- bash commands
You can generate deployment config with CLI:
shuttle generate static
To run project test suite execute:
bundle exec rake test
The MIT License
Copyright (c) 2012-2015 Dan Sosedoff