├── .gemrelease ├── .gitignore ├── Gemfile ├── Gemfile.lock ├── LICENSE ├── README.md ├── Rakefile ├── capistrano-wpcli.gemspec └── lib ├── capistrano-wpcli.rb └── capistrano ├── tasks ├── wpcli.rake ├── wpdb.rake ├── wprewrite.rake └── wpuploads.rake ├── wpcli.rb └── wpcli └── version.rb /.gemrelease: -------------------------------------------------------------------------------- 1 | bump: 2 | release: true 3 | tag: true -------------------------------------------------------------------------------- /.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 | /lib/bundler/man/ 26 | 27 | # for a library or gem, you might want to ignore these files since the code is 28 | # intended to run in multiple environments; otherwise, check them in: 29 | # Gemfile.lock 30 | # .ruby-version 31 | # .ruby-gemset 32 | 33 | # unless supporting rvm < 1.11.0 or doing something fancy, ignore this: 34 | .rvmrc 35 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | # Specify your gem's dependencies in capistrano-wpcli.gemspec 4 | gemspec 5 | -------------------------------------------------------------------------------- /Gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: . 3 | specs: 4 | capistrano-wpcli (0.1.5) 5 | capistrano (~> 3.6) 6 | sshkit (~> 1.11) 7 | 8 | GEM 9 | remote: https://rubygems.org/ 10 | specs: 11 | airbrussh (1.1.1) 12 | sshkit (>= 1.6.1, != 1.7.0) 13 | capistrano (3.7.1) 14 | airbrussh (>= 1.0.0) 15 | capistrano-harrow 16 | i18n 17 | rake (>= 10.0.0) 18 | sshkit (>= 1.9.0) 19 | capistrano-harrow (0.5.3) 20 | i18n (0.7.0) 21 | net-scp (1.2.1) 22 | net-ssh (>= 2.6.5) 23 | net-ssh (3.2.0) 24 | rake (13.0.1) 25 | sshkit (1.11.5) 26 | net-scp (>= 1.1.2) 27 | net-ssh (>= 2.8.0) 28 | 29 | PLATFORMS 30 | ruby 31 | 32 | DEPENDENCIES 33 | bundler (~> 1.12) 34 | capistrano-wpcli! 35 | rake (~> 13.0) 36 | 37 | BUNDLED WITH 38 | 1.13.6 39 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 lavmeiker 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. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Capistrano::WPCLI 2 | 3 | [![Dependency Status](https://www.versioneye.com/user/projects/561c9bfda193340f2f001728/badge.svg?style=flat)](https://www.versioneye.com/user/projects/561c9bfda193340f2f001728) 4 | [![Gem Version](https://badge.fury.io/rb/capistrano-wpcli.svg)](https://badge.fury.io/rb/capistrano-wpcli) 5 | 6 | **Note: this plugin works only with Capistrano 3.** 7 | 8 | Provides command line tools to facilitate Wordpress deploy. 9 | 10 | ## Installation 11 | 12 | Add this line to your application's Gemfile: 13 | 14 | gem 'capistrano-wpcli' 15 | 16 | And then execute: 17 | 18 | $ bundle 19 | 20 | Or install it yourself as: 21 | 22 | $ gem install capistrano-wpcli 23 | 24 | ## Usage 25 | 26 | All you need to do is put the following in `Capfile` file: 27 | 28 | require 'capistrano/wpcli' 29 | 30 | ### How it works (Tasks) 31 | 32 | wpcli:run 33 | 34 | Executes the WP-CLI command passed as parameter. 35 | 36 | cap production wpcli:run["core language install fr_FR"] 37 | 38 | - - - 39 | 40 | wpcli:db:push 41 | 42 | Pushes the local WP database to the remote server and replaces the urls. 43 | 44 | Optionally backs up the remote database before pushing (if `wpcli_backup_db` is set to true, see Configuration). 45 | 46 | cap production wpcli:db:push 47 | 48 | - - - 49 | 50 | wpcli:db:pull 51 | 52 | Pulls the remote server WP database to local and replaces the urls. 53 | 54 | cap production wpcli:db:pull 55 | 56 | - - - 57 | 58 | wpcli:db:backup:remote 59 | 60 | Pulls the remote server WP database to localhost, uses `wpcli_local_db_backup_dir` to define the location of the export. 61 | 62 | - - - 63 | 64 | wpcli:db:backup:local 65 | 66 | Backs up the local WP database to localhost, uses `wpcli_local_db_backup_dir` to define the location of the export. 67 | 68 | - - - 69 | 70 | wpcli:rewrite:flush 71 | 72 | Flush rewrite rules. 73 | 74 | - - - 75 | 76 | wpcli:rewrite:hard_flush 77 | 78 | Perform a hard flush - updates `.htaccess` rules as well as rewrite rules in database. 79 | 80 | - - - 81 | 82 | wpcli:uploads:rsync:push 83 | 84 | Push local uploads delta to remote machine using rsync. 85 | 86 | - - - 87 | 88 | wpcli:uploads:rsync:pull 89 | 90 | Pull remote uploads delta to local machine using rsync. 91 | 92 | ### Configuration 93 | 94 | This plugin needs some configuration to work properly. You can put all your configs in Capistrano stage files i.e. `config/deploy/production.rb`. 95 | 96 | Here's the list of options and the defaults for each option: 97 | 98 | - - - 99 | 100 | set :wpcli_remote_url 101 | 102 | Url of the WP root installation on the remote server (used by search-replace command). 103 | 104 | - - - 105 | 106 | set :wpcli_local_url 107 | 108 | Url of the WP root installation on the local server (used by search-replace command). 109 | 110 | - - - 111 | 112 | set :local_tmp_dir 113 | 114 | Absolute path to local directory temporary directory which is read and writeable. 115 | 116 | Defaults to `/tmp` 117 | 118 | - - - 119 | 120 | set :wpcli_backup_db 121 | 122 | Set to true if you would like to create backups of databases on each push. Defaults to false. 123 | 124 | - - - 125 | 126 | set :wpcli_local_db_backup_dir 127 | 128 | Absolute or relative path to local directory for storing database backups which is read and writeable. 129 | 130 | Defaults to `config/backup` 131 | 132 | **IMPORTANT: Make sure to add the folder to .gitignore to prevent db backups from being in version control.** 133 | 134 | - - - 135 | 136 | set :wpcli_args 137 | 138 | You can pass arguments directly to WPCLI using this var. 139 | 140 | Defaults to `ENV['WPCLI_ARGS']` 141 | 142 | - - - 143 | 144 | set :wpcli_local_uploads_dir 145 | 146 | Absolute or relative path to local WP uploads directory. 147 | 148 | Defaults to `web/app/uploads/`. 149 | 150 | **IMPORTANT: Add trailing slash!** 151 | 152 | - - - 153 | 154 | set :wpcli_remote_uploads_dir 155 | 156 | Absolute path to remote wordpress uploads directory. 157 | 158 | Defaults to `#{shared_path.to_s}/web/app/uploads/` 159 | 160 | **IMPORTANT: Add trailing slash!** 161 | 162 | ### FAQ 163 | 164 | - What if i want to use a custom port for rsync? 165 | You can by setting your port somewhere inside the :ssh_options precedence. 166 | See here: http://capistranorb.com/documentation/advanced-features/properties/#precedence 167 | 168 | ### Vagrant 169 | 170 | If you are using another machine as a development server (Vagrant for example), you should define a `dev` role and indicate the path where the project lives on that server. This normally goes on `deploy.rb` file. Here's an example: 171 | 172 | server "example.dev", user: 'vagrant', password: 'vagrant', roles: %w{dev} 173 | 174 | set :dev_path, '/srv/www/example.dev/current' 175 | 176 | ## Contributing 177 | 178 | 1. Fork it ( https://github.com/lavmeiker/capistrano-wpcli/fork ) 179 | 2. Create your feature branch (`git checkout -b my-new-feature`) 180 | 3. Commit your changes (`git commit -am 'Add some feature'`) 181 | 4. Push to the branch (`git push origin my-new-feature`) 182 | 5. Create a new Pull Request 183 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | require "bundler/gem_tasks" 2 | 3 | -------------------------------------------------------------------------------- /capistrano-wpcli.gemspec: -------------------------------------------------------------------------------- 1 | # coding: utf-8 2 | lib = File.expand_path('../lib', __FILE__) 3 | $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) 4 | require 'capistrano/wpcli/version' 5 | 6 | Gem::Specification.new do |spec| 7 | spec.name = "capistrano-wpcli" 8 | spec.version = Capistrano::Wpcli::VERSION 9 | spec.authors = ["Juancito Arias", "Jeremy Zahner"] 10 | spec.email = ["trasgofurioso@gmail.com"] 11 | spec.summary = %q{Simple Capistrano wrapper around WP-CLI} 12 | spec.description = %q{Capistrano tasks for managing Wordpress} 13 | spec.homepage = "https://github.com/lavmeiker/capistrano-wpcli" 14 | spec.license = "MIT" 15 | 16 | spec.files = `git ls-files -z`.split("\x0") 17 | spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) } 18 | spec.test_files = spec.files.grep(%r{^(test|spec|features)/}) 19 | spec.require_paths = ["lib"] 20 | 21 | spec.add_dependency 'capistrano', '~> 3.6' 22 | spec.add_dependency 'sshkit', '~> 1.11' 23 | 24 | spec.add_development_dependency "bundler", "~> 1.12" 25 | spec.add_development_dependency "rake", "~> 13.0" 26 | 27 | end 28 | -------------------------------------------------------------------------------- /lib/capistrano-wpcli.rb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lavmeiker/capistrano-wpcli/5201da44a0d7f47e8e2cb94b81d009d0a229bf20/lib/capistrano-wpcli.rb -------------------------------------------------------------------------------- /lib/capistrano/tasks/wpcli.rake: -------------------------------------------------------------------------------- 1 | namespace :load do 2 | task :defaults do 3 | set :wp_roles, :all 4 | 5 | # You can pass parameters to WPCLI setting 6 | # env var WPCLI_ARGS on each run 7 | set :wpcli_args, ENV['WPCLI_ARGS'] 8 | end 9 | end 10 | 11 | namespace :wpcli do 12 | desc "Runs a WP-CLI command" 13 | task :run, :command do |t, args| 14 | args.with_defaults(:command => :help) 15 | on release_roles(fetch(:wp_roles)) do 16 | within release_path do 17 | execute :wp, args[:command], fetch(:wpcli_args) 18 | end 19 | end 20 | end 21 | end -------------------------------------------------------------------------------- /lib/capistrano/tasks/wpdb.rake: -------------------------------------------------------------------------------- 1 | namespace :load do 2 | 3 | task :defaults do 4 | 5 | # The url under which the wordpress installation is 6 | # available on the remote server 7 | set :wpcli_remote_url, "http://example.com" 8 | 9 | # The url under which the wordpress installation is 10 | # available on the local server 11 | set :wpcli_local_url, "http://example.dev" 12 | 13 | # A local temp dir which is read and writeable 14 | set :local_tmp_dir, "/tmp" 15 | 16 | # Use current time for annotating the backup file 17 | set :current_time, -> { Time.now.strftime("%Y%m%d%H%M") } 18 | 19 | # Boolean to determine wether the database should be backed up or not 20 | set :wpcli_backup_db, false 21 | 22 | # Set the location of the db backup files. This is relative to the local project root path. 23 | set :wpcli_local_db_backup_dir, "config/backup" 24 | 25 | # Temporary db dumps path 26 | set :wpcli_remote_db_file, -> {"#{fetch(:tmp_dir)}/wpcli_database.sql.gz"} 27 | set :wpcli_local_db_file, -> {"#{fetch(:local_tmp_dir)}/wpcli_database.sql.gz"} 28 | 29 | # Backup file filename 30 | set :wpcli_local_db_backup_filename, -> {"db_#{fetch(:stage)}_#{fetch(:current_time)}.sql.gz"} 31 | 32 | end 33 | 34 | end 35 | 36 | namespace :wpcli do 37 | 38 | namespace :db do 39 | 40 | desc "Pull the remote database" 41 | task :pull do 42 | on roles(:web) do 43 | within release_path do 44 | execute :wp, :db, :export, "- |", :gzip, ">", fetch(:wpcli_remote_db_file) 45 | download! fetch(:wpcli_remote_db_file), fetch(:wpcli_local_db_file) 46 | execute :rm, fetch(:wpcli_remote_db_file) 47 | end 48 | end 49 | 50 | unless roles(:dev).empty? 51 | on roles(:dev) do 52 | within fetch(:dev_path) do 53 | local_tmp_file = fetch(:wpcli_local_db_file).gsub(/\.gz$/, "") 54 | upload! fetch(:wpcli_local_db_file), fetch(:wpcli_local_db_file) 55 | execute :gunzip, "-c", fetch(:wpcli_local_db_file), ">", local_tmp_file 56 | execute :wp, :db, :import, local_tmp_file 57 | execute :rm, fetch(:wpcli_local_db_file), local_tmp_file 58 | execute :wp, "search-replace", fetch(:wpcli_remote_url), fetch(:wpcli_local_url), fetch(:wpcli_args) || "--skip-columns=guid", "--url=" + fetch(:wpcli_remote_url) 59 | end 60 | end 61 | run_locally do 62 | execute :rm, fetch(:wpcli_local_db_file) 63 | end 64 | else 65 | run_locally do 66 | local_tmp_file = fetch(:wpcli_local_db_file).gsub(/\.gz$/, "") 67 | execute :gunzip, "-c", fetch(:wpcli_local_db_file), ">", local_tmp_file 68 | execute :wp, :db, :import, local_tmp_file 69 | execute :rm, fetch(:wpcli_local_db_file), local_tmp_file 70 | execute :wp, "search-replace", fetch(:wpcli_remote_url), fetch(:wpcli_local_url), fetch(:wpcli_args) || "--skip-columns=guid", "--url=" + fetch(:wpcli_remote_url) 71 | end 72 | end 73 | end 74 | 75 | desc "Push the local database" 76 | task :push do 77 | unless roles(:dev).empty? 78 | on roles(:dev) do 79 | within fetch(:dev_path) do 80 | execute :wp, :db, :export, "- |", :gzip, ">", fetch(:wpcli_local_db_file) 81 | download! fetch(:wpcli_local_db_file), fetch(:wpcli_local_db_file) 82 | end 83 | end 84 | else 85 | run_locally do 86 | execute :wp, :db, :export, "- |", :gzip, ">", fetch(:wpcli_local_db_file) 87 | end 88 | end 89 | on roles(:web) do 90 | upload! fetch(:wpcli_local_db_file), fetch(:wpcli_remote_db_file) 91 | within release_path do 92 | remote_tmp_file = fetch(:wpcli_remote_db_file).gsub(/\.gz$/, "") 93 | execute :gunzip, "-c", fetch(:wpcli_remote_db_file), ">", remote_tmp_file 94 | execute :wp, :db, :import, remote_tmp_file 95 | execute :rm, fetch(:wpcli_remote_db_file), remote_tmp_file 96 | execute :wp, "search-replace", fetch(:wpcli_local_url), fetch(:wpcli_remote_url), fetch(:wpcli_args) || "--skip-columns=guid", "--url=" + fetch(:wpcli_local_url) 97 | end 98 | end 99 | unless roles(:dev).empty? 100 | on roles(:dev) do 101 | within fetch(:dev_path) do 102 | execute :rm, fetch(:wpcli_local_db_file) 103 | end 104 | end 105 | end 106 | run_locally do 107 | execute :rm, fetch(:wpcli_local_db_file) 108 | end 109 | end 110 | 111 | namespace :backup do 112 | 113 | desc "Checking / Creating backup directory" 114 | task :create_backup_dir do 115 | run_locally do 116 | unless test("[ -d #{fetch(:wpcli_local_db_backup_dir)} ]") 117 | execute :mkdir, Pathname.new(fetch(:wpcli_local_db_backup_dir)) 118 | end 119 | end 120 | end 121 | 122 | desc "Backup the remote database" 123 | task :remote do 124 | on roles(:web) do 125 | within release_path do 126 | execute :wp, :db, :export, "- |", :gzip, ">", fetch(:wpcli_remote_db_file) 127 | download! fetch(:wpcli_remote_db_file), File.join(fetch(:wpcli_local_db_backup_dir), fetch(:wpcli_local_db_backup_filename)) 128 | execute :rm, fetch(:wpcli_remote_db_file) 129 | end 130 | end 131 | end 132 | 133 | desc "Backup the local database" 134 | task :local do 135 | run_locally do 136 | set :stage, :local 137 | execute :wp, :db, :export, "- |", :gzip, ">", File.join(fetch(:wpcli_local_db_backup_dir), fetch(:wpcli_local_db_backup_filename)) 138 | end 139 | end 140 | 141 | before :push, 'backup:remote' if :wpcli_backup_db 142 | before :local, :create_backup_dir 143 | before :remote, :create_backup_dir 144 | 145 | end 146 | end 147 | end 148 | -------------------------------------------------------------------------------- /lib/capistrano/tasks/wprewrite.rake: -------------------------------------------------------------------------------- 1 | namespace :wpcli do 2 | namespace :rewrite do 3 | desc "Flush rewrite rules." 4 | task :flush do 5 | on roles(:web) do 6 | within release_path do 7 | execute :wp, :rewrite, :flush, fetch(:wpcli_args) 8 | end 9 | end 10 | end 11 | 12 | desc "Perform a hard flush - update `.htaccess` rules as well as rewrite rules in database." 13 | task :hard_flush do 14 | on roles(:web) do 15 | within release_path do 16 | execute :wp, :rewrite, :flush, "--hard", fetch(:wpcli_args) 17 | end 18 | end 19 | end 20 | end 21 | end -------------------------------------------------------------------------------- /lib/capistrano/tasks/wpuploads.rake: -------------------------------------------------------------------------------- 1 | namespace :load do 2 | task :defaults do 3 | 4 | # These options are passed directly to rsync 5 | # Append your options, overwriting the defaults may result in malfunction 6 | # Ex: --recursive --delete --exclude .git* 7 | set :wpcli_rsync_options, "-avz --rsh=ssh --progress" 8 | 9 | # Local dir where WP stores the uploads 10 | # IMPORTANT: Add trailing slash! 11 | set :wpcli_local_uploads_dir, "web/app/uploads/" 12 | 13 | # Remote dir where WP stores the uploads 14 | # IMPORTANT: Add trailing slash! 15 | set :wpcli_remote_uploads_dir, -> {"#{shared_path.to_s}/web/app/uploads/"} 16 | 17 | end 18 | end 19 | 20 | namespace :wpcli do 21 | namespace :uploads do 22 | namespace :rsync do 23 | 24 | desc "Push local uploads delta to remote machine" 25 | task :push do 26 | roles(:web).each do |role| 27 | puts role.netssh_options[:port] 28 | port = role.netssh_options[:port] || 22 29 | set :wpcli_rsync_options, fetch(:wpcli_rsync_options) + (" -e 'ssh -p #{port}'") 30 | run_locally do 31 | execute :rsync, fetch(:wpcli_rsync_options), fetch(:wpcli_local_uploads_dir), "#{role.user}@#{role.hostname}:#{fetch(:wpcli_remote_uploads_dir)}" 32 | end 33 | end 34 | end 35 | 36 | desc "Pull remote uploads delta to local machine" 37 | task :pull do 38 | roles(:web).each do |role| 39 | run_locally do 40 | puts role.netssh_options[:port] 41 | port = role.netssh_options[:port] || 22 42 | set :wpcli_rsync_options, fetch(:wpcli_rsync_options) + (" -e 'ssh -p #{port}'") 43 | execute :rsync, fetch(:wpcli_rsync_options), "#{role.user}@#{role.hostname}:#{fetch(:wpcli_remote_uploads_dir)}", fetch(:wpcli_local_uploads_dir) 44 | end 45 | end 46 | end 47 | end 48 | end 49 | end 50 | -------------------------------------------------------------------------------- /lib/capistrano/wpcli.rb: -------------------------------------------------------------------------------- 1 | # Load all tasks 2 | files = Dir[File.join(File.dirname(__FILE__), 'tasks', '*.rake')] 3 | files.each do |file| 4 | load file 5 | end -------------------------------------------------------------------------------- /lib/capistrano/wpcli/version.rb: -------------------------------------------------------------------------------- 1 | module Capistrano 2 | module Wpcli 3 | VERSION = "0.1.5" 4 | end 5 | end 6 | --------------------------------------------------------------------------------