[DRE-commits] [ruby-mina] 01/04: Imported Upstream version 0.3.1
Aggelos Avgerinos
avgerinos-guest at moszumanska.debian.org
Wed Jan 14 11:50:50 UTC 2015
This is an automated email from the git hooks/post-receive script.
avgerinos-guest pushed a commit to branch master
in repository ruby-mina.
commit b635287c22c791c58baac6665ec19f61099000f8
Author: Aggelos Avgerinos <avgerinos at skroutz.gr>
Date: Wed Jan 14 10:25:17 2015 +0200
Imported Upstream version 0.3.1
---
.gitignore | 10 +
.rspec | 1 +
.travis.yml | 21 +
CONTRIBUTING.md | 124 +++
Gemfile | 10 +
HISTORY.md | 348 ++++++++
LICENSE | 23 +
Makefile | 29 +
Notes.md | 70 ++
Rakefile | 20 +
Readme.md | 1009 ++++++++++++++++++++++++
bin/mina | 65 ++
data/deploy.rb | 80 ++
data/deploy.sh.erb | 106 +++
lib/mina.rb | 23 +
lib/mina/bundler.rb | 49 ++
lib/mina/chruby.rb | 49 ++
lib/mina/default.rb | 145 ++++
lib/mina/deploy.rb | 138 ++++
lib/mina/deploy_helpers.rb | 34 +
lib/mina/exec_helpers.rb | 111 +++
lib/mina/foreman.rb | 82 ++
lib/mina/git.rb | 62 ++
lib/mina/helpers.rb | 386 +++++++++
lib/mina/output_helpers.rb | 92 +++
lib/mina/rails.rb | 206 +++++
lib/mina/rake.rb | 9 +
lib/mina/rbenv.rb | 47 ++
lib/mina/rvm.rb | 88 +++
lib/mina/settings.rb | 32 +
lib/mina/ssh_helpers.rb | 123 +++
lib/mina/tools.rb | 20 +
lib/mina/version.rb | 5 +
lib/mina/whenever.rb | 27 +
manual/index.md | 15 +
manual/modules.md | 2 +
metadata.yml | 176 +++++
mina.gemspec | 17 +
spec/command_helper.rb | 52 ++
spec/commands/cleanup_spec.rb | 16 +
spec/commands/command_spec.rb | 71 ++
spec/commands/custom_config_spec.rb | 20 +
spec/commands/deploy_spec.rb | 36 +
spec/commands/outside_project_spec.rb | 35 +
spec/commands/real_deploy_spec.rb | 53 ++
spec/commands/ssh_spec.rb | 14 +
spec/commands/verbose_spec.rb | 21 +
spec/dsl/invoke_spec.rb | 48 ++
spec/dsl/queue_spec.rb | 49 ++
spec/dsl/settings_in_rake_spec.rb | 39 +
spec/dsl/settings_spec.rb | 61 ++
spec/dsl/to_spec.rb | 20 +
spec/fixtures/custom_file_env/custom_deploy.rb | 15 +
spec/fixtures/empty_env/config/deploy.rb | 15 +
spec/helpers/exec_helper_spec.rb | 19 +
spec/helpers/output_helper_spec.rb | 38 +
spec/spec_helper.rb | 27 +
support/Readme-footer.md | 32 +
support/Readme-header.md | 16 +
support/guide.md | 297 +++++++
support/index.html | 53 ++
support/to_md.rb | 11 +
test_env/config/deploy.rb | 69 ++
63 files changed, 4981 insertions(+)
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..e3b1815
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,10 @@
+doc
+test_env/deploy
+.rvmrc
+.ruby-gemset
+.ruby-version
+Gemfile.lock
+pkg/
+docs
+support/helpers.md
+support/modules.md
diff --git a/.rspec b/.rspec
new file mode 100644
index 0000000..51fd40e
--- /dev/null
+++ b/.rspec
@@ -0,0 +1 @@
+-c --order rand -t ~ssh
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..016724e
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,21 @@
+language: ruby
+rvm:
+ - 1.8.7
+ - 1.9.3
+ - 2.0.0
+ - 2.1.2
+ - rbx-2
+ - jruby
+env:
+ - "rake=0.8"
+ - "rake=0.9"
+ - "rake=10"
+# before_script:
+# - cat ~/.ssh/*.pub >> ~/.ssh/authorized_keys
+# - ssh -o StrictHostKeyChecking=no localhost "exit"
+script: "bundle exec rspec"
+notifications:
+ email:
+ - dropbox+travis at ricostacruz.com
+ - dario at uxtemple.com
+ - gabrijel.skoro at infinum.hr
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 0000000..1681955
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,124 @@
+# Contributing to Mina
+
+Want to get involved? Thanks! There are plenty of ways to help!
+
+## Reporting issues
+
+A bug is a _demonstrable problem_ that is caused by the code in the
+repository.
+
+Please read the following guidelines before you [report an issue][issues]:
+
+1. **Use the GitHub issue search** — check if the issue has already been
+ reported. If it has been, please comment on the existing issue.
+
+2. **Check if the issue has been fixed** — the latest `master` or
+ development branch may already contain a fix.
+
+3. **Isolate the demonstrable problem** — make sure that the code in the
+ project's repository is _definitely_ responsible for the issue. Create a
+ [reduced test case](http://css-tricks.com/6263-reduced-test-cases/) - an
+ extremely simple and immediately viewable example of the issue.
+
+Please try to be as detailed as possible in your report too. What is your
+environment? What steps will reproduce the issue? What would you expect to be
+the outcome? All these details will help people to assess and fix any potential
+bugs.
+
+### Example of a good bug report:
+
+> Short and descriptive title
+>
+> A summary of the issue and the OS environment in which it occurs. If
+> suitable, include the steps required to reproduce the bug.
+>
+> 1. This is the first step
+> 2. This is the second step
+> 3. Further steps, etc.
+>
+> `<url>` (a link to the reduced test case)
+>
+> Any other information you want to share that is relevant to the issue being
+> reported. This might include the lines of code that you have identified as
+> causing the bug, and potential solutions (and your opinions on their
+> merits).
+
+A good bug report shouldn't leave people needing to chase you up to get further
+information that is required to assess or fix the bug.
+
+**[File a bug report][issues]**
+
+## Responding to issues
+
+Feel free to respond to other people's issues! Some people may be reporting
+issues that can easily be solved even without modification to the project's
+code.
+
+You can also help by verifying issues reported.
+
+**[View issues][issues]**
+
+## The 'help wanted' tag
+
+Some [issues] are tagged with the 'help wanted' tag. These issues often:
+
+ - are missing an actual implementation, or
+ - need people's help in verifying and replicating the issue, or
+ - need test cases.
+
+If you would like to contribute code and don't have any specific issue you want
+to fix, this would be a good place to start looking at!
+
+**[View issues][issues]**
+
+## Pull requests
+
+Good pull requests — patches, improvements, new features — are a fantastic
+help. They should remain focused in scope and avoid containing unrelated
+commits.
+
+If your contribution involves a significant amount of work or substantial
+changes to any part of the project, please open an issue to discuss it first.
+
+Please follow this process; it's the best way to get your work included in the
+project:
+
+1. [Fork](http://help.github.com/fork-a-repo/) the project.
+
+2. Clone your fork (`git clone
+ https://github.com/<your-username>/html5-boilerplate.git`).
+
+3. Add an `upstream` remote (`git remote add upstream
+ https://github.com/nadarei/mina.git`).
+
+4. Get the latest changes from upstream (e.g. `git pull upstream
+ <dev-branch>`).
+
+5. Create a new topic branch to contain your feature, change, or fix (`git
+ checkout -b <topic-branch-name>`).
+
+6. Make sure that your changes adhere to the current coding conventions used
+ throughout the project - indentation, accurate comments, etc. Please update
+ any documentation that is relevant to the change you are making.
+
+7. Commit your changes in logical chunks; use git's [interactive
+ rebase](https://help.github.com/articles/interactive-rebase) feature to tidy
+ up your commits before making them public. Please adhere to these [git commit
+ message
+ guidelines](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html)
+ or your pull request is unlikely be merged into the main project.
+
+8. Locally merge (or rebase) the upstream branch into your topic branch.
+
+9. Push your topic branch up to your fork (`git push origin
+ <topic-branch-name>`).
+
+10. [Open a Pull Request](http://help.github.com/send-pull-requests/) with a
+ clear title and description. Please mention which browsers you tested in.
+
+## Acknowledgements
+
+This contributing guide has been adapted from [HTML5 boilerplate's guide][g].
+
+[g]: https://github.com/h5bp/html5-boilerplate/blob/master/CONTRIBUTING.md
+[issues]: https://github.com/nadarei/mina/issues/
diff --git a/Gemfile b/Gemfile
new file mode 100644
index 0000000..c37e69c
--- /dev/null
+++ b/Gemfile
@@ -0,0 +1,10 @@
+# Why use bundler?
+# Well, not all development dependencies install on all rubies. Moreover, `gem
+# install mina --development` doesn't work, as it will also try to install
+# development dependencies of our dependencies, and those are not conflict free.
+# So, here we are, `bundle install`.
+
+source "https://rubygems.org"
+gemspec
+
+gem 'rake', "~> #{ENV['rake'] || "0.9"}.0"
diff --git a/HISTORY.md b/HISTORY.md
new file mode 100644
index 0000000..ed3f1be
--- /dev/null
+++ b/HISTORY.md
@@ -0,0 +1,348 @@
+## v0.3.2 - unreleased
+
+v0.3.1 - October 17, 2014
+-------------------------
+
+* Fix copy command for assets. (#150) [Joshua Dover]
+* Add comment for system-wide RVM install. (#112) [Sam Qiu]
+* Incorrect exit status if deploy fails (#95) [Alexander Borovsky]
+* Bundler: Allow configuration of groups to be skipped during installation (#123) [Luis Lavena]
+* Parse task string to reenable task (#189) [Pedro Chambino]
+* Update Travis CI to test via Ruby 2.1.2. (#197) [Luciano Sousa]
+* Add jRuby support by using threads instead of fork. (#147, #148) [Jan Berdajs]
+* Add rescue for rubinius SignalException. (#204) [Qen]
+* Using `bundle_bin` instead `bundle` in whenever tasks. (#195) [Maxim Dorofienko]
+* Convert specs to RSpec expect syntax with transpec (#194) [Logan Hasson]
+* Remove binstubs options from defaults (#219) [lucapette]
+* Updated deploy.rb template to use shared_path (#235) [postmodern]
+* Allow the foreman export format to be configurable (#232) [postmodern]
+* fix: bin/mina exit_status -> exitstatus (#212) [Zhomart Mukhamejanov]
+* Add foreman_location and foreman_sudo configs (#239) [Pedro Chambino]
+* Check db/migrate/ instead of schema.rb (#177) [Charles Dale]
+* Fix mina deploy --help, should not cause a deploy (#238)
+* Fix git:clone on win7 x64 had error (#216)
+* Add deploy:cleanup after deploy
+* Prevent foreman export from expanding the current/ symlink (#241)
+* Support pretty_system on ruby 1.8.7 (#237)
+* Ruby 1.8.7 doesn't support empty symbols (#240)
+
+
+[Joshua Dover]: https://github.com/gerfuls
+[Sam Qiu]: https://github.com/samqiu
+[Alexander Borovsky]: https://github.com/borovsky
+[Luis Lavena]: https://github.com/luislavena
+[Pedro Chambino]: https://github.com/PChambino
+[Luciano Sousa]: https://github.com/lucianosousa
+[Jan Berdajs]: https://github.com/mrbrdo
+[Qen]: https://github.com/qen
+[Maxim Dorofienko]: https://github.com/mdorfin
+[Logan Hasson]: https://github.com/loganhasson
+[lucapette]: https://github.com/lucapette
+[postmodern]: https://github.com/postmodern
+[Zhomart Mukhamejanov]: https://github.com/Zhomart
+[Charles Dale]: https://github.com/chuckd
+
+v0.3.0 - July 10, 2013
+----------------------
+
+ * **Stdin is now being passed, thereby making git prompts work.**
+ * Foreman: Add foreman support. (#71) [Dan Sosedoff]
+ * Foreman: Fix 'command not found' error. (#89, #101)
+ * Foreman: Fix forman stop. [Andrew Rosa]
+ * Fix `mina setup` showing an error. (#64) [Anthony Hristov]
+ * Fix "broken pipe" error after deploying. (#64) [Tomas Varneckas]
+ * Fix error regarding "open4" in Windows environments. (#58)
+ * Fix the default script's "touch tmp/restart.txt" to work for reliably. (#77)
+ [Eugene Diachkin]
+ * Fix errors that happen when the host string is frozen. [sonots]
+ * RVM: use 'rvm use --create'. (#81) [Marcos Beirigo]
+ * RVM: Add 'rvm:wrapper' task to create wrappers. (#81) [Marcos Beirigo]
+ * New helper method called 'capture' to capture SSH output. (#113) [Naoki
+ Ainoya]
+ * Fix encoding errors. (#68) [Faud Saud]
+
+Special thanks to all the contributors who made this release happen.
+
+https://github.com/mina-deploy/mina/compare/v0.2.1...v0.3.0
+
+[sonots]: https://github.com/sonots
+[Tomas Varneckas]: https://github.com/tomasv
+[Anthony Hristov]: https://github.com/muxcmux
+[Dan Sosedoff]: https://github.com/sosedoff
+[Eugene Diachkin]: https://github.com/ineu
+[Marcos Beirigo]: https://github.com/marcosbeirigo
+[Andrew Rosa]: https://github.com/andrewhr
+[Naoki Ainoya]: https://github.com/saketoba
+[Faud Saud]: https://github.com/faudsaud
+
+v0.2.1 - Sep 08, 2012
+---------------------
+
+This release is to fix some issues that should've been cleaned up in the
+previous release, but wasn't.
+
+### Fixed:
+ * **Fix SSH helpers giving a 'class required' error.**
+ * **Send stdout even in term_mode = :pretty mode.**
+ * Rbenv: Fix compatibility with Debian, Arch, Fedora. (#44)
+ * Supress the "--depth is ignored in local clones" warning. (#56)
+
+### Added:
+ * Add the `:ssh_options` setting. (#23)
+ * Add the `:forward_agent` setting. (#23)
+
+### Changed:
+ * Make the `:term_mode` setting accept strings, not just symbols. (eg: `set
+ :term_mode, 'exec'`)
+
+v0.2.0 - Sep 08, 2012
+---------------------
+
+This release had two pre releases:
+
+ * v0.2.0.pre2 (Aug 2, 2012)
+ * v0.1.3.pre1 (Jul 13, 2012)
+
+### Fixed:
+ * Allow changing `:term_mode` in the setup task. (#51, @alfuken)
+ * Prevent `git log` from using a pager. (#42, @tmak)
+ * `deploy:cleanup` can now be called in a deploy script. (#50, @dariocravero)
+ * Don't invoke bash anymore (!), assume that bash is the shell for the user.
+ Fixes Ubuntu 12, and many other things.
+ * Fixed `ssh(cmd, return: true)` that used to exit. (#53 from @jpascal)
+ * [pre2] Call ssh with no double use `-t` parameter.
+ * [pre2] Fix Ruby 1.8 compatibility.
+ * [pre2] Fix the "undefined method > for Process::Status" error.
+ * [pre2] Using `force_migrate=1` and `force_assets=1` to `rails:db_migrate`
+ and `rails:assets_precompile` now works well.
+ * [pre1] Respect the `bundle_bin` setting when doing `bundle exec` in Rails commands. (#29)
+ * [pre1] Doing `rails:assets_precompile` now properly skips asset compilation if not needed. (#25)
+
+### Added:
+ * __Added the 'queue!' helper.__
+ * Add support for __Whenever__. (#47, @jpascal)
+ * Add a new `:environment` task that gets loaded on setup/deploy.
+ * __Add explicit support for rbenv/rvm.__ (#5, #39)
+ * Implement :'rvm:use[...]'. (#5, #39)
+ * Implement :'rbenv:load'. (#5, #39)
+ * Revert `rails:optimize_for_3.2` from the pre2 release. (#32)
+ * [pre2] __Optimize git:clone by caching the repository.__ This way, updates are
+ faster because not the entire repo is cloned everytime. (#10)
+ * [pre2] __Show elapsed time that a deploy takes.__
+ * [pre2] __Display the git commit nicely when deploying.__
+ * [pre2] __Force quit when 2 `^C`s are pressed.__
+ * [pre2] New `die` helper.
+ * [pre2] New `report_time` helper.
+ * [pre2] New `to_directory` helper. (#35)
+ * [pre2] Put optional optimizations for Rails 3.2 asset pipeline. (#32) -- reverted
+ * Update sample deploy script:
+ - [pre2] Update default deploy.rb to note :branch.
+ - [pre2] Add `link_shared_paths` to the sample deploy script.
+ * [pre1] Doing `rails:db_migrate` now skips doing migrations if they're not needed. (#18)
+ * [pre1] Added the `mina console` command for Rails.
+ * [pre1] Make asset paths configurable using the `asset_paths` setting.
+
+### Changed:
+ * Force removal of shared path destinations before linking with
+ `deploy:link_shared_paths`. Fixes symlinking of `log/` in Rails projects.
+ * __Rails: speed up default asset compilation a bit by invoking
+ `assets:precompile` with `RAILS_GROUPS=assets`.__
+ * Add helpful error message when there is a problem with
+ deploy.rb or a custom Rakefile. (#37, @sge-jesse-adams)
+ * Update the default deploy.rb to add notes about 'mina setup' customizations.
+ * Make `mina run`, `mina rake`, `mina console` use the new `:environment` task.
+ * Allow calling `die` without arguments.
+ * [pre2] __Improve output of `mina init`.__
+ * [pre2] Prettier output for `mina setup`. Also, show a better error message for it.
+ * [pre1] Refactor pretty printing to be simpler, cleaner, and extensible.
+ * [pre1] Show prettier abort messages when ^C'd.
+
+v0.1.2 - Jul 06, 2012
+---------------------
+
+This release had two prereleases: v0.1.2.pre1 and v0.1.2.pre2.
+
+### Fixed:
+ * __Show stdout output properly on deploy.__
+ * 'mina rake' now works.
+ * [.pre2] __Fix `deploy:link_shared_paths` to use absolute paths.__
+ * [.pre2] Fix console logs for task init.
+ * [.pre1] __Fixed JRuby support.__
+ * [.pre1] __Respect .bashrc.__ (#5)
+
+### Added:
+ * [.pre2] Add `:bundle_bin` option.
+ * [.pre2] Add `:ssh` port option.
+
+### Changed: (v0.1.2)
+ * Refactor pretty printing to be simpler, cleaner, and extensible.
+ * Show prettier abort messages when ^C'd.
+ * Use the new error message format. (See lib/mina/output_helpers.rb)
+ * [.pre1] Implement `ssh("..", return: true)`.
+ * [.pre1] Rename `simulate_mode` to `simulate_mode?`. Same with `verbose_mode?`.
+ * [.pre1] Show the SSH command in the simulation output.
+
+v0.1.1 - Jun 07, 2012
+---------------------
+
+### Added:
+ * Check for releases_path directory in deploy script.
+ * mina deploy:cleanup
+ * Support for -f option.
+
+### Changed:
+ * Gem description.
+
+### Fixed:
+ * deploy.rb template (domain, user, git:clone).
+ * Handle empty Git repository.
+ * Add pkg to gitignore.
+
+v0.1.0 - Jun 06, 2012
+---------------------
+
+Renamed to Mina from Van Helsing.
+
+
+v0.0.1.pre7 - Jun 06, 2012
+--------------------------
+
+### Added:
+ * __`vh rails[command]` and `vh rake[command]` tasks.__
+ * __Add `vh run`.__
+ * `-S` as an alias for `--simulate`.
+ * the `#set_default` helper.
+ * the `bundle_prefix` setting.
+ * New `term_mode` setting.
+
+### Changed:
+ * `--simulate` show things without the `ssh` command or shellescaping.
+
+v0.0.1.pre6 - Jun 06, 2012
+--------------------------
+
+Thanks to @sosedoff for his contributions that made it to this release.
+
+### Added:
+ * __Rubinius support.__
+ * __Ruby 1.8 support.__
+ * Prelimenary JRuby support.
+ * MIT license.
+ * Highlight errors as red in deploy.
+ * Use popen4 instead of popen3. Support JRuby via IO.popen4.
+
+### Changed:
+ * __Rename `to :restart` to `to :launch`.__
+ * __Make deploys fail if renaming the build (eg, not setup properly) fails.__
+
+### Tests:
+ * Added `rake spec` (aliased as just `rake`) task. It tests with Rake 0.8 and 0.9 both.
+ * Integrate with [Travis CI](http://travis-ci.org).
+ * Make the SSH test more portable.
+ * Removed `rake spec:verbose`.
+
+v0.0.1.pre5 - Jun 05, 2012
+--------------------------
+
+### Added:
+ * Add `--trace` to the `vh help` screen.
+ * Rake 0.8 compatibility.
+ * Ruby 1.8.7 compatibility.
+
+### Changed:
+ * Use `:domain` instead of `:host`.
+
+### Misc:
+ * Allow rake 0.8 testing using `rake=0.8 rspec`.
+ * Add more README examples.
+
+v0.0.1.pre4 - Jun 05, 2012
+--------------------------
+
+### Added:
+ * `--simulate` switch.
+ * `--verbose` switch.
+ * The help screen now shows command line switches (like `--verbose`).
+ * Build in `tmp/` instead of in `releases/`.
+ * Use `verbose_mode` and `simulate_mode` instead. Using 'verbose' causes
+ problems.
+ * New `#deploy_script` helper, to make things more transparent.
+
+### Misc:
+ * Added a test for an actual deployment.
+ * Make the `test_env` runnable even without a net connection.
+ * New tests for actual deployment. Just do `rspec -t ssh`.
+ * Cleanup `git:clone` code.
+ * A buncha code cleanups.
+
+v0.0.1.pre3 - Jun 04, 2012
+--------------------------
+
+### Added:
+ * A help screen. You can see it with `vh --help`, `vh -h` or just plain `vh`.
+ * Implemented `vh --version`.
+ * Sequential release versions. Yay!
+ * Added the `build_path` setting, which supercedes the now-removed `release_path`.
+
+### Removed:
+ * `release_path` has been deprecated.
+
+### Fixed:
+ * Stupid critical bug fix: fix `vh:setup` giving the world access to deploy_to.
+ * Ensure that SSH stderr output is shown properly.
+ * Make `#invoke` work with tasks with arguments (eg, :'site:scrape[ensogo]')
+
+### Changed:
+ * Edit the default deploy.rb to have a description for the deploy task.
+ * Make `vh -T` show `vh` instead of `rake`.
+ * Make `vh setup` ensure ownership of the `deploy_to` path.
+ * Make deploy steps more explicit by echoing more statuses.
+ * When deploys fail, you now don't see the default Ruby backtrace. It now
+ behaves like Rake where you need to add `--trace` to see the trace.
+
+### Misc:
+ * Fixed the error that sometimes happens when invoking `vh` without a deploy.rb.
+ * Update the sample deploy.rb file to be more readable.
+ * The *test_env/* project can now be deployed without problems, so you can try
+ things out.
+ * Lots of new tests.
+ * rspec test order is now randomized.
+ * rspec output is colored (thanks to .rspec).
+ * Better script indentation when running in simulation mode.
+ * In symlinking `./current/`, use `ln -nfs` instead of `rm -f && ln -s`.
+
+v0.0.1.pre2 - Jun 03, 2012
+--------------------------
+
+### Added:
+ * Implement `vh init` which creates a sample *deploy.rb*.
+ * Implement 'vh setup'.
+ * Added the configurable `:releases_path` setting, so you may change where to keep releases.
+ * Added documentation via Reacco.
+ * Allow settings to throw errors on missing settings by adding a bang (e.g.,
+ `bundle_path!` or `settings.bundle_path!`)
+
+### Changed:
+ * Allow `bundle:install` to skip having shared bundle paths if `:bundle_path` is set to nil.
+ * Rename `force_unlock` to `deploy:force_unlock`.
+ * Rename `vh:link_shared_paths` to `deploy:link_shared_paths`.
+ * Invoking `deploy:force_unlock` now shows the command it uses.
+
+### Fixed:
+ * The `bundle:install` task now honors the `bundle_path` setting.
+ * Fixed `deploy:force_unlock` always throwing an error.
+ * The `deploy:force_unlock` task now honors the `lock_file`
+ setting, so the user may change the location of the lock file.
+ * Fixed `rails:assets_precompile` not compiling if no older assets found.
+
+### Removed:
+ * Deprecate `#validate_set`.
+
+### Other things:
+ * Move deploy settings to deploy.rb.
+ * Rename the `default` addon to `deploy`.
+
+v0.0.1.pre1 - Jun 02, 2012
+--------------------------
+
+Initial version.
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..6e4bacb
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,23 @@
+LICENSE
+
+The MIT License
+
+Copyright (c) 2014 Nadarei, Inc.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..50ea6c6
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,29 @@
+Readme.md: \
+ support/Readme-header.md \
+ support/guide.md \
+ support/helpers.md \
+ support/modules.md \
+ support/Readme-footer.md
+ cat $^ > $@
+
+support/modules.md: \
+ lib/mina/bundler.rb \
+ lib/mina/default.rb \
+ lib/mina/deploy.rb \
+ lib/mina/foreman.rb \
+ lib/mina/git.rb \
+ lib/mina/rails.rb \
+ lib/mina/rbenv.rb \
+ lib/mina/rvm.rb \
+ lib/mina/whenever.rb
+ cat $^ | ruby support/to_md.rb > $@
+
+support/helpers.md: \
+ lib/mina/helpers.rb \
+ lib/mina/deploy_helpers.rb
+ cat $^ | ruby support/to_md.rb > $@
+
+clean:
+ rm Readme.md support/modules.md support/helpers.md
+
+.PHONY: clean
diff --git a/Notes.md b/Notes.md
new file mode 100644
index 0000000..894e8db
--- /dev/null
+++ b/Notes.md
@@ -0,0 +1,70 @@
+Readme
+------
+
+The readme file is auto-generated using make.
+
+ $ make Readme.md
+
+Documentation
+-------------
+
+Please consult the [project documentation](http://mina-deploy.github.io/mina) for full
+details.
+
+Problems or suggestions? File issues at the [issue tracker][issues].
+
+Documentation sources
+---------------------
+
+See [mina-deploy/mina-docs](https://github.com/mina-deploy/mina-docs) for the sources of
+the documentation site. Please ensure that docs there are in sync with the
+features here.
+
+Development & testing
+---------------------
+
+To test out stuff in development:
+
+``` sh
+# Run specs
+$ rspec
+$ rspec -t ssh # Run SSH tests (read test_env/config/deploy.rb first)
+$ rake=10 rspec
+$ rake=0.9 rspec
+$ rake=0.8 rspec
+
+# Alias your 'mina' to use it everywhere
+$ alias mina="`pwd -LP`/bin/mina"
+```
+
+### Doing test deploys
+
+Try out the test environment:
+
+``` sh
+$ cd test_env
+$ mina deploy --simulate
+$ mina deploy
+
+# There's an rspec task for it too
+$ rspec -t ssh
+```
+
+### Gem management
+
+``` sh
+# To release the gem:
+# Install the Git changelog helper: https://gist.github.com/2880525
+# Then:
+
+$ vim lib/mina/version.rb
+$ git clog -w
+$ vim HISTORY.md
+$ git commit -m "Release v0.8.4."
+$ rake release
+
+# Please don't forget to tag the release in github.com/nadarei/mina-docs too!
+
+$ rake build # Builds the gem file
+$ rake install # Installs the gem locally
+```
diff --git a/Rakefile b/Rakefile
new file mode 100644
index 0000000..5b554df
--- /dev/null
+++ b/Rakefile
@@ -0,0 +1,20 @@
+require 'bundler'
+require 'bundler/gem_tasks'
+
+github = ENV['github'] || 'nadarei/mina'
+
+task :spec do
+ system "rm Gemfile.lock; sh -c 'rake=0.8 bundle exec rspec'"
+ system "rm Gemfile.lock; sh -c 'rake=0.9 bundle exec rspec'"
+end
+
+task :docs do
+ files = ['manual/index.md', 'manual/modules.md', 'HISTORY.md'] + Dir['lib/**/*.rb']
+ system "lidoc #{files.join ' '} -o docs --github #{github}"
+end
+
+task :'docs:deploy' => :docs do
+ system "git-update-ghpages #{github} -i docs -p docs"
+end
+
+task :default => :spec
diff --git a/Readme.md b/Readme.md
new file mode 100644
index 0000000..37bc6b3
--- /dev/null
+++ b/Readme.md
@@ -0,0 +1,1009 @@
+# Mina
+
+Really fast deployer and server automation tool.
+
+Mina works really fast because it's a deploy Bash script generator. It
+generates an entire procedure as a Bash script and runs it remotely in the
+server.
+
+Compare this to the likes of Vlad or Capistrano, where each command
+is run separately on their own SSH sessions. Mina only creates *one* SSH
+session per deploy, minimizing the SSH connection overhead.
+
+ $ gem install mina
+ $ mina
+
+[](https://travis-ci.org/mina-deploy/mina) [](http://badge.fury.io/rb/mina)
+
+User guide
+==========
+
+Setting up a project
+--------------------
+
+Let's deploy a project using Mina.
+
+### Step 1: Create a config/deploy.rb
+
+In your project, type `mina init` to create a sample of this file.
+
+ $ mina init
+ Created config/deploy.rb.
+
+This is just a Rake file with tasks! See [About deploy.rb](#about-deployrb) for
+more info on what *deploy.rb* is. You will want to at least configure your
+server:
+
+~~~ ruby
+# config/deploy.rb
+set :user, 'username'
+set :domain, 'your.server.com'
+set :deploy_to, '/var/www/flipstack.com'
+...
+~~~
+
+### Step 2: Set up your server
+
+Make a directory in your server called `/var/www/flipstack.com` (in *deploy_to*)
+change it's ownership to the correct user.
+
+ $ ssh username at your.server.com
+
+ # Once in your server, create the deploy folder:
+ ~@your.server.com$ mkdir /var/www/flipstack.com
+ ~@your.server.com$ chown -R username /var/www/flipstack.com
+
+### Step 3: Run 'mina setup'
+
+Back at your computer, do `mina setup` to set up the [folder
+structure](#directory_structure) in this path. This will connect to your server
+via SSH and create the right directories.
+
+ $ mina setup
+ -----> Creating folders... done.
+
+See [directory structure](#directory-structure) for more info.
+
+### Step 4: Deploy!
+
+Use `mina deploy` to run the `deploy` task defined in *config/deploy.rb*.
+
+ $ mina deploy
+ -----> Deploying to 2012-06-12-040248
+ ...
+ Lots of things happening...
+ ...
+ -----> Done.
+
+About deploy.rb
+---------------
+
+The file `deploy.rb` is simply a Rakefile invoked by Rake. In fact, `mina` is
+mostly an alias that invokes Rake to load `deploy.rb`.
+
+~~~ ruby
+# Sample config/deploy.rb
+set :domain, 'your.server.com'
+
+task :restart do
+ queue 'sudo service restart apache'
+end
+~~~
+
+As it's all Rake, you can define tasks that you can invoke using `mina`. In this
+example, it provides the `mina restart` command.
+
+The magic of Mina is in the new commands it gives you.
+
+The `queue` command queues up Bash commands to be run on the remote server.
+If you invoke `mina restart`, it will invoke the task above and run the queued
+commands on the remote server `your.server.com` via SSH.
+
+See [the command queue](#the-command-queue) for more information on the *queue*
+command.
+
+The command queue
+-----------------
+
+At the heart of it, Mina is merely sugar on top of Rake to queue commands
+and execute them remotely at the end. Take a look at this minimal *deploy.rb*
+configuration:
+
+~~~ ruby
+# config/deploy.rb
+set :user, 'john'
+set :domain, 'flipstack.com'
+
+task :logs do
+ queue 'echo "Contents of the log file are as follows:"'
+ queue "tail -f /var/log/apache.log"
+end
+~~~
+
+Once you type `mina logs` in your terminal, it invokes the *queue*d commands
+remotely on the server using the command `ssh john at flipstack.com`.
+
+~~~ sh
+$ mina logs --simulate
+# Execute the following commands via
+# ssh john at flipstack.com:
+#
+echo "Contents of the log file are as follows:"
+tail -f /var/log/apache.log
+~~~
+
+Subtasks
+--------
+
+Mina provides the helper `invoke` to invoke other tasks from a
+task.
+
+~~~ ruby
+# config/deploy.rb
+task :down do
+ invoke :maintenance_on
+ invoke :restart
+end
+
+task :maintenance_on
+ queue 'touch maintenance.txt'
+end
+
+task :restart
+ queue 'sudo service restart apache'
+end
+~~~
+
+In this example above, if you type `mina down`, it simply invokes the other
+subtasks which queues up their commands. The commands will be run after
+everything.
+
+Directory structure
+-------------------
+
+The deploy procedures make the assumption that you have a folder like so:
+
+ /var/www/flipstack.com/ # The deploy_to path
+ |- releases/ # Holds releases, one subdir per release
+ | |- 1/
+ | |- 2/
+ | |- 3/
+ | '- ...
+ |- shared/ # Holds files shared between releases
+ | |- logs/ # Log files are usually stored here
+ | `- ...
+ '- current/ # A symlink to the current release in releases/
+
+It also assumes that the `deploy_to` path is fully writeable/readable for the
+user we're going to SSH with.
+
+Deploying
+---------
+
+Mina provides the `deploy` command which *queue*s up a deploy script for
+you.
+
+~~~ ruby
+# config/deploy.rb
+set :domain, 'flipstack.com'
+set :user, 'flipstack'
+set :deploy_to, '/var/www/flipstack.com'
+set :repository, 'http://github.com/flipstack/flipstack.git'
+
+task :deploy do
+ deploy do
+ # Put things that prepare the empty release folder here.
+ # Commands queued here will be run on a new release directory.
+ invoke :'git:clone'
+ invoke :'bundle:install'
+
+ # These are instructions to start the app after it's been prepared.
+ to :launch do
+ queue "mkdir -p #{deploy_to}/#{current_path}/tmp/"
+ queue "touch #{deploy_to}/#{current_path}/tmp/restart.txt"
+ end
+
+ # This optional block defines how a broken release should be cleaned up.
+ to :clean do
+ queue 'log "failed deployment"'
+ end
+ end
+end
+~~~
+
+It works by capturing the *queue*d commands inside the block, wrapping them
+in a deploy script, then *queue*ing them back in.
+
+### How deploying works
+
+Here is an example of a deploy! (Note that some commands have been simplified
+to illustrate the point better.)
+
+### Step 1: Build it
+
+The deploy process builds a new temp folder with instructions you provide.
+In this example, it will do `git:clone` and `bundle:install`.
+
+ $ mina deploy --verbose
+ -----> Creating the build path
+ $ mkdir tmp/build-128293482394
+ -----> Cloning the Git repository
+ $ git clone https://github.com/flipstack/flipstack.git . -n --recursive
+ Cloning... done.
+ -----> Installing gem dependencies using Bundler
+ $ bundle install --without development:test
+ Using i18n (0.6.0)
+ Using multi_json (1.0.4)
+ ...
+ Your bundle is complete! It was installed to ./vendor/bundle
+
+### Step 2: Move it to releases
+
+Once the project has been built, it will be moved to `releases/`. A symlink
+called `current/` will be created to point to the active release.
+
+ $
+ -----> Moving to releases/4
+ $ mv "./tmp/build-128293482394" "releases/4"
+ -----> Symlinking to current
+ $ ln -nfs releases/4 current
+
+### Step 3: Launch it
+
+Invoke the commands queued up in the `to :launch` block. These often
+commands to restart the webserver process. Once this in complete, you're done!
+
+ $
+ -----> Launching
+ $ cd releases/4
+ $ sudo service nginx restart
+ -----> Done. Deployed v4
+
+### What about failure?
+
+If it fails at any point, the release path will be deleted. If any commands are
+queued using the `to :clean` block, they will be run. It will be as if nothing
+happened. Lets see what happens if a build fails:
+
+ $
+ -----> Launching
+ $ cd releases/4
+ $ sudo service nginx restart
+ Starting nginx... error: can't start service
+ -----> ERROR: Deploy failed.
+ -----> Cleaning up build
+ $ rm -rf tmp/build-128293482394
+ -----> Unlinking current
+ $ ln -nfs releases/3 current
+ OK
+
+Command line options
+--------------------
+
+Basic usage:
+
+ $ mina [OPTIONS] [TASKS] [VAR1=val VAR2=val ...]
+
+### Options
+
+* `-v` / `--verbose` - This will show commands being done on the server. Off by
+ default.
+
+* `-S` / `--simulate` - This will not invoke any SSH connections; instead, it
+ will simply output the script it builds.
+
+* `-t` / `--trace` - Show backtraces when errors occur.
+
+* `-f FILE` - Use a custom deploy.rb configuration.
+
+* `-V` / `--version` - Shows the current version.
+
+### Tasks
+
+There are many tasks available. See the [tasks reference](http://mina-deploy.github.io/mina/tasks/index.html), or
+type `mina tasks`.
+
+### Variables
+
+You may specify additional variables in the `KEY=value` style, just like Rake.
+You can add as many variables as needed.
+
+ $ mina restart on=staging
+
+ # This sets the ENV['on'] variable to 'staging'.
+
+
+# Helpers
+
+### invoke
+Invokes another Rake task. By default if the task has already been invoked it will not been executed again (see the `:reenable` option).
+
+Invokes the task given in `task`. Returns nothing.
+
+~~~ ruby
+invoke :'git:clone'
+invoke :restart
+~~~
+
+__Options:__
+ `:reenable` (bool) - Execute the task even next time. Defaults to `false`
+
+### erb
+Evaluates an ERB block in the current scope and returns a string.
+
+~~~ ruby
+a = 1
+b = 2
+# Assuming foo.erb is <%= a %> and <%= b %>
+puts erb('foo.erb')
+#=> "1 and 2"
+~~~
+
+Returns the output string of the ERB template.
+
+### run!
+SSHs into the host and runs the code that has been queued.
+
+This is already automatically invoked before Rake exits to run all
+commands that have been queued up.
+
+~~~ ruby
+queue "sudo restart"
+run!
+~~~
+
+Returns nothing.
+
+### report_time
+Report time elapsed in the block.
+Returns the output of the block.
+
+~~~ ruby
+report_time do
+ sleep 2
+ # do other things
+end
+# Output:
+# Elapsed time: 2.00 seconds
+~~~
+
+### measure
+Measures the time (in seconds) a block takes.
+Returns a [time, output] tuple.
+
+### mina_cleanup
+__Internal:__ Invoked when Rake exits.
+
+Returns nothing.
+
+## Errors
+
+### die
+Exits with a nice looking message.
+Returns nothing.
+
+~~~ ruby
+die 2
+die 2, "Tests failed"
+~~~
+
+### error
+__Internal:__ Prints to stdout.
+Consider using `print_error` instead.
+
+## Queueing
+
+### queue
+Queues code to be run.
+
+This queues code to be run to the current code bucket (defaults to `:default`).
+To get the things that have been queued, use commands[:default]
+
+Returns nothing.
+
+~~~ ruby
+queue "sudo restart"
+queue "true"
+commands == ['sudo restart', 'true']
+~~~
+
+### queue!
+Shortcut for `queue`ing a command that shows up in verbose mode.
+
+### echo_cmd
+Converts a bash command to a command that echoes before execution.
+Used to show commands in verbose mode. This does nothing unless verbose mode is on.
+
+Returns a string of the compound bash command, typically in the format of
+`echo xx && xx`. However, if `verbose_mode?` is false, it returns the
+input string unharmed.
+
+~~~ ruby
+echo_cmd("ln -nfs releases/2 current")
+#=> echo "$ ln -nfs releases/2 current" && ln -nfs releases/2 current
+~~~
+
+## Commands
+
+### commands
+Returns an array of queued code strings.
+
+You may give an optional `aspect`.
+
+Returns an array of strings.
+
+~~~ ruby
+queue "sudo restart"
+queue "true"
+to :clean do
+ queue "rm"
+end
+commands == ["sudo restart", "true"]
+commands(:clean) == ["rm"]
+~~~
+
+### isolate
+Starts a new block where new `commands` are collected.
+
+Returns nothing.
+
+~~~ ruby
+queue "sudo restart"
+queue "true"
+commands.should == ['sudo restart', 'true']
+isolate do
+ queue "reload"
+ commands.should == ['reload']
+end
+commands.should == ['sudo restart', 'true']
+~~~
+
+### in_directory
+Starts a new block where #commands are collected, to be executed inside `path`.
+
+Returns nothing.
+
+~~~ ruby
+in_directory './webapp' do
+ queue "./reload"
+end
+commands.should == ['cd ./webapp && (./reload && true)']
+~~~
+
+### to
+Defines instructions on how to do a certain thing.
+This makes the commands that are `queue`d go into a different bucket in commands.
+
+Returns nothing.
+
+~~~ ruby
+to :prepare do
+ run "bundle install"
+end
+to :launch do
+ run "nginx -s restart"
+end
+commands(:prepare) == ["bundle install"]
+commands(:restart) == ["nginx -s restart"]
+~~~
+
+## Settings helpers
+
+### set
+Sets settings.
+Sets given symbol `key` to value in `value`.
+
+Returns the value.
+
+~~~ ruby
+set :domain, 'kickflip.me'
+~~~
+
+### set_default
+Sets default settings.
+Sets given symbol `key` to value in `value` only if the key isn't set yet.
+
+Returns the value.
+
+~~~ ruby
+set_default :term_mode, :pretty
+set :term_mode, :system
+settings.term_mode.should == :system
+set :term_mode, :system
+set_default :term_mode, :pretty
+settings.term_mode.should == :system
+~~~
+
+### settings
+Accesses the settings hash.
+
+~~~ ruby
+set :domain, 'kickflip.me'
+settings.domain #=> 'kickflip.me'
+domain #=> 'kickflip.me'
+~~~
+
+### method_missing
+Hook to get settings.
+See #settings for an explanation.
+
+Returns things.
+
+## Command line mode helpers
+
+### verbose_mode?
+Checks if Rake was invoked with --verbose.
+
+Returns true or false.
+
+~~~ ruby
+if verbose_mode?
+ queue %[echo "-----> Starting a new process"]
+end
+~~~
+
+### simulate_mode?
+Checks if Rake was invoked with --simulate.
+
+Returns true or false.
+
+## Internal helpers
+
+### indent
+Indents a given code block with `count` spaces before it.
+
+### unindent
+__Internal:__ Normalizes indentation on a given string.
+
+Returns the normalized string without extraneous indentation.
+
+~~~ ruby
+puts unindent %{
+ Hello
+ There
+}
+# Output:
+# Hello
+# There
+~~~
+
+### reindent
+Resets the indentation on a given code block.
+
+### capture
+Returns the output of command via SSH.
+
+# Helpers: Deploy helpers
+Helpers for deployment.
+
+### deploy
+Wraps the things inside it in a deploy script and queues it.
+This generates a script using deploy_script and queues it.
+
+Returns nothing.
+
+### deploy_script
+Wraps the things inside it in a deploy script.
+
+~~~ ruby
+script = deploy_script do
+ invoke :'git:checkout'
+end
+queue script
+~~~
+
+Returns the deploy script as a string, ready for `queue`ing.
+
+# Modules: Bundler
+Adds settings and tasks for managing Ruby Bundler.
+
+~~~ ruby
+require 'mina/bundler'
+~~~
+
+## Settings
+Any and all of these settings can be overriden in your `deploy.rb`.
+
+### bundle_bin
+Sets the bundle path.
+
+### bundle_path
+Sets the path to where the gems are expected to be.
+
+This path will be symlinked to `./shared/bundle` so that the gems cache will
+be shared between all releases.
+
+### bundle_options
+Sets the options for installing gems via Bundler.
+
+## Deploy tasks
+These tasks are meant to be invoked inside deploy scripts, not invoked on
+their own.
+
+### bundle:install
+Installs gems.
+
+# Modules: Default
+This module is loaded when invoking `mina` with or without a project.
+
+## Settings
+Here are some of the common settings. All settings are optional unless
+otherwise noted.
+
+### deploy_to
+(Required) Path to deploy to.
+
+### domain
+(Required) Host name to deploy to.
+
+### port
+SSH port number.
+
+### forward_agent
+If set to `true`, enables SSH agent forwarding.
+
+### identity_file
+The local path to the SSH private key file.
+
+### ssh_options
+Switches to be passed to the `ssh` command.
+
+## Tasks
+Any and all of these settings can be overriden in your `deploy.rb`.
+
+### environment
+Make the `:environment` task exist by default. This is meant to be overridden
+by users.
+
+### init
+Initializes a new Mina project.
+
+~~~ ruby
+$ mina init
+~~~
+
+### help
+Shows the help screen.
+
+### tasks
+Display all tasks in a nice table.
+
+~~~ ruby
+$ mina tasks
+~~~
+
+# Modules: Deployment
+This module is automatically loaded for all Mina projects.
+
+## Settings
+Any and all of these settings can be overriden in your `deploy.rb`.
+
+### releases_path
+(default: 'releases')
+
+### shared_path
+(default: 'shared')
+
+### current_path
+(default: 'current_path')
+
+### lock_file
+Name of the file to generate while a deploy is currently ongoing.
+(default: 'deploy.lock')
+
+### keep_releases
+Number of releases to keep when doing the `deploy:cleanup` task.
+(default: 5)
+
+## Tasks
+
+### deploy:force_unlock
+Forces a deploy unlock by deleting the lock file.
+
+~~~ ruby
+$ mina deploy:force_unlock
+~~~
+
+You can also combine that task with `deploy`:
+
+~~~ ruby
+$ mina deploy:force_unlock deploy
+~~~
+
+### deploy:link_shared_paths
+Links the shared paths in the `shared_paths` setting.
+
+### deploy:cleanup
+Cleans up old releases.
+
+By default, the last 5 releases are kept on each server (though you can
+change this with the keep_releases setting). All other deployed revisions
+are removed from the servers."
+
+### setup
+Sets up a site's directory structure.
+
+### run[]
+Runs a command on a server.
+
+~~~ ruby
+$ mina run[tail -f logs.txt]
+~~~
+
+# Modules: Foreman
+Adds settings and tasks for managing projects with [foreman].
+
+NOTE: Requires sudo privileges
+
+[foreman]: http://rubygems.org/ddolar/foreman
+
+ require 'mina/foreman'
+
+## Common usage
+
+ set :application, "app-name"
+
+ task :deploy => :environment do
+~~~ ruby
+ deploy do
+ # ...
+ invoke 'foreman:export'
+ # ...
+ end
+ to :launch do
+ invoke 'foreman:restart'
+ end
+~~~
+
+ end
+
+## Settings
+Any and all of these settings can be overriden in your `deploy.rb`.
+
+### foreman_app
+Sets the service name that foreman will export to upstart. Uses *application*
+variable as a default. It should be set, otherwise export command will fail.
+
+### foreman_user
+Sets the user under which foreman will execute the service. Defaults to *user*
+
+### foreman_log
+Sets the foreman log path. Defaults to *shared/log*
+
+encoding: utf-8
+
+# Modules: Git
+Adds settings and tasks related to managing Git.
+
+~~~ ruby
+require 'mina/git'
+~~~
+
+## Settings
+Any and all of these settings can be overriden in your `deploy.rb`.
+
+### branch
+Sets the branch to be deployed.
+
+## Deploy tasks
+These tasks are meant to be invoked inside deploy scripts, not invoked on
+their own.
+
+### git:clone
+Clones the Git repository. Meant to be used inside a deploy script.
+
+# Modules: Rails
+Adds settings and tasks for managing Rails projects.
+
+~~~ ruby
+require 'mina/rails'
+~~~
+
+## Settings
+Any and all of these settings can be overriden in your `deploy.rb`.
+
+### rails_env
+Sets the Rails environment for `rake` and `rails` commands.
+
+Note that changing this will NOT change the environment that your application
+is run in.
+
+### bundle_prefix
+Prefix for Bundler commands. Often to something like `RAILS_ENV=production
+bundle exec`.
+
+~~~ ruby
+queue! "#{bundle_prefix} annotate -r"
+~~~
+
+### rake
+The prefix for `rake` commands. Use like so:
+
+~~~ ruby
+queue! "#{rake} db:migrate"
+~~~
+
+### rails
+The prefix for `rails` commands. Use like so:
+
+~~~ ruby
+queue! "#{rails} console"
+~~~
+
+### asset_paths
+The paths to be checked.
+
+Whenever assets are compiled, the asset files are checked if they have
+changed from the previous release.
+
+If they're unchanged, compiled assets will simply be copied over to the new
+release.
+
+Override this if you have custom asset paths declared in your Rails's
+`config.assets.paths` setting.
+
+### rake_assets_precompile
+The command to invoke when precompiling assets.
+Override me if you like.
+
+----
+
+Macro used later by :rails, :rake, etc
+
+## Command-line tasks
+These tasks can be invoked in the command line.
+
+### rails[]
+Invokes a rails command.
+
+~~~ ruby
+$ mina rails[console]
+~~~
+
+### rake[]
+Invokes a rake command.
+
+~~~ ruby
+$ mina rake db:cleanup
+~~~
+
+### console
+Opens the Ruby console for the currently-deployed version.
+
+~~~ ruby
+$ mina console
+~~~
+
+## Deploy tasks
+These tasks are meant to be invoked inside deploy scripts, not invoked on
+their own.
+
+### rails:db_migrate
+
+### rails:db_migrate:force
+
+### rails:assets_precompile:force
+
+### rails:assets_precompile
+
+# Modules: rbenv
+Adds settings and tasks for managing [rbenv] installations.
+
+[rbenv]: https://github.com/sstephenson/rbenv
+
+~~~ ruby
+require 'mina/rbenv'
+~~~
+
+## Common usage
+
+~~~ ruby
+task :environment do
+ invoke :'rbenv:load'
+end
+task :deploy => :environment do
+ ...
+end
+~~~
+
+## Settings
+Any and all of these settings can be overriden in your `deploy.rb`.
+
+### rbenv_path
+Sets the path where *rbenv* is installed.
+
+You may override this if rbenv is placed elsewhere in your setup.
+
+## Tasks
+
+### rbenv:load
+Loads the *rbenv* runtime.
+
+# Modules: RVM
+Adds settings and tasks for managing [RVM] installations.
+
+[rvm]: http://rvm.io
+
+~~~ ruby
+require 'mina/rvm'
+~~~
+
+## Common usage
+
+~~~ ruby
+task :environment do
+ invoke :'rvm:use[ruby-1.9.3-p125 at gemset_name]'
+end
+task :deploy => :environment do
+ ...
+end
+~~~
+
+## Settings
+Any and all of these settings can be overriden in your `deploy.rb`.
+
+### rvm_path
+Sets the path to RVM.
+
+You can override this in your projects if RVM is installed in a different
+path, say, if you have a system-wide RVM install.
+
+## Tasks
+
+### rvm:use[]
+Uses a given RVM environment provided as an argument.
+
+This is usually placed in the `:environment` task.
+
+~~~ ruby
+task :environment do
+ invoke :'rvm:use[ruby-1.9.3-p125 at gemset_name]'
+end
+~~~
+
+### rvm:wrapper[]
+Creates a rvm wrapper for a given executable.
+
+This is usually placed in the `:setup` task.
+
+~~~ ruby
+task ::setup => :environment do
+ ...
+ invoke :'rvm:wrapper[ruby-1.9.3-p125 at gemset_name,wrapper_name,binary_name]'
+end
+~~~
+
+Adds settings and tasks for managing projects with [whenever].
+[whenever]: http://rubygems.org/gems/whenever
+
+Acknowledgements
+----------------
+
+© 2012-2014, Nadarei. Released under the [MIT
+License](http://www.opensource.org/licenses/mit-license.php).
+
+Mina is authored and maintained by [Rico Sta. Cruz][rsc] and [Michael
+Galero][mg] with help from its [contributors][c]. It is sponsored by our
+startup, [Nadarei][nd].
+
+ * [Nadarei](http://nadarei.co) (nadarei.co)
+ * [Github](http://github.com/nadarei) (@nadarei)
+
+Rico:
+
+ * [My website](http://ricostacruz.com) (ricostacruz.com)
+ * [Github](http://github.com/rstacruz) (@rstacruz)
+ * [Twitter](http://twitter.com/rstacruz) (@rstacruz)
+
+Michael:
+
+ * [My website][mg] (michaelgalero.com)
+ * [Github](http://github.com/mikong) (@mikong)
+
+[rsc]: http://ricostacruz.com
+[mg]: http://devblog.michaelgalero.com/
+[c]: https://github.com/mina-deploy/mina/graphs/contributors
+[nd]: http://nadarei.co
+[issues]: https://github.com/mina-deploy/mina/issues
+[trello]: https://trello.com/board/mina/4fc8b3023d9c9a4d72e573e6
+
diff --git a/bin/mina b/bin/mina
new file mode 100755
index 0000000..7a38908
--- /dev/null
+++ b/bin/mina
@@ -0,0 +1,65 @@
+#!/usr/bin/env ruby
+$:.unshift File.expand_path('../../lib', __FILE__)
+
+require 'rubygems' unless Object.const_defined?(:Gem)
+require 'mina'
+require 'rake'
+
+# Intercept: if invoked as 'mina --help', don't let it pass through Rake, or else
+# we'll see the Rake help screen. Redirect it to 'mina help'.
+if ARGV.delete('--help') || ARGV.delete('-h')
+ ARGV << 'help'
+end
+
+if ARGV.delete('--version') || ARGV.delete('-V')
+ puts "Mina, version v#{Mina.version}"
+ exit
+end
+
+if ARGV.delete('--simulate') || ARGV.delete('-S')
+ ENV['simulate'] = '1'
+end
+
+scope = self
+
+Rake.application.instance_eval do
+ standard_exception_handling do
+ begin
+ # Initialize Rake and make it think it's Mina.
+ init 'mina'
+
+ # (The only way @rakefiles has only 1 value is if -f is specified.)
+ custom_rakefile = (@rakefiles.size == 1)
+ @rakefiles = ['Minafile', 'config/deploy.rb'] unless custom_rakefile
+
+ # Workaround: Rake 0.9+ doesn't record task descriptions unless it's needed.
+ # Need it for 'mina help'
+ if Rake::TaskManager.respond_to?(:record_task_metadata)
+ Rake::TaskManager.record_task_metadata = true
+ end
+
+ # Load the Mina Rake DSL.
+ require 'mina/rake'
+
+ # Allow running without a Rakefile
+ begin
+ load_rakefile if have_rakefile || custom_rakefile
+ rescue Exception
+ puts "Error loading Rakefile!"
+ raise "There may be a problem with config/deploy.rb and/or Rakefile"
+ end
+
+ # Run tasks
+ top_level
+
+ scope.mina_cleanup! if top_level_tasks.any?
+
+ rescue Mina::Failed => e
+ puts ""
+ scope.print_error "Command failed."
+ scope.print_stderr "#{e.message}"
+ exit(e.exitstatus > 255 ? e.exitstatus >> 8 : e.exitstatus)
+ end
+ end
+end
+
diff --git a/data/deploy.rb b/data/deploy.rb
new file mode 100644
index 0000000..56c2d57
--- /dev/null
+++ b/data/deploy.rb
@@ -0,0 +1,80 @@
+require 'mina/bundler'
+require 'mina/rails'
+require 'mina/git'
+# require 'mina/rbenv' # for rbenv support. (http://rbenv.org)
+# require 'mina/rvm' # for rvm support. (http://rvm.io)
+
+# Basic settings:
+# domain - The hostname to SSH to.
+# deploy_to - Path to deploy into.
+# repository - Git repo to clone from. (needed by mina/git)
+# branch - Branch name to deploy. (needed by mina/git)
+
+set :domain, 'foobar.com'
+set :deploy_to, '/var/www/foobar.com'
+set :repository, 'git://...'
+set :branch, 'master'
+
+# For system-wide RVM install.
+# set :rvm_path, '/usr/local/rvm/bin/rvm'
+
+# Manually create these paths in shared/ (eg: shared/config/database.yml) in your server.
+# They will be linked in the 'deploy:link_shared_paths' step.
+set :shared_paths, ['config/database.yml', 'log']
+
+# Optional settings:
+# set :user, 'foobar' # Username in the server to SSH to.
+# set :port, '30000' # SSH port number.
+# set :forward_agent, true # SSH forward_agent.
+
+# This task is the environment that is loaded for most commands, such as
+# `mina deploy` or `mina rake`.
+task :environment do
+ # If you're using rbenv, use this to load the rbenv environment.
+ # Be sure to commit your .rbenv-version to your repository.
+ # invoke :'rbenv:load'
+
+ # For those using RVM, use this to load an RVM version at gemset.
+ # invoke :'rvm:use[ruby-1.9.3-p125 at default]'
+end
+
+# Put any custom mkdir's in here for when `mina setup` is ran.
+# For Rails apps, we'll make some of the shared paths that are shared between
+# all releases.
+task :setup => :environment do
+ queue! %[mkdir -p "#{deploy_to}/#{shared_path}/log"]
+ queue! %[chmod g+rx,u+rwx "#{deploy_to}/#{shared_path}/log"]
+
+ queue! %[mkdir -p "#{deploy_to}/#{shared_path}/config"]
+ queue! %[chmod g+rx,u+rwx "#{deploy_to}/#{shared_path}/config"]
+
+ queue! %[touch "#{deploy_to}/#{shared_path}/config/database.yml"]
+ queue %[echo "-----> Be sure to edit '#{deploy_to}/#{shared_path}/config/database.yml'."]
+end
+
+desc "Deploys the current version to the server."
+task :deploy => :environment do
+ deploy do
+ # Put things that will set up an empty directory into a fully set-up
+ # instance of your project.
+ invoke :'git:clone'
+ invoke :'deploy:link_shared_paths'
+ invoke :'bundle:install'
+ invoke :'rails:db_migrate'
+ invoke :'rails:assets_precompile'
+ invoke :'deploy:cleanup'
+
+ to :launch do
+ queue "mkdir -p #{deploy_to}/#{current_path}/tmp/"
+ queue "touch #{deploy_to}/#{current_path}/tmp/restart.txt"
+ end
+ end
+end
+
+# For help in making your deploy script, see the Mina documentation:
+#
+# - http://nadarei.co/mina
+# - http://nadarei.co/mina/tasks
+# - http://nadarei.co/mina/settings
+# - http://nadarei.co/mina/helpers
+
diff --git a/data/deploy.sh.erb b/data/deploy.sh.erb
new file mode 100644
index 0000000..172b592
--- /dev/null
+++ b/data/deploy.sh.erb
@@ -0,0 +1,106 @@
+<%
+ prepare = commands(:default).map { |s| "(\n\n#{indent 2, s}\n\n)" }.join(" && ")
+ launch = commands(:launch).map { |s| "(\n\n#{indent 2, s}\n\n)" }.join(" && ")
+ clean = commands(:clean).map { |s| "(\n\n#{indent 2, s}\n\n)" }.join(" && ")
+%>
+#!/usr/bin/env bash
+
+# Go to the deploy path
+cd "<%= deploy_to %>" || (
+ echo "! ERROR: not set up."
+ echo "The path '<%= deploy_to %>' is not accessible on the server."
+ echo "You may need to run 'mina setup' first."
+ false
+) || exit 15
+
+# Check releases path
+if [ ! -d "<%= releases_path %>" ]; then
+ echo "! ERROR: not set up."
+ echo "The directory '<%= releases_path %>' does not exist on the server."
+ echo "You may need to run 'mina setup' first."
+ exit 16
+fi
+
+# Check lockfile
+if [ -e "<%= lock_file %>" ]; then
+ echo "! ERROR: another deployment is ongoing."
+ echo "The file '<%= lock_file %>' was found."
+ echo "If no other deployment is ongoing, delete the file to continue."
+ exit 17
+fi
+
+# Determine $previous_path and other variables
+[ -h "<%= current_path %>" ] && [ -d "<%= current_path %>" ] && previous_path=$(cd "<%= current_path %>" >/dev/null && pwd -LP)
+build_path="./tmp/build-`date +%s`$RANDOM"
+version=$((`cat "<%= deploy_to %>/last_version" 2>/dev/null`+1))
+release_path="<%= releases_path %>/$version"
+
+# Sanity check
+if [ -e "$build_path" ]; then
+ echo "! ERROR: Path already exists."
+ exit 18
+fi
+
+# Bootstrap script (in deployer)
+(
+ echo "-----> Creating a temporary build path"
+ <%= echo_cmd %[touch "#{lock_file}"] %> &&
+ <%= echo_cmd %[mkdir -p "$build_path"] %> &&
+ <%= echo_cmd %[cd "$build_path"] %> &&
+ (
+<%= indent 4, (prepare.empty? ? "true" : prepare) %>
+ )
+) &&
+
+#
+# Rename to the real release path, then symlink 'current'
+(
+ echo "-----> Build finished"
+ echo "-----> Moving build to $release_path"
+ <%= echo_cmd %[mv "$build_path" "$release_path"] %> &&
+
+ echo "-----> Updating the <%= current_path %> symlink" &&
+ <%= echo_cmd %[ln -nfs "$release_path" "#{current_path}"] %>
+) &&
+
+# ============================
+# === Start up serve => (in deployer)
+(
+ echo "-----> Launching"
+ <%= echo_cmd %[cd "$release_path"] %>
+<%= indent 2, (launch.empty? ? "true" : launch) %>
+) &&
+
+# ============================
+# === Complete & unlock
+(
+ rm -f "<%= lock_file %>"
+ echo "$version" > "./last_version"
+ echo "-----> Done. Deployed v$version"
+) ||
+
+# ============================
+# === Failed deployment
+(
+ echo "! ERROR: Deploy failed."
+
+<%= indent 2, clean %>
+
+ echo "-----> Cleaning up build"
+ [ -e "$build_path" ] && (
+ <%= echo_cmd %[rm -rf "$build_path"] %>
+ )
+ [ -e "$release_path" ] && (
+ echo "Deleting release"
+ <%= echo_cmd %[rm -rf "$release_path"] %>
+ )
+ (
+ echo "Unlinking current"
+ [ -n "$previous_path" ] && <%= echo_cmd %[ln -nfs "$previous_path" "#{current_path}"] %>
+ )
+
+ # Unlock
+ <%= echo_cmd %[rm -f "#{lock_file}"] %>
+ echo "OK"
+ exit 19
+)
diff --git a/lib/mina.rb b/lib/mina.rb
new file mode 100644
index 0000000..3428ea8
--- /dev/null
+++ b/lib/mina.rb
@@ -0,0 +1,23 @@
+module Mina
+ PREFIX = File.dirname(__FILE__)
+ ROOT = File.expand_path('../../', __FILE__)
+
+ require 'mina/version'
+
+ autoload :DeployHelpers, 'mina/deploy_helpers'
+ autoload :OutputHelpers, 'mina/output_helpers'
+ autoload :SshHelpers, 'mina/ssh_helpers'
+ autoload :ExecHelpers, 'mina/exec_helpers'
+ autoload :Helpers, 'mina/helpers'
+ autoload :Settings, 'mina/settings'
+ autoload :Tools, 'mina/tools'
+
+ Error = Class.new(Exception)
+ class Failed < Error
+ attr_accessor :exitstatus
+ end
+
+ def self.root_path(*a)
+ File.join ROOT, *a
+ end
+end
diff --git a/lib/mina/bundler.rb b/lib/mina/bundler.rb
new file mode 100644
index 0000000..d41fdc8
--- /dev/null
+++ b/lib/mina/bundler.rb
@@ -0,0 +1,49 @@
+# # Modules: Bundler
+# Adds settings and tasks for managing Ruby Bundler.
+#
+# require 'mina/bundler'
+
+# ## Settings
+# Any and all of these settings can be overriden in your `deploy.rb`.
+
+# ### bundle_bin
+# Sets the bundle path.
+
+set_default :bundle_bin, 'bundle'
+
+# ### bundle_path
+# Sets the path to where the gems are expected to be.
+#
+# This path will be symlinked to `./shared/bundle` so that the gems cache will
+# be shared between all releases.
+
+set_default :bundle_path, './vendor/bundle'
+
+# ### bundle_withouts
+# Sets the colon-separated list of groups to be skipped from installation.
+
+set_default :bundle_withouts, 'development:test'
+
+# ### bundle_options
+# Sets the options for installing gems via Bundler.
+
+set_default :bundle_options, lambda { %{--without #{bundle_withouts} --path "#{bundle_path}" --deployment} }
+
+# ## Deploy tasks
+# These tasks are meant to be invoked inside deploy scripts, not invoked on
+# their own.
+
+namespace :bundle do
+ # ### bundle:install
+ # Installs gems.
+ desc "Install gem dependencies using Bundler."
+ task :install do
+ queue %{
+ echo "-----> Installing gem dependencies using Bundler"
+ #{echo_cmd %[mkdir -p "#{deploy_to}/#{shared_path}/bundle"]}
+ #{echo_cmd %[mkdir -p "#{File.dirname bundle_path}"]}
+ #{echo_cmd %[ln -s "#{deploy_to}/#{shared_path}/bundle" "#{bundle_path}"]}
+ #{echo_cmd %[#{bundle_bin} install #{bundle_options}]}
+ }
+ end
+end
diff --git a/lib/mina/chruby.rb b/lib/mina/chruby.rb
new file mode 100644
index 0000000..115c0ed
--- /dev/null
+++ b/lib/mina/chruby.rb
@@ -0,0 +1,49 @@
+# # Modules: chruby
+# Adds settings and tasks for managing [chruby] installations.
+#
+# [chruby]: https://github.com/postmodern/chruby
+#
+# require 'mina/chruby'
+#
+# ## Common usage
+#
+# task :environment do
+# invoke :'chruby[ruby-1.9.3-p392]'
+# end
+#
+# task :deploy => :environment do
+# ...
+# end
+
+# ## Settings
+# Any and all of these settings can be overriden in your `deploy.rb`.
+
+# ### chruby_path
+# Path where *chruby* init scripts are installed.
+#
+set_default :chruby_path, "/etc/profile.d/chruby.sh"
+
+# ## Tasks
+
+# ### chruby[version]
+# Switch to given Ruby version
+
+task :chruby, :env do |t, args|
+ unless args[:env]
+ print_error "Task 'chruby' needs a Ruby version as an argument."
+ print_error "Example: invoke :'chruby[ruby-1.9.3-p392]'"
+ die
+ end
+
+ queue %{
+ echo "-----> chruby to version: '#{args[:env]}'"
+
+ if [[ ! -s "#{chruby_path}" ]]; then
+ echo "! chruby.sh init file not found"
+ exit 1
+ fi
+
+ source #{chruby_path}
+ #{echo_cmd %{chruby "#{args[:env]}"}} || exit 1
+ }
+end
diff --git a/lib/mina/default.rb b/lib/mina/default.rb
new file mode 100644
index 0000000..d3de035
--- /dev/null
+++ b/lib/mina/default.rb
@@ -0,0 +1,145 @@
+# # Modules: Default
+# This module is loaded when invoking `mina` with or without a project.
+
+# ## Settings
+# Here are some of the common settings. All settings are optional unless
+# otherwise noted.
+#
+# ### deploy_to
+# (Required) Path to deploy to.
+#
+# ### domain
+# (Required) Host name to deploy to.
+#
+# ### port
+# SSH port number.
+#
+# ### forward_agent
+# If set to `true`, enables SSH agent forwarding.
+#
+# ### identity_file
+# The local path to the SSH private key file.
+#
+# ### ssh_options
+# Switches to be passed to the `ssh` command.
+
+# ## Tasks
+# Any and all of these settings can be overriden in your `deploy.rb`.
+
+# ### environment
+# Make the `:environment` task exist by default. This is meant to be overridden
+# by users.
+
+task :environment do
+end
+
+# ### init
+# Initializes a new Mina project.
+#
+# $ mina init
+
+desc "Creates a sample config file."
+task :init => :environment do
+ name = Rake.application.name
+ config_file = Rake.application.rakefile
+
+ unless config_file.to_s.empty?
+ print_str "! You already have #{config_file}."
+ exit 8
+ end
+
+ outfile = './config/deploy.rb'
+ require 'fileutils'
+ FileUtils.mkdir_p './config'
+ FileUtils.cp Mina.root_path('data/deploy.rb'), outfile
+
+ print_str "-----> Created #{outfile}"
+ print_str "Edit this file, then run `#{name} setup` after."
+end
+
+task :default => :help
+
+module HelpHelpers
+ def get_tasks(&blk)
+ Rake.application.tasks.select &blk
+ end
+
+ def print_tasks(tasks, width=nil)
+ name = Rake.application.name
+
+ width ||= tasks.map { |t| t.name_with_args.length }.max || 10
+ tasks.each do |t|
+ if t.comment
+ puts " #{name} %-#{width}s # %s" % [ t.name_with_args, t.comment ]
+ else
+ puts " #{name} %s" % [ t.name_with_args ]
+ end
+ end
+ end
+
+ SYSTEM_TASKS = %w[help tasks init]
+ def system_tasks() get_tasks { |t| SYSTEM_TASKS.include? t.name }; end
+ def top_tasks() get_tasks { |t| ! t.name.include?(':') && t.comment && !system_tasks.include?(t) }; end
+ def sub_tasks() get_tasks { |t| t.name.include?(':') }; end
+
+ def show_task_help(options={})
+ puts "Basic usage:"
+ print_tasks system_tasks
+
+ if top_tasks.any?
+ puts "\nServer tasks:"
+ print_tasks top_tasks
+ end
+
+ if sub_tasks.any? && options[:full]
+ puts "\nMore tasks:"
+ print_tasks sub_tasks
+ end
+ end
+end
+
+extend HelpHelpers
+
+# ### help
+# Shows the help screen.
+
+desc "Show help."
+task :help do
+ name = Rake.application.name
+
+ puts "#{name} - Really fast server deployment and automation tool\n\n"
+ puts "Options:"
+
+ opts = [
+ [ "-h, --help", "Show help" ],
+ [ "-V, --version", "Show program version" ],
+ [ "-v, --verbose", "Show commands as they happen" ],
+ [ "-S, --simulate", "Run in simulation mode" ],
+ [ "-t, --trace", "Show backtraces when errors occur" ],
+ [ "-f FILE", "Use FILE as the deploy configuration" ]
+ ]
+ opts.each { |args| puts " %-17s %s" % args }
+ puts ""
+
+ show_task_help
+
+ unless Rake.application.have_rakefile
+ puts ""
+ puts "Run this command in a project with a 'config/deploy.rb' file to see more options."
+ end
+
+ puts ""
+ puts "All of Rake's options are also available as '#{name}' options. See 'rake --help'"
+ puts "for more information."
+ exit
+end
+
+# ### tasks
+# Display all tasks in a nice table.
+#
+# $ mina tasks
+
+desc "Show all tasks."
+task :tasks do
+ show_task_help :full => true
+end
diff --git a/lib/mina/deploy.rb b/lib/mina/deploy.rb
new file mode 100644
index 0000000..1ff8780
--- /dev/null
+++ b/lib/mina/deploy.rb
@@ -0,0 +1,138 @@
+# # Modules: Deployment
+# This module is automatically loaded for all Mina projects.
+
+# ## Settings
+# Any and all of these settings can be overriden in your `deploy.rb`.
+
+# ### releases_path
+# (default: 'releases')
+set_default :releases_path, "releases"
+
+# ### shared_path
+# (default: 'shared')
+set_default :shared_path, "shared"
+
+# ### current_path
+# (default: 'current_path')
+set_default :current_path, "current"
+
+# ### lock_file
+# Name of the file to generate while a deploy is currently ongoing.
+# (default: 'deploy.lock')
+set_default :lock_file, "deploy.lock"
+
+# ### keep_releases
+# Number of releases to keep when doing the `deploy:cleanup` task.
+# (default: 5)
+set_default :keep_releases, 5
+
+namespace :deploy do
+ # ## Tasks
+
+ # ### deploy:force_unlock
+ # Forces a deploy unlock by deleting the lock file.
+ #
+ # $ mina deploy:force_unlock
+ #
+ # You can also combine that task with `deploy`:
+ #
+ # $ mina deploy:force_unlock deploy
+
+ desc "Forces a deploy unlock."
+ task :force_unlock do
+ queue %{echo "-----> Unlocking"}
+ queue echo_cmd %{rm -f "#{deploy_to}/#{lock_file}"}
+ end
+
+ # ### deploy:link_shared_paths
+ # Links the shared paths in the `shared_paths` setting.
+
+ desc "Links paths set in :shared_paths."
+ task :link_shared_paths do
+ dirs = settings.shared_paths!.map { |file| File.dirname("./#{file}") }.uniq
+
+ cmds = dirs.map do |dir|
+ echo_cmd %{mkdir -p "#{dir}"}
+ end
+
+ cmds += shared_paths.map do |file|
+ [
+ echo_cmd(%{rm -rf "./#{file}"}),
+ echo_cmd(%{ln -s "#{deploy_to}/#{shared_path}/#{file}" "./#{file}"})
+ ]
+ end
+
+ queue %{
+ echo "-----> Symlinking shared paths"
+ #{cmds.flatten.join(" &&\n")}
+ }
+ end
+
+ # ### deploy:cleanup
+ # Cleans up old releases.
+ #
+ # By default, the last 5 releases are kept on each server (though you can
+ # change this with the keep_releases setting). All other deployed revisions
+ # are removed from the servers."
+
+ desc "Clean up old releases."
+ task :cleanup do
+ queue %{
+ echo "-----> Cleaning up old releases (keeping #{keep_releases!})"
+ #{echo_cmd %{cd "#{deploy_to!}/#{releases_path!}" || exit 15}}
+ #{echo_cmd %{count=`ls -1d [0-9]* | sort -rn | wc -l`}}
+ #{echo_cmd %{remove=$((count > #{keep_releases} ? count - #{keep_releases} : 0))}}
+ #{echo_cmd %{ls -1d [0-9]* | sort -rn | tail -n $remove | xargs rm -rf {}}}
+ }
+ end
+end
+
+# ### setup
+# Sets up a site's directory structure.
+
+desc "Sets up a site."
+task :setup do
+ set_default :term_mode, :pretty
+
+ settings.deploy_to!
+
+ user = settings.user? ? "#{settings.user}" : "username"
+
+ queue %{
+ echo "-----> Setting up #{deploy_to}" && (
+ #{echo_cmd %{mkdir -p "#{deploy_to}"}} &&
+ #{echo_cmd %{chown -R `whoami` "#{deploy_to}"}} &&
+ #{echo_cmd %{chmod g+rx,u+rwx "#{deploy_to}"}} &&
+ #{echo_cmd %{cd "#{deploy_to}"}} &&
+ #{echo_cmd %{mkdir -p "#{releases_path}"}} &&
+ #{echo_cmd %{chmod g+rx,u+rwx "#{releases_path}"}} &&
+ #{echo_cmd %{mkdir -p "#{shared_path}"}} &&
+ #{echo_cmd %{chmod g+rx,u+rwx "#{shared_path}"}} &&
+ echo "" &&
+ #{echo_cmd %{ls -la "#{deploy_to}"}} &&
+ echo "" &&
+ echo "-----> Done."
+ ) || (
+ echo "! ERROR: Setup failed."
+ echo "! Ensure that the path '#{deploy_to}' is accessible to the SSH user."
+ echo "! Try doing:"
+ echo "! sudo mkdir -p \\"#{deploy_to}\\" && sudo chown -R #{user} \\"#{deploy_to}\\""
+ )
+ }
+end
+
+# ### run[]
+# Runs a command on a server.
+#
+# $ mina run[tail -f logs.txt]
+
+desc "Runs a command in the server."
+task :run, [:command] => [:environment] do |t, args|
+ command = args[:command]
+ unless command
+ puts %[You need to provide a command. Try: mina "run[ls -la]"]
+ exit 1
+ end
+
+ queue %[cd #{deploy_to!} && #{command}]
+end
diff --git a/lib/mina/deploy_helpers.rb b/lib/mina/deploy_helpers.rb
new file mode 100644
index 0000000..3baf3c5
--- /dev/null
+++ b/lib/mina/deploy_helpers.rb
@@ -0,0 +1,34 @@
+# # Helpers: Deploy helpers
+# Helpers for deployment.
+module Mina
+ module DeployHelpers
+ # ### deploy
+ # Wraps the things inside it in a deploy script and queues it.
+ # This generates a script using deploy_script and queues it.
+ #
+ # Returns nothing.
+ #
+ def deploy(&blk)
+ queue deploy_script(&blk)
+ end
+
+ # ### deploy_script
+ # Wraps the things inside it in a deploy script.
+ #
+ # script = deploy_script do
+ # invoke :'git:checkout'
+ # end
+ #
+ # queue script
+ #
+ # Returns the deploy script as a string, ready for `queue`ing.
+ #
+ def deploy_script(&blk)
+ set_default :term_mode, :pretty
+ code = isolate do
+ yield
+ erb Mina.root_path('data/deploy.sh.erb')
+ end
+ end
+ end
+end
diff --git a/lib/mina/exec_helpers.rb b/lib/mina/exec_helpers.rb
new file mode 100644
index 0000000..75a6f6e
--- /dev/null
+++ b/lib/mina/exec_helpers.rb
@@ -0,0 +1,111 @@
+# # Helpers: Exec helpers
+# Provides `pretty_system` which Mina uses to parse SSH output, and delegate to
+# the appropriate Output helper.
+
+module Mina
+ module ExecHelpers
+
+ # ### pretty_system
+ # __Internal:__ A pretty version of the default `#system` commands, but
+ # indents and puts color.
+ #
+ # Returns the exit code in integer form.
+ #
+ def pretty_system(code)
+ require 'shellwords'
+ cmds = Shellwords.shellsplit(code)
+ coathooks = 0
+
+ status =
+ Tools.popen4(*cmds) do |pid, i, o, e|
+ # Handle `^C`.
+ trap("INT") { Sys.handle_sigint(coathooks += 1, pid, self) }
+
+ # __In the background,__ make stdin passthru, and stream stderr.
+ th_err = Sys.stream_stderr!(e) { |str| print_stderr str }
+ th_in = Sys.stream_stdin! { |chr| i.putc chr }
+
+ # __In the foreground,__ stream stdout to the output helper.
+ Sys.stream_stdout(o) { |ch| print_char ch }
+
+ th_err.join
+ th_in.terminate
+ end
+
+ status.exitstatus
+ end
+
+ # ## Private methods
+ # Delegate functions, mostly.
+
+ module Sys
+
+ extend self
+
+ # ### Sys.handle_sigint!
+ # Called when a `^C` is pressed. The param `count` is how many times it's
+ # been pressed since. Returns nothing.
+
+ def handle_sigint(count, pid, this)
+ puts ""
+ if count > 1
+ this.print_status "Mina: SIGINT received again. Force quitting..."
+ Process.kill "KILL", pid
+ else
+ this.print_status "Mina: SIGINT received."
+ Process.kill "TERM", pid
+ end
+ end
+
+ # ### Sys.stream_stderr!
+ # __Internal:__ Read from stderr stream `err` *[0]*, supress expected
+ # errors *[1]*, and yield. Returns the thread.
+
+ def stream_stderr!(err, &blk)
+ Thread.new do
+ begin
+ while str = err.gets #[0]
+ next if str.include? "bash: no job control in this shell" #[1]
+ next if str.include? "stdin is not a terminal"
+
+ yield str.strip #[2]
+ end
+ rescue Interrupt
+ end
+ end
+ end
+
+ # ### Sys.stream_stdin!
+ # __Internal:__ Read from the real stdin stream and pass it onto the given
+ # stdin stream `i`. Returns the thread.
+
+ def stream_stdin!(&blk)
+ Thread.new do
+ begin
+ while (char = STDIN.getbyte rescue nil)
+ yield char if char
+ end
+ rescue Interrupt
+ # rubinius
+ rescue SignalException
+ end
+ end
+ end
+
+ # ### Sys.stream_stdout
+ # __Internal:__ Read from given stdout stream `o` and delegate it to the
+ # output helper.
+
+ def stream_stdout(o, &blk)
+ while str = o.getc
+ # Ruby 1.8.7 fix
+ str = str.chr if str.is_a? Fixnum
+
+ yield str
+ end
+ end
+
+ end
+
+ end
+end
diff --git a/lib/mina/foreman.rb b/lib/mina/foreman.rb
new file mode 100644
index 0000000..43f848c
--- /dev/null
+++ b/lib/mina/foreman.rb
@@ -0,0 +1,82 @@
+# # Modules: Foreman
+# Adds settings and tasks for managing projects with [foreman].
+#
+# NOTE: Requires sudo privileges
+#
+# [foreman]: http://rubygems.org/ddolar/foreman
+#
+# require 'mina/foreman'
+#
+# ## Common usage
+#
+# set :application, "app-name"
+#
+# task :deploy => :environment do
+# deploy do
+# # ...
+# invoke 'foreman:export'
+# # ...
+# end
+#
+# to :launch do
+# invoke 'foreman:restart'
+# end
+# end
+#
+
+# ## Settings
+# Any and all of these settings can be overriden in your `deploy.rb`.
+
+# ### foreman_app
+# Sets the service name that foreman will export to upstart. Uses *application*
+# variable as a default. It should be set, otherwise export command will fail.
+
+# ### foreman_user
+# Sets the user under which foreman will execute the service. Defaults to *user*
+
+# ### foreman_log
+# Sets the foreman log path. Defaults to *shared/log*
+
+set_default :foreman_app, lambda { application }
+set_default :foreman_user, lambda { user }
+set_default :foreman_log, lambda { "#{deploy_to!}/#{shared_path}/log" }
+set_default :foreman_sudo, true
+set_default :foreman_format, 'upstart'
+set_default :foreman_location, '/etc/init'
+
+namespace :foreman do
+ desc 'Export the Procfile to Ubuntu upstart scripts'
+ task :export do
+ sudo_cmd = "sudo" if foreman_sudo
+ export_cmd = "#{sudo_cmd} bundle exec foreman export #{foreman_format} #{foreman_location} -a #{foreman_app} -u #{foreman_user} -d #{deploy_to!}/#{current_path!} -l #{foreman_log}"
+
+ queue %{
+ echo "-----> Exporting foreman procfile for #{foreman_app}"
+ #{echo_cmd %[cd #{deploy_to!}/#{current_path!} ; #{export_cmd}]}
+ }
+ end
+
+ desc "Start the application services"
+ task :start do
+ queue %{
+ echo "-----> Starting #{foreman_app} services"
+ #{echo_cmd %[sudo start #{foreman_app}]}
+ }
+ end
+
+ desc "Stop the application services"
+ task :stop do
+ queue %{
+ echo "-----> Stopping #{foreman_app} services"
+ #{echo_cmd %[sudo stop #{foreman_app}]}
+ }
+ end
+
+ desc "Restart the application services"
+ task :restart do
+ queue %{
+ echo "-----> Restarting #{foreman_app} services"
+ #{echo_cmd %[sudo start #{foreman_app} || sudo restart #{foreman_app}]}
+ }
+ end
+end
diff --git a/lib/mina/git.rb b/lib/mina/git.rb
new file mode 100644
index 0000000..cc9ce74
--- /dev/null
+++ b/lib/mina/git.rb
@@ -0,0 +1,62 @@
+# encoding: utf-8
+
+# # Modules: Git
+# Adds settings and tasks related to managing Git.
+#
+# require 'mina/git'
+
+# ## Settings
+# Any and all of these settings can be overriden in your `deploy.rb`.
+
+# ### branch
+# Sets the branch to be deployed.
+
+set_default :branch, 'master'
+
+namespace :git do
+ # ## Deploy tasks
+ # These tasks are meant to be invoked inside deploy scripts, not invoked on
+ # their own.
+
+ # ### git:clone
+ # Clones the Git repository. Meant to be used inside a deploy script.
+
+ desc "Clones the Git repository to the release path."
+ task :clone do
+ if revision?
+ error "The Git option `:revision` has now been deprecated."
+ error "Please use `:commit` or `:branch` instead."
+ exit
+ end
+
+ clone = if commit?
+ %[
+ echo "-----> Using git commit '#{commit}'" &&
+ #{echo_cmd %[git clone "#{repository!}" . --recursive]} &&
+ #{echo_cmd %[git checkout -b current_release "#{commit}" --force]} &&
+ ]
+ else
+ %{
+ if [ ! -d "#{deploy_to}/scm/objects" ]; then
+ echo "-----> Cloning the Git repository"
+ #{echo_cmd %[git clone "#{repository!}" "#{deploy_to}/scm" --bare]}
+ else
+ echo "-----> Fetching new git commits"
+ #{echo_cmd %[(cd "#{deploy_to}/scm" && git fetch "#{repository!}" "#{branch}:#{branch}" --force)]}
+ fi &&
+ echo "-----> Using git branch '#{branch}'" &&
+ #{echo_cmd %[git clone "#{deploy_to}/scm" . --recursive --branch "#{branch}"]} &&
+ }
+ end
+
+ status = %[
+ echo "-----> Using this git commit" &&
+ echo &&
+ #{echo_cmd %[git --no-pager log --format='%aN (%h):%n> %s' -n 1]} &&
+ #{echo_cmd %[rm -rf .git]} &&
+ echo
+ ]
+
+ queue clone + status
+ end
+end
diff --git a/lib/mina/helpers.rb b/lib/mina/helpers.rb
new file mode 100644
index 0000000..05e356f
--- /dev/null
+++ b/lib/mina/helpers.rb
@@ -0,0 +1,386 @@
+# # Helpers
+
+module Mina
+ module Helpers
+
+ # ### invoke
+ # Invokes another Rake task.
+ #
+ # Invokes the task given in `task`. Returns nothing.
+ #
+ # invoke :'git:clone'
+ # invoke :restart
+ #
+ # Options:
+ # reenable (bool) - Execute the task even next time.
+ #
+
+ def invoke(task, options = {})
+ Rake.application.invoke_task task
+ if options[:reenable]
+ name = Rake.application.parse_task_string(task).first
+ Rake::Task[name].reenable
+ end
+ end
+
+ # ### erb
+ # Evaluates an ERB block in the current scope and returns a string.
+ #
+ # a = 1
+ # b = 2
+ #
+ # # Assuming foo.erb is <%= a %> and <%= b %>
+ # puts erb('foo.erb')
+ #
+ # #=> "1 and 2"
+ #
+ # Returns the output string of the ERB template.
+
+ def erb(file, b=binding)
+ require 'erb'
+ erb = ERB.new(File.read(file))
+ erb.result b
+ end
+
+ # ### run!
+ # SSHs into the host and runs the code that has been queued.
+ #
+ # This is already automatically invoked before Rake exits to run all
+ # commands that have been queued up.
+ #
+ # queue "sudo restart"
+ # run!
+ #
+ # Returns nothing.
+
+ def run!
+ report_time { ssh commands(:default) }
+ end
+
+ # ### report_time
+ # Report time elapsed in the block.
+ # Returns the output of the block.
+ #
+ # report_time do
+ # sleep 2
+ # # do other things
+ # end
+ #
+ # # Output:
+ # # Elapsed time: 2.00 seconds
+
+ def report_time(&blk)
+ time, output = measure &blk
+ print_str "Elapsed time: %.2f seconds" % [time]
+ output
+ end
+
+ # ### measure
+ # Measures the time (in seconds) a block takes.
+ # Returns a [time, output] tuple.
+
+ def measure(&blk)
+ t = Time.now
+ output = yield
+ [Time.now - t, output]
+ end
+
+ # ### mina_cleanup
+ # __Internal:__ Invoked when Rake exits.
+ #
+ # Returns nothing.
+
+ def mina_cleanup!
+ run! if commands.any?
+ end
+
+ # ## Errors
+
+ # ### die
+ # Exits with a nice looking message.
+ # Returns nothing.
+ #
+ # die 2
+ # die 2, "Tests failed"
+
+ def die(code=1, msg=null)
+ str = "Failed with status #{code}"
+ str += " (#{msg})" if msg
+ err = Failed.new(str)
+ err.exitstatus = code
+ raise err
+ end
+
+ # ### error
+ # __Internal:__ Prints to stdout.
+ # Consider using `print_error` instead.
+
+ def error(str)
+ $stderr.write "#{str}\n"
+ end
+
+ # ## Queueing
+
+ # ### queue
+ # Queues code to be run.
+ #
+ # This queues code to be run to the current code bucket (defaults to `:default`).
+ # To get the things that have been queued, use commands[:default]
+ #
+ # Returns nothing.
+ #
+ # queue "sudo restart"
+ # queue "true"
+ #
+ # commands == ['sudo restart', 'true']
+
+ def queue(code)
+ commands
+ commands(@to) << unindent(code)
+ end
+
+ # ### queue!
+ # Shortcut for `queue`ing a command that shows up in verbose mode.
+
+ def queue!(code)
+ queue echo_cmd(code)
+ end
+
+ # ### echo_cmd
+ # Converts a bash command to a command that echoes before execution.
+ # Used to show commands in verbose mode. This does nothing unless verbose mode is on.
+ #
+ # Returns a string of the compound bash command, typically in the format of
+ # `echo xx && xx`. However, if `verbose_mode?` is false, it returns the
+ # input string unharmed.
+ #
+ # echo_cmd("ln -nfs releases/2 current")
+ # #=> echo "$ ln -nfs releases/2 current" && ln -nfs releases/2 current
+
+ def echo_cmd(str)
+ if verbose_mode?
+ require 'shellwords'
+ "echo #{Shellwords.escape("$ " + str)} &&\n#{str}"
+ else
+ str
+ end
+ end
+
+ # ## Commands
+
+ # ### commands
+ # Returns an array of queued code strings.
+ #
+ # You may give an optional `aspect`.
+ #
+ # Returns an array of strings.
+ #
+ # queue "sudo restart"
+ # queue "true"
+ #
+ # to :clean do
+ # queue "rm"
+ # end
+ #
+ # commands == ["sudo restart", "true"]
+ # commands(:clean) == ["rm"]
+
+ def commands(aspect=:default)
+ (@commands ||= begin
+ @to = :default
+ Hash.new { |h, k| h[k] = Array.new }
+ end)[aspect]
+ end
+
+ # ### isolate
+ # Starts a new block where new `commands` are collected.
+ #
+ # Returns nothing.
+ #
+ # queue "sudo restart"
+ # queue "true"
+ # commands.should == ['sudo restart', 'true']
+ #
+ # isolate do
+ # queue "reload"
+ # commands.should == ['reload']
+ # end
+ #
+ # commands.should == ['sudo restart', 'true']
+
+ def isolate(&blk)
+ old, @commands = @commands, nil
+ result = yield
+ new_code, @commands = @commands, old
+ result
+ end
+
+ # ### in_directory
+ # Starts a new block where #commands are collected, to be executed inside `path`.
+ #
+ # Returns nothing.
+ #
+ # in_directory './webapp' do
+ # queue "./reload"
+ # end
+ #
+ # commands.should == ['cd ./webapp && (./reload && true)']
+
+ def in_directory(path, &blk)
+ isolated_commands = isolate { yield; commands }
+ isolated_commands.each { |cmd| queue "(cd #{path} && (#{cmd}))" }
+ end
+
+ # ### to
+ # Defines instructions on how to do a certain thing.
+ # This makes the commands that are `queue`d go into a different bucket in commands.
+ #
+ # Returns nothing.
+ #
+ # to :prepare do
+ # run "bundle install"
+ # end
+ # to :launch do
+ # run "nginx -s restart"
+ # end
+ #
+ # commands(:prepare) == ["bundle install"]
+ # commands(:restart) == ["nginx -s restart"]
+
+ def to(name, &blk)
+ old, @to = @to, name
+ yield
+ ensure
+ @to = old
+ end
+
+ # ## Settings helpers
+
+ # ### set
+ # Sets settings.
+ # Sets given symbol `key` to value in `value`.
+ #
+ # Returns the value.
+ #
+ # set :domain, 'kickflip.me'
+
+ def set(key, value)
+ settings.send :"#{key}=", value
+ end
+
+ # ### set_default
+ # Sets default settings.
+ # Sets given symbol `key` to value in `value` only if the key isn't set yet.
+ #
+ # Returns the value.
+ #
+ # set_default :term_mode, :pretty
+ # set :term_mode, :system
+ # settings.term_mode.should == :system
+ #
+ # set :term_mode, :system
+ # set_default :term_mode, :pretty
+ # settings.term_mode.should == :system
+
+ def set_default(key, value)
+ settings.send :"#{key}=", value unless settings.send(:"#{key}?")
+ end
+
+ # ### settings
+ # Accesses the settings hash.
+ #
+ # set :domain, 'kickflip.me'
+ #
+ # settings.domain #=> 'kickflip.me'
+ # domain #=> 'kickflip.me'
+
+ def settings
+ @settings ||= Settings.new
+ end
+
+ # ### method_missing
+ # Hook to get settings.
+ # See #settings for an explanation.
+ #
+ # Returns things.
+
+ def method_missing(meth, *args, &blk)
+ settings.send meth, *args
+ end
+
+ # ## Command line mode helpers
+
+ # ### verbose_mode?
+ # Checks if Rake was invoked with --verbose.
+ #
+ # Returns true or false.
+ #
+ # if verbose_mode?
+ # queue %[echo "-----> Starting a new process"]
+ # end
+
+ def verbose_mode?
+ if Rake.respond_to?(:verbose)
+ #- Rake 0.9.x
+ Rake.verbose == true
+ else
+ #- Rake 0.8.x
+ RakeFileUtils.verbose_flag != :default
+ end
+ end
+
+ # ### simulate_mode?
+ # Checks if Rake was invoked with --simulate.
+ #
+ # Returns true or false.
+
+ def simulate_mode?
+ !! ENV['simulate']
+ end
+
+ # ## Internal helpers
+
+ # ### indent
+ # Indents a given code block with `count` spaces before it.
+
+ def indent(count, str)
+ str.gsub(/^/, " "*count)
+ end
+
+ # ### unindent
+ # __Internal:__ Normalizes indentation on a given string.
+ #
+ # Returns the normalized string without extraneous indentation.
+ #
+ # puts unindent %{
+ # Hello
+ # There
+ # }
+ # # Output:
+ # # Hello
+ # # There
+
+ def unindent(code)
+ if code =~ /^\n([ \t]+)/
+ code = code.gsub(/^#{$1}/, '')
+ end
+
+ code.strip
+ end
+
+ # ### reindent
+ # Resets the indentation on a given code block.
+
+ def reindent(n, code)
+ indent n, unindent(code)
+ end
+
+ # ### capture
+ # Returns the output of command via SSH.
+
+ def capture(cmd, options={})
+ ssh cmd, options.merge(:return => true)
+ end
+
+ end
+end
diff --git a/lib/mina/output_helpers.rb b/lib/mina/output_helpers.rb
new file mode 100644
index 0000000..405e942
--- /dev/null
+++ b/lib/mina/output_helpers.rb
@@ -0,0 +1,92 @@
+# # Helpers: Output helpers
+# Protip! make a module that overrides these settings, then use `extend YourModule`
+# to make your own pretty printing thing.
+module Mina
+ module OutputHelpers
+
+ # ### print_str
+ # Prints a string by delegating it to the proper output helper.
+ #
+ # It takes an input with text and prints them nicely. The text block can
+ # have statuses (prefixed with `-----> `), errors (prefixed with `! `),
+ # commands (prefixed with `$ `) or anything else. Depending on the type of
+ # the message, they will be delegated to the proper print_* helper.
+ #
+ # -----> Unlocking
+ # $ unlock foo
+ # Unlocked.
+ # ! ERROR: Failed
+ #
+ # Returns nothing.
+ #
+ def print_str(line)
+ if line =~ /^\-+> (.*?)$/
+ print_status $1
+ elsif line =~ /^! (.*?)$/
+ print_error $1
+ elsif line =~ /^\$ (.*?)$/
+ print_command $1
+ else
+ print_stdout line
+ end
+ end
+
+ # ### print_char
+ # Prints a single character.
+ def print_char(ch)
+ $last ||= ''
+
+ if ch == "\n"
+ print_clear
+ print_str $last
+ $last = ''
+ else
+ print ' ' if $last == ''
+ print ch
+ $last += ch
+ end
+ end
+
+ def print_clear
+ print "\033[1K\r"
+ end
+
+ # ### print_status
+ # Prints a status message. (`----->`)
+ def print_status(msg)
+ puts "" if verbose_mode?
+ puts "#{color('----->', 32)} #{msg}"
+ end
+
+ # ### print_error
+ # Prints an error message (header).
+ def print_error(msg)
+ puts " #{color("!", 33)} #{color(msg, 31)}"
+ end
+
+ # ### print_stderr
+ # Prints an error message (body), or prints stderr output.
+ def print_stderr(msg)
+ puts " #{color(msg, 31)}"
+ end
+
+ # ### print_command
+ # Prints a command.
+ def print_command(msg)
+ puts " #{color("$", 32)} #{color(msg, 32)}"
+ end
+
+ # ### print_stdout
+ # Prints a normal message.
+ def print_stdout(msg)
+ puts " #{msg}"
+ end
+
+ # ### color
+ # Colorizes a string.
+ # Returns the string `str` with the color `c`.
+ def color(str, c)
+ ENV['NO_COLOR'] ? str : "\033[#{c}m#{str}\033[0m"
+ end
+ end
+end
diff --git a/lib/mina/rails.rb b/lib/mina/rails.rb
new file mode 100644
index 0000000..b361b78
--- /dev/null
+++ b/lib/mina/rails.rb
@@ -0,0 +1,206 @@
+# # Modules: Rails
+# Adds settings and tasks for managing Rails projects.
+#
+# require 'mina/rails'
+
+require 'mina/bundler'
+
+# ## Settings
+# Any and all of these settings can be overriden in your `deploy.rb`.
+
+# ### rails_env
+# Sets the Rails environment for `rake` and `rails` commands.
+#
+# Note that changing this will NOT change the environment that your application
+# is run in.
+
+set_default :rails_env, 'production'
+
+# ### bundle_prefix
+# Prefix for Bundler commands. Often to something like `RAILS_ENV=production
+# bundle exec`.
+#
+# queue! "#{bundle_prefix} annotate -r"
+
+set_default :bundle_prefix, lambda { %{RAILS_ENV="#{rails_env}" #{bundle_bin} exec} }
+
+# ### rake
+# The prefix for `rake` commands. Use like so:
+#
+# queue! "#{rake} db:migrate"
+
+set_default :rake, lambda { %{#{bundle_prefix} rake} }
+
+# ### rails
+# The prefix for `rails` commands. Use like so:
+#
+# queue! "#{rails} console"
+
+set_default :rails, lambda { %{#{bundle_prefix} rails} }
+
+# ### asset_paths
+# The paths to be checked.
+#
+# Whenever assets are compiled, the asset files are checked if they have
+# changed from the previous release.
+#
+# If they're unchanged, compiled assets will simply be copied over to the new
+# release.
+#
+# Override this if you have custom asset paths declared in your Rails's
+# `config.assets.paths` setting.
+
+set_default :asset_paths, ['vendor/assets/', 'app/assets/']
+
+# ### rake_assets_precompile
+# The command to invoke when precompiling assets.
+# Override me if you like.
+
+settings.rake_assets_precompile ||= lambda { "#{rake} assets:precompile RAILS_GROUPS=assets" }
+
+# ----
+
+# Macro used later by :rails, :rake, etc
+make_run_task = lambda { |name, sample_args|
+ task name, [:arguments] => :environment do |t, args|
+ arguments = args[:arguments]
+ command = send name
+ unless arguments
+ puts %{You need to provide arguments. Try: mina "#{name}[#{sample_args}]"}
+ exit 1
+ end
+ queue echo_cmd %[cd "#{deploy_to!}/#{current_path!}" && #{command} #{arguments}]
+ end
+}
+
+def check_for_changes_script(options={})
+ diffs = options[:at].map { |path|
+ %[diff -r "#{deploy_to}/#{current_path}/#{path}" "./#{path}" 2>/dev/null]
+ }.join("\n")
+
+ unindent %[
+ if [ -e "#{deploy_to}/#{current_path}/#{options[:check]}" ]; then
+ count=`(
+ #{reindent 4, diffs}
+ ) | wc -l`
+
+ if [ "$((count))" = "0" ]; then
+ #{reindent 4, options[:skip]} &&
+ exit
+ else
+ #{reindent 4, options[:changed]}
+ fi
+ else
+ #{reindent 2, options[:default]}
+ fi
+ ]
+end
+
+# ## Command-line tasks
+# These tasks can be invoked in the command line.
+
+# ### rails[]
+# Invokes a rails command.
+#
+# $ mina rails[console]
+
+desc "Execute a Rails command in the current deploy."
+make_run_task[:rails, 'console']
+
+# ### rake[]
+# Invokes a rake command.
+#
+# $ mina rake db:cleanup
+
+desc "Execute a Rake command in the current deploy."
+make_run_task[:rake, 'db:migrate']
+
+# ### console
+# Opens the Ruby console for the currently-deployed version.
+#
+# $ mina console
+
+desc "Starts an interactive console."
+task :console do
+ queue echo_cmd %[cd "#{deploy_to!}/#{current_path!}" && #{rails} console && exit]
+end
+
+# ## Deploy tasks
+# These tasks are meant to be invoked inside deploy scripts, not invoked on
+# their own.
+
+namespace :rails do
+ # ### rails:db_migrate
+ desc "Migrates the Rails database (skips if nothing has changed since the last release)."
+ task :db_migrate do
+ if ENV['force_migrate']
+ invoke :'rails:db_migrate:force'
+ else
+ message = verbose_mode? ?
+ '$((count)) changes found, migrating database' :
+ 'Migrating database'
+
+ queue check_for_changes_script \
+ :check => 'db/migrate/',
+ :at => ['db/migrate/'],
+ :skip => %[
+ echo "-----> DB migrations unchanged; skipping DB migration"
+ ],
+ :changed => %[
+ echo "-----> #{message}"
+ #{echo_cmd %[#{rake} db:migrate]}
+ ],
+ :default => %[
+ echo "-----> Migrating database"
+ #{echo_cmd %[#{rake} db:migrate]}
+ ]
+ end
+ end
+
+ # ### rails:db_migrate:force
+ desc "Migrates the Rails database."
+ task :'db_migrate:force' do
+ queue %{
+ echo "-----> Migrating database"
+ #{echo_cmd %[#{rake} db:migrate]}
+ }
+ end
+
+ # ### rails:assets_precompile:force
+ desc "Precompiles assets."
+ task :'assets_precompile:force' do
+ queue %{
+ echo "-----> Precompiling asset files"
+ #{echo_cmd %[#{rake_assets_precompile}]}
+ }
+ end
+
+ # ### rails:assets_precompile
+ desc "Precompiles assets (skips if nothing has changed since the last release)."
+ task :'assets_precompile' do
+ if ENV['force_assets']
+ invoke :'rails:assets_precompile:force'
+ else
+ message = verbose_mode? ?
+ '$((count)) changes found, precompiling asset files' :
+ 'Precompiling asset files'
+
+ queue check_for_changes_script \
+ :check => 'public/assets/',
+ :at => [*asset_paths],
+ :skip => %[
+ echo "-----> Skipping asset precompilation"
+ #{echo_cmd %[cp -R "#{deploy_to}/#{current_path}/public/assets" "./public"]}
+ ],
+ :changed => %[
+ echo "-----> #{message}"
+ #{echo_cmd %[#{rake_assets_precompile}]}
+ ],
+ :default => %[
+ echo "-----> Precompiling asset files"
+ #{echo_cmd %[#{rake_assets_precompile}]}
+ ]
+ end
+ end
+
+end
diff --git a/lib/mina/rake.rb b/lib/mina/rake.rb
new file mode 100644
index 0000000..3fb9ea7
--- /dev/null
+++ b/lib/mina/rake.rb
@@ -0,0 +1,9 @@
+# This file is invoked from Rake.
+extend Mina::Helpers
+extend Mina::DeployHelpers
+extend Mina::SshHelpers
+extend Mina::OutputHelpers
+extend Mina::ExecHelpers
+
+require 'mina/default'
+require 'mina/deploy' if Rake.application.have_rakefile
diff --git a/lib/mina/rbenv.rb b/lib/mina/rbenv.rb
new file mode 100644
index 0000000..0f74ec5
--- /dev/null
+++ b/lib/mina/rbenv.rb
@@ -0,0 +1,47 @@
+# # Modules: rbenv
+# Adds settings and tasks for managing [rbenv] installations.
+#
+# [rbenv]: https://github.com/sstephenson/rbenv
+#
+# require 'mina/rbenv'
+#
+# ## Common usage
+#
+# task :environment do
+# invoke :'rbenv:load'
+# end
+#
+# task :deploy => :environment do
+# ...
+# end
+
+# ## Settings
+# Any and all of these settings can be overriden in your `deploy.rb`.
+
+# ### rbenv_path
+# Sets the path where *rbenv* is installed.
+#
+# You may override this if rbenv is placed elsewhere in your setup.
+
+set_default :rbenv_path, "$HOME/.rbenv"
+
+# ## Tasks
+
+# ### rbenv:load
+# Loads the *rbenv* runtime.
+
+task :'rbenv:load' do
+ queue %{
+ echo "-----> Loading rbenv"
+ #{echo_cmd %{export RBENV_ROOT="#{rbenv_path}"}}
+ #{echo_cmd %{export PATH="#{rbenv_path}/bin:$PATH"}}
+
+ if ! which rbenv >/dev/null; then
+ echo "! rbenv not found"
+ echo "! If rbenv is installed, check your :rbenv_path setting."
+ exit 1
+ fi
+
+ #{echo_cmd %{eval "$(rbenv init -)"}}
+ }
+end
diff --git a/lib/mina/rvm.rb b/lib/mina/rvm.rb
new file mode 100644
index 0000000..001db5d
--- /dev/null
+++ b/lib/mina/rvm.rb
@@ -0,0 +1,88 @@
+# # Modules: RVM
+# Adds settings and tasks for managing [RVM] installations.
+#
+# [rvm]: http://rvm.io
+#
+# require 'mina/rvm'
+#
+# ## Common usage
+#
+# task :environment do
+# invoke :'rvm:use[ruby-1.9.3-p125 at gemset_name]'
+# end
+#
+# task :deploy => :environment do
+# ...
+# end
+
+# ## Settings
+# Any and all of these settings can be overriden in your `deploy.rb`.
+
+# ### rvm_path
+# Sets the path to RVM.
+#
+# You can override this in your projects if RVM is installed in a different
+# path, say, if you have a system-wide RVM install.
+
+set_default :rvm_path, "$HOME/.rvm/scripts/rvm"
+
+# ## Tasks
+
+# ### rvm:use[]
+# Uses a given RVM environment provided as an argument.
+#
+# This is usually placed in the `:environment` task.
+#
+# task :environment do
+# invoke :'rvm:use[ruby-1.9.3-p125 at gemset_name]'
+# end
+#
+task :'rvm:use', :env do |t, args|
+ unless args[:env]
+ print_error "Task 'rvm:use' needs an RVM environment name as an argument."
+ print_error "Example: invoke :'rvm:use[ruby-1.9.2 at default]'"
+ die
+ end
+
+ queue %{
+ echo "-----> Using RVM environment '#{args[:env]}'"
+ if [[ ! -s "#{rvm_path}" ]]; then
+ echo "! Ruby Version Manager not found"
+ echo "! If RVM is installed, check your :rvm_path setting."
+ exit 1
+ fi
+
+ source #{rvm_path}
+ #{echo_cmd %{rvm use "#{args[:env]}" --create}} || exit 1
+ }
+end
+
+# ### rvm:wrapper[]
+# Creates a rvm wrapper for a given executable.
+#
+# This is usually placed in the `:setup` task.
+#
+# task ::setup => :environment do
+# ...
+# invoke :'rvm:wrapper[ruby-1.9.3-p125 at gemset_name,wrapper_name,binary_name]'
+# end
+#
+task :'rvm:wrapper', :env, :name, :bin do |t,args|
+ unless args[:env] && args[:name] && args[:bin]
+ print_error "Task 'rvm:wrapper' needs an RVM environment name, an wrapper name and the binary name as arguments"
+ print_error "Example: invoke :'rvm:wrapper[ruby-1.9.2 at myapp,myapp,unicorn_rails]'"
+ die
+ end
+
+ queue %{
+ echo "-----> creating RVM wrapper '#{args[:name]}_#{args[:bin]}' using '#{args[:env]}'"
+ if [[ ! -s "#{rvm_path}" ]]; then
+ echo "! Ruby Version Manager not found"
+ echo "! If RVM is installed, check your :rvm_path setting."
+ exit 1
+ fi
+
+ source #{rvm_path}
+ #{echo_cmd %{rvm wrapper #{args[:env]} #{args[:name]} #{args[:bin]} }} || exit 1
+ }
+end
\ No newline at end of file
diff --git a/lib/mina/settings.rb b/lib/mina/settings.rb
new file mode 100644
index 0000000..d303696
--- /dev/null
+++ b/lib/mina/settings.rb
@@ -0,0 +1,32 @@
+module Mina
+ class Settings < Hash
+ def method_missing(meth, *args, &blk)
+ name = meth.to_s
+
+ return evaluate(self[meth]) if name.size == 1
+
+ # Ruby 1.8.7 doesn't let you do string[-1]
+ key, suffix = name[0..-2].to_sym, name[-1..-1]
+
+ case suffix
+ when '='
+ self[key] = args.first
+ when '?'
+ include? key
+ when '!'
+ raise Error, "Setting :#{key} is not set" unless include?(key)
+ evaluate self[key]
+ else
+ evaluate self[meth]
+ end
+ end
+
+ def evaluate(value)
+ if value.is_a?(Proc)
+ value.call
+ else
+ value
+ end
+ end
+ end
+end
diff --git a/lib/mina/ssh_helpers.rb b/lib/mina/ssh_helpers.rb
new file mode 100644
index 0000000..8b059a0
--- /dev/null
+++ b/lib/mina/ssh_helpers.rb
@@ -0,0 +1,123 @@
+# # Helpers: SSH helpers
+# You don't need to invoke these helpers, they're already invoked automatically.
+
+module Mina
+ module SshHelpers
+
+ # ### ssh
+ # Executes a command via SSH.
+ #
+ # Returns nothing usually, but if `{ return: true }` is given, returns the
+ # STDOUT output of the SSH session.
+ #
+ # `options` is a hash of options:
+ #
+ # - `:pretty` - Prettify the output if true.
+ # - `:return` - If set to true, returns the output.
+ #
+ # Example
+ #
+ # ssh("ls", return: true)
+
+ def ssh(cmd, options={})
+ require 'shellwords'
+
+ cmd = cmd.join("\n") if cmd.is_a?(Array)
+ script = Shellwords.escape(cmd)
+
+ if options[:return] == true
+ `#{ssh_command} -- #{script}`
+
+ elsif simulate_mode?
+ Ssh.simulate(cmd, ssh_command)
+
+ else
+ result = Ssh.invoke(script, self)
+ Ssh.ensure_successful result, self
+ end
+ end
+
+ # ### ssh_command
+ # Returns the SSH command to be executed.
+ #
+ # set :domain, 'foo.com'
+ # set :user, 'diggity'
+ #
+ # puts ssh_command
+ # #=> 'ssh diggity at foo.com'
+
+ def ssh_command
+ args = domain!.dup
+ args = "#{user}@#{args}" if user?
+ args << " -i #{identity_file}" if identity_file?
+ args << " -p #{port}" if port?
+ args << " -A" if forward_agent?
+ args << " #{ssh_options}" if ssh_options?
+ args << " -t"
+ "ssh #{args}"
+ end
+
+ # ## Private methods
+ # `ssh` delegates to these.
+
+ module Ssh
+
+ extend self
+
+ # ### Ssh.simulate
+ # __Internal:__ Prints SSH command. Called by `ssh`.
+
+ def simulate(cmd, ssh_command)
+ str = "Executing the following via '#{ssh_command}':"
+ puts "#!/usr/bin/env bash"
+ puts "# #{str}"
+ puts "#"
+
+ puts cmd
+
+ 0
+ end
+
+ # ### Ssh.invoke
+ # __Internal:__ Initiates an SSH session with script `script` with given
+ # `term_mode`. Called by `ssh`.
+
+ def invoke(script, this)
+ # Ruby 1.8.7 doesn't let you have empty symbols
+ term_mode = :"#{this.settings.term_mode}" if this.settings.term_mode
+ code = "#{this.ssh_command} -- #{script}"
+
+ # Certain environments can't do :pretty mode.
+ term_mode = :exec if term_mode == :pretty && !pretty_supported?
+
+ case term_mode
+ when :pretty
+ this.pretty_system(code)
+ when :exec
+ exec code
+ else
+ system code
+ $?.to_i
+ end
+ end
+
+ def pretty_supported?
+ # open4 is not supported under Windows.
+ # https://github.com/nadarei/mina/issues/58
+ require 'rbconfig'
+ ! (RbConfig::CONFIG['host_os'] =~ /mswin|mingw/)
+ end
+
+ # ### Ssh.ensure_successful
+ # __Internal:__ Halts the execution if the given result code is not
+ # successful (non-zero).
+
+ def ensure_successful(result, this)
+ this.die result if result.is_a?(Fixnum) && result > 0
+ result
+ end
+
+ end
+
+ end
+end
diff --git a/lib/mina/tools.rb b/lib/mina/tools.rb
new file mode 100644
index 0000000..432c31f
--- /dev/null
+++ b/lib/mina/tools.rb
@@ -0,0 +1,20 @@
+module Mina
+ module Tools
+ if IO.respond_to?(:popen4)
+ def self.popen4(*cmd, &blk)
+ IO.popen4 *cmd, &blk
+ $?
+ end
+ else
+ def self.popen4(*cmd, &blk)
+ require 'open4'
+ Open4.popen4 *cmd, &blk
+ end
+ end
+
+ def self.pfork4(*cmd, &blk)
+ require 'open4'
+ Open4.pfork4 *cmd, &blk
+ end
+ end
+end
diff --git a/lib/mina/version.rb b/lib/mina/version.rb
new file mode 100644
index 0000000..431af7a
--- /dev/null
+++ b/lib/mina/version.rb
@@ -0,0 +1,5 @@
+module Mina
+ def self.version
+ "0.3.1"
+ end
+end
diff --git a/lib/mina/whenever.rb b/lib/mina/whenever.rb
new file mode 100644
index 0000000..756c0c0
--- /dev/null
+++ b/lib/mina/whenever.rb
@@ -0,0 +1,27 @@
+# # Modules: Whenever
+# Adds settings and tasks for managing projects with [whenever].
+# [whenever]: http://rubygems.org/gems/whenever
+
+namespace :whenever do
+ desc "Clear crontab"
+ task :clear do
+ queue %{
+ echo "-----> Clear crontab for #{domain}_#{rails_env}"
+ #{echo_cmd %[cd #{deploy_to!}/#{current_path!} ; #{bundle_bin} exec whenever --clear-crontab #{domain}_#{rails_env} --set 'environment=#{rails_env}&path=#{deploy_to!}/#{current_path!}']}
+ }
+ end
+ desc "Update crontab"
+ task :update do
+ queue %{
+ echo "-----> Update crontab for #{domain}_#{rails_env}"
+ #{echo_cmd %[cd #{deploy_to!}/#{current_path!} ; #{bundle_bin} exec whenever --update-crontab #{domain}_#{rails_env} --set 'environment=#{rails_env}&path=#{deploy_to!}/#{current_path!}']}
+ }
+ end
+ desc "Write crontab"
+ task :write do
+ queue %{
+ echo "-----> Update crontab for #{domain}_#{rails_env}"
+ #{echo_cmd %[cd #{deploy_to!}/#{current_path!} ; #{bundle_bin} exec whenever --write-crontab #{domain}_#{rails_env} --set 'environment=#{rails_env}&path=#{deploy_to!}/#{current_path!}']}
+ }
+ end
+end
diff --git a/manual/index.md b/manual/index.md
new file mode 100644
index 0000000..715307c
--- /dev/null
+++ b/manual/index.md
@@ -0,0 +1,15 @@
+# Welcome to Mina
+
+Really fast deployer and server automation tool.
+
+Mina works really fast because it's a deploy Bash script generator. It
+generates an entire procedure as a Bash script and runs it remotely in the
+server.
+
+Compare this to the likes of Vlad or Capistrano, where each command
+is ran separately on their own SSH sessions. Mina only creates *one* SSH
+session per deploy, minimizing the SSH connection overhead.
+
+ $ gem install mina
+ $ mina
+
diff --git a/manual/modules.md b/manual/modules.md
new file mode 100644
index 0000000..79e62b9
--- /dev/null
+++ b/manual/modules.md
@@ -0,0 +1,2 @@
+Modules
+=======
diff --git a/metadata.yml b/metadata.yml
new file mode 100644
index 0000000..c4a145d
--- /dev/null
+++ b/metadata.yml
@@ -0,0 +1,176 @@
+--- !ruby/object:Gem::Specification
+name: mina
+version: !ruby/object:Gem::Version
+ hash: 17
+ prerelease:
+ segments:
+ - 0
+ - 3
+ - 1
+ version: 0.3.1
+platform: ruby
+authors:
+- Rico Sta. Cruz
+- Michael Galero
+autorequire:
+bindir: bin
+cert_chain: []
+
+date: 2014-10-17 00:00:00 +02:00
+default_executable:
+dependencies:
+- !ruby/object:Gem::Dependency
+ name: rake
+ prerelease: false
+ requirement: &id001 !ruby/object:Gem::Requirement
+ none: false
+ requirements:
+ - - ">="
+ - !ruby/object:Gem::Version
+ hash: 3
+ segments:
+ - 0
+ version: "0"
+ type: :runtime
+ version_requirements: *id001
+- !ruby/object:Gem::Dependency
+ name: open4
+ prerelease: false
+ requirement: &id002 !ruby/object:Gem::Requirement
+ none: false
+ requirements:
+ - - ~>
+ - !ruby/object:Gem::Version
+ hash: 19
+ segments:
+ - 1
+ - 3
+ - 4
+ version: 1.3.4
+ type: :runtime
+ version_requirements: *id002
+- !ruby/object:Gem::Dependency
+ name: rspec
+ prerelease: false
+ requirement: &id003 !ruby/object:Gem::Requirement
+ none: false
+ requirements:
+ - - ~>
+ - !ruby/object:Gem::Version
+ hash: 7
+ segments:
+ - 3
+ - 0
+ - 0
+ version: 3.0.0
+ type: :development
+ version_requirements: *id003
+description: Really fast deployer and server automation tool.
+email:
+- rico at nadarei.co
+- mikong at nadarei.co
+executables:
+- mina
+extensions: []
+
+extra_rdoc_files: []
+
+files:
+- .gitignore
+- .rspec
+- .travis.yml
+- CONTRIBUTING.md
+- Gemfile
+- HISTORY.md
+- LICENSE
+- Makefile
+- Notes.md
+- Rakefile
+- Readme.md
+- bin/mina
+- data/deploy.rb
+- data/deploy.sh.erb
+- lib/mina.rb
+- lib/mina/bundler.rb
+- lib/mina/chruby.rb
+- lib/mina/default.rb
+- lib/mina/deploy.rb
+- lib/mina/deploy_helpers.rb
+- lib/mina/exec_helpers.rb
+- lib/mina/foreman.rb
+- lib/mina/git.rb
+- lib/mina/helpers.rb
+- lib/mina/output_helpers.rb
+- lib/mina/rails.rb
+- lib/mina/rake.rb
+- lib/mina/rbenv.rb
+- lib/mina/rvm.rb
+- lib/mina/settings.rb
+- lib/mina/ssh_helpers.rb
+- lib/mina/tools.rb
+- lib/mina/version.rb
+- lib/mina/whenever.rb
+- manual/index.md
+- manual/modules.md
+- mina.gemspec
+- spec/command_helper.rb
+- spec/commands/cleanup_spec.rb
+- spec/commands/command_spec.rb
+- spec/commands/custom_config_spec.rb
+- spec/commands/deploy_spec.rb
+- spec/commands/outside_project_spec.rb
+- spec/commands/real_deploy_spec.rb
+- spec/commands/ssh_spec.rb
+- spec/commands/verbose_spec.rb
+- spec/dsl/invoke_spec.rb
+- spec/dsl/queue_spec.rb
+- spec/dsl/settings_in_rake_spec.rb
+- spec/dsl/settings_spec.rb
+- spec/dsl/to_spec.rb
+- spec/fixtures/custom_file_env/custom_deploy.rb
+- spec/fixtures/empty_env/config/deploy.rb
+- spec/helpers/exec_helper_spec.rb
+- spec/helpers/output_helper_spec.rb
+- spec/spec_helper.rb
+- support/Readme-footer.md
+- support/Readme-header.md
+- support/guide.md
+- support/index.html
+- support/to_md.rb
+- test_env/config/deploy.rb
+has_rdoc: true
+homepage: http://github.com/nadarei/mina
+licenses: []
+
+post_install_message:
+rdoc_options: []
+
+require_paths:
+- lib
+required_ruby_version: !ruby/object:Gem::Requirement
+ none: false
+ requirements:
+ - - ">="
+ - !ruby/object:Gem::Version
+ hash: 3
+ segments:
+ - 0
+ version: "0"
+required_rubygems_version: !ruby/object:Gem::Requirement
+ none: false
+ requirements:
+ - - ">="
+ - !ruby/object:Gem::Version
+ hash: 3
+ segments:
+ - 0
+ version: "0"
+requirements: []
+
+rubyforge_project:
+rubygems_version: 1.6.2
+signing_key:
+specification_version: 3
+summary: Really fast deployer and server automation tool.
+test_files: []
+
diff --git a/mina.gemspec b/mina.gemspec
new file mode 100644
index 0000000..a1ed854
--- /dev/null
+++ b/mina.gemspec
@@ -0,0 +1,17 @@
+require './lib/mina/version'
+
+Gem::Specification.new do |s|
+ s.name = "mina"
+ s.version = Mina.version
+ s.summary = %{Really fast deployer and server automation tool.}
+ s.description = %Q{Really fast deployer and server automation tool.}
+ s.authors = ["Rico Sta. Cruz", "Michael Galero"]
+ s.email = ["rico at nadarei.co", "mikong at nadarei.co"]
+ s.homepage = "http://github.com/nadarei/mina"
+ s.files = `git ls-files`.strip.split("\n")
+ s.executables = Dir["bin/*"].map { |f| File.basename(f) }
+
+ s.add_dependency "rake"
+ s.add_dependency "open4", "~> 1.3.4"
+ s.add_development_dependency "rspec", "~> 3.0.0"
+end
diff --git a/spec/command_helper.rb b/spec/command_helper.rb
new file mode 100644
index 0000000..d26c05b
--- /dev/null
+++ b/spec/command_helper.rb
@@ -0,0 +1,52 @@
+# Invokes the main 'mina' command.
+def run_command(*args)
+ out = ''
+ err = ''
+ @result = nil
+
+ if ENV['rake']
+ rake_version = "~> #{ENV['rake'] || '0.9'}.0"
+ script = %[require 'rubygems' unless Object.const_defined?(:Gem);]
+ script += %[gem 'rake', '#{rake_version}';]
+ script += %[load '#{root('bin/mina')}']
+ cmd = ['ruby', '-e', "#{script}", "--", *args]
+ else
+ cmd = [root('bin/mina'), *args]
+ end
+
+ status =
+ Mina::Tools.popen4(*cmd) do |pid, i, o, e|
+ out = o.read
+ err = e.read
+ end
+
+ @result = status.exitstatus
+
+ @out = out
+ @err = err
+
+ @result
+end
+
+# Invokes the main 'mina' command and ensures the exit status is success.
+def mina(*args)
+ run_command *args
+ if exitstatus != 0 && ENV['verbose']
+ puts stdout
+ puts stderr
+ end
+
+ expect(exitstatus).to eq(0)
+end
+
+def stdout
+ @out
+end
+
+def stderr
+ @err
+end
+
+def exitstatus
+ @result
+end
diff --git a/spec/commands/cleanup_spec.rb b/spec/commands/cleanup_spec.rb
new file mode 100644
index 0000000..9663d00
--- /dev/null
+++ b/spec/commands/cleanup_spec.rb
@@ -0,0 +1,16 @@
+require 'spec_helper'
+require 'command_helper'
+
+describe "Invoking the 'mina deploy:cleanup' command" do
+ before :each do
+ Dir.chdir root('test_env')
+ end
+
+ it "should cleanup old deployments", :ssh => true do
+ 3.times { mina 'deploy' }
+
+ mina 'deploy:cleanup'
+
+ expect(Dir["deploy/releases/*"].length).to eq(2)
+ end
+end
diff --git a/spec/commands/command_spec.rb b/spec/commands/command_spec.rb
new file mode 100644
index 0000000..784197e
--- /dev/null
+++ b/spec/commands/command_spec.rb
@@ -0,0 +1,71 @@
+require 'spec_helper'
+require 'command_helper'
+
+describe "Invoking the 'mina' command in a project" do
+ before :each do
+ Dir.chdir root('test_env')
+ end
+
+ it "should think it's 'mina', not 'rake' (1)" do
+ run_command 'pinkledills'
+ expect(exitstatus).not_to eq(0)
+ expect(stderr).to include 'mina aborted'
+ end
+
+ it "should think it's 'mina', not 'rake' (1)" do
+ mina '-T'
+ expect(stdout).to include 'mina help'
+ expect(stdout).to include 'mina git:clone'
+ end
+
+ it 'with --version should print the version' do
+ mina '--version'
+ expect(stdout).to include Mina.version
+ end
+
+ it 'with -V should print the version' do
+ mina '-V'
+ expect(stdout).to include Mina.version
+ end
+
+ describe 'without arguments' do
+ before :each do
+ mina
+ end
+
+ it 'should print standard help tasks' do
+ mina
+ expect(stdout).to include 'mina help'
+ expect(stdout).to include 'mina init'
+ expect(stdout).to include 'mina tasks'
+ end
+
+ it 'should print project-specific tasks' do
+ mina
+ expect(stdout).to include 'mina deploy'
+ expect(stdout).to include 'mina restart'
+ expect(stdout).to include 'mina setup'
+ end
+
+ it "should be the same as running 'help'" do
+ previous_out = stdout
+
+ mina 'help'
+ expect(stdout).to eq(previous_out)
+ end
+ end
+
+ it "with 'mina -f' on a non-existing file should fail" do
+ run_command '-f', 'foobar'
+ expect(stderr).to include 'mina aborted'
+ expect(stderr).to include 'No Rakefile found'
+ end
+
+ it "with 'mina tasks' should print tasks" do
+ mina 'tasks'
+
+ expect(stdout).to include('bundle:install')
+ expect(stdout).to include('Install gem dependencies using Bundler')
+ expect(stdout).to include('passenger:restart')
+ end
+end
diff --git a/spec/commands/custom_config_spec.rb b/spec/commands/custom_config_spec.rb
new file mode 100644
index 0000000..331e57c
--- /dev/null
+++ b/spec/commands/custom_config_spec.rb
@@ -0,0 +1,20 @@
+require 'spec_helper'
+require 'command_helper'
+
+describe "Invoking the 'mina' command in a project without a deploy.rb" do
+ before :each do
+ Dir.chdir root('spec/fixtures/custom_file_env')
+ FileUtils.rm_rf 'deploy'
+ end
+
+ it 'should fail' do
+ run_command 'deploy', '--simulate'
+ expect(exitstatus).to be > 0
+ end
+
+ it 'should pass if you provide a new rakefile' do
+ mina 'deploy', '--simulate', '-f', 'custom_deploy.rb'
+ expect(stdout).to include 'Creating a temporary build path'
+ end
+end
+
diff --git a/spec/commands/deploy_spec.rb b/spec/commands/deploy_spec.rb
new file mode 100644
index 0000000..34748e3
--- /dev/null
+++ b/spec/commands/deploy_spec.rb
@@ -0,0 +1,36 @@
+require 'spec_helper'
+require 'command_helper'
+
+describe "Invoking the 'mina' command in a project" do
+ before :each do
+ Dir.chdir root('test_env')
+ end
+
+ describe "to do a simulated deploy" do
+ before :each do
+ mina 'deploy', 'simulate=1'
+ end
+
+ it "should take care of the lockfile" do
+ expect(stdout).to match(/ERROR: another deployment is ongoing/)
+ expect(stdout).to match(/touch ".*deploy\.lock"/)
+ expect(stdout).to match(/rm -f ".*deploy\.lock"/)
+ end
+
+ it "should honor releases_path" do
+ expect(stdout).to include "releases/"
+ end
+
+ it "should symlink the current_path" do
+ expect(stdout).to match(/ln .*current/)
+ end
+
+ it "should include deploy directives" do
+ expect(stdout).to include "bundle exec rake db:migrate"
+ end
+
+ it "should include 'to :launch' directives" do
+ expect(stdout).to include "touch tmp/restart.txt"
+ end
+ end
+end
diff --git a/spec/commands/outside_project_spec.rb b/spec/commands/outside_project_spec.rb
new file mode 100644
index 0000000..ad8c4f1
--- /dev/null
+++ b/spec/commands/outside_project_spec.rb
@@ -0,0 +1,35 @@
+require 'spec_helper'
+require 'command_helper'
+
+describe "Invoking the 'mina' command outside a project" do
+ before :each do
+ Dir.chdir root
+ end
+
+ describe "without arguments" do
+ before :each do
+ mina
+ end
+
+ it 'should print standard help tasks' do
+ expect(stdout).to include('mina help')
+ expect(stdout).to include('mina init')
+ expect(stdout).to include('mina tasks')
+ end
+
+ it "should not print project-specific tasks" do
+ expect(stdout).not_to include('mina deploy')
+ expect(stdout).not_to include('mina restart')
+ expect(stdout).not_to include('mina setup')
+ end
+
+ %w[-h --help].each do |arg|
+ it "should have the same output as 'mina #{arg}'" do
+ @previous_output = stdout
+ mina arg
+ expect(stdout).to eq(@previous_output)
+ end
+ end
+ end
+end
+
diff --git a/spec/commands/real_deploy_spec.rb b/spec/commands/real_deploy_spec.rb
new file mode 100644
index 0000000..9067106
--- /dev/null
+++ b/spec/commands/real_deploy_spec.rb
@@ -0,0 +1,53 @@
+require 'spec_helper'
+require 'command_helper'
+require 'fileutils'
+require 'tmpdir'
+
+describe "Invoking the 'mina' command in a project", :ssh => true do
+ before :each do
+ @path = Dir.mktmpdir
+ Dir.chdir @path
+
+ FileUtils.mkdir_p './config'
+ FileUtils.cp root('test_env/config/deploy.rb'), './config/deploy.rb'
+ FileUtils.rm_rf './deploy'
+ FileUtils.mkdir_p './deploy'
+ end
+
+ # after :each do
+ # FileUtils.rm_rf @path
+ # end
+
+ it 'should set up and deploy fine' do
+ print "[setup]" if ENV['verbose']
+ mina 'setup', '--verbose'
+ expect(File.directory?('deploy')).to be_truthy
+ expect(File.directory?('deploy/releases')).to be_truthy
+ expect(File.directory?('deploy/shared')).to be_truthy
+ expect(File.exists?('deploy/last_version')).to be_falsey
+ expect(File.exists?('deploy/deploy.lock')).to be_falsey
+
+ print "[deploy 1]" if ENV['verbose']
+ mina 'deploy', '--verbose'
+ expect(stdout).to include "-----> Creating a temporary build path"
+ expect(stdout).to include "rm -rf .git"
+ expect(stdout).to include "mkdir -p"
+ expect(File.exists?('deploy/last_version')).to be_truthy
+ expect(File.exists?('deploy/deploy.lock')).to be_falsey
+ expect(File.directory?('deploy/releases')).to be_truthy
+ expect(File.directory?('deploy/releases/1')).to be_truthy
+ expect(File.exists?('deploy/releases/1/README.md')).to be_truthy
+ expect(File.directory?('deploy/releases/2')).to be_falsey
+ expect(File.exists?('deploy/current')).to be_truthy
+ expect(File.read('deploy/last_version').strip).to eq('1')
+ expect(File.exists?('deploy/current/tmp/restart.txt')).to be_truthy
+
+ # And again, to test out sequential versions and stuff
+ print "[deploy 2]" if ENV['verbose']
+ mina 'deploy'
+ expect(stdout).not_to include "rm -rf .git"
+ expect(stdout).not_to include "mkdir -p"
+ expect(File.directory?('deploy/releases/2')).to be_truthy
+ expect(File.read('deploy/last_version').strip).to eq('2')
+ end
+end
diff --git a/spec/commands/ssh_spec.rb b/spec/commands/ssh_spec.rb
new file mode 100644
index 0000000..a29cf74
--- /dev/null
+++ b/spec/commands/ssh_spec.rb
@@ -0,0 +1,14 @@
+require 'spec_helper'
+require 'command_helper'
+
+describe "Invoking the 'mina' command in a project" do
+
+ it "should build ssh command even with frozen String as a domain" do
+ ENV['simulate'] = 'true'
+ rake {
+ set :domain, 'localhost'.freeze
+ ssh("ls")
+ }
+ end
+
+end
diff --git a/spec/commands/verbose_spec.rb b/spec/commands/verbose_spec.rb
new file mode 100644
index 0000000..c2609ed
--- /dev/null
+++ b/spec/commands/verbose_spec.rb
@@ -0,0 +1,21 @@
+require 'spec_helper'
+require 'command_helper'
+require 'shellwords'
+
+describe "Invoking the 'mina' command in a project" do
+ before :each do
+ Dir.chdir root('test_env')
+ end
+
+ it 'should echo commands in verbose mode' do
+ mina 'deploy', '--verbose', '--simulate'
+
+ expect(stdout).to include %[echo #{Shellwords.escape('$ git')}]
+ end
+
+ it 'should not echo commands when not in verbose mode' do
+ mina 'deploy', '--simulate'
+
+ expect(stdout).not_to include %[echo #{Shellwords.escape('$ git')}]
+ end
+end
diff --git a/spec/dsl/invoke_spec.rb b/spec/dsl/invoke_spec.rb
new file mode 100644
index 0000000..011d81f
--- /dev/null
+++ b/spec/dsl/invoke_spec.rb
@@ -0,0 +1,48 @@
+require 'spec_helper'
+
+describe 'Mina' do
+ it '#invoke should work' do
+
+ rake {
+ task :clone do
+ queue 'git clone'
+ end
+ }
+
+ 2.times {
+ rake { invoke :clone }
+ }
+
+ expect(rake.commands).to eq(['git clone'])
+ end
+
+ it '#invoke should work with :reenable option' do
+
+ rake {
+ task :pull do
+ queue 'git pull'
+ end
+ }
+
+ 2.times {
+ rake { invoke :pull, :reenable => true }
+ }
+
+ expect(rake.commands).to eq(['git pull', 'git pull'])
+ end
+
+ it '#invoke with task arguments should work with :reenable option' do
+
+ rake {
+ task :hello, [:world] do |t, args|
+ queue "echo Hello #{args[:world]}"
+ end
+ }
+
+ %w(World Pirate).each { |name|
+ rake { invoke :"hello[#{name}]", :reenable => true }
+ }
+
+ expect(rake.commands).to eq(['echo Hello World', 'echo Hello Pirate'])
+ end
+end
diff --git a/spec/dsl/queue_spec.rb b/spec/dsl/queue_spec.rb
new file mode 100644
index 0000000..21fba16
--- /dev/null
+++ b/spec/dsl/queue_spec.rb
@@ -0,0 +1,49 @@
+require 'spec_helper'
+
+describe 'Mina' do
+ it '#invoke should work' do
+ rake {
+ task :hello do
+ @hello = 'world'
+ end
+ invoke :hello
+ }
+ expect(rake.instance_variable_get(:@hello)).to eq('world')
+ end
+
+ it '#queue should work' do
+ rake {
+ queue 'sudo service nginx restart'
+ }
+
+ expect(rake.commands).to eq(['sudo service nginx restart'])
+ end
+
+ it '#queue should work with multiple commands' do
+ rake {
+ queue 'echo Restarting'
+ queue 'sudo service nginx restart'
+ }
+
+ expect(rake.commands).to eq(['echo Restarting', 'sudo service nginx restart'])
+ end
+
+ it '#queue should work inside tasks' do
+ rake {
+ task :restart do
+ queue 'echo Restarting'
+ invoke :'passenger:restart'
+ end
+
+ namespace :passenger do
+ task :restart do
+ queue 'touch tmp/restart.txt'
+ end
+ end
+ }
+
+ rake { invoke :restart }
+
+ expect(rake.commands).to eq(['echo Restarting', 'touch tmp/restart.txt'])
+ end
+end
diff --git a/spec/dsl/settings_in_rake_spec.rb b/spec/dsl/settings_in_rake_spec.rb
new file mode 100644
index 0000000..ce57101
--- /dev/null
+++ b/spec/dsl/settings_in_rake_spec.rb
@@ -0,0 +1,39 @@
+require 'spec_helper'
+
+describe 'Settings in rake tasks' do
+ it '#set should work' do
+ rake { set :domain, 'localhost' }
+
+ expect(rake.domain).to eq('localhost')
+ expect(rake.settings.domain).to eq('localhost')
+ end
+
+ it '#settings ||= should work' do
+ rake {
+ set :version, '2'
+ settings.version ||= '3'
+ }
+
+ expect(rake.settings.version).to eq('2')
+ expect(rake.version).to eq('2')
+ end
+
+ it '#settings with lambdas should work' do
+ rake {
+ set :version, '42'
+ set :path, lambda { "/var/www/#{version}" }
+ }
+
+ expect(rake.path).to eq("/var/www/42")
+ expect(rake.path?).to be_truthy
+ end
+
+ it '#settings with a bang should work' do
+ expect {
+ rake {
+ set :path, lambda { "/var/www/#{version!}" }
+ }
+ rake.path
+ }.to raise_error(Mina::Error, /version/)
+ end
+end
diff --git a/spec/dsl/settings_spec.rb b/spec/dsl/settings_spec.rb
new file mode 100644
index 0000000..31fb2dc
--- /dev/null
+++ b/spec/dsl/settings_spec.rb
@@ -0,0 +1,61 @@
+require 'spec_helper'
+
+describe 'Settings' do
+ describe 'instances' do
+ before :each do
+ @settings = Mina::Settings.new
+ end
+
+ it 'setting/getting should work' do
+ @settings.domain = '192.168.1.1'
+
+ expect(@settings.domain).to eq('192.168.1.1')
+ end
+
+ it 'question mark should work' do
+ @settings.deploy_to = '/var/www/there'
+
+ expect(@settings.deploy_to?).to be_truthy
+ expect(@settings.foobar?).to be_falsey
+ end
+
+ it 'question mark should work with nils' do
+ @settings.deploy_to = nil
+
+ expect(@settings.deploy_to?).to be_truthy
+ expect(@settings.foobar?).to be_falsey
+ end
+
+ it '||= should work (1)' do
+ @settings.x = 2
+ @settings.x ||= 3
+
+ expect(@settings.x).to eq(2)
+ end
+
+ it '||= should work (2)' do
+ @settings.x ||= 3
+
+ expect(@settings.x).to eq(3)
+ end
+
+ it 'lambdas should work' do
+ @settings.path = lambda { "/var/www/#{@settings.version}" }
+ @settings.version = '3'
+
+ expect(@settings.path?).to be_truthy
+ expect(@settings.path).to eq("/var/www/3")
+ end
+
+ it 'bangs should check for settings' do
+ expect { @settings.non_existent_setting! }.to raise_error(Mina::Error, /non_existent_setting/)
+ end
+
+ it 'bangs should return settings' do
+ @settings.version = 4
+
+ expect(@settings.version!).to eq(4)
+ end
+ end
+end
+
diff --git a/spec/dsl/to_spec.rb b/spec/dsl/to_spec.rb
new file mode 100644
index 0000000..0bfc84b
--- /dev/null
+++ b/spec/dsl/to_spec.rb
@@ -0,0 +1,20 @@
+require 'spec_helper'
+
+describe 'Mina' do
+ it '#to should work' do
+ rake {
+ task :deploy do
+ queue 'git clone'
+
+ to :restart do
+ queue 'touch tmp/restart.txt'
+ end
+ end
+ }
+
+ rake { invoke :deploy }
+
+ expect(rake.commands).to eq(['git clone'])
+ expect(rake.commands(:restart)).to eq(['touch tmp/restart.txt'])
+ end
+end
diff --git a/spec/fixtures/custom_file_env/custom_deploy.rb b/spec/fixtures/custom_file_env/custom_deploy.rb
new file mode 100644
index 0000000..da8cfe9
--- /dev/null
+++ b/spec/fixtures/custom_file_env/custom_deploy.rb
@@ -0,0 +1,15 @@
+require 'fileutils'
+FileUtils.mkdir_p "#{Dir.pwd}/deploy"
+
+require 'mina/git'
+
+set :domain, 'localhost'
+set :deploy_to, "#{Dir.pwd}/deploy"
+set :repository, "#{Dir.pwd}"
+
+desc "Deploys."
+task :deploy do
+ deploy do
+ invoke :'git:clone'
+ end
+end
diff --git a/spec/fixtures/empty_env/config/deploy.rb b/spec/fixtures/empty_env/config/deploy.rb
new file mode 100644
index 0000000..da8cfe9
--- /dev/null
+++ b/spec/fixtures/empty_env/config/deploy.rb
@@ -0,0 +1,15 @@
+require 'fileutils'
+FileUtils.mkdir_p "#{Dir.pwd}/deploy"
+
+require 'mina/git'
+
+set :domain, 'localhost'
+set :deploy_to, "#{Dir.pwd}/deploy"
+set :repository, "#{Dir.pwd}"
+
+desc "Deploys."
+task :deploy do
+ deploy do
+ invoke :'git:clone'
+ end
+end
diff --git a/spec/helpers/exec_helper_spec.rb b/spec/helpers/exec_helper_spec.rb
new file mode 100644
index 0000000..28223b4
--- /dev/null
+++ b/spec/helpers/exec_helper_spec.rb
@@ -0,0 +1,19 @@
+require 'spec_helper'
+
+describe 'Exec Helpers' do
+ before :each do
+ @exec = Object.new
+ @exec.send :extend, Mina::ExecHelpers
+
+ allow(@exec).to receive(:print_char)
+ end
+
+ it 'pretty_system' do
+ @exec.pretty_system "echo 'Hello there'"
+
+ expect(@exec).to have_received(:print_char).
+ with("e").with("r").with("e").with("h").with("t").
+ with(" ").
+ with("o").with("l").with("l").with("e").with("H")
+ end
+end
diff --git a/spec/helpers/output_helper_spec.rb b/spec/helpers/output_helper_spec.rb
new file mode 100644
index 0000000..60d007c
--- /dev/null
+++ b/spec/helpers/output_helper_spec.rb
@@ -0,0 +1,38 @@
+require 'spec_helper'
+
+describe 'Output Helpers' do
+ before :each do
+ @out = Object.new
+ @out.send :extend, Mina::OutputHelpers
+
+ allow(@out).to receive(:print_stdout)
+ allow(@out).to receive(:print_status)
+ allow(@out).to receive(:print_error)
+ allow(@out).to receive(:print_command)
+ allow(@out).to receive(:print_clear)
+ end
+
+ it 'print_str to stdout' do
+ @out.print_str "Hello there\n"
+
+ expect(@out).to have_received(:print_stdout).with("Hello there\n")
+ end
+
+ it 'print_str to status' do
+ @out.print_str "-----> Getting password"
+
+ expect(@out).to have_received(:print_status).with("Getting password")
+ end
+
+ it 'print_str to status (2)' do
+ @out.print_str "-> Getting password"
+
+ expect(@out).to have_received(:print_status).with("Getting password")
+ end
+
+ it 'print_str to error' do
+ @out.print_str "! Something went wrong"
+
+ expect(@out).to have_received(:print_error).with("Something went wrong")
+ end
+end
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
new file mode 100644
index 0000000..fd8ad09
--- /dev/null
+++ b/spec/spec_helper.rb
@@ -0,0 +1,27 @@
+require 'mina'
+require 'rake'
+
+RSpec.configure do |config|
+ config.order = 'random'
+ config.seed = '12345'
+end
+
+class RakeScope
+ include Rake::DSL if Rake.const_defined?(:DSL)
+ include Mina::Helpers
+ include Mina::SshHelpers
+end
+
+def rake(&blk)
+ if block_given?
+ @scope ||= RakeScope.new
+ @scope.instance_eval &blk
+ end
+
+ @scope
+end
+
+def root(*a)
+ File.join File.expand_path('../../', __FILE__), *a
+end
+
diff --git a/support/Readme-footer.md b/support/Readme-footer.md
new file mode 100644
index 0000000..1bc7461
--- /dev/null
+++ b/support/Readme-footer.md
@@ -0,0 +1,32 @@
+
+Acknowledgements
+----------------
+
+© 2012-2014, Nadarei. Released under the [MIT
+License](http://www.opensource.org/licenses/mit-license.php).
+
+Mina is authored and maintained by [Rico Sta. Cruz][rsc] and [Michael
+Galero][mg] with help from its [contributors][c]. It is sponsored by our
+startup, [Nadarei][nd].
+
+ * [Nadarei](http://nadarei.co) (nadarei.co)
+ * [Github](http://github.com/nadarei) (@nadarei)
+
+Rico:
+
+ * [My website](http://ricostacruz.com) (ricostacruz.com)
+ * [Github](http://github.com/rstacruz) (@rstacruz)
+ * [Twitter](http://twitter.com/rstacruz) (@rstacruz)
+
+Michael:
+
+ * [My website][mg] (michaelgalero.com)
+ * [Github](http://github.com/mikong) (@mikong)
+
+[rsc]: http://ricostacruz.com
+[mg]: http://devblog.michaelgalero.com/
+[c]: http://github.com/nadarei/mina/contributors
+[nd]: http://nadarei.co
+[issues]: https://github.com/nadarei/mina/issues
+[trello]: https://trello.com/board/mina/4fc8b3023d9c9a4d72e573e6
+
diff --git a/support/Readme-header.md b/support/Readme-header.md
new file mode 100644
index 0000000..0d5d834
--- /dev/null
+++ b/support/Readme-header.md
@@ -0,0 +1,16 @@
+# Mina
+
+Really fast deployer and server automation tool.
+
+Mina works really fast because it's a deploy Bash script generator. It
+generates an entire procedure as a Bash script and runs it remotely in the
+server.
+
+Compare this to the likes of Vlad or Capistrano, where each command
+is run separately on their own SSH sessions. Mina only creates *one* SSH
+session per deploy, minimizing the SSH connection overhead.
+
+ $ gem install mina
+ $ mina
+
+[](https://travis-ci.org/mina-deploy/mina) [](http://badge.fury.io/rb/mina)
diff --git a/support/guide.md b/support/guide.md
new file mode 100644
index 0000000..3929930
--- /dev/null
+++ b/support/guide.md
@@ -0,0 +1,297 @@
+
+User guide
+==========
+
+Setting up a project
+--------------------
+
+Let's deploy a project using Mina.
+
+### Step 1: Create a config/deploy.rb
+
+In your project, type `mina init` to create a sample of this file.
+
+ $ mina init
+ Created config/deploy.rb.
+
+This is just a Rake file with tasks! See [About deploy.rb](#about-deployrb) for
+more info on what *deploy.rb* is. You will want to at least configure your
+server:
+
+~~~ ruby
+# config/deploy.rb
+set :user, 'username'
+set :domain, 'your.server.com'
+set :deploy_to, '/var/www/flipstack.com'
+...
+~~~
+
+### Step 2: Set up your server
+
+Make a directory in your server called `/var/www/flipstack.com` (in *deploy_to*)
+change it's ownership to the correct user.
+
+ $ ssh username at your.server.com
+
+ # Once in your server, create the deploy folder:
+ ~@your.server.com$ mkdir /var/www/flipstack.com
+ ~@your.server.com$ chown -R username /var/www/flipstack.com
+
+### Step 3: Run 'mina setup'
+
+Back at your computer, do `mina setup` to set up the [folder
+structure](#directory_structure) in this path. This will connect to your server
+via SSH and create the right directories.
+
+ $ mina setup
+ -----> Creating folders... done.
+
+See [directory structure](#directory_structure) for more info.
+
+### Step 4: Deploy!
+
+Use `mina deploy` to run the `deploy` task defined in *config/deploy.rb*.
+
+ $ mina deploy
+ -----> Deploying to 2012-06-12-040248
+ ...
+ Lots of things happening...
+ ...
+ -----> Done.
+
+About deploy.rb
+---------------
+
+The file `deploy.rb` is simply a Rakefile invoked by Rake. In fact, `mina` is
+mostly an alias that invokes Rake to load `deploy.rb`.
+
+~~~ ruby
+# Sample config/deploy.rb
+set :domain, 'your.server.com'
+
+task :restart do
+ queue 'sudo service restart apache'
+end
+~~~
+
+As it's all Rake, you can define tasks that you can invoke using `mina`. In this
+example, it provides the `mina restart` command.
+
+The magic of Mina is in the new commands it gives you.
+
+The `queue` command queues up Bash commands to be run on the remote server.
+If you invoke `mina restart`, it will invoke the task above and run the queued
+commands on the remote server `your.server.com` via SSH.
+
+See [the command queue](#the-command-queue) for more information on the *queue*
+command.
+
+The command queue
+-----------------
+
+At the heart of it, Mina is merely sugar on top of Rake to queue commands
+and execute them remotely at the end. Take a look at this minimal *deploy.rb*
+configuration:
+
+~~~ ruby
+# config/deploy.rb
+set :user, 'john'
+set :domain, 'flipstack.com'
+
+task :logs do
+ queue 'echo "Contents of the log file are as follows:"'
+ queue "tail -f /var/log/apache.log"
+end
+~~~
+
+Once you type `mina logs` in your terminal, it invokes the *queue*d commands
+remotely on the server using the command `ssh john at flipstack.com`.
+
+~~~ sh
+$ mina logs --simulate
+# Execute the following commands via
+# ssh john at flipstack.com:
+#
+echo "Contents of the log file are as follows:"
+tail -f /var/log/apache.log
+~~~
+
+Subtasks
+--------
+
+Mina provides the helper `invoke` to invoke other tasks from a
+task.
+
+~~~ ruby
+# config/deploy.rb
+task :down do
+ invoke :maintenance_on
+ invoke :restart
+end
+
+task :maintenance_on
+ queue 'touch maintenance.txt'
+end
+
+task :restart
+ queue 'sudo service restart apache'
+end
+~~~
+
+In this example above, if you type `mina down`, it simply invokes the other
+subtasks which queues up their commands. The commands will be run after
+everything.
+
+Directory structure
+-------------------
+
+The deploy procedures make the assumption that you have a folder like so:
+
+ /var/www/flipstack.com/ # The deploy_to path
+ |- releases/ # Holds releases, one subdir per release
+ | |- 1/
+ | |- 2/
+ | |- 3/
+ | '- ...
+ |- shared/ # Holds files shared between releases
+ | |- logs/ # Log files are usually stored here
+ | `- ...
+ '- current/ # A symlink to the current release in releases/
+
+It also assumes that the `deploy_to` path is fully writeable/readable for the
+user we're going to SSH with.
+
+Deploying
+---------
+
+Mina provides the `deploy` command which *queue*s up a deploy script for
+you.
+
+~~~ ruby
+# config/deploy.rb
+set :domain, 'flipstack.com'
+set :user, 'flipstack'
+set :deploy_to, '/var/www/flipstack.com'
+set :repository, 'http://github.com/flipstack/flipstack.git'
+
+task :deploy do
+ deploy do
+ # Put things that prepare the empty release folder here.
+ # Commands queued here will be run on a new release directory.
+ invoke :'git:clone'
+ invoke :'bundle:install'
+
+ # These are instructions to start the app after it's been prepared.
+ to :launch do
+ queue 'touch tmp/restart.txt'
+ end
+
+ # This optional block defines how a broken release should be cleaned up.
+ to :clean do
+ queue 'log "failed deployment"'
+ end
+ end
+end
+~~~
+
+It works by capturing the *queue*d commands inside the block, wrapping them
+in a deploy script, then *queue*ing them back in.
+
+### How deploying works
+
+Here is an example of a deploy! (Note that some commands have been simplified
+to illustrate the point better.)
+
+### Step 1: Build it
+
+The deploy process builds a new temp folder with instructions you provide.
+In this example, it will do `git:clone` and `bundle:install`.
+
+ $ mina deploy --verbose
+ -----> Creating the build path
+ $ mkdir tmp/build-128293482394
+ -----> Cloning the Git repository
+ $ git clone https://github.com/flipstack/flipstack.git . -n --recursive
+ Cloning... done.
+ -----> Installing gem dependencies using Bundler
+ $ bundle install --without development:test
+ Using i18n (0.6.0)
+ Using multi_json (1.0.4)
+ ...
+ Your bundle is complete! It was installed to ./vendor/bundle
+
+### Step 2: Move it to releases
+
+Once the project has been built, it will be moved to `releases/`. A symlink
+called `current/` will be created to point to the active release.
+
+ $
+ -----> Moving to releases/4
+ $ mv "./tmp/build-128293482394" "releases/4"
+ -----> Symlinking to current
+ $ ln -nfs releases/4 current
+
+### Step 3: Launch it
+
+Invoke the commands queued up in the `to :launch` block. These often
+commands to restart the webserver process. Once this in complete, you're done!
+
+ $
+ -----> Launching
+ $ cd releases/4
+ $ sudo service nginx restart
+ -----> Done. Deployed v4
+
+### What about failure?
+
+If it fails at any point, the release path will be deleted. If any commands are
+queued using the `to :clean` block, they will be run. It will be as if nothing
+happened. Lets see what happens if a build fails:
+
+ $
+ -----> Launching
+ $ cd releases/4
+ $ sudo service nginx restart
+ Starting nginx... error: can't start service
+ -----> ERROR: Deploy failed.
+ -----> Cleaning up build
+ $ rm -rf tmp/build-128293482394
+ -----> Unlinking current
+ $ ln -nfs releases/3 current
+ OK
+
+Command line options
+--------------------
+
+Basic usage:
+
+ $ mina [OPTIONS] [TASKS] [VAR1=val VAR2=val ...]
+
+### Options
+
+* `-v` / `--verbose` - This will show commands being done on the server. Off by
+ default.
+
+* `-S` / `--simulate` - This will not invoke any SSH connections; instead, it
+ will simply output the script it builds.
+
+* `-t` / `--trace` - Show backtraces when errors occur.
+
+* `-f FILE` - Use a custom deploy.rb configuration.
+
+* `-V` / `--version` - Shows the current version.
+
+### Tasks
+
+There are many tasks available. See the [tasks reference](tasks/index.html), or
+type `mina tasks`.
+
+### Variables
+
+You may specify additional variables in the `KEY=value` style, just like Rake.
+You can add as many variables as needed.
+
+ $ mina restart on=staging
+
+ # This sets the ENV['on'] variable to 'staging'.
+
diff --git a/support/index.html b/support/index.html
new file mode 100644
index 0000000..0e41e70
--- /dev/null
+++ b/support/index.html
@@ -0,0 +1,53 @@
+<html>
+<head>
+ <meta charset='utf-8'>
+ <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
+ <meta name="viewport" content="width=device-width">
+
+ <title>Mina</title>
+
+ <!-- Flatdoc -->
+ <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
+ <script src='http://rstacruz.github.io/flatdoc/v/0.8.0/legacy.js'></script>
+ <script src='http://rstacruz.github.io/flatdoc/v/0.8.0/flatdoc.js'></script>
+
+ <!-- Flatdoc theme -->
+ <link href='http://rstacruz.github.io/flatdoc/v/0.8.0/theme-white/style.css' rel='stylesheet'>
+ <script src='http://rstacruz.github.io/flatdoc/v/0.8.0/theme-white/script.js'></script>
+
+ <!-- Meta -->
+ <meta content="Mina" property="og:title">
+ <meta content="Mina deployer tool." name="description">
+
+ <!-- Initializer -->
+ <script>
+ Flatdoc.run({
+ fetcher: location.hostname.match(/localhost/) ? Flatdoc.file('../Readme.md') : Flatdoc.github('nadarei/mina')
+ });
+ </script>
+</head>
+<body role='flatdoc'>
+
+ <div class='header'>
+ <div class='left'>
+ <h1>Mina</h1>
+ <ul>
+ <li><a href='https://github.com/nadarei/mina'>View on GitHub</a></li>
+ <li><a href='https://github.com/nadarei/mina/issues'>Issues</a></li>
+ </ul>
+ </div>
+ <div class='right'>
+ <!-- GitHub buttons: see http://ghbtns.com -->
+ <iframe src="http://ghbtns.com/github-btn.html?user=nadarei&repo=mina&type=watch&count=true" allowtransparency="true" frameborder="0" scrolling="0" width="110" height="20"></iframe>
+ </div>
+ </div>
+
+ <div class='content-root'>
+ <div class='menubar'>
+ <div class='menu section' role='flatdoc-menu'></div>
+ </div>
+ <div role='flatdoc-content' class='content'></div>
+ </div>
+
+</body>
+</html>
diff --git a/support/to_md.rb b/support/to_md.rb
new file mode 100644
index 0000000..4e21759
--- /dev/null
+++ b/support/to_md.rb
@@ -0,0 +1,11 @@
+#!/usr/bin/env ruby
+c = /(?:#|\/\/)/ # Comment prefix
+lang = "ruby" # Default language
+blocks = STDIN.read.scan(/(?:^[ \t]*#{c} [^\n]*\n)+/) # Read contiguous comments
+blocks.map! { |s| s.gsub!(/(?:^|\n)+[ \t]*#{c} /, "\n") } # Strip out prefixes
+
+# Code blocks
+md = blocks.join("")
+md.gsub!(/((?:^ .*\n+)+)/) { |f| "~~~ #{lang}\n" + f.gsub(/^ /, '').gsub(/\s*$/, '') + "\n~~~\n\n" }
+
+puts md
diff --git a/test_env/config/deploy.rb b/test_env/config/deploy.rb
new file mode 100644
index 0000000..881b2bf
--- /dev/null
+++ b/test_env/config/deploy.rb
@@ -0,0 +1,69 @@
+# NOTE:
+# Yes, you can deploy this project. It will deploy into the ./deploy/
+# directory. The commands have been stubbed, so it's harmless. No rails or
+# bundler magic will happen.
+
+# ASSUMPTIONS:
+# - You have git installed. (of course you do)
+# - You have SSH enabled. In OS X, this is "Remote Login" under the Sharing pref pane.
+# - You have your own SSH key added to your own user so you can SSH to your own machine.
+
+# In fact, let's make that folder right now.
+require 'fileutils'
+FileUtils.mkdir_p "#{Dir.pwd}/deploy"
+FileUtils.mkdir_p "#{Dir.pwd}/deploy/config"
+File.open("#{Dir.pwd}/deploy/config/database.yml", 'w') { |f| f.write "Hello" }
+
+# -- Stubs end, deploy script begins! --------------
+
+require 'mina/rails'
+require 'mina/bundler'
+require 'mina/git'
+
+set :domain, 'localhost'
+set :deploy_to, "#{Dir.pwd}/deploy"
+set :repository, "#{Mina.root_path}"
+set :shared_paths, ['config/database.yml']
+
+set :keep_releases, 2
+
+task :environment do
+ queue %[echo "-----> Loading env"]
+end
+
+desc "Deploys."
+task :deploy => :environment do
+ queue "bundle() { true; }" # Stub the bundle command.
+
+ deploy do
+ queue %[ruby -e "\\$stderr.write \\\"This is stdout output\n\\\""]
+ invoke :'git:clone'
+ invoke :'deploy:link_shared_paths'
+ invoke :'bundle:install'
+ invoke :'rails:db_migrate'
+
+ to :launch do
+ invoke :'passenger:restart'
+ end
+ end
+end
+
+desc "Restarts the passenger server."
+task :restart do
+ invoke :'passenger:restart'
+end
+
+namespace :passenger do
+ task :restart do
+ queue %{
+ echo "-----> Restarting passenger"
+ #{echo_cmd %[mkdir -p tmp]}
+ #{echo_cmd %[touch tmp/restart.txt]}
+ }
+ end
+end
+
+task :get_password do
+ set :term_mode, :pretty
+ queue %[echo "-> Getting password"; echo -n "Password: "; read x; echo ""; echo out: $x;]
+end
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-ruby-extras/ruby-mina.git
More information about the Pkg-ruby-extras-commits
mailing list