(these are merely ideas, not a concrete plan on where Mina is headed from now!)
There are many tools available for app deployment, but they can all use some form of improvement.
- Capistrano is flexible, but slow, and takes too much effort to customize.
- Cap and Mina can work with any language, but the Capfiles and deploy.rb's are all written in Ruby, making anyone writing in Node/Python/Scala feel a little left out.
- Cap and Mina both let you declare your deploy manifests imperatively, not declaratively.
- Mina doesn't have native support for handling multiple servers and environments (although it can easily do this).
- Mina is fast, but can be made even faster.
Here's my vision to what Mina's successor should be like:
- Write your deploy files in a declarative manner in a YAML file
- Plain ol' YAML files - no need to learn Ruby. Also, you can take advantage of YAML constructs, like inheritance.
- Deployment manifests are shorter and more manageable than Cap/Mina.
- Semi-inspired by Ansible.
Write your config/deploy.yml
. Here's a full example:
---
# (Optional) declare what libraries you want. You can also add relative paths
# to your own extensions.
use:
- mina/rails
- mina/rvm
- ../lib/mina-ext.rb
# List down your hosts here, grouped by 'environment'. In this case, we have
# one production server. (In the real world, you probably will have
# `production` and `staging` at the very least, and they can share variables
# via YAML inheritance.)
hosts:
production:
- host: [email protected] # <- some variables here
deploy_to: /var/www/myapp
git: https://github.com/me/myapp
rails_env: production
shared_paths:
- config/database.yml
- config/settings.yml
- public
- logs
# Task definitions go here.
tasks:
setup:
- shell: mkdir -p {{deploy_to}}/{releases,tmp,shared/pids,shared/public,shared/logs}
- shell: chown -R {{owner}} {{deploy_to}}
- rvm: create_gemset 2.0.0-p0@myapp
deploy.build:
- rvm: use 2.0.0-p0@myapp
- rails: assets_precompile
- rails: db_migrate
deploy.after:
- rake: cdn:propagate
- task: restart
# You can write any task, and invoke it as `m2 <taskname>` (eg, in this case:
# `m2 restart`). It can also be called in another task using `- task: <taskname>`.
restart:
- shell: touch tmp/restart.txt
logs:
- shell: tail -f {{deploy_to}}/shared/logs/production.log
console:
- rails: console
# Complicated tasks are no problem.
clean:
- shell: |
rm -rf {{deploy_to}}/shared/public/assets &&
rm -rf {{deploy_to}}/shared/logs/*
Run it:
$ m2 setup
$ m2 deploy
$ m2 deploy production
$ m2 logs
$ m2 console