├── lib ├── capistrano-pm2.rb └── capistrano │ ├── pm2.rb │ └── tasks │ └── pm2.rake ├── Rakefile ├── Gemfile ├── .gitignore ├── capistrano-pm2.gemspec ├── LICENSE └── README.md /lib/capistrano-pm2.rb: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | require 'bundler/gem_tasks' 2 | -------------------------------------------------------------------------------- /lib/capistrano/pm2.rb: -------------------------------------------------------------------------------- 1 | load File.expand_path('../tasks/pm2.rake', __FILE__) 2 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | # Specify your gem's dependencies in capistrano-bundler.gemspec 4 | gemspec 5 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.gem 2 | *.rbc 3 | /.config 4 | /coverage/ 5 | /InstalledFiles 6 | /pkg/ 7 | /spec/reports/ 8 | /test/tmp/ 9 | /test/version_tmp/ 10 | /tmp/ 11 | 12 | ## Specific to RubyMotion: 13 | .dat* 14 | .repl_history 15 | build/ 16 | 17 | ## Documentation cache and generated files: 18 | /.yardoc/ 19 | /_yardoc/ 20 | /doc/ 21 | /rdoc/ 22 | 23 | ## Environment normalisation: 24 | /.bundle/ 25 | /vendor/bundle 26 | /lib/bundler/man/ 27 | 28 | # for a library or gem, you might want to ignore these files since the code is 29 | # intended to run in multiple environments; otherwise, check them in: 30 | # Gemfile.lock 31 | # .ruby-version 32 | # .ruby-gemset 33 | 34 | # unless supporting rvm < 1.11.0 or doing something fancy, ignore this: 35 | .rvmrc 36 | -------------------------------------------------------------------------------- /capistrano-pm2.gemspec: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | lib = File.expand_path('../lib', __FILE__) 3 | $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) 4 | 5 | Gem::Specification.new do |spec| 6 | spec.name = 'capistrano-pm2' 7 | spec.version = '1.0.4' 8 | spec.authors = ['Tom Hanoldt'] 9 | spec.email = ['monotom@gmail.com'] 10 | spec.description = 'nodejs pm2 support for Capistrano 3.x' 11 | spec.summary = 'nodejs pm2 support for Capistrano 3.x' 12 | spec.homepage = 'https://github.com/creative-workflow/capistrano-pm2' 13 | spec.license = 'MIT' 14 | 15 | spec.files = `git ls-files`.split($INPUT_RECORD_SEPARATOR) 16 | spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) } 17 | spec.test_files = spec.files.grep(%r{^(test|spec|features)/}) 18 | spec.require_paths = ['lib'] 19 | 20 | spec.add_dependency 'capistrano', '>= 3.0.0' 21 | 22 | spec.add_development_dependency 'bundler', '~> 1.3' 23 | spec.add_development_dependency 'rake' 24 | end 25 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 creative-workflow 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Capistrano::pm2 [![Gem Version](https://badge.fury.io/rb/capistrano-pm2.svg)](http://badge.fury.io/rb/capistrano-pm2) 2 | 3 | nodejs [pm2](https://github.com/Unitech/pm2) support for Capistrano 3.x 4 | 5 | ## Installation 6 | 7 | Add this line to your application's Gemfile: 8 | 9 | ```ruby 10 | gem 'capistrano', '~> 3.1.0' 11 | gem 'capistrano-pm2' 12 | ``` 13 | 14 | And then execute: 15 | 16 | $ bundle 17 | 18 | Or install it yourself as: 19 | 20 | $ gem install capistrano-pm2 21 | 22 | ## Usage 23 | 24 | Require in `Capfile` to use the default task: 25 | 26 | ```ruby 27 | require 'capistrano/pm2' 28 | ``` 29 | 30 | The task will run before `deploy:restart` as part of Capistrano's default deploy, 31 | or can be run in isolation with `cap production pm2:restart`. You can also invoke it in your `deploy.rb`: 32 | ```ruby 33 | namespace :deploy do 34 | desc 'Restart application' 35 | task :restart do 36 | # invoke 'npm:install' 37 | invoke 'pm2:restart' 38 | end 39 | 40 | after :publishing, :restart 41 | end 42 | ``` 43 | 44 | 45 | Available Tasks 46 | ```ruby 47 | cap pm2:delete # Delete pm2 application 48 | cap pm2:list # Show pm2 application info 49 | cap pm2:logs # Watch pm2 logs 50 | cap pm2:restart # Restart app gracefully 51 | cap pm2:setup # Install pm2 via npm on the remote host 52 | cap pm2:start # Start pm2 application 53 | cap pm2:status # List all pm2 applications 54 | cap pm2:stop # Stop pm2 application 55 | cap pm2:save # Save pm2 state so it can be loaded after restart 56 | ``` 57 | 58 | Configurable options: 59 | ```ruby 60 | set :pm2_app_command, 'main.js' # the main program 61 | set :pm2_app_name, fetch(:application) # name for pm2 app 62 | set :pm2_target_path, -> { release_path } # where to run pm2 commands 63 | set :pm2_roles, :all # server roles where pm2 runs on 64 | set :pm2_env_variables, {} # default: env vars for pm2 65 | set :pm2_start_params, '' # pm2 start params see http://pm2.keymetrics.io/docs/usage/quick-start/#cheat-sheet 66 | ``` 67 | 68 | ## Contributing 69 | 70 | 1. Fork it 71 | 2. Create your feature branch (`git checkout -b my-new-feature`) 72 | 3. Commit your changes (`git commit -am 'Add some feature'`) 73 | 4. Push to the branch (`git push origin my-new-feature`) 74 | 5. Create new Pull Request 75 | -------------------------------------------------------------------------------- /lib/capistrano/tasks/pm2.rake: -------------------------------------------------------------------------------- 1 | require 'json' 2 | 3 | namespace :pm2 do 4 | desc 'Restart app gracefully' 5 | task :restart do 6 | on roles fetch(:pm2_roles) do 7 | case app_status 8 | when nil 9 | info 'App is not registerd' 10 | invoke 'pm2:start' 11 | when 'stopped' 12 | info 'App is stopped' 13 | restart_app 14 | when 'errored' 15 | info 'App has errored' 16 | restart_app 17 | when 'online' 18 | info 'App is online' 19 | restart_app 20 | end 21 | end 22 | end 23 | 24 | before 'deploy:restart', 'pm2:restart' 25 | 26 | desc 'List all pm2 applications' 27 | task :status do 28 | run_task :pm2, :list 29 | end 30 | 31 | desc 'Start pm2 application' 32 | task :start do 33 | run_task :pm2, :start, fetch(:pm2_app_command), "--cwd #{current_path} --name #{app_name} #{fetch(:pm2_start_params)}" 34 | end 35 | 36 | desc 'Stop pm2 application' 37 | task :stop do 38 | run_task :pm2, :stop, app_name 39 | end 40 | 41 | desc 'Delete pm2 application' 42 | task :delete do 43 | run_task :pm2, :delete, app_name 44 | end 45 | 46 | desc 'Show pm2 application info' 47 | task :list do 48 | run_task :pm2, :show, app_name 49 | end 50 | 51 | desc 'Watch pm2 logs' 52 | task :logs do 53 | run_task :pm2, :logs 54 | end 55 | 56 | desc 'Save pm2 state so it can be loaded after restart' 57 | task :save do 58 | run_task :pm2, :save 59 | end 60 | 61 | desc 'Install pm2 via npm on the remote host' 62 | task :setup do 63 | run_task :npm, :install, 'pm2 -g' 64 | end 65 | 66 | def app_name 67 | fetch(:pm2_app_name) || fetch(:application) 68 | end 69 | 70 | def app_status 71 | within release_path do 72 | with fetch(:pm2_env_variables) do 73 | ps = JSON.parse(capture :pm2, :jlist, :'-s') 74 | 75 | # find the process with our app name 76 | ps.each do |child| 77 | if child['name'] == app_name 78 | # status: online, errored, stopped 79 | return child['pm2_env']['status'] 80 | end 81 | end 82 | 83 | return nil 84 | end 85 | end 86 | end 87 | 88 | def restart_app 89 | within release_path do 90 | with fetch(:pm2_env_variables) do 91 | execute :pm2, :restart, app_name 92 | end 93 | end 94 | end 95 | 96 | def run_task(*args) 97 | on roles fetch(:pm2_roles) do 98 | within fetch(:pm2_target_path, release_path) do 99 | with fetch(:pm2_env_variables) do 100 | execute *args 101 | end 102 | end 103 | end 104 | end 105 | end 106 | 107 | namespace :load do 108 | task :defaults do 109 | set :pm2_app_command, 'main.js' 110 | set :pm2_app_name, nil 111 | set :pm2_start_params, '' 112 | set :pm2_roles, :all 113 | set :pm2_env_variables, {} 114 | end 115 | end 116 | --------------------------------------------------------------------------------