From 3df2fb1a6f1a90703928362295445da38484e37a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Villarreal?= Date: Mon, 23 Dec 2013 02:34:13 -0200 Subject: [PATCH 01/52] Cleanup line on deploy user creation. The line about creation of deploy user does not break. Because of that, and given its extension, it is not completely visible without looking at the source code. --- README.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 3e45078..903ed6a 100644 --- a/README.md +++ b/README.md @@ -47,8 +47,9 @@ Capistrano is a code deployment tool. When you have code that is ready to go "li ### Setup -1. Create a `deploy` user on your system (Ubuntu: `addgroup deploy; adduser --system --shell /bin/bash --ingroup deploy --disabled-password --home /home/deploy deploy -`). +1. Create a `deploy` user on your system. In Ubuntu: + * `addgroup deploy` + * `adduser --system --shell /bin/bash --ingroup deploy --disabled-password --home /home/deploy deploy` 2. Create an SSH key for `deploy`, make sure it can SSH to all of your web servers, and make sure it can pull down your site repo code. * Switch to the deploy user (`su deploy`). * `ssh-keygen` @@ -92,4 +93,4 @@ If you're not using [WordPress Skeleton](https://github.com/markjaquith/WordPres * `%%DB_USER%%` — Database username. * `%%DB_PASSWORD%%` — Database password. * `%%WP_STAGE%%` – will be `production` or `staging` after deploy. -3. WP Stack uses the constants `WP_STAGE` (which should be set to `'%%WP_STAGE%%'`) and `STAGING_DOMAIN`, which should be set to the domain you want to use for staging (something like `staging.example.com`). \ No newline at end of file +3. WP Stack uses the constants `WP_STAGE` (which should be set to `'%%WP_STAGE%%'`) and `STAGING_DOMAIN`, which should be set to the domain you want to use for staging (something like `staging.example.com`). From 2de603dbc510266a642ce85bbb4f6016a9ff6f08 Mon Sep 17 00:00:00 2001 From: andrezrv Date: Mon, 13 Jan 2014 02:18:18 +0000 Subject: [PATCH 02/52] Added docs and local stage. --- Capfile | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/Capfile b/Capfile index f3761f7..425a179 100644 --- a/Capfile +++ b/Capfile @@ -1,12 +1,27 @@ +# Capfile +# +# This is the main file of the package and the first to be executed. +# +# Capistrano reads its instructions from here. In ordinary cases, the Capfile is +# where you will tell Capistrano about the servers you want to connect to and +# the tasks you want to perform on those servers. Here we do somethig different: +# we're just gonna use this file to set up the most basic values and load our +# required libraries, and will configure the rest of our deployment application +# via config/config.rb and some hook files that we're gonna call here and there. + +# Load required modules. require 'rubygems' require 'railsless-deploy' -load 'lib/misc' -# Multistage -set :stages, ['production', 'staging'] +# Set up multistage +set :stages, ['production', 'staging', 'local'] set :default_stage, 'production' -require 'capistrano/ext/multistage' +# Load Stage WP libraries +load 'lib/misc' load 'lib/tasks' load 'lib/deploy' # Loads config/config.rb after load 'lib/deploy-after' + +# Delay loading of multistage module, so we can override :stages if needed +require 'capistrano/ext/multistage' From ad59d19317390681151fde1ea5d47f0220fb1773 Mon Sep 17 00:00:00 2001 From: andrezrv Date: Mon, 13 Jan 2014 02:21:33 +0000 Subject: [PATCH 03/52] Avoid tty fatal error. --- Capfile | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Capfile b/Capfile index 425a179..f5b991d 100644 --- a/Capfile +++ b/Capfile @@ -17,6 +17,9 @@ require 'railsless-deploy' set :stages, ['production', 'staging', 'local'] set :default_stage, 'production' +# Avoid tty fatal error +default_run_options[:pty] = true + # Load Stage WP libraries load 'lib/misc' load 'lib/tasks' From 03d823aab5fd3a9d2926b1c9d30d3738c0485595 Mon Sep 17 00:00:00 2001 From: andrezrv Date: Mon, 13 Jan 2014 02:36:02 +0000 Subject: [PATCH 04/52] Added hook for Customfile. --- Capfile | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Capfile b/Capfile index f5b991d..9a01787 100644 --- a/Capfile +++ b/Capfile @@ -26,5 +26,8 @@ load 'lib/tasks' load 'lib/deploy' # Loads config/config.rb after load 'lib/deploy-after' +# Load a Customfile if we have one +loadFile 'Customfile' + # Delay loading of multistage module, so we can override :stages if needed require 'capistrano/ext/multistage' From fa810031a130c0930bf8069d5170159611846f1d Mon Sep 17 00:00:00 2001 From: andrezrv Date: Mon, 13 Jan 2014 03:27:02 +0000 Subject: [PATCH 05/52] Adjusted to Ruby coding standards. --- Capfile | 24 ++++++++-------- config/SAMPLE.config.rb | 64 ++++++++++++++++++++++++++++++----------- lib/deploy-after.rb | 2 +- 3 files changed, 60 insertions(+), 30 deletions(-) diff --git a/Capfile b/Capfile index 9a01787..a11ca46 100644 --- a/Capfile +++ b/Capfile @@ -5,29 +5,29 @@ # Capistrano reads its instructions from here. In ordinary cases, the Capfile is # where you will tell Capistrano about the servers you want to connect to and # the tasks you want to perform on those servers. Here we do somethig different: -# we're just gonna use this file to set up the most basic values and load our +# we"re just gonna use this file to set up the most basic values and load our # required libraries, and will configure the rest of our deployment application -# via config/config.rb and some hook files that we're gonna call here and there. +# via config/config.rb and some hook files that we"re gonna call here and there. # Load required modules. -require 'rubygems' -require 'railsless-deploy' +require "rubygems" +require "railsless-deploy" # Set up multistage -set :stages, ['production', 'staging', 'local'] -set :default_stage, 'production' +set :stages, ["production", "staging", "local"] +set :default_stage, "production" # Avoid tty fatal error default_run_options[:pty] = true # Load Stage WP libraries -load 'lib/misc' -load 'lib/tasks' -load 'lib/deploy' # Loads config/config.rb after -load 'lib/deploy-after' +load "lib/misc" +load "lib/tasks" +load "lib/deploy" # Loads config/config.rb after +load "lib/deploy-after" # Load a Customfile if we have one -loadFile 'Customfile' +loadFile "Customfile" # Delay loading of multistage module, so we can override :stages if needed -require 'capistrano/ext/multistage' +require "capistrano/ext/multistage" diff --git a/config/SAMPLE.config.rb b/config/SAMPLE.config.rb index 6bf9e49..339a7a9 100644 --- a/config/SAMPLE.config.rb +++ b/config/SAMPLE.config.rb @@ -1,36 +1,66 @@ -# Customize this file, and then rename it to config.rb +# Stage WP configuration file +# +# This is a sample config file. It manages settings for your remote repository, +# your default domains and your database values. Copy it to config.rb and +# customize it to your own needs. -set :application, "WP Stack Site" -set :repository, "set your git repository location here" +# Repository settings +set :application, "Local WordPress Installation" +set :repository, "git://github.com/username/website.git" set :scm, :git -# Or: `accurev`, `bzr`, `cvs`, `darcs`, `git`, `mercurial`, `perforce`, `subversion` or `none` +# Or: `accurev`, `bzr`, `cvs`, `darcs`, `git`, `mercurial`, `perforce`, +# `subversion` or `none` -# Using Git Submodules? +# Using Git submodules? set :git_enable_submodules, 1 # This should be the same as :deploy_to in production.rb -set :production_deploy_to, '/srv/www/example.com' +set :production_deploy_to, "/srv/www/website/application" + +# The domain name used for your production environment +set :production_domain, "" # The domain name used for your staging environment -set :staging_domain, 'staging.example.com' +set :staging_domain, "" # Database -# Set the values for host, user, pass, and name for both production and staging. +# Set the values for host, user, pass, and name for production, staging and +# local stages. You can also specify a backup directory where your mysqldumps +# should be saved. set :wpdb do { :production => { - :host => 'PRODUCTION DB HOST', - :user => 'PRODUCTION DB USER', - :password => 'PRODUCTION DB PASS', - :name => 'PRODUCTION DB NAME', + :host => "localhost", + :user => "root", + :password => "root", + :name => "production_db", + :backups_dir => "/srv/www/website/backups/dumps", + :dump_suffix => "production", # A string to differentiate mysqldumps }, :staging => { - :host => 'STAGING DB HOST', - :user => 'STAGING DB USER', - :password => 'STAGING DB PASS', - :name => 'STAGING DB NAME', + :host => "localhost", + :user => "root", + :password => "root", + :name => "staging_db", + :backups_dir => "/srv/www/website/backups/dumps", + :dump_suffix => "staging", # A string to differentiate mysqldumps + }, + :local => { + :host => "localhost", + :user => "root", + :password => "root", + :name => "local_db", + :backups_dir => "/srv/www/website/backups/dumps", + :dump_suffix => "local", # A string to differentiate mysqldumps } } end -# You're not done! You must also configure production.rb and staging.rb +# Path to your local uploads folder. +set :local_shared_folder, "/srv/www/website/application/application/shared" + +# Load additional files +loadFile "lib/custom-hooks.rb" +loadFile "lib/custom-tasks.rb" + +# You"re not done! You must also configure production.rb and staging.rb diff --git a/lib/deploy-after.rb b/lib/deploy-after.rb index 7453918..03025a7 100644 --- a/lib/deploy-after.rb +++ b/lib/deploy-after.rb @@ -1 +1 @@ -before( "deploy", "git:submodule_tags" ) if git_enable_submodules +before("deploy", "git:submodule_tags") if git_enable_submodules From 44e36c5c6179bf7f41bf750f9539175fb80eb2c8 Mon Sep 17 00:00:00 2001 From: andrezrv Date: Mon, 13 Jan 2014 03:32:34 +0000 Subject: [PATCH 06/52] :deploy_to and first :web values are obtained from config.rb --- config/SAMPLE.production.rb | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/config/SAMPLE.production.rb b/config/SAMPLE.production.rb index cd2cf17..52d3ad2 100644 --- a/config/SAMPLE.production.rb +++ b/config/SAMPLE.production.rb @@ -1,14 +1,17 @@ -# This file is only loaded for the production environment -# Customize it and rename it as production.rb +# production.rb +# +# This file is only loaded for the production stage. +# Customize it and copy it as production.rb. # Where should the site deploy to? -set :deploy_to, "/srv/www/example.com" +set :deploy_to, :production_deploy_to # Now configure the servers for this environment # OPTION 1 +# Your web servers IP addresses or hostnamen go here -# role :web, "your web server IP address or hostname here" +role :web, :production_domain # role :web, "second web server here" # role :web, "third web server here, etc" From fde202ab296170edfcc550f6d879f34e28321f33 Mon Sep 17 00:00:00 2001 From: andrezrv Date: Mon, 13 Jan 2014 15:02:34 +0000 Subject: [PATCH 07/52] Added files for local stage; improved inline docs; added default values for sample staging config file; renamed sample files. --- config/.gitignore | 1 + config/{SAMPLE.config.rb => config-sample.rb} | 54 +++++++++++++------ config/deploy/local.rb | 2 + config/deploy/production.rb | 3 +- config/deploy/staging.rb | 3 +- config/local-sample.rb | 9 ++++ ...PLE.production.rb => production-sample.rb} | 8 +-- .../{SAMPLE.staging.rb => staging-sample.rb} | 13 +++-- 8 files changed, 68 insertions(+), 25 deletions(-) rename config/{SAMPLE.config.rb => config-sample.rb} (51%) create mode 100644 config/deploy/local.rb create mode 100644 config/local-sample.rb rename config/{SAMPLE.production.rb => production-sample.rb} (75%) rename config/{SAMPLE.staging.rb => staging-sample.rb} (63%) diff --git a/config/.gitignore b/config/.gitignore index 75c107e..ebdc885 100644 --- a/config/.gitignore +++ b/config/.gitignore @@ -1,3 +1,4 @@ /config.rb /production.rb /staging.rb +/local.rb diff --git a/config/SAMPLE.config.rb b/config/config-sample.rb similarity index 51% rename from config/SAMPLE.config.rb rename to config/config-sample.rb index 339a7a9..7e71442 100644 --- a/config/SAMPLE.config.rb +++ b/config/config-sample.rb @@ -1,32 +1,54 @@ -# Stage WP configuration file +# Stage WP configuration file. # # This is a sample config file. It manages settings for your remote repository, # your default domains and your database values. Copy it to config.rb and # customize it to your own needs. -# Repository settings +# Application settings. + +# // The name of your application. It can be any string. set :application, "Local WordPress Installation" + +# Repository settings + +# // Location of your remote repository. set :repository, "git://github.com/username/website.git" + +# // Your preferred method for source control. Supports :accurev, :bzr, :cvs, +# // :darcs, :git, :mercurial, :perforce, :subversion or :none. set :scm, :git -# Or: `accurev`, `bzr`, `cvs`, `darcs`, `git`, `mercurial`, `perforce`, -# `subversion` or `none` -# Using Git submodules? +# // Using Git submodules? set :git_enable_submodules, 1 -# This should be the same as :deploy_to in production.rb +# Default deploy directories. + +# // :deploy_to in production.rb will use this value as default set :production_deploy_to, "/srv/www/website/application" -# The domain name used for your production environment -set :production_domain, "" +# // :deploy_to in staging.rb will use this value as default +set :staging_deploy_to, "/srv/www/website/application" + +# Default domains. + +# // :deploy_to in production.rb will use this value as default +set :production_domain, "www.website.com" -# The domain name used for your staging environment -set :staging_domain, "" +# // :deploy_to in staging.rb will use this value as default +set :staging_domain, "staging.website.com" -# Database +# Local stage default settings. + +# // Path to your local shared folder. +set :local_shared_folder, "/srv/www/website/application/shared" + +# WordPress database settings. +# # Set the values for host, user, pass, and name for production, staging and # local stages. You can also specify a backup directory where your mysqldumps -# should be saved. +# should be saved. Note that placeholders like %%DB_NAME%% and %%DB_PASSWORD%% +# in your wp-config.php file will be automatically replaced when `cap deploy` is +# executed, so you only have to configure these values here. set :wpdb do { :production => { @@ -56,11 +78,11 @@ } end -# Path to your local uploads folder. -set :local_shared_folder, "/srv/www/website/application/application/shared" +# Additional hook files. -# Load additional files +# // Load a file meant to contain your custom hooks for tasks. loadFile "lib/custom-hooks.rb" +# // Load a file meant to contain your custom tasks. loadFile "lib/custom-tasks.rb" -# You"re not done! You must also configure production.rb and staging.rb +# You're not done! You must also configure production.rb, staging.rb and local.rb diff --git a/config/deploy/local.rb b/config/deploy/local.rb new file mode 100644 index 0000000..b3400c9 --- /dev/null +++ b/config/deploy/local.rb @@ -0,0 +1,2 @@ +# This file will load the required values for your local stage. +loadFile 'config/local.rb' diff --git a/config/deploy/production.rb b/config/deploy/production.rb index ac3cde1..9fe7906 100644 --- a/config/deploy/production.rb +++ b/config/deploy/production.rb @@ -1 +1,2 @@ -loadFile 'config/production.rb' \ No newline at end of file +# This file will load the required values for your production stage. +loadFile 'config/production.rb' diff --git a/config/deploy/staging.rb b/config/deploy/staging.rb index bd3279d..f833e20 100644 --- a/config/deploy/staging.rb +++ b/config/deploy/staging.rb @@ -1 +1,2 @@ -loadFile 'config/staging.rb' \ No newline at end of file +# This file will load the required values for your staging stage. +loadFile 'config/staging.rb' diff --git a/config/local-sample.rb b/config/local-sample.rb new file mode 100644 index 0000000..b157d78 --- /dev/null +++ b/config/local-sample.rb @@ -0,0 +1,9 @@ +# local-sample.rb +# +# This file is only loaded for the local stage. It contains values that +# will be present when you run tasks related to local. +# +# Customize this file to your own needs and copy it as local.rb. + +# Where is your local shared folder? +set :shared_folder, :local_shared_folder diff --git a/config/SAMPLE.production.rb b/config/production-sample.rb similarity index 75% rename from config/SAMPLE.production.rb rename to config/production-sample.rb index 52d3ad2..0297607 100644 --- a/config/SAMPLE.production.rb +++ b/config/production-sample.rb @@ -1,7 +1,9 @@ -# production.rb +# production-sample.rb # -# This file is only loaded for the production stage. -# Customize it and copy it as production.rb. +# This file is only loaded for the production stage. It contains values that +# will be present when you run tasks related to production. +# +# Customize this file to your own needs and copy it as production.rb. # Where should the site deploy to? set :deploy_to, :production_deploy_to diff --git a/config/SAMPLE.staging.rb b/config/staging-sample.rb similarity index 63% rename from config/SAMPLE.staging.rb rename to config/staging-sample.rb index fa2081b..72f51dd 100644 --- a/config/SAMPLE.staging.rb +++ b/config/staging-sample.rb @@ -1,14 +1,19 @@ -# This file is only loaded for the staging environment -# Customize it and rename it as staging.rb +# staging-sample.rb +# +# This file is only loaded for the staging stage. It contains values that +# will be present when you run tasks related to staging. +# +# Customize this file to your own needs and copy it as staging.rb. # Where should the site deploy to? -set :deploy_to, "/srv/www/example.com" +set :deploy_to, :staging_deploy_to # Now configure the servers for this environment # OPTION 1 +# Your web servers IP addresses or hostnamen go here -# role :web, "your web server IP address or hostname here" +role :web, :staging_domain # role :web, "second web server here" # role :web, "third web server here, etc" From 276f92dcbc38ae0b9bfc3b39265f045e347ec7cc Mon Sep 17 00:00:00 2001 From: andrezrv Date: Mon, 13 Jan 2014 15:07:27 +0000 Subject: [PATCH 08/52] Fixed typo. --- Capfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Capfile b/Capfile index a11ca46..3ea246a 100644 --- a/Capfile +++ b/Capfile @@ -5,7 +5,7 @@ # Capistrano reads its instructions from here. In ordinary cases, the Capfile is # where you will tell Capistrano about the servers you want to connect to and # the tasks you want to perform on those servers. Here we do somethig different: -# we"re just gonna use this file to set up the most basic values and load our +# we're just gonna use this file to set up the most basic values and load our # required libraries, and will configure the rest of our deployment application # via config/config.rb and some hook files that we"re gonna call here and there. From 522ad14f544eda35b5ac63d719cda4546252dee5 Mon Sep 17 00:00:00 2001 From: andrezrv Date: Tue, 14 Jan 2014 05:48:18 +0000 Subject: [PATCH 09/52] Added sample Customfile. --- Customfile-sample | 28 ++++++++++++++++++++++++++++ config/config-sample.rb | 1 + 2 files changed, 29 insertions(+) create mode 100644 Customfile-sample diff --git a/Customfile-sample b/Customfile-sample new file mode 100644 index 0000000..7be83e3 --- /dev/null +++ b/Customfile-sample @@ -0,0 +1,28 @@ +# Customfile-sample +# +# This is a sample Customfile. It is meant to be loaded at the end of the +# Capfile. In case you need it, copy it as "Capfile" and customize it as it +# suits you. + +# Overridable settings. + +# // Stages that you're gonna be using in your workflow. +set :stages, ["production", "staging", "local"] + +# // Default stage +set :default_stage, "production" + +# // The user that will log to your remote systems. +set :user, "deploy" + +# // Use sudo for Capistrano built-in tasks. +set :use_sudo, false + +# // Deploy method. It can be :remote_cache or :copy. +set :deploy_via, :remote_cache + +# // Filename patters to exclude on your deploys. +set :copy_exclude, [".git", ".gitmodules", ".DS_Store", ".gitignore"] + +# // Number of releases to keep on your remote servers. +set :keep_releases, 5 diff --git a/config/config-sample.rb b/config/config-sample.rb index 7e71442..c078c6d 100644 --- a/config/config-sample.rb +++ b/config/config-sample.rb @@ -4,6 +4,7 @@ # your default domains and your database values. Copy it to config.rb and # customize it to your own needs. + # Application settings. # // The name of your application. It can be any string. From 62b5e68b7f1b1cb5a0e19d0202ed09e2b42b9013 Mon Sep 17 00:00:00 2001 From: andrezrv Date: Tue, 14 Jan 2014 05:55:43 +0000 Subject: [PATCH 10/52] Added sample file for custom hooks. --- lib/custom-hooks-sample.rb | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 lib/custom-hooks-sample.rb diff --git a/lib/custom-hooks-sample.rb b/lib/custom-hooks-sample.rb new file mode 100644 index 0000000..90dfc1a --- /dev/null +++ b/lib/custom-hooks-sample.rb @@ -0,0 +1,12 @@ +# custom-hooks-sample.rb +# +# This is a sample file for custom task hooks. Copy this file to +# custom-hooks.rb and add your own hooks or use the following ones. +# custom-hooks.rb is not required, and if it exists, it will be loaded +# automatically from /config/config.rb. + +# Backup remote database before making symbolic link to current release. +before "deploy:create_symlink", "db:backup" + +# Clone Git submodules before making symbolic link to current release. +before "deploy:create_symlink", "git:submodule_tags" From 311b03181189bda3d345b024e1f266cbc4c1e052 Mon Sep 17 00:00:00 2001 From: andrezrv Date: Tue, 14 Jan 2014 05:58:54 +0000 Subject: [PATCH 11/52] Added sample file for custom tasks. --- lib/custom-tasks-sample.rb | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 lib/custom-tasks-sample.rb diff --git a/lib/custom-tasks-sample.rb b/lib/custom-tasks-sample.rb new file mode 100644 index 0000000..544d321 --- /dev/null +++ b/lib/custom-tasks-sample.rb @@ -0,0 +1,28 @@ +# custom-tasks-sample.rb +# +# This is a sample file for custom tasks. Copy this file to custom-tasks.rb and +# add your own tasks or use the following ones. custom-tasks.rb is not +# required, and if it exists, it will be loaded automatically from +# /config/config.rb. + +namespace :static do + desc "Upload non-repository files" + task :upload, :roles => :web do + if stage == :local then + puts "[ERROR] You must run static:upload from staging with cap staging static:upload or from production with cap production static:upload" + else + uploads = [ + [ "/example/source", "/example/destination" ], + ] + uploads.each do |upload| + if File.exists? upload[0] then + current_host = capture("echo $CAPISTRANO:HOST$").strip + command = "scp -r #{upload[0]} #{user}@#{current_host}:#{upload[1]}" + system command + else + puts "The path #{upload[0]} does not exists" + end + end + end + end +end \ No newline at end of file From 21ac04dcae36052faa519296a5b8bfe42645d4a5 Mon Sep 17 00:00:00 2001 From: andrezrv Date: Tue, 14 Jan 2014 06:42:57 +0000 Subject: [PATCH 12/52] Added new tasks. --- config/config-sample.rb | 8 ++ lib/custom-tasks-sample.rb | 5 +- lib/tasks.rb | 267 ++++++++++++++++++++++++++++++++++--- 3 files changed, 256 insertions(+), 24 deletions(-) diff --git a/config/config-sample.rb b/config/config-sample.rb index c078c6d..7bbcffa 100644 --- a/config/config-sample.rb +++ b/config/config-sample.rb @@ -43,6 +43,14 @@ # // Path to your local shared folder. set :local_shared_folder, "/srv/www/website/application/shared" +# Where is your wp-config.php file located within #{release_path}? +# // Your release path points to the newer copy of your repository, so you must +# // specify where your wp-config.php file is located within your remore repo. +# // WordPress Bareboner puts the file in the "app" subfolder, so it needs to +# // be "#{release_path}/app", but if you are using WordPress-Skeleton, just +# // "#{release_path}" should do the trick and this value should be left empty. +set :wp_config_location, "/app" + # WordPress database settings. # # Set the values for host, user, pass, and name for production, staging and diff --git a/lib/custom-tasks-sample.rb b/lib/custom-tasks-sample.rb index 544d321..91582d9 100644 --- a/lib/custom-tasks-sample.rb +++ b/lib/custom-tasks-sample.rb @@ -1,9 +1,8 @@ # custom-tasks-sample.rb # # This is a sample file for custom tasks. Copy this file to custom-tasks.rb and -# add your own tasks or use the following ones. custom-tasks.rb is not -# required, and if it exists, it will be loaded automatically from -# /config/config.rb. +# add your own tasks or use the following ones. custom-tasks.rb is not required, +# and if it exists, it will be loaded automatically from /config/config.rb. namespace :static do desc "Upload non-repository files" diff --git a/lib/tasks.rb b/lib/tasks.rb index 4765b18..3fd041e 100644 --- a/lib/tasks.rb +++ b/lib/tasks.rb @@ -1,29 +1,68 @@ +# tasks.rb +# +# This file contains the core tasks for Stage WP. You can override any of these +# tasks and add your own into custom-tasks.rb. + namespace :shared do + desc "Create shared folder" task :make_shared_dir do run "if [ ! -d #{shared_path}/files ]; then mkdir #{shared_path}/files; fi" end + desc "Create symlinks to shared folder" task :make_symlinks do run "if [ ! -h #{release_path}/shared ]; then ln -s #{shared_path}/files/ #{release_path}/shared; fi" run "for p in `find -L #{release_path} -type l`; do t=`readlink $p | grep -o 'shared/.*$'`; sudo mkdir -p #{release_path}/$t; sudo chown www-data:www-data #{release_path}/$t; done" end + desc "Pulls shared files from remote location" + task :pull do + if stage == :local then + puts "[ERROR] You must run shared:pull from staging or production with cap staging shared:pull or cap production shared:pull" + else + random = rand(10 ** 5).to_s.rjust(5, '0') + current_host = capture("echo $CAPISTRANO:HOST$").strip + run "cd #{shared_path}; sudo zip -r /tmp/#{ramdom}-shared .;" + system "cd #{local_shared_folder}; sudo mkdir #{random}; sudo mkdir ../#{random}; sudo mv * ../#{random}/; sudo scp #{user}@#{current_host}:/tmp/#{ramdom}-shared.zip #{local_shared_folder}; sudo unzip #{ramdom}-shared.zip; sudo rm -rf shared.zip ../#{ramdom};" + end + end + desc "Pushes shared files to remote location" + task :push do + if stage == :local then + puts "[ERROR] You must run shared:pull from staging or production with cap staging shared:pull or cap production shared:pull" + else + random = rand(10 ** 5).to_s.rjust(5, '0') + current_host = capture("echo $CAPISTRANO:HOST$").strip + puts "Current user is #{user}" + system "cd #{local_shared_folder}; sudo zip -r /tmp/#{random}-shared .;" + system "sudo scp /tmp/shared.zip #{user}@#{current_host}:#{shared_path}" + run "cd #{shared_path}; sudo mkdir ../#{random};" + run "cd #{shared_path}/../#{random}; sudo unzip /tmp/#{random}-shared.zip;" + run "mv #{shared_path} #{shared_path}-#{random}; mv #{shared_path}/../#{random} #{shared_path}; rm -rf #{shared_path}-#{random}" + run "sudo chown -R #{user}:#{user} #{shared_path}" + system "cd #{local_shared_folder}; sudo rm -f uploads.zip" + end + end end namespace :nginx do - desc "Restarts nginx" + desc "Restart nginx" task :restart do run "sudo /etc/init.d/nginx reload" end end namespace :phpfpm do - desc" Restarts PHP-FPM" + desc "Restart PHP-FPM" task :restart do - run "sudo /etc/init.d/php-fpm restart" + begin # For non-Ubuntu systems + run "sudo /etc/init.d/php-fpm restart" + rescue Exception => e # For Ubuntu systems + run "sudo /etc/init.d/php-fpm restart" + end end end namespace :git do - desc "Updates git submodule tags" + desc "Update Git submodule tags" task :submodule_tags do run "if [ -d #{shared_path}/cached-copy/ ]; then cd #{shared_path}/cached-copy/ && git submodule foreach --recursive git fetch origin --tags; fi" end @@ -44,25 +83,211 @@ end namespace :db do + desc "Initialize the WordPress database in a remote stage" # This is a tricky one + task :init, :roles => :web do + if stage == :local then + puts "[ERROR] You must run db:init from staging or production with cap staging db:init or cap production db:init" + else + s = (stage == :production) ? wpdb[:production] : wpdb[:staging] + # Obtain MySQL admin credentials + admin_name = Capistrano::CLI.ui.ask "Please provide the name of your MySQL admin user [root] " + admin_name = "root" if admin_name.empty? + admin_password = Capistrano::CLI.password_prompt "Please provide the password of your MySQL admin user [root] " + admin_password = "root" if admin_password.empty? + # Store query strings + create = "CREATE DATABASE IF NOT EXISTS #{s[:name]};" + grant = "GRANT ALL PRIVILEGES ON #{s[:name]}.* TO '#{s[:user]}'@'#{s[:host]}' IDENTIFIED BY '#{s[:password]}';" + show = "SHOW DATABASES;" + # Initialize output + output = "" + # Check if database already exists + run "mysql -u #{admin_name} -p -e \"#{show}\"" do |channel, stream, data| + if data =~ /^Enter password: / + # Securely pass admin password + channel.send_data "#{admin_password}\n" + end + output += data + end + if output.include? s[:name] then # If database exists ... + puts "Database already exists." + else # In case database does not exist ... + output = "" + # Try to create database + run "mysql -u #{admin_name} -p -e \"#{create} #{grant} #{show}\"" do |channel, stream, data| + if data =~ /^Enter password: / + # Securely pass admin password + channel.send_data "#{admin_password}\n" + end + output += data + end + if output.include? s[:name] then # If database was created ... + puts "Remote database was initialized." + else # If database wasn't created ... + puts "Remote database could not be created." + end + end + end + end desc "Syncs the staging database (and uploads) from production" task :sync, :roles => :web do - if stage != :staging then - puts "[ERROR] You must run db:sync from staging with cap staging db:sync" + if stage == :production then + puts "[ERROR] You must run db:sync from staging with cap staging db:sync or from local with cap local db:sync" + else + if stage == :staging then + puts "Hang on... this might take a while." + random = rand(10 ** 5).to_s.rjust(5, '0') + p = wpdb[:production] + s = wpdb[:staging] + puts "db:sync" + puts stage + run "ssh #{user}@#{production_domain} \"mysqldump -u #{p[:user]} --result-file=/tmp/wpstack-#{random}.sql -h #{p[:host]} -p#{p[:password]} #{p[:name]}\"" + run "scp #{user}@#{production_domain}:/tmp/wpstack-#{random}.sql /tmp/" + run "mysql -u #{s[:user]} -h #{s[:host]} -p#{s[:password]} #{s[:name]} < /tmp/wpstack-#{random}.sql && rm /tmp/wpstack-#{random}.sql" + puts "Database synced to staging" + # Now to copy files + find_servers( :roles => :web ).each do |server| + run "rsync -avz --delete #{user}@#{production_domain}:#{production_deploy_to}/shared/files/ #{staging_deploy_to}/shared/files/" + end + end + if stage == :local then + puts "Hang on... this might take a while." + random = rand(10 ** 5).to_s.rjust(5, '0') + p = wpdb[:production] + l = wpdb[:local] + puts "db:sync" + puts stage + system "ssh #{user}@#{production_domain} \"mysqldump -u #{p[:user]} --result-file=/tmp/wpstack-#{random}.sql -h #{p[:host]} -p#{p[:password]} #{p[:name]}\"" + system "scp -#{user}@#{production_domain}:/tmp/wpstack-#{random}.sql /tmp/" + system "mysql -u #{l[:user]} -h #{l[:host]} -p#{l[:password]} #{l[:name]} < /tmp/wpstack-#{random}.sql && rm /tmp/wpstack-#{random}.sql" + puts "Database synced to local" + # memcached.restart + puts "Memcached flushed" + # Now to copy files + system "rsync -avz --delete #{user}@#{production_domain}:#{production_deploy_to}/shared/files/ #{local_shared_folder}/files/" + end + end + end + desc "Backup database" + task :backup, :roles => :web do + if stage == :local then + l = wpdb[:local] + puts "Backing up MySQL local database..." + filename = "#{l[:backups_dir]}/#{release_name}-#{l[:dump_suffix]}.sql" + # Create folder for dumps, in case that it doesn't exist + system "sudo mkdir -p #{l[:backups_dir]}" + system "sudo mysqldump -u #{l[:user]} -p#{l[:password]} #{l[:name]} > #{filename}" + if File.exists? filename then + puts "MySQL local database saved to #{filename}" + else + puts "MySQL local database could not be saved." + end + end + if stage == :production || stage == :staging then + s = (stage == :production) ? wpdb[:production] : wpdb[:staging] + puts "Backing up remote MySQL database..." + filename = "#{s[:backups_dir]}/#{release_name}-#{s[:dump_suffix]}.sql" + # Create folder for dumps, in case that it doesn't exist + run "mkdir -p #{s[:backups_dir]}" + begin + run "mysqldump -u #{s[:user]} -p #{s[:name]} > #{filename}" do |channel, stream, data| + if data =~ /^Enter password: / + channel.send_data "#{s[:password]}\n" + end + end + puts "Remote MySQL database saved to #{filename}" + rescue Exception => error + puts "Remote MySQL database could not be saved." + end + end + end + desc "Restore database from backup" + task :restore, :roles => :web do + if stage == :local then + l = wpdb[:local] + puts "Searching for available local backups..." + # List contents from dumps folder + backups = `ls -1 #{l[:backups_dir]}/`.split("\n") + # Define default backup + default_backup = backups.last + puts "Available backups: " + puts backups + backup = Capistrano::CLI.ui.ask "Which backup would you like to restore? [#{default_backup}] " + backup_file = backup + backup_file = default_backup if backup_file.empty? + if system "mysql -u #{l[:user]} -p#{l[:password]} #{l[:name]} < #{l[:backups_dir]}/#{backup_file}" then + puts "Local database restored to backup saved in #{l[:backups_dir]}/#{backup_file}." + else + puts "Local database could not be restored from backup." + end + else + env = (stage == :production) ? wpdb[:production] : wpdb[:staging] + puts "Searching for available remote backups..." + # List contents from dumps folder + backups = capture("ls -1 #{env[:backups_dir]}").split("\n") + # Define default backup + default_backup = backups.last + puts "Available backups: " + puts backups + backup = Capistrano::CLI.ui.ask "Which backup would you like to restore? [#{default_backup}] " + backup_file = default_backup if backup.empty? + backup_file = "#{env[:backups_dir]}/#{backup_file}" + begin + run "mysql -u #{env[:user]} -p#{env[:password]} #{env[:name]} < #{backup_file}" do |channel, stream, data| + if data =~ /^Enter password: / + channel.send_data "#{p[:password]}\n" + end + end + puts "Remote database restored to backup saved in #{backup_file}." + rescue Exception => error + puts "Remote database could not be restored from backup." + end + end + end + desc "Pull a remote database backup to local" + task :pull, :roles => :web do + if stage == :local then + puts "[ERROR] You must run db:pull from staging or production with cap staging db:pull or cap production db:pull" + else + env = (stage == :production) ? wpdb[:production] : wpdb[:staging] + l = wpdb[:local] + puts "Searching for available remote backups..." + # List contents from dumps folder + backups = capture("ls -1 #{env[:backups_dir]}").split("\n") + # Define default backup + default_backup = backups.last + puts "Available backups: " + puts backups + backup = Capistrano::CLI.ui.ask "Which backup would you like to pull? [#{default_backup}] " + backup_file = default_backup if backup.empty? + current_host = capture("echo $CAPISTRANO:HOST$").strip + if system "scp #{user}@#{current_host}:#{env[:backups_dir]}/#{backup_file} #{l[:backups_dir]}" then + puts "Remote database saved to local host at #{l[:backups_dir]}/#{backup_file}." + else + puts "Remote database could not be pulled from backup." + end + end + end + desc "Push a remote database backup to remote from local" + task :push, :roles => :web do + if stage == :local then + puts "[ERROR] You must run db:push from staging or production with cap staging db:push or cap production db:push" else - puts "Hang on... this might take a while." - random = rand( 10 ** 5 ).to_s.rjust( 5, '0' ) - p = wpdb[ :production ] - s = wpdb[ :staging ] - puts "db:sync" - puts stage - system "mysqldump -u #{p[:user]} --result-file=/tmp/wpstack-#{random}.sql -h #{p[:host]} -p#{p[:password]} #{p[:name]}" - system "mysql -u #{s[:user]} -h #{s[:host]} -p#{s[:password]} #{s[:name]} < /tmp/wpstack-#{random}.sql && rm /tmp/wpstack-#{random}.sql" - puts "Database synced to staging" - # memcached.restart - puts "Memcached flushed" - # Now to copy files - find_servers( :roles => :web ).each do |server| - system "rsync -avz --delete #{production_deploy_to}/shared/files/ #{server}:#{shared_path}/files/" + env = (stage == :production) ? wpdb[:production] : wpdb[:staging] + l = wpdb[:local] + puts "Searching for available local backups..." + # List contents from dumps folder + backups = `ls -1 #{l[:backups_dir]}/`.split("\n") + # Define default backup + default_backup = backups.last + puts "Available backups: " + puts backups + backup = Capistrano::CLI.ui.ask "Which backup would you like to push? [#{default_backup}] " + backup_file = default_backup if backup.empty? + current_host = capture("echo $CAPISTRANO:HOST$").strip + if system "scp #{l[:backups_dir]}/#{backup_file} #{user}@#{current_host}:#{env[:backups_dir]}" then + puts "Local database uploaded to remote host at #{env[:backups_dir]}/#{backup_file}." + else + puts "Local database could not be pushed from backup." end end end @@ -70,7 +295,7 @@ task :make_config do set :staging_domain, '' unless defined? staging_domain {:'%%WP_STAGING_DOMAIN%%' => staging_domain, :'%%WP_STAGE%%' => stage, :'%%DB_NAME%%' => wpdb[stage][:name], :'%%DB_USER%%' => wpdb[stage][:user], :'%%DB_PASSWORD%%' => wpdb[stage][:password], :'%%DB_HOST%%' => wpdb[stage][:host]}.each do |k,v| - run "sed -i 's/#{k}/#{v}/' #{release_path}/wp-config.php", :roles => :web + run "sed -i 's/#{k}/#{v}/' #{release_path}#{wp_config_location}/wp-config.php", :roles => :web end end end From 80195501da72c540d087235266060ddfb71f0d63 Mon Sep 17 00:00:00 2001 From: andrezrv Date: Tue, 14 Jan 2014 07:02:54 +0000 Subject: [PATCH 13/52] Reordered hooks and added inline docs. --- lib/custom-hooks-sample.rb | 3 --- lib/deploy-after.rb | 9 ++++++++- lib/deploy.rb | 7 ++++++- 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/lib/custom-hooks-sample.rb b/lib/custom-hooks-sample.rb index 90dfc1a..871850a 100644 --- a/lib/custom-hooks-sample.rb +++ b/lib/custom-hooks-sample.rb @@ -7,6 +7,3 @@ # Backup remote database before making symbolic link to current release. before "deploy:create_symlink", "db:backup" - -# Clone Git submodules before making symbolic link to current release. -before "deploy:create_symlink", "git:submodule_tags" diff --git a/lib/deploy-after.rb b/lib/deploy-after.rb index 03025a7..e16da92 100644 --- a/lib/deploy-after.rb +++ b/lib/deploy-after.rb @@ -1 +1,8 @@ -before("deploy", "git:submodule_tags") if git_enable_submodules +# deploy-after.rb +# +# This file is loaded after deploy.rb, and includes hooks to be executed when +# all the config settings are loaded. + + +# Clone Git submodules before making symbolic link to current release. +before "deploy:create_symlink", "git:submodule_tags" if git_enable_submodules diff --git a/lib/deploy.rb b/lib/deploy.rb index 2998f1e..7bf8780 100644 --- a/lib/deploy.rb +++ b/lib/deploy.rb @@ -1,4 +1,7 @@ -# +# deploy.rb +# +# This file includes default settings and hooks for the deployment process. + set :user, "deploy" set :use_sudo, false set :deploy_via, :remote_cache @@ -11,5 +14,7 @@ after "deploy:update_code", "db:make_config" after "deploy", "memcached:update" +before "deploy:setup", "db:init" + # Pull in the config file loadFile 'config/config.rb' From 6752dfa369575b699d6cb4ab78d5a41f634350e5 Mon Sep 17 00:00:00 2001 From: andrezrv Date: Tue, 14 Jan 2014 14:22:58 +0000 Subject: [PATCH 14/52] Renamed dropins folder. --- {WordPress-Dropins => wordpress-mu-plugins}/wp-stack-cdn.php | 0 .../wp-stack-manual-db-upgrades.php | 0 .../wp-stack-ms-uploads.php | 0 {WordPress-Dropins => wordpress-mu-plugins}/wp-stack-staging.php | 0 4 files changed, 0 insertions(+), 0 deletions(-) rename {WordPress-Dropins => wordpress-mu-plugins}/wp-stack-cdn.php (100%) rename {WordPress-Dropins => wordpress-mu-plugins}/wp-stack-manual-db-upgrades.php (100%) rename {WordPress-Dropins => wordpress-mu-plugins}/wp-stack-ms-uploads.php (100%) rename {WordPress-Dropins => wordpress-mu-plugins}/wp-stack-staging.php (100%) diff --git a/WordPress-Dropins/wp-stack-cdn.php b/wordpress-mu-plugins/wp-stack-cdn.php similarity index 100% rename from WordPress-Dropins/wp-stack-cdn.php rename to wordpress-mu-plugins/wp-stack-cdn.php diff --git a/WordPress-Dropins/wp-stack-manual-db-upgrades.php b/wordpress-mu-plugins/wp-stack-manual-db-upgrades.php similarity index 100% rename from WordPress-Dropins/wp-stack-manual-db-upgrades.php rename to wordpress-mu-plugins/wp-stack-manual-db-upgrades.php diff --git a/WordPress-Dropins/wp-stack-ms-uploads.php b/wordpress-mu-plugins/wp-stack-ms-uploads.php similarity index 100% rename from WordPress-Dropins/wp-stack-ms-uploads.php rename to wordpress-mu-plugins/wp-stack-ms-uploads.php diff --git a/WordPress-Dropins/wp-stack-staging.php b/wordpress-mu-plugins/wp-stack-staging.php similarity index 100% rename from WordPress-Dropins/wp-stack-staging.php rename to wordpress-mu-plugins/wp-stack-staging.php From 6c36dff5b27f126d614b5c882130bf4fe4fd107d Mon Sep 17 00:00:00 2001 From: andrezrv Date: Tue, 14 Jan 2014 14:26:15 +0000 Subject: [PATCH 15/52] Added inline docs. --- lib/deploy.rb | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/deploy.rb b/lib/deploy.rb index 7bf8780..c20047e 100644 --- a/lib/deploy.rb +++ b/lib/deploy.rb @@ -2,18 +2,21 @@ # # This file includes default settings and hooks for the deployment process. +# Set some default values set :user, "deploy" set :use_sudo, false set :deploy_via, :remote_cache set :copy_exclude, [".git", ".gitmodules", ".DS_Store", ".gitignore"] set :keep_releases, 5 +# Put some hooks before deploy tasks after "deploy:update", "deploy:cleanup" after "deploy:update_code", "shared:make_shared_dir" after "deploy:update_code", "shared:make_symlinks" after "deploy:update_code", "db:make_config" after "deploy", "memcached:update" +# Put some hooks after deploy tasks before "deploy:setup", "db:init" # Pull in the config file From ce9191502fe7058be680084f46eb8b03bbefc4ba Mon Sep 17 00:00:00 2001 From: andrezrv Date: Wed, 15 Jan 2014 01:31:52 +0000 Subject: [PATCH 16/52] Separated plugin class and renamed plugins. --- wordpress-mu-plugins/stage-wp-cdn.php | 124 ++++++++++++++++++ .../stage-wp-manual-db-upgrades.php | 68 ++++++++++ wordpress-mu-plugins/stage-wp-ms-uploads.php | 98 ++++++++++++++ .../stage-wp-plugin.class.php | 49 +++++++ wordpress-mu-plugins/stage-wp-staging.php | 63 +++++++++ wordpress-mu-plugins/wp-stack-cdn.php | 73 ----------- .../wp-stack-manual-db-upgrades.php | 34 ----- wordpress-mu-plugins/wp-stack-ms-uploads.php | 58 -------- wordpress-mu-plugins/wp-stack-staging.php | 32 ----- 9 files changed, 402 insertions(+), 197 deletions(-) create mode 100644 wordpress-mu-plugins/stage-wp-cdn.php create mode 100644 wordpress-mu-plugins/stage-wp-manual-db-upgrades.php create mode 100644 wordpress-mu-plugins/stage-wp-ms-uploads.php create mode 100644 wordpress-mu-plugins/stage-wp-plugin.class.php create mode 100644 wordpress-mu-plugins/stage-wp-staging.php delete mode 100644 wordpress-mu-plugins/wp-stack-cdn.php delete mode 100644 wordpress-mu-plugins/wp-stack-manual-db-upgrades.php delete mode 100644 wordpress-mu-plugins/wp-stack-ms-uploads.php delete mode 100644 wordpress-mu-plugins/wp-stack-staging.php diff --git a/wordpress-mu-plugins/stage-wp-cdn.php b/wordpress-mu-plugins/stage-wp-cdn.php new file mode 100644 index 0000000..241d838 --- /dev/null +++ b/wordpress-mu-plugins/stage-wp-cdn.php @@ -0,0 +1,124 @@ + + * @license GPL2 + * @link http://github.com/andrezrv/stage-wp/ + * @copyright 2014 Andrés Villarreal + * + * @wordpress-plugin + * Plugin name: Stage WP CDN + * Plugin URI: http://github.com/andrezrv/stage-wp/ + * Description: This is a very simple CDN plugin. Simply configure the constant WP_STACK_CDN_DOMAIN in your wp-config.php or hook in and override the wp_stack_cdn_domain option. Provide a domain name only, like static.example.com. The plugin will look for static file URLs on your domain and repoint them to the CDN domain. Original credits go to Mark Jaquith. + * Author: Andrés Villarreal + * Author URI: http://about.me/andrezrv + * Version: 1.0 + * License: GPL2 + */ +// Load required class. +if ( !class_exists( 'Stage_WP_Plugin' ) ) { + if ( defined( 'STAGE_WP_PLUGIN_LOCATION' ) && file_exists( $file = STAGE_WP_PLUGIN_LOCATION ) ) { + require( $file ); + } elseif ( file_exists( $file = dirname( __FILE__ ) . '/stage-wp-plugin.class.php' ) ) { + require( $file ); + } +} + +// Once class is loaded, extend it. +if ( class_exists( 'Stage_WP_Plugin' ) ) { + + class Stage_WP_CDN_Plugin extends Stage_WP_Plugin { + + public static $instance; + public $site_domain; + public $cdn_domain; + public $upload_dir; + public $uploads_only; + public $extensions; + + public function __construct() { + self::$instance = $this; + $this->hook( 'plugins_loaded' ); + } + + public function plugins_loaded() { + + $domain_set_up = get_option( 'wp_stack_cdn_domain' ) || ( defined( 'WP_STACK_CDN_DOMAIN' ) && WP_STACK_CDN_DOMAIN ); + $production = defined( 'WP_STAGE' ) && WP_STAGE === 'production'; + $staging = defined( 'WP_STAGE' ) && WP_STAGE === 'staging'; + $uploads_only = defined( 'WP_STACK_CDN_UPLOADS_ONLY' ) && WP_STACK_CDN_UPLOADS_ONLY; + + if ( $domain_set_up && !$staging && ( $production || $uploads_only ) ) { + $this->hook( 'init' ); + } + + } + + public function init() { + + $this->uploads_only = apply_filters( 'wp_stack_cdn_uploads_only', defined( 'WP_STACK_CDN_UPLOADS_ONLY' ) ? WP_STACK_CDN_UPLOADS_ONLY : false ); + $this->extensions = apply_filters( 'wp_stack_cdn_extensions', array( 'jpe?g', 'gif', 'png', 'css', 'bmp', 'js', 'ico' ) ); + + if ( !is_admin() ) { + + $this->hook( 'template_redirect' ); + + if ( $this->uploads_only ) { + $this->hook( 'wp_stack_cdn_content', 'filter_uploads_only' ); + } else { + $this->hook( 'wp_stack_cdn_content', 'filter' ); + } + + $this->site_domain = parse_url( get_bloginfo( 'url' ), PHP_URL_HOST ); + $this->cdn_domain = defined( 'WP_STACK_CDN_DOMAIN' ) ? WP_STACK_CDN_DOMAIN : get_option( 'wp_stack_cdn_domain' ); + + } + + } + + public function filter_uploads_only( $content ) { + + $upload_dir = wp_upload_dir(); + $upload_dir = $upload_dir['baseurl']; + $domain = preg_quote( parse_url( $upload_dir, PHP_URL_HOST ), '#' ); + $path = parse_url( $upload_dir, PHP_URL_PATH ); + $preg_path = preg_quote( $path, '#' ); + + // Targeted replace just on uploads URLs + return preg_replace( "#=([\"'])(https?://{$domain})?$preg_path/((?:(?!\\1]).)+)\.(" . implode( '|', $this->extensions ) . ")(\?((?:(?!\\1).)+))?\\1#", '=$1http://' . $this->cdn_domain . $path . '/$3.$4$5$1', $content ); + + } + + public function filter( $content ) { + return preg_replace( "#=([\"'])(https?://{$this->site_domain})?/([^/](?:(?!\\1).)+)\.(" . implode( '|', $this->extensions ) . ")(\?((?:(?!\\1).)+))?\\1#", '=$1http://' . $this->cdn_domain . '/$3.$4$5$1', $content ); + } + + public function template_redirect() { + ob_start( array( $this, 'ob' ) ); + } + + public function ob( $contents ) { + return apply_filters( 'wp_stack_cdn_content', $contents, $this ); + } + } + + new Stage_WP_CDN_Plugin; + +} diff --git a/wordpress-mu-plugins/stage-wp-manual-db-upgrades.php b/wordpress-mu-plugins/stage-wp-manual-db-upgrades.php new file mode 100644 index 0000000..e875439 --- /dev/null +++ b/wordpress-mu-plugins/stage-wp-manual-db-upgrades.php @@ -0,0 +1,68 @@ +/wp-admin/ requests to the WordPress + * database upgrade screen. On large sites, or sites with a lot of active + * authors, this may not be desired. This plugin prevents the automatic + * redirect and instead lets you manually go to + * /wp-admin/upgrade.php to upgrade a site. + * + * Original credits go to Mark Jaquith: {@link http://github.com/markjaquith/WP-Stack} + * + * @package Stage_WP_Manual_Database_Upgrades + * @author Andrés Villarreal + * @license GPL2 + * @link http://github.com/andrezrv/stage-wp/ + * @copyright 2014 Andrés Villarreal + * + * @wordpress-plugin + * Plugin name: Stage WP Manual Database Upgrades + * Plugin URI: http://github.com/andrezrv/stage-wp/ + * Description: Normally, after you updgraded WordPress to a version that requires database modifications, it redirects /wp-admin/ requests to the WordPress database upgrade screen. On large sites, or sites with a lot of active authors, this may not be desired. This plugin prevents the automatic redirect and instead lets you manually go to /wp-admin/upgrade.php to upgrade a site. Original credits go to Mark Jaquith. + * Author: Andrés Villarreal + * Author URI: http://about.me/andrezrv + * Version: 1.0 + * License: GPL2 + */ +// Load required class. +if ( !class_exists( 'Stage_WP_Plugin' ) ) { + if ( defined( 'STAGE_WP_PLUGIN_LOCATION' ) && file_exists( $file = STAGE_WP_PLUGIN_LOCATION ) ) { + require( $file ); + } elseif ( file_exists( $file = dirname( __FILE__ ) . '/stage-wp-plugin.class.php' ) ) { + require( $file ); + } +} + +// Once class is loaded, extend it. +if ( class_exists( 'Stage_WP_Plugin' ) ) { + + class Stage_WP_Manual_DB_Upgrades_Plugin extends Stage_WP_Plugin { + + public static $instance; + + public function __construct() { + self::$instance = $this; + $this->hook( 'plugins_loaded' ); + } + + public function plugins_loaded() { + $this->hook( 'option_db_version' ); + } + + public function option_db_version( $version ) { + + if ( strpos( $_SERVER['REQUEST_URI'], '/wp-admin/upgrade.php' ) === false ) { + return $GLOBALS['wp_db_version']; + } + + return $version; + + } + + } + + new Stage_WP_Manual_DB_Upgrades_Plugin; + +} diff --git a/wordpress-mu-plugins/stage-wp-ms-uploads.php b/wordpress-mu-plugins/stage-wp-ms-uploads.php new file mode 100644 index 0000000..7c8ed39 --- /dev/null +++ b/wordpress-mu-plugins/stage-wp-ms-uploads.php @@ -0,0 +1,98 @@ + + * @license GPL2 + * @link http://github.com/andrezrv/stage-wp/ + * @copyright 2014 Andrés Villarreal + * + * @wordpress-plugin + * Plugin name: Stage WP Multisite Uploads + * Plugin URI: http://github.com/andrezrv/stage-wp/ + * Description: The way WordPress Multisite serves uploads is not ideal. It streams them through a PHP file. Professional sites should not do this. This plugin allows one NGINX rewrite rule to handle all uploads, eliminating the need for PHP streaming. It uses the following URL scheme for uploads: {scheme}://{domain}/wp-files/{blog_id}/. By inserting the $blog_id, one rewrite rule can make sure file requests go to the correct blog. Note: You will need to implement this NGINX rewrite rule for this to work: rewrite ^/wp-files/([0-9]+)/(.*)$ /wp-content/blogs.dir/$1/files/$2; Original credits go to Mark Jaquith. + * Author: Andrés Villarreal + * Author URI: http://about.me/andrezrv + * Version: 1.0 + * License: GPL2 + */ +// Load required class. +if ( !class_exists( 'Stage_WP_Plugin' ) ) { + if ( defined( 'STAGE_WP_PLUGIN_LOCATION' ) && file_exists( $file = STAGE_WP_PLUGIN_LOCATION ) ) { + require( $file ); + } elseif ( file_exists( $file = dirname( __FILE__ ) . '/stage-wp-plugin.class.php' ) ) { + require( $file ); + } +} + +// Once class is loaded, extend it. +if ( class_exists( 'Stage_WP_Plugin' ) ) { + + class Stage_WP_MS_Uploads_Plugin extends Stage_WP_Plugin { + + public static $instance; + + public function __construct() { + self::$instance = $this; + if ( is_multisite() ) { + $this->hook( 'init' ); + } + } + + public function init() { + global $blog_id; + if ( $blog_id != 1 ) { + $this->hook( 'option_fileupload_url' ); + $this->hook( 'upload_dir' ); + } + } + + public function upload_dir( $upload ) { + + /** + * $upload expected format: + * $upload = array( + * 'subdir' => '/2012/07', + * 'basedir' => '/Users/mark/Sites/wp.git/wp-content/uploads', + * 'path' => '/Users/mark/Sites/wp.git/wp-content/uploads/2012/07', + * 'baseurl' => 'http://wp.git/wp-files/1', + * 'url' => 'http://wp.git/wp-content/uploads/2012/07', + * 'error' => false + * ); + */ + + global $blog_id; + $parsed = parse_url( $upload['baseurl'] ); + $upload['baseurl'] = $parsed['scheme'] . '://' . $parsed['host'] . '/wp-files/' . $blog_id; + $upload['url'] = $upload['baseurl'] . $upload['subdir']; + var_export( $upload ); die(); + return $upload; + + } + + // Does core even use this anymore? + public function option_fileupload_url( $url ) { + global $blog_id; + $parsed = parse_url( $url ); + $url = $parsed['scheme'] . '://' . $parsed['host'] . '/wp-files/' . $blog_id . '/'; + return $url; + } + + } + + new Stage_WP_MS_Uploads_Plugin; + +} diff --git a/wordpress-mu-plugins/stage-wp-plugin.class.php b/wordpress-mu-plugins/stage-wp-plugin.class.php new file mode 100644 index 0000000..5c8ff64 --- /dev/null +++ b/wordpress-mu-plugins/stage-wp-plugin.class.php @@ -0,0 +1,49 @@ + + * @license GPL2 + * @link http://github.com/andrezrv/stage-wp/ + * @copyright 2014 Andrés Villarreal + * + * @wordpress-plugin + * Plugin name: Stage WP Plugin Class + * Plugin URI: http://github.com/andrezrv/wordpress-bareboner/ + * Description: Just a helper class for Stage WP must-use plugins. Original credits go to Mark Jaquith. + * Author: Andrés Villarreal + * Author URI: http://about.me/andrezrv + * Version: 1.0 + * License: GPL2 + */ +class Stage_WP_Plugin { + + function hook( $h ) { + + $p = 10; + $m = $this->sanitize_method( $h ); + $b = func_get_args(); + + unset( $b[0] ); + + foreach( ( array )$b as $a ){ + if ( is_int( $a ) ) { + $p = $a + } else { + $m = $a + } + } + + return add_action( $h, array( $this, $m ), $p, 999 ); + } + + private function sanitize_method( $m ){ + return str_replace( array( '.', '-' ), array( '_DOT_', '_DASH_' ), $m ); + } + +} diff --git a/wordpress-mu-plugins/stage-wp-staging.php b/wordpress-mu-plugins/stage-wp-staging.php new file mode 100644 index 0000000..3951ba0 --- /dev/null +++ b/wordpress-mu-plugins/stage-wp-staging.php @@ -0,0 +1,63 @@ + + * @license GPL2 + * @link http://github.com/andrezrv/stage-wp/ + * @copyright 2014 Andrés Villarreal + * + * @wordpress-plugin + * Plugin name: Stage WP Staging + * Plugin URI: http://github.com/andrezrv/stage-wp/ + * Description: For staging environments, this plugin will replace your production domain with the staging one. Original credits go to Mark Jaquith. + * Author: Andrés Villarreal + * Author URI: http://about.me/andrezrv + * Version: 1.0 + * License: GPL2 + */ +// Load required class. +if ( !class_exists( 'Stage_WP_Plugin' ) ) { + if ( defined( 'STAGE_WP_PLUGIN_LOCATION' ) && file_exists( $file = STAGE_WP_PLUGIN_LOCATION ) ) { + require( $file ); + } elseif ( file_exists( $file = dirname( __FILE__ ) . '/stage-wp-plugin.class.php' ) ) { + require( $file ); + } +} + +// Once class is loaded, extend it. +if ( class_exists( 'Stage_WP_Plugin' ) ) { + + class Stage_WP_Staging_Plugin extends Stage_WP_Plugin { + + public static $instance; + + public function __construct() { + + self::$instance = $this; + + if ( !defined( 'WP_STAGE' ) || WP_STAGE !== 'staging' || !defined( 'STAGING_DOMAIN' ) ) { + return; + } + + $this->hook( 'option_home', 'replace_domain' ); + $this->hook( 'option_siteurl', 'replace_domain' ); + + } + + public function replace_domain ( $url ) { + $current_domain = parse_url( $url, PHP_URL_HOST ); + $url = str_replace( '//' . $current_domain, '//' . STAGING_DOMAIN, $url ); + return $url; + } + } + + new Stage_WP_Staging_Plugin; + +} diff --git a/wordpress-mu-plugins/wp-stack-cdn.php b/wordpress-mu-plugins/wp-stack-cdn.php deleted file mode 100644 index 4099276..0000000 --- a/wordpress-mu-plugins/wp-stack-cdn.php +++ /dev/null @@ -1,73 +0,0 @@ -sanitize_method($h);$b=func_get_args();unset($b[0]);foreach((array)$b as $a){if(is_int($a))$p=$a;else $m=$a;}return add_action($h,array($this,$m),$p,999);}private function sanitize_method($m){return str_replace(array('.','-'),array('_DOT_','_DASH_'),$m);}}} - -// The plugin -class WP_Stack_CDN_Plugin extends WP_Stack_Plugin { - public static $instance; - public $site_domain; - public $cdn_domain; - public $upload_dir; - public $uploads_only; - public $extensions; - - public function __construct() { - self::$instance = $this; - $this->hook( 'plugins_loaded' ); - } - - public function plugins_loaded() { - $domain_set_up = get_option( 'wp_stack_cdn_domain' ) || ( defined( 'WP_STACK_CDN_DOMAIN' ) && WP_STACK_CDN_DOMAIN ); - $production = defined( 'WP_STAGE' ) && WP_STAGE === 'production'; - $staging = defined( 'WP_STAGE' ) && WP_STAGE === 'staging'; - $uploads_only = defined( 'WP_STACK_CDN_UPLOADS_ONLY' ) && WP_STACK_CDN_UPLOADS_ONLY; - if ( $domain_set_up && !$staging && ( $production || $uploads_only ) ) - $this->hook( 'init' ); - } - - public function init() { - $this->uploads_only = apply_filters( 'wp_stack_cdn_uploads_only', defined( 'WP_STACK_CDN_UPLOADS_ONLY' ) ? WP_STACK_CDN_UPLOADS_ONLY : false ); - $this->extensions = apply_filters( 'wp_stack_cdn_extensions', array( 'jpe?g', 'gif', 'png', 'css', 'bmp', 'js', 'ico' ) ); - if ( !is_admin() ) { - $this->hook( 'template_redirect' ); - if ( $this->uploads_only ) - $this->hook( 'wp_stack_cdn_content', 'filter_uploads_only' ); - else - $this->hook( 'wp_stack_cdn_content', 'filter' ); - $this->site_domain = parse_url( get_bloginfo( 'url' ), PHP_URL_HOST ); - $this->cdn_domain = defined( 'WP_STACK_CDN_DOMAIN' ) ? WP_STACK_CDN_DOMAIN : get_option( 'wp_stack_cdn_domain' ); - } - } - - public function filter_uploads_only( $content ) { - $upload_dir = wp_upload_dir(); - $upload_dir = $upload_dir['baseurl']; - $domain = preg_quote( parse_url( $upload_dir, PHP_URL_HOST ), '#' ); - $path = parse_url( $upload_dir, PHP_URL_PATH ); - $preg_path = preg_quote( $path, '#' ); - - // Targeted replace just on uploads URLs - return preg_replace( "#=([\"'])(https?://{$domain})?$preg_path/((?:(?!\\1]).)+)\.(" . implode( '|', $this->extensions ) . ")(\?((?:(?!\\1).)+))?\\1#", '=$1http://' . $this->cdn_domain . $path . '/$3.$4$5$1', $content ); - } - - public function filter( $content ) { - return preg_replace( "#=([\"'])(https?://{$this->site_domain})?/([^/](?:(?!\\1).)+)\.(" . implode( '|', $this->extensions ) . ")(\?((?:(?!\\1).)+))?\\1#", '=$1http://' . $this->cdn_domain . '/$3.$4$5$1', $content ); - } - - public function template_redirect() { - ob_start( array( $this, 'ob' ) ); - } - - public function ob( $contents ) { - return apply_filters( 'wp_stack_cdn_content', $contents, $this ); - } -} - -new WP_Stack_CDN_Plugin; diff --git a/wordpress-mu-plugins/wp-stack-manual-db-upgrades.php b/wordpress-mu-plugins/wp-stack-manual-db-upgrades.php deleted file mode 100644 index 9d85a8b..0000000 --- a/wordpress-mu-plugins/wp-stack-manual-db-upgrades.php +++ /dev/null @@ -1,34 +0,0 @@ -sanitize_method($h);$b=func_get_args();unset($b[0]);foreach((array)$b as $a){if(is_int($a))$p=$a;else $m=$a;}return add_action($h,array($this,$m),$p,999);}private function sanitize_method($m){return str_replace(array('.','-'),array('_DOT_','_DASH_'),$m);}}} - -// The plugin -class WP_Stack_Manual_DB_Upgrades_Plugin extends WP_Stack_Plugin { - public static $instance; - - public function __construct() { - self::$instance = $this; - $this->hook( 'plugins_loaded' ); - } - - public function plugins_loaded() { - $this->hook( 'option_db_version' ); - } - - public function option_db_version( $version ) { - if ( strpos( $_SERVER['REQUEST_URI'], '/wp-admin/upgrade.php' ) === false ) - return $GLOBALS['wp_db_version']; - else - return $version; - } - -} - -new WP_Stack_Manual_DB_Upgrades_Plugin; diff --git a/wordpress-mu-plugins/wp-stack-ms-uploads.php b/wordpress-mu-plugins/wp-stack-ms-uploads.php deleted file mode 100644 index 6b6b753..0000000 --- a/wordpress-mu-plugins/wp-stack-ms-uploads.php +++ /dev/null @@ -1,58 +0,0 @@ -sanitize_method($h);$b=func_get_args();unset($b[0]);foreach((array)$b as $a){if(is_int($a))$p=$a;else $m=$a;}return add_action($h,array($this,$m),$p,999);}private function sanitize_method($m){return str_replace(array('.','-'),array('_DOT_','_DASH_'),$m);}}} - -// The plugin -class WP_Stack_MS_Uploads_Plugin extends WP_Stack_Plugin { - public static $instance; - - public function __construct() { - self::$instance = $this; - if ( is_multisite() ) - $this->hook( 'init' ); - } - - public function init() { - global $blog_id; - if ( $blog_id != 1 ) { - $this->hook( 'option_fileupload_url' ); - $this->hook( 'upload_dir' ); - } - } - - public function upload_dir( $upload ) { - /* - array( - 'subdir' => '/2012/07', - 'basedir' => '/Users/mark/Sites/wp.git/wp-content/uploads', - 'path' => '/Users/mark/Sites/wp.git/wp-content/uploads/2012/07', - 'baseurl' => 'http://wp.git/wp-files/1', - 'url' => 'http://wp.git/wp-content/uploads/2012/07', - 'error' => false - ) - */ - global $blog_id; - $parsed = parse_url( $upload['baseurl'] ); - $upload['baseurl'] = $parsed['scheme'] . '://' . $parsed['host'] . '/wp-files/' . $blog_id; - $upload['url'] = $upload['baseurl'] . $upload['subdir']; - var_export( $upload ); die(); - return $upload; - } - - // Does core even use this anymore? - public function option_fileupload_url( $url ) { - global $blog_id; - $parsed = parse_url( $url ); - $url = $parsed['scheme'] . '://' . $parsed['host'] . '/wp-files/' . $blog_id . '/'; - return $url; - } -} - -new WP_Stack_MS_Uploads_Plugin; diff --git a/wordpress-mu-plugins/wp-stack-staging.php b/wordpress-mu-plugins/wp-stack-staging.php deleted file mode 100644 index 3cdc740..0000000 --- a/wordpress-mu-plugins/wp-stack-staging.php +++ /dev/null @@ -1,32 +0,0 @@ -sanitize_method($h);$b=func_get_args();unset($b[0]);foreach((array)$b as $a){if(is_int($a))$p=$a;else $m=$a;}return add_action($h,array($this,$m),$p,999);}private function sanitize_method($m){return str_replace(array('.','-'),array('_DOT_','_DASH_'),$m);}}} - -// The plugin -class WP_Stack_Staging_Plugin extends WP_Stack_Plugin { - public static $instance; - - public function __construct() { - self::$instance = $this; - if ( !defined( 'WP_STAGE' ) || WP_STAGE !== 'staging' || !defined( 'STAGING_DOMAIN' ) ) - return; - $this->hook( 'option_home', 'replace_domain' ); - $this->hook( 'option_siteurl', 'replace_domain' ); - } - - public function replace_domain ( $url ) { - $current_domain = parse_url( $url, PHP_URL_HOST ); - $url = str_replace( '//' . $current_domain, '//' . STAGING_DOMAIN, $url ); - return $url; - } -} - -new WP_Stack_Staging_Plugin; - From 91c882278273d7d49192a8c8de5cc8fb7a3fb8b9 Mon Sep 17 00:00:00 2001 From: andrezrv Date: Wed, 15 Jan 2014 06:37:01 +0000 Subject: [PATCH 17/52] Added utilitary tasks. --- Capfile | 4 +- config/config-sample.rb | 41 ++++++++++++++------ lib/deploy.rb | 1 + lib/tasks.rb | 85 ++++++++++++++++++++++++++++++++--------- 4 files changed, 101 insertions(+), 30 deletions(-) diff --git a/Capfile b/Capfile index 3ea246a..5452559 100644 --- a/Capfile +++ b/Capfile @@ -27,7 +27,9 @@ load "lib/deploy" # Loads config/config.rb after load "lib/deploy-after" # Load a Customfile if we have one -loadFile "Customfile" +if File.exists?("Customfile") then + loadFile "Customfile" +end # Delay loading of multistage module, so we can override :stages if needed require "capistrano/ext/multistage" diff --git a/config/config-sample.rb b/config/config-sample.rb index 7bbcffa..b81bf69 100644 --- a/config/config-sample.rb +++ b/config/config-sample.rb @@ -10,6 +10,24 @@ # // The name of your application. It can be any string. set :application, "Local WordPress Installation" +# // A shortname to identify your application. +set :application_id, "wordpress" + +# Where is your wp-config.php file located within #{release_path}? +# // Your release path points to the newer copy of your repository, so you must +# // specify where your wp-config.php file is located within your remore repo. +# // WordPress Bareboner puts the file in the "app" subfolder, so it needs to +# // be "#{release_path}/app", but if you are using WordPress-Skeleton, just +# // "#{release_path}" should do the trick and this value should be left empty. +set :application_path, "/app" + +# Where are your shell tasks located within #{release_path}? +# // If you're using WordPress Bareboner, the tasks should be by default into +# // /app/tasks. If you are using another WordPress starting repo, you should +# // adjust this value to your own configuration. However, all tasks related to +# // this setting will not be executed if following path does'n t exist. +set :tasks_path, "/app/tasks" + # Repository settings # // Location of your remote repository. @@ -43,14 +61,6 @@ # // Path to your local shared folder. set :local_shared_folder, "/srv/www/website/application/shared" -# Where is your wp-config.php file located within #{release_path}? -# // Your release path points to the newer copy of your repository, so you must -# // specify where your wp-config.php file is located within your remore repo. -# // WordPress Bareboner puts the file in the "app" subfolder, so it needs to -# // be "#{release_path}/app", but if you are using WordPress-Skeleton, just -# // "#{release_path}" should do the trick and this value should be left empty. -set :wp_config_location, "/app" - # WordPress database settings. # # Set the values for host, user, pass, and name for production, staging and @@ -66,6 +76,7 @@ :password => "root", :name => "production_db", :backups_dir => "/srv/www/website/backups/dumps", + :max_backups => "3", :dump_suffix => "production", # A string to differentiate mysqldumps }, :staging => { @@ -74,6 +85,7 @@ :password => "root", :name => "staging_db", :backups_dir => "/srv/www/website/backups/dumps", + :max_backups => "3", :dump_suffix => "staging", # A string to differentiate mysqldumps }, :local => { @@ -82,6 +94,7 @@ :password => "root", :name => "local_db", :backups_dir => "/srv/www/website/backups/dumps", + :max_backups => "3", :dump_suffix => "local", # A string to differentiate mysqldumps } } @@ -89,9 +102,13 @@ # Additional hook files. -# // Load a file meant to contain your custom hooks for tasks. -loadFile "lib/custom-hooks.rb" -# // Load a file meant to contain your custom tasks. -loadFile "lib/custom-tasks.rb" +# // Load (if exists) a file meant to contain your custom hooks for tasks. +if File.exists?("lib/custom-hooks.rb") then + loadFile "lib/custom-hooks.rb" +end +# // Load (if exists) a file meant to contain your custom tasks. +if File.exists?("lib/custom-hooks.rb") then + loadFile "lib/custom-tasks.rb" +end # You're not done! You must also configure production.rb, staging.rb and local.rb diff --git a/lib/deploy.rb b/lib/deploy.rb index c20047e..5ef01a9 100644 --- a/lib/deploy.rb +++ b/lib/deploy.rb @@ -14,6 +14,7 @@ after "deploy:update_code", "shared:make_shared_dir" after "deploy:update_code", "shared:make_symlinks" after "deploy:update_code", "db:make_config" +after "deploy:update_code", "util:make_config" after "deploy", "memcached:update" # Put some hooks after deploy tasks diff --git a/lib/tasks.rb b/lib/tasks.rb index 3fd041e..91223aa 100644 --- a/lib/tasks.rb +++ b/lib/tasks.rb @@ -16,7 +16,7 @@ desc "Pulls shared files from remote location" task :pull do if stage == :local then - puts "[ERROR] You must run shared:pull from staging or production with cap staging shared:pull or cap production shared:pull" + puts "[Error] You must run shared:pull from staging or production with cap staging shared:pull or cap production shared:pull" else random = rand(10 ** 5).to_s.rjust(5, '0') current_host = capture("echo $CAPISTRANO:HOST$").strip @@ -27,7 +27,7 @@ desc "Pushes shared files to remote location" task :push do if stage == :local then - puts "[ERROR] You must run shared:pull from staging or production with cap staging shared:pull or cap production shared:pull" + puts "[Error] You must run shared:pull from staging or production with cap staging shared:pull or cap production shared:pull" else random = rand(10 ** 5).to_s.rjust(5, '0') current_host = capture("echo $CAPISTRANO:HOST$").strip @@ -84,9 +84,9 @@ namespace :db do desc "Initialize the WordPress database in a remote stage" # This is a tricky one - task :init, :roles => :web do + task :init do if stage == :local then - puts "[ERROR] You must run db:init from staging or production with cap staging db:init or cap production db:init" + puts "[Error] You must run db:init from staging or production with cap staging db:init or cap production db:init" else s = (stage == :production) ? wpdb[:production] : wpdb[:staging] # Obtain MySQL admin credentials @@ -129,9 +129,9 @@ end end desc "Syncs the staging database (and uploads) from production" - task :sync, :roles => :web do + task :sync do if stage == :production then - puts "[ERROR] You must run db:sync from staging with cap staging db:sync or from local with cap local db:sync" + puts "[Error] You must run db:sync from staging with cap staging db:sync or from local with cap local db:sync" else if stage == :staging then puts "Hang on... this might take a while." @@ -168,7 +168,7 @@ end end desc "Backup database" - task :backup, :roles => :web do + task :backup do if stage == :local then l = wpdb[:local] puts "Backing up MySQL local database..." @@ -195,13 +195,13 @@ end end puts "Remote MySQL database saved to #{filename}" - rescue Exception => error + rescue Exception => Error puts "Remote MySQL database could not be saved." end end end desc "Restore database from backup" - task :restore, :roles => :web do + task :restore do if stage == :local then l = wpdb[:local] puts "Searching for available local backups..." @@ -238,15 +238,15 @@ end end puts "Remote database restored to backup saved in #{backup_file}." - rescue Exception => error + rescue Exception => Error puts "Remote database could not be restored from backup." end end end desc "Pull a remote database backup to local" - task :pull, :roles => :web do + task :pull do if stage == :local then - puts "[ERROR] You must run db:pull from staging or production with cap staging db:pull or cap production db:pull" + puts "[Error] You must run db:pull from staging or production with cap staging db:pull or cap production db:pull" else env = (stage == :production) ? wpdb[:production] : wpdb[:staging] l = wpdb[:local] @@ -268,9 +268,9 @@ end end desc "Push a remote database backup to remote from local" - task :push, :roles => :web do + task :push do if stage == :local then - puts "[ERROR] You must run db:push from staging or production with cap staging db:push or cap production db:push" + puts "[Error] You must run db:push from staging or production with cap staging db:push or cap production db:push" else env = (stage == :production) ? wpdb[:production] : wpdb[:staging] l = wpdb[:local] @@ -291,11 +291,62 @@ end end end - desc "Sets the database credentials (and other settings) in wp-config.php" + desc "Set the database credentials (and other settings) in wp-config.php" + task :make_config do + set :staging_domain, '' unless defined? staging_domain + {:'%%WP_STAGING_DOMAIN%%' => staging_domain, + :'%%WP_STAGE%%' => stage, + :'%%DB_NAME%%' => wpdb[stage][:name], + :'%%DB_USER%%' => wpdb[stage][:user], + :'%%DB_PASSWORD%%' => wpdb[stage][:password], + :'%%DB_HOST%%' => wpdb[stage][:host] + }.each do |k, v| + run "sed -i 's/#{k}/#{v}/' #{release_path}#{application_path}/wp-config.php", :roles => :web + end + end +end + +namespace :util do + if !File.exists?("#{release_path}#{tasks_path}/config.sh") then + abort("Backup tasks are not configured.") + end + desc "Set the database credentials (and other settings) in config.sh" task :make_config do set :staging_domain, '' unless defined? staging_domain - {:'%%WP_STAGING_DOMAIN%%' => staging_domain, :'%%WP_STAGE%%' => stage, :'%%DB_NAME%%' => wpdb[stage][:name], :'%%DB_USER%%' => wpdb[stage][:user], :'%%DB_PASSWORD%%' => wpdb[stage][:password], :'%%DB_HOST%%' => wpdb[stage][:host]}.each do |k,v| - run "sed -i 's/#{k}/#{v}/' #{release_path}#{wp_config_location}/wp-config.php", :roles => :web + run "sudo rm -f #{release_path}#{tasks_location}/config.sh" + run "sudo cp #{release_path}#{tasks_location}/config-sample.sh #{release_path}#{tasks_location}/config.sh" + {:'%%DB_NAME%%' => wpdb[stage][:name], + :'%%DB_USER%%' => wpdb[stage][:user], + :'%%DB_PASSWORD%%' => wpdb[stage][:password], + :'%%DB_BACKUP_PATH%%' => wpdb[stage][:backups_dir], + :'%%DB_MAX_BACKUPS%%' => wpdb[stage][:max_backups], + :'%%PROJECT_PATH%%' => release_path, + :'%%USR_BIN_PREFIX%%' => application_id, + :'%%APPLICATION_PATH%%' => application_path, + :'%%APPLICATION_BACKUP_PATH%%' => application_backup_path, + :'%%APPLICATION_MAX_BACKUPS%%' => application_max_backups, + }.each do |k, v| + run "sed -i 's/#{k}/#{v}/' #{release_path}#{tasks_path}/config.sh", :roles => :web end end + desc "Add tasks commands to /usr/bin" + task :make_commands do + run "sudo bash #{release_path}#{tasks_location}/add-to-bin.sh" + end + desc "Zip and save all application files to #{application_backup_path}" + task :backup_application do + run "sudo bash #{release_path}#{tasks_location}/website-backup-application.sh" + end + desc "Perform a mysql dump of the WordPress database and save it to #{wpdb[stage][:backups_dir]}" + task :backup_db do + run "sudo bash #{release_path}#{tasks_location}/website-backup-database.sh" + end + desc "Switches the state of your site from live to maintenance and vice versa" + task :switch do + run "sudo bash #{release_path}#{tasks_location}/website-switch.sh" + end + desc "Perform a full backup (files and database)" + task :full_backup do + run "sudo bash #{release_path}#{tasks_location}/website-full-backup.sh" + end end From cac851cc4d81dda9c11ef785a1b1a908dd7f9c08 Mon Sep 17 00:00:00 2001 From: andrezrv Date: Wed, 15 Jan 2014 06:51:20 +0000 Subject: [PATCH 18/52] Fixed formatting issues. --- config/config-sample.rb | 24 ++++---- lib/tasks.rb | 62 ++++++++++---------- wordpress-mu-plugins/stage-wp-ms-uploads.php | 13 ++-- 3 files changed, 49 insertions(+), 50 deletions(-) diff --git a/config/config-sample.rb b/config/config-sample.rb index b81bf69..5716c32 100644 --- a/config/config-sample.rb +++ b/config/config-sample.rb @@ -71,28 +71,28 @@ set :wpdb do { :production => { - :host => "localhost", - :user => "root", - :password => "root", - :name => "production_db", + :host => "localhost", + :user => "root", + :password => "root", + :name => "production_db", :backups_dir => "/srv/www/website/backups/dumps", :max_backups => "3", :dump_suffix => "production", # A string to differentiate mysqldumps }, :staging => { - :host => "localhost", - :user => "root", - :password => "root", - :name => "staging_db", + :host => "localhost", + :user => "root", + :password => "root", + :name => "staging_db", :backups_dir => "/srv/www/website/backups/dumps", :max_backups => "3", :dump_suffix => "staging", # A string to differentiate mysqldumps }, :local => { - :host => "localhost", - :user => "root", - :password => "root", - :name => "local_db", + :host => "localhost", + :user => "root", + :password => "root", + :name => "local_db", :backups_dir => "/srv/www/website/backups/dumps", :max_backups => "3", :dump_suffix => "local", # A string to differentiate mysqldumps diff --git a/lib/tasks.rb b/lib/tasks.rb index 91223aa..fdf6bf7 100644 --- a/lib/tasks.rb +++ b/lib/tasks.rb @@ -56,7 +56,7 @@ begin # For non-Ubuntu systems run "sudo /etc/init.d/php-fpm restart" rescue Exception => e # For Ubuntu systems - run "sudo /etc/init.d/php-fpm restart" + run "sudo /etc/init.d/php5-fpm restart" end end end @@ -91,12 +91,12 @@ s = (stage == :production) ? wpdb[:production] : wpdb[:staging] # Obtain MySQL admin credentials admin_name = Capistrano::CLI.ui.ask "Please provide the name of your MySQL admin user [root] " - admin_name = "root" if admin_name.empty? + admin_name = "root" if admin_name.empty? admin_password = Capistrano::CLI.password_prompt "Please provide the password of your MySQL admin user [root] " - admin_password = "root" if admin_password.empty? - # Store query strings - create = "CREATE DATABASE IF NOT EXISTS #{s[:name]};" - grant = "GRANT ALL PRIVILEGES ON #{s[:name]}.* TO '#{s[:user]}'@'#{s[:host]}' IDENTIFIED BY '#{s[:password]}';" + admin_password = "root" if admin_password.empty? + # Store query strings + create = "CREATE DATABASE IF NOT EXISTS #{s[:name]};" + grant = "GRANT ALL PRIVILEGES ON #{s[:name]}.* TO '#{s[:user]}'@'#{s[:host]}' IDENTIFIED BY '#{s[:password]}';" show = "SHOW DATABASES;" # Initialize output output = "" @@ -201,19 +201,19 @@ end end desc "Restore database from backup" - task :restore do - if stage == :local then - l = wpdb[:local] + task :restore do + if stage == :local then + l = wpdb[:local] puts "Searching for available local backups..." # List contents from dumps folder - backups = `ls -1 #{l[:backups_dir]}/`.split("\n") + backups = `ls -1 #{l[:backups_dir]}/`.split("\n") # Define default backup - default_backup = backups.last - puts "Available backups: " - puts backups - backup = Capistrano::CLI.ui.ask "Which backup would you like to restore? [#{default_backup}] " - backup_file = backup - backup_file = default_backup if backup_file.empty? + default_backup = backups.last + puts "Available backups: " + puts backups + backup = Capistrano::CLI.ui.ask "Which backup would you like to restore? [#{default_backup}] " + backup_file = backup + backup_file = default_backup if backup_file.empty? if system "mysql -u #{l[:user]} -p#{l[:password]} #{l[:name]} < #{l[:backups_dir]}/#{backup_file}" then puts "Local database restored to backup saved in #{l[:backups_dir]}/#{backup_file}." else @@ -223,14 +223,14 @@ env = (stage == :production) ? wpdb[:production] : wpdb[:staging] puts "Searching for available remote backups..." # List contents from dumps folder - backups = capture("ls -1 #{env[:backups_dir]}").split("\n") + backups = capture("ls -1 #{env[:backups_dir]}").split("\n") # Define default backup - default_backup = backups.last - puts "Available backups: " - puts backups - backup = Capistrano::CLI.ui.ask "Which backup would you like to restore? [#{default_backup}] " - backup_file = default_backup if backup.empty? - backup_file = "#{env[:backups_dir]}/#{backup_file}" + default_backup = backups.last + puts "Available backups: " + puts backups + backup = Capistrano::CLI.ui.ask "Which backup would you like to restore? [#{default_backup}] " + backup_file = default_backup if backup.empty? + backup_file = "#{env[:backups_dir]}/#{backup_file}" begin run "mysql -u #{env[:user]} -p#{env[:password]} #{env[:name]} < #{backup_file}" do |channel, stream, data| if data =~ /^Enter password: / @@ -252,9 +252,9 @@ l = wpdb[:local] puts "Searching for available remote backups..." # List contents from dumps folder - backups = capture("ls -1 #{env[:backups_dir]}").split("\n") + backups = capture("ls -1 #{env[:backups_dir]}").split("\n") # Define default backup - default_backup = backups.last + default_backup = backups.last puts "Available backups: " puts backups backup = Capistrano::CLI.ui.ask "Which backup would you like to pull? [#{default_backup}] " @@ -276,13 +276,13 @@ l = wpdb[:local] puts "Searching for available local backups..." # List contents from dumps folder - backups = `ls -1 #{l[:backups_dir]}/`.split("\n") + backups = `ls -1 #{l[:backups_dir]}/`.split("\n") # Define default backup - default_backup = backups.last - puts "Available backups: " - puts backups - backup = Capistrano::CLI.ui.ask "Which backup would you like to push? [#{default_backup}] " - backup_file = default_backup if backup.empty? + default_backup = backups.last + puts "Available backups: " + puts backups + backup = Capistrano::CLI.ui.ask "Which backup would you like to push? [#{default_backup}] " + backup_file = default_backup if backup.empty? current_host = capture("echo $CAPISTRANO:HOST$").strip if system "scp #{l[:backups_dir]}/#{backup_file} #{user}@#{current_host}:#{env[:backups_dir]}" then puts "Local database uploaded to remote host at #{env[:backups_dir]}/#{backup_file}." diff --git a/wordpress-mu-plugins/stage-wp-ms-uploads.php b/wordpress-mu-plugins/stage-wp-ms-uploads.php index 7c8ed39..b6cf533 100644 --- a/wordpress-mu-plugins/stage-wp-ms-uploads.php +++ b/wordpress-mu-plugins/stage-wp-ms-uploads.php @@ -64,13 +64,12 @@ public function upload_dir( $upload ) { /** * $upload expected format: - * $upload = array( - * 'subdir' => '/2012/07', - * 'basedir' => '/Users/mark/Sites/wp.git/wp-content/uploads', - * 'path' => '/Users/mark/Sites/wp.git/wp-content/uploads/2012/07', - * 'baseurl' => 'http://wp.git/wp-files/1', - * 'url' => 'http://wp.git/wp-content/uploads/2012/07', - * 'error' => false + * $upload = array( 'subdir' => '/2012/07', + * 'basedir' => '/Users/mark/Sites/wp.git/wp-content/uploads', + * 'path' => '/Users/mark/Sites/wp.git/wp-content/uploads/2012/07', + * 'baseurl' => 'http://wp.git/wp-files/1', + * 'url' => 'http://wp.git/wp-content/uploads/2012/07', + * 'error' => false * ); */ From 13571985017387b821ea2b3d9469642fe6d57511 Mon Sep 17 00:00:00 2001 From: andrezrv Date: Wed, 15 Jan 2014 06:51:20 +0000 Subject: [PATCH 19/52] Fixed format issues --- config/config-sample.rb | 24 ++++---- lib/tasks.rb | 62 ++++++++++---------- wordpress-mu-plugins/stage-wp-ms-uploads.php | 13 ++-- 3 files changed, 49 insertions(+), 50 deletions(-) diff --git a/config/config-sample.rb b/config/config-sample.rb index b81bf69..5716c32 100644 --- a/config/config-sample.rb +++ b/config/config-sample.rb @@ -71,28 +71,28 @@ set :wpdb do { :production => { - :host => "localhost", - :user => "root", - :password => "root", - :name => "production_db", + :host => "localhost", + :user => "root", + :password => "root", + :name => "production_db", :backups_dir => "/srv/www/website/backups/dumps", :max_backups => "3", :dump_suffix => "production", # A string to differentiate mysqldumps }, :staging => { - :host => "localhost", - :user => "root", - :password => "root", - :name => "staging_db", + :host => "localhost", + :user => "root", + :password => "root", + :name => "staging_db", :backups_dir => "/srv/www/website/backups/dumps", :max_backups => "3", :dump_suffix => "staging", # A string to differentiate mysqldumps }, :local => { - :host => "localhost", - :user => "root", - :password => "root", - :name => "local_db", + :host => "localhost", + :user => "root", + :password => "root", + :name => "local_db", :backups_dir => "/srv/www/website/backups/dumps", :max_backups => "3", :dump_suffix => "local", # A string to differentiate mysqldumps diff --git a/lib/tasks.rb b/lib/tasks.rb index 91223aa..fdf6bf7 100644 --- a/lib/tasks.rb +++ b/lib/tasks.rb @@ -56,7 +56,7 @@ begin # For non-Ubuntu systems run "sudo /etc/init.d/php-fpm restart" rescue Exception => e # For Ubuntu systems - run "sudo /etc/init.d/php-fpm restart" + run "sudo /etc/init.d/php5-fpm restart" end end end @@ -91,12 +91,12 @@ s = (stage == :production) ? wpdb[:production] : wpdb[:staging] # Obtain MySQL admin credentials admin_name = Capistrano::CLI.ui.ask "Please provide the name of your MySQL admin user [root] " - admin_name = "root" if admin_name.empty? + admin_name = "root" if admin_name.empty? admin_password = Capistrano::CLI.password_prompt "Please provide the password of your MySQL admin user [root] " - admin_password = "root" if admin_password.empty? - # Store query strings - create = "CREATE DATABASE IF NOT EXISTS #{s[:name]};" - grant = "GRANT ALL PRIVILEGES ON #{s[:name]}.* TO '#{s[:user]}'@'#{s[:host]}' IDENTIFIED BY '#{s[:password]}';" + admin_password = "root" if admin_password.empty? + # Store query strings + create = "CREATE DATABASE IF NOT EXISTS #{s[:name]};" + grant = "GRANT ALL PRIVILEGES ON #{s[:name]}.* TO '#{s[:user]}'@'#{s[:host]}' IDENTIFIED BY '#{s[:password]}';" show = "SHOW DATABASES;" # Initialize output output = "" @@ -201,19 +201,19 @@ end end desc "Restore database from backup" - task :restore do - if stage == :local then - l = wpdb[:local] + task :restore do + if stage == :local then + l = wpdb[:local] puts "Searching for available local backups..." # List contents from dumps folder - backups = `ls -1 #{l[:backups_dir]}/`.split("\n") + backups = `ls -1 #{l[:backups_dir]}/`.split("\n") # Define default backup - default_backup = backups.last - puts "Available backups: " - puts backups - backup = Capistrano::CLI.ui.ask "Which backup would you like to restore? [#{default_backup}] " - backup_file = backup - backup_file = default_backup if backup_file.empty? + default_backup = backups.last + puts "Available backups: " + puts backups + backup = Capistrano::CLI.ui.ask "Which backup would you like to restore? [#{default_backup}] " + backup_file = backup + backup_file = default_backup if backup_file.empty? if system "mysql -u #{l[:user]} -p#{l[:password]} #{l[:name]} < #{l[:backups_dir]}/#{backup_file}" then puts "Local database restored to backup saved in #{l[:backups_dir]}/#{backup_file}." else @@ -223,14 +223,14 @@ env = (stage == :production) ? wpdb[:production] : wpdb[:staging] puts "Searching for available remote backups..." # List contents from dumps folder - backups = capture("ls -1 #{env[:backups_dir]}").split("\n") + backups = capture("ls -1 #{env[:backups_dir]}").split("\n") # Define default backup - default_backup = backups.last - puts "Available backups: " - puts backups - backup = Capistrano::CLI.ui.ask "Which backup would you like to restore? [#{default_backup}] " - backup_file = default_backup if backup.empty? - backup_file = "#{env[:backups_dir]}/#{backup_file}" + default_backup = backups.last + puts "Available backups: " + puts backups + backup = Capistrano::CLI.ui.ask "Which backup would you like to restore? [#{default_backup}] " + backup_file = default_backup if backup.empty? + backup_file = "#{env[:backups_dir]}/#{backup_file}" begin run "mysql -u #{env[:user]} -p#{env[:password]} #{env[:name]} < #{backup_file}" do |channel, stream, data| if data =~ /^Enter password: / @@ -252,9 +252,9 @@ l = wpdb[:local] puts "Searching for available remote backups..." # List contents from dumps folder - backups = capture("ls -1 #{env[:backups_dir]}").split("\n") + backups = capture("ls -1 #{env[:backups_dir]}").split("\n") # Define default backup - default_backup = backups.last + default_backup = backups.last puts "Available backups: " puts backups backup = Capistrano::CLI.ui.ask "Which backup would you like to pull? [#{default_backup}] " @@ -276,13 +276,13 @@ l = wpdb[:local] puts "Searching for available local backups..." # List contents from dumps folder - backups = `ls -1 #{l[:backups_dir]}/`.split("\n") + backups = `ls -1 #{l[:backups_dir]}/`.split("\n") # Define default backup - default_backup = backups.last - puts "Available backups: " - puts backups - backup = Capistrano::CLI.ui.ask "Which backup would you like to push? [#{default_backup}] " - backup_file = default_backup if backup.empty? + default_backup = backups.last + puts "Available backups: " + puts backups + backup = Capistrano::CLI.ui.ask "Which backup would you like to push? [#{default_backup}] " + backup_file = default_backup if backup.empty? current_host = capture("echo $CAPISTRANO:HOST$").strip if system "scp #{l[:backups_dir]}/#{backup_file} #{user}@#{current_host}:#{env[:backups_dir]}" then puts "Local database uploaded to remote host at #{env[:backups_dir]}/#{backup_file}." diff --git a/wordpress-mu-plugins/stage-wp-ms-uploads.php b/wordpress-mu-plugins/stage-wp-ms-uploads.php index 7c8ed39..b6cf533 100644 --- a/wordpress-mu-plugins/stage-wp-ms-uploads.php +++ b/wordpress-mu-plugins/stage-wp-ms-uploads.php @@ -64,13 +64,12 @@ public function upload_dir( $upload ) { /** * $upload expected format: - * $upload = array( - * 'subdir' => '/2012/07', - * 'basedir' => '/Users/mark/Sites/wp.git/wp-content/uploads', - * 'path' => '/Users/mark/Sites/wp.git/wp-content/uploads/2012/07', - * 'baseurl' => 'http://wp.git/wp-files/1', - * 'url' => 'http://wp.git/wp-content/uploads/2012/07', - * 'error' => false + * $upload = array( 'subdir' => '/2012/07', + * 'basedir' => '/Users/mark/Sites/wp.git/wp-content/uploads', + * 'path' => '/Users/mark/Sites/wp.git/wp-content/uploads/2012/07', + * 'baseurl' => 'http://wp.git/wp-files/1', + * 'url' => 'http://wp.git/wp-content/uploads/2012/07', + * 'error' => false * ); */ From 20d4c3cfa8916aed3bd956e2b03d092f9c5c8cd0 Mon Sep 17 00:00:00 2001 From: andrezrv Date: Wed, 15 Jan 2014 13:55:43 +0000 Subject: [PATCH 20/52] Added /custom folder; more extensive .gitignore. --- .gitignore | 16 ++++++++++++++++ config/.gitignore | 4 ---- custom/README.md | 3 +++ 3 files changed, 19 insertions(+), 4 deletions(-) create mode 100644 .gitignore delete mode 100644 config/.gitignore create mode 100644 custom/README.md diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a65738a --- /dev/null +++ b/.gitignore @@ -0,0 +1,16 @@ +# No need to share Customfile +/Customfile + +# No need to share custom config files +/config/config.rb +/config/production.rb +/config/staging.rb +/config/local.rb + +# No need to share custom libraries +/lib/custom-hooks.rb +/lib/custom-tasks.rb + +# Ignore contents of /custom folder, except for readme file +/custom/* +!/custom/README.md diff --git a/config/.gitignore b/config/.gitignore deleted file mode 100644 index ebdc885..0000000 --- a/config/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -/config.rb -/production.rb -/staging.rb -/local.rb diff --git a/custom/README.md b/custom/README.md new file mode 100644 index 0000000..3223473 --- /dev/null +++ b/custom/README.md @@ -0,0 +1,3 @@ +## Custom folder + +Include here all the files you need that are not considered by the other folders within this package. Everything you put here will be ignored by Git, and should be loaded only from files that are also being ignored, such as Customfile or /config/config.rb. \ No newline at end of file From 2e9231ab4853547688fb1af5cbcb99f96a0298a5 Mon Sep 17 00:00:00 2001 From: andrezrv Date: Wed, 15 Jan 2014 14:24:36 +0000 Subject: [PATCH 21/52] Added config sample file with placeholders for easier auto-configuration. --- config/config-sample-placeholded.rb | 114 ++++++++++++++++++++++++++++ 1 file changed, 114 insertions(+) create mode 100644 config/config-sample-placeholded.rb diff --git a/config/config-sample-placeholded.rb b/config/config-sample-placeholded.rb new file mode 100644 index 0000000..e197034 --- /dev/null +++ b/config/config-sample-placeholded.rb @@ -0,0 +1,114 @@ +# Stage WP configuration file. +# +# This is a sample config file. It manages settings for your remote repository, +# your default domains and your database values. Copy it to config.rb and +# customize it to your own needs. + + +# Application settings. + +# // The name of your application. It can be any string. +set :application, "%%APPLICATION%%" + +# // A shortname to identify your application. +set :application_id, "%%APPLICATION_ID%%" + +# Where is your wp-config.php file located within #{release_path}? +# // Your release path points to the newer copy of your repository, so you must +# // specify where your wp-config.php file is located within your remore repo. +# // WordPress Bareboner puts the file in the "app" subfolder, so it needs to +# // be "#{release_path}/app", but if you are using WordPress-Skeleton, just +# // "#{release_path}" should do the trick and this value should be left empty. +set :application_path, "%%APPLICATION_PATH%%" + +# Where are your shell tasks located within #{release_path}? +# // If you're using WordPress Bareboner, the tasks should be by default into +# // /app/tasks. If you are using another WordPress starting repo, you should +# // adjust this value to your own configuration. However, all tasks related to +# // this setting will not be executed if following path does'n t exist. +set :tasks_path, "%%TASKS_PATH%%" + +# Repository settings + +# // Location of your remote repository. +set :repository, "%%REPOSITORY%%" + +# // Your preferred method for source control. Supports :accurev, :bzr, :cvs, +# // :darcs, :git, :mercurial, :perforce, :subversion or :none. +set :scm, :git + +# // Using Git submodules? +set :git_enable_submodules, 1 + +# Default deploy directories. + +# // :deploy_to in production.rb will use this value as default +set :production_deploy_to, "%%PRODUCTION_DEPLOY_TO%%" + +# // :deploy_to in staging.rb will use this value as default +set :staging_deploy_to, "%%STAGING_DEPLOY_TO%%" + +# Default domains. + +# // :deploy_to in production.rb will use this value as default +set :production_domain, "%%PRODUCTION_DOMAIN%%" + +# // :deploy_to in staging.rb will use this value as default +set :staging_domain, "%%STAGING_DOMAIN%%" + +# Local stage default settings. + +# // Path to your local shared folder. +set :local_shared_folder, "%%LOCAL_SHARED_FOLDER%%" + +# WordPress database settings. +# +# Set the values for host, user, pass, and name for production, staging and +# local stages. You can also specify a backup directory where your mysqldumps +# should be saved. Note that placeholders like %%DB_NAME%% and %%DB_PASSWORD%% +# in your wp-config.php file will be automatically replaced when `cap deploy` is +# executed, so you only have to configure these values here. +set :wpdb do + { + :production => { + :host => "%%PRODUCTION_HOST%%", + :user => "%%PRODUCTION_USER%%", + :password => "%%PRODUCTION_PASSWORD%%", + :name => "%%PRODUCTION_DB%%", + :backups_dir => "%%PRODUCTION_BACKUPS_DIR%%", + :max_backups => "%%PRODUCTION_MAX_BACKUPS%%", + :dump_suffix => "%%PRODUCTION_DUMP_SUFFIX%%", # A string to differentiate mysqldumps + }, + :staging => { + :host => "%%STAGING_HOST%%", + :user => "%%STAGING_USER%%", + :password => "%%STAGING_PASSWORD%%", + :name => "%%STAGING_DB%%", + :backups_dir => "%%STAGING_BACKUPS_DIR%%", + :max_backups => "%%STAGING_MAX_BACKUPS%%", + :dump_suffix => "%%STAGING_DUMP_SUFFIX%%", # A string to differentiate mysqldumps + }, + :local => { + :host => "%%LOCAL_HOST%%", + :user => "%%LOCAL_USER%%", + :password => "%%LOCAL_PASSWORD%%", + :name => "%%LOCAL_DB%%", + :backups_dir => "%%LOCAL_BACKUPS_DIR%%", + :max_backups => "%%LOCAL_MAX_BACKUPS%%", + :dump_suffix => "%%LOCAL_DUMP_SUFFIX%%", # A string to differentiate mysqldumps + } + } +end + +# Additional hook files. + +# // Load (if exists) a file meant to contain your custom hooks for tasks. +if File.exists?("lib/custom-hooks.rb") then + loadFile "lib/custom-hooks.rb" +end +# // Load (if exists) a file meant to contain your custom tasks. +if File.exists?("lib/custom-hooks.rb") then + loadFile "lib/custom-tasks.rb" +end + +# You're not done! You must also configure production.rb, staging.rb and local.rb From 375fc241c2fcd4b1a51d12d1e25d3438791940ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Villarreal?= Date: Tue, 28 Jan 2014 21:05:51 -0200 Subject: [PATCH 22/52] Fixed syntax error. --- wordpress-mu-plugins/stage-wp-plugin.class.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/wordpress-mu-plugins/stage-wp-plugin.class.php b/wordpress-mu-plugins/stage-wp-plugin.class.php index 5c8ff64..f2e7b6a 100644 --- a/wordpress-mu-plugins/stage-wp-plugin.class.php +++ b/wordpress-mu-plugins/stage-wp-plugin.class.php @@ -33,9 +33,9 @@ function hook( $h ) { foreach( ( array )$b as $a ){ if ( is_int( $a ) ) { - $p = $a + $p = $a; } else { - $m = $a + $m = $a; } } From e24757842782ee60429bdc8f430dd59cf64b133a Mon Sep 17 00:00:00 2001 From: andrezrv Date: Thu, 30 Jan 2014 03:28:59 +0000 Subject: [PATCH 23/52] Removed old plugin info. --- wordpress-mu-plugins/stage-wp-cdn.php | 7 ------- 1 file changed, 7 deletions(-) diff --git a/wordpress-mu-plugins/stage-wp-cdn.php b/wordpress-mu-plugins/stage-wp-cdn.php index 241d838..6a0fa50 100644 --- a/wordpress-mu-plugins/stage-wp-cdn.php +++ b/wordpress-mu-plugins/stage-wp-cdn.php @@ -1,11 +1,4 @@ Date: Fri, 31 Jan 2014 01:32:01 +0000 Subject: [PATCH 24/52] Fixed minor bugs. --- config/config-sample-placeholded.rb | 14 +++++++-- config/config-sample.rb | 10 ++++++ config/local-sample.rb | 2 +- config/production-sample.rb | 8 +++-- config/staging-sample.rb | 8 +++-- lib/deploy.rb | 1 + lib/tasks.rb | 48 +++++++++-------------------- 7 files changed, 51 insertions(+), 40 deletions(-) diff --git a/config/config-sample-placeholded.rb b/config/config-sample-placeholded.rb index e197034..0094012 100644 --- a/config/config-sample-placeholded.rb +++ b/config/config-sample-placeholded.rb @@ -19,14 +19,14 @@ # // WordPress Bareboner puts the file in the "app" subfolder, so it needs to # // be "#{release_path}/app", but if you are using WordPress-Skeleton, just # // "#{release_path}" should do the trick and this value should be left empty. -set :application_path, "%%APPLICATION_PATH%%" +set :application_path, "/app" # Where are your shell tasks located within #{release_path}? # // If you're using WordPress Bareboner, the tasks should be by default into # // /app/tasks. If you are using another WordPress starting repo, you should # // adjust this value to your own configuration. However, all tasks related to # // this setting will not be executed if following path does'n t exist. -set :tasks_path, "%%TASKS_PATH%%" +set :tasks_path, "/app/tasks" # Repository settings @@ -61,6 +61,16 @@ # // Path to your local shared folder. set :local_shared_folder, "%%LOCAL_SHARED_FOLDER%%" +# Backup settings + +# // Where do you want to save your application remote backups? +set :production_backup_path, "%%PRODUCTION_BACKUP_PATH%%" +set :staging_backup_path, "%%STAGING_BACKUP_PATH%%" + +# // How many application backups do you want to save? +set :production_max_backups, "3" +set :staging_max_backups, "3" + # WordPress database settings. # # Set the values for host, user, pass, and name for production, staging and diff --git a/config/config-sample.rb b/config/config-sample.rb index 5716c32..104f058 100644 --- a/config/config-sample.rb +++ b/config/config-sample.rb @@ -61,6 +61,16 @@ # // Path to your local shared folder. set :local_shared_folder, "/srv/www/website/application/shared" +# Backup settings + +# // Where do you want to save your application remote backups? +set :production_backup_path, '/srv/www/website/backups/app' +set :staging_backup_path, '/srv/www/website/backups/app' + +# // How many application backups do you want to save? +set :production_max_backups, '3' +set :staging_max_backups, '3' + # WordPress database settings. # # Set the values for host, user, pass, and name for production, staging and diff --git a/config/local-sample.rb b/config/local-sample.rb index b157d78..4cbbd77 100644 --- a/config/local-sample.rb +++ b/config/local-sample.rb @@ -6,4 +6,4 @@ # Customize this file to your own needs and copy it as local.rb. # Where is your local shared folder? -set :shared_folder, :local_shared_folder +set :shared_folder, local_shared_folder diff --git a/config/production-sample.rb b/config/production-sample.rb index 0297607..031107c 100644 --- a/config/production-sample.rb +++ b/config/production-sample.rb @@ -6,14 +6,18 @@ # Customize this file to your own needs and copy it as production.rb. # Where should the site deploy to? -set :deploy_to, :production_deploy_to +set :deploy_to, production_deploy_to + +# Backup settings +set :application_backup_path, production_backup_path +set :application_max_backups, production_max_backups # Now configure the servers for this environment # OPTION 1 # Your web servers IP addresses or hostnamen go here -role :web, :production_domain +role :web, production_domain # role :web, "second web server here" # role :web, "third web server here, etc" diff --git a/config/staging-sample.rb b/config/staging-sample.rb index 72f51dd..0562fbc 100644 --- a/config/staging-sample.rb +++ b/config/staging-sample.rb @@ -6,14 +6,18 @@ # Customize this file to your own needs and copy it as staging.rb. # Where should the site deploy to? -set :deploy_to, :staging_deploy_to +set :deploy_to, staging_deploy_to + +# Backup settings +set :application_backup_path, staging_backup_path +set :application_max_backups, staging_max_backups # Now configure the servers for this environment # OPTION 1 # Your web servers IP addresses or hostnamen go here -role :web, :staging_domain +role :web, staging_domain # role :web, "second web server here" # role :web, "third web server here, etc" diff --git a/lib/deploy.rb b/lib/deploy.rb index 5ef01a9..f725e88 100644 --- a/lib/deploy.rb +++ b/lib/deploy.rb @@ -15,6 +15,7 @@ after "deploy:update_code", "shared:make_symlinks" after "deploy:update_code", "db:make_config" after "deploy:update_code", "util:make_config" +after "util:make_config", "util:make_commands" after "deploy", "memcached:update" # Put some hooks after deploy tasks diff --git a/lib/tasks.rb b/lib/tasks.rb index fdf6bf7..a594b77 100644 --- a/lib/tasks.rb +++ b/lib/tasks.rb @@ -18,10 +18,8 @@ if stage == :local then puts "[Error] You must run shared:pull from staging or production with cap staging shared:pull or cap production shared:pull" else - random = rand(10 ** 5).to_s.rjust(5, '0') current_host = capture("echo $CAPISTRANO:HOST$").strip - run "cd #{shared_path}; sudo zip -r /tmp/#{ramdom}-shared .;" - system "cd #{local_shared_folder}; sudo mkdir #{random}; sudo mkdir ../#{random}; sudo mv * ../#{random}/; sudo scp #{user}@#{current_host}:/tmp/#{ramdom}-shared.zip #{local_shared_folder}; sudo unzip #{ramdom}-shared.zip; sudo rm -rf shared.zip ../#{ramdom};" + system "rsync -avz --delete #{user}@#{current_host}:#{deploy_to}/shared/files/ #{local_shared_folder}/" end end desc "Pushes shared files to remote location" @@ -29,16 +27,8 @@ if stage == :local then puts "[Error] You must run shared:pull from staging or production with cap staging shared:pull or cap production shared:pull" else - random = rand(10 ** 5).to_s.rjust(5, '0') current_host = capture("echo $CAPISTRANO:HOST$").strip - puts "Current user is #{user}" - system "cd #{local_shared_folder}; sudo zip -r /tmp/#{random}-shared .;" - system "sudo scp /tmp/shared.zip #{user}@#{current_host}:#{shared_path}" - run "cd #{shared_path}; sudo mkdir ../#{random};" - run "cd #{shared_path}/../#{random}; sudo unzip /tmp/#{random}-shared.zip;" - run "mv #{shared_path} #{shared_path}-#{random}; mv #{shared_path}/../#{random} #{shared_path}; rm -rf #{shared_path}-#{random}" - run "sudo chown -R #{user}:#{user} #{shared_path}" - system "cd #{local_shared_folder}; sudo rm -f uploads.zip" + system "rsync -avz --delete #{local_shared_folder}/ #{user}@#{current_host}:#{deploy_to}/shared/files/" end end end @@ -138,8 +128,6 @@ random = rand(10 ** 5).to_s.rjust(5, '0') p = wpdb[:production] s = wpdb[:staging] - puts "db:sync" - puts stage run "ssh #{user}@#{production_domain} \"mysqldump -u #{p[:user]} --result-file=/tmp/wpstack-#{random}.sql -h #{p[:host]} -p#{p[:password]} #{p[:name]}\"" run "scp #{user}@#{production_domain}:/tmp/wpstack-#{random}.sql /tmp/" run "mysql -u #{s[:user]} -h #{s[:host]} -p#{s[:password]} #{s[:name]} < /tmp/wpstack-#{random}.sql && rm /tmp/wpstack-#{random}.sql" @@ -154,10 +142,8 @@ random = rand(10 ** 5).to_s.rjust(5, '0') p = wpdb[:production] l = wpdb[:local] - puts "db:sync" - puts stage system "ssh #{user}@#{production_domain} \"mysqldump -u #{p[:user]} --result-file=/tmp/wpstack-#{random}.sql -h #{p[:host]} -p#{p[:password]} #{p[:name]}\"" - system "scp -#{user}@#{production_domain}:/tmp/wpstack-#{random}.sql /tmp/" + system "scp #{user}@#{production_domain}:/tmp/wpstack-#{random}.sql /tmp/" system "mysql -u #{l[:user]} -h #{l[:host]} -p#{l[:password]} #{l[:name]} < /tmp/wpstack-#{random}.sql && rm /tmp/wpstack-#{random}.sql" puts "Database synced to local" # memcached.restart @@ -307,46 +293,42 @@ end namespace :util do - if !File.exists?("#{release_path}#{tasks_path}/config.sh") then - abort("Backup tasks are not configured.") - end desc "Set the database credentials (and other settings) in config.sh" task :make_config do - set :staging_domain, '' unless defined? staging_domain - run "sudo rm -f #{release_path}#{tasks_location}/config.sh" - run "sudo cp #{release_path}#{tasks_location}/config-sample.sh #{release_path}#{tasks_location}/config.sh" + run "sudo rm -f #{release_path}#{tasks_path}/config.sh" + run "sudo cp #{release_path}#{tasks_path}/config-sample.sh #{release_path}#{tasks_path}/config.sh" {:'%%DB_NAME%%' => wpdb[stage][:name], :'%%DB_USER%%' => wpdb[stage][:user], :'%%DB_PASSWORD%%' => wpdb[stage][:password], :'%%DB_BACKUP_PATH%%' => wpdb[stage][:backups_dir], :'%%DB_MAX_BACKUPS%%' => wpdb[stage][:max_backups], - :'%%PROJECT_PATH%%' => release_path, + :'%%PROJECT_PATH%%' => "#{deploy_to}", :'%%USR_BIN_PREFIX%%' => application_id, - :'%%APPLICATION_PATH%%' => application_path, + :'%%APPLICATION_PATH%%' => "#{deploy_to}/current#{application_path}", :'%%APPLICATION_BACKUP_PATH%%' => application_backup_path, :'%%APPLICATION_MAX_BACKUPS%%' => application_max_backups, }.each do |k, v| - run "sed -i 's/#{k}/#{v}/' #{release_path}#{tasks_path}/config.sh", :roles => :web + run "sed -i 's|#{k}|#{v}|' #{release_path}#{tasks_path}/config.sh", :roles => :web end end desc "Add tasks commands to /usr/bin" task :make_commands do - run "sudo bash #{release_path}#{tasks_location}/add-to-bin.sh" + run "sudo bash #{deploy_to}/current#{tasks_path}/add-to-bin.sh" end - desc "Zip and save all application files to #{application_backup_path}" + desc "Zip and save all application files to ${application_backup_path}" task :backup_application do - run "sudo bash #{release_path}#{tasks_location}/website-backup-application.sh" + run "sudo bash #{deploy_to}/current#{tasks_path}/website-backup-application.sh" end - desc "Perform a mysql dump of the WordPress database and save it to #{wpdb[stage][:backups_dir]}" + desc "Perform a mysqldump of the WordPress database and save it to wpdb[stage][:backups_dir]" task :backup_db do - run "sudo bash #{release_path}#{tasks_location}/website-backup-database.sh" + run "sudo bash #{deploy_to}/current#{tasks_path}/website-backup-database.sh" end desc "Switches the state of your site from live to maintenance and vice versa" task :switch do - run "sudo bash #{release_path}#{tasks_location}/website-switch.sh" + run "sudo bash #{deploy_to}/current#{tasks_path}/website-switch.sh" end desc "Perform a full backup (files and database)" task :full_backup do - run "sudo bash #{release_path}#{tasks_location}/website-full-backup.sh" + run "sudo bash #{deploy_to}/current#{tasks_path}/website-full-backup.sh" end end From 0104e77fa730e5fad027211e86ca0ed8052eb83f Mon Sep 17 00:00:00 2001 From: andrezrv Date: Fri, 31 Jan 2014 23:07:15 +0000 Subject: [PATCH 25/52] Tag 1.0 --- Capfile | 2 +- Customfile-sample | 2 +- README.md | 162 ++++++++++++++++++++++++++++++---------------- 3 files changed, 108 insertions(+), 58 deletions(-) diff --git a/Capfile b/Capfile index 5452559..78ca1ab 100644 --- a/Capfile +++ b/Capfile @@ -7,7 +7,7 @@ # the tasks you want to perform on those servers. Here we do somethig different: # we're just gonna use this file to set up the most basic values and load our # required libraries, and will configure the rest of our deployment application -# via config/config.rb and some hook files that we"re gonna call here and there. +# via config/config.rb and some hook files that we're gonna call here and there. # Load required modules. require "rubygems" diff --git a/Customfile-sample b/Customfile-sample index 7be83e3..8a2312b 100644 --- a/Customfile-sample +++ b/Customfile-sample @@ -1,7 +1,7 @@ # Customfile-sample # # This is a sample Customfile. It is meant to be loaded at the end of the -# Capfile. In case you need it, copy it as "Capfile" and customize it as it +# Capfile. In case you need it, copy it as "Customfile" and customize it as it # suits you. # Overridable settings. diff --git a/README.md b/README.md index 903ed6a..c8b4098 100644 --- a/README.md +++ b/README.md @@ -1,96 +1,146 @@ -# WP Stack -A toolkit for creating professional [WordPress][wp] deployments. +# Stage WP -Commissioned by [Knewton](http://www.knewton.com/). +A toolkit for creating professional [WordPress][wp] deployments, forked from Mark Jaquith's [WP-Stack][wpstack]. It uses Capistrano as a code deployment system, and offers a complete set of tasks for you to scale your WordPress project to different servers, both from local and remote environments. -[wp]: http://wordpress.org/ +**Current stable version**: [1.0](https://github.com/andrezrv/stage-wp/tree/1.0) + +## Why do you need this? + +Because WordPress runs professional sites, and you should have a professional deployment tool to go along with it. Stage WP is a toolkit that helps you manage that. -## Why -WordPress runs professional sites. You should have a professional deployment to go along with it. You should be using: +## Getting Started -* Version control (like Git) -* A code deployment system (like Capistrano) -* A staging environment to test changes before they go live -* CDN for static assets +### Assumptions about your workflow + +* You mantain your code under a version control system (like [Git](http://git-scm.com/)). Stage WP works specially well with [WordPress Bareboner][wpbareboner]. +* You develop locally before deploying your code. +* Ideally, you have a staging environment to test changes before they go to production. +* Ideally, you use a CDN for static assets. +* You deploy your code from a local environment. Additionally, you should be able to easily scale out to multiple web servers, if needed. -WP Stack is a toolkit that helps you do all that. +### Capistrano -## WordPress Must-use Plugins +Capistrano is a code deployment tool. When you have code that is ready to go "live", this is what we you're gonna use to do it. -"Must-use" plugins aka `mu-plugins` are WordPress plugins that are dropped into the `{WordPress content dir}/mu-plugins/` directory. They are autoloaded — no need to activate them. WP Stack comes with a number of these plugins for your use: +### Setting Up Your Local System -### CDN +1. Create a `deploy` user on each of your remote web servers (staging and production). This will be the user that is going to perform all the deployment actions on your remote systems. + * `addgroup deploy` + * `adduser --system --shell /bin/bash --ingroup deploy --disabled-password --home /home/deploy deploy` + If you want a user with another name, it must be the same as the one you set for `:user` within `/config/config.rb`. +2. Make sure that `deploy` can pull down your site repo code with `git clone $your_repo` from all your servers. +3. Create (if you don't have one) and upload an SSH key to the list of authorized keys for the `deploy` user in each of your web servers. + * `ssh-keygen` + * `cat ~/.ssh/id_rsa.pub | ssh deploy@$your_server "cat - >> ~/.ssh/authorized_keys"` +3. [Install RubyGems][rubygems]. + * `sudo apt-get install rubygems` +4. Install Capistrano and extras. + * `sudo gem install capistrano -v 2.15.5` + * `sudo gem install capistrano-ext railsless-deploy` -`wp-stack-cdn.php` +### Setting Up Stage WP -This is a very simple CDN plugin. Simply configure the constant `WP_STACK_CDN_DOMAIN` in your `wp-config.php` or hook in and override the `wp_stack_cdn_domain` option. Provide a domain name only, like `static.example.com`. The plugin will look for static file URLs on your domain and repoint them to the CDN domain. +1. Check out Stage WP somewhere on your local system. + * `git clone git@github.com:andrezrv/Stage-WP.git /srv/www/website/stage-wp` +2. Customize and rename `/config/{config|local|production|staging}-sample.rb` +3. Make sure your remote `:production_deploy_to` and `:staging_deploy_to` paths exist and are owned by the deploy user. + * `chown -R deploy:deploy /path/to/your/deployment` +4. Go to your Stage WP directory and run `cap deploy:setup` to setup the initial `shared` and `releases` directories. -### Multisite Uploads +### Deploying -`wp-stack-ms-uploads.php` +1. `cd` to your Stage WP directory. +2. Run `cap production deploy` (to deploy to staging, use `cap staging deploy`). -The way WordPress Multisite serves uploads is not ideal. It streams them through a PHP file. Professional sites should not do this. This plugin allows one nginx rewrite rule to handle all uploads, eliminating the need for PHP streaming. It uses the following URL scheme for uploads: `{scheme}://{domain}/wp-files/{blog_id}/`. By inserting the `$blog_id`, one rewrite rule can make sure file requests go to the correct blog. +### Rolling Back -**Note:** You will need to implement this Nginx rewrite rule for this to work: +If something went wrong with your deployment, you can always go back to the previous version: -`rewrite ^/wp-files/([0-9]+)/(.*)$ /wp-content/blogs.dir/$1/files/$2;` +1. `cd` to your Stage WP directory. +2. Run `cap deploy:rollback` -### Manual DB Upgrades +### About Stages -Normally, WordPress redirects `/wp-admin/` requests to the WordPress database upgrade screen. On large sites, or sites with a lot of active authors, this may not be desired. This drop-in prevents the automatic redirect and instead lets you manually go to `/wp-admin/upgrade.php` to upgrade a site. +There are three "stages": local, production and staging. The first one is your development environment. The other two should be remote systems, and can be completely different servers, or different paths on the same set of servers. -## Capistrano +Stage WP, unlike WP-Stack, is meant to be used from a development environment, performing actions on remote servers from a local system. -Capistrano is a code deployment tool. When you have code that is ready to go "live", this is what does it. +You can still use it in a remote system, like your production or staging servers, but this comes with a trick: if Stage WP is running on staging or production, your local stage will be the same as your remote one. -### Setup +### Database Tasks -1. Create a `deploy` user on your system. In Ubuntu: - * `addgroup deploy` - * `adduser --system --shell /bin/bash --ingroup deploy --disabled-password --home /home/deploy deploy` -2. Create an SSH key for `deploy`, make sure it can SSH to all of your web servers, and make sure it can pull down your site repo code. - * Switch to the deploy user (`su deploy`). - * `ssh-keygen` - * `cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys` - * Add the contents of `~/.ssh/id_rsa.pub` to `~/.ssh/authorized_keys` on every server you're deploying to. -3. [Install RubyGems][rubygems]. -4. Install Capistrano and friends: `sudo gem install capistrano capistrano-ext railsless-deploy` -5. Switch to the deploy user (`su deploy`) and check out WP Stack somewhere on your server: `git clone git@github.com:markjaquith/WP-Stack.git ~/deploy` -6. Customize and rename `config/SAMPLE.{config|production|staging}.rb` -7. Make sure your `:deploy_to` path exists and is owned by the deploy user: `chown -R deploy:deploy /path/to/your/deployment` -8. Run `cap deploy:setup` (from your WP Stack directory) to setup the initial `shared` and `releases` directories. +With Stage WP, you can create your database, backup, restore and move mysqldumps from the local stage to production and staging with the help of the following commands: -[rubygems]: http://rubygems.org/pages/download +* `cap {staging|production} db:init`: Initializes the WordPress database in a remote stage. +* `cap {local|staging} db:sync`: Syncs the local or staging database and uploads from production. +* `cap {local|staging|production} db:backup`: Performs a mysqldump of your WordPress database and saves it within the selected stage. +* `cap {local|staging|production} db:restore`: Restores the WordPress database from a backup stored in the selected stage. +* `cap {staging|production} db:pull`: Downloads a database backup from the selected stage and stores it locally. +* `cap {staging|production} db:push`: Uploads a local database backup to the selected stage. -### Deploying +### Managing Shared Files -1. Switch to the deploy user: `su deploy` -2. `cd` to the WP Stack directory. -3. Run `cap production deploy` (to deploy to staging, use `cap staging deploy`) +You can synchronize your shared files both from local to remote stages and from remote stages to local with the help of the following commands: -### Rolling Back +* `cap {staging|production} shared:pull`: Synchronizes your local shared files from the selected stage. +* `cap {staging|production} shared:push`: Synchronizes your selected stage shared files from local. -1. Switch to the deploy user: `su deploy` -2. `cd` to the WP Stack directory. -3. Run `cap deploy:rollback` +### Full Synchronization -### About Stages +You can synchronize both database and shared files from production to staging or local using `cap {local|staging} db:sync`. + +## WordPress Must Use Plugins + +Must Use plugins are WordPress plugins that usually live into the `mu-plugins` directory. They are autoloaded — no need to activate them. Stage WP comes with a number of these plugins for your use: + +### Stage WP CDN -There are two "stages": production and staging. These can be completely different servers, or different paths on the same set of servers. +This is a very simple CDN plugin. Simply configure the constant `WP_STACK_CDN_DOMAIN` in your `wp-config.php` or hook in and override the `wp_stack_cdn_domain` option. Provide a domain name only, like `static.example.com`. The plugin will look for static file URLs on your domain and repoint them to the CDN domain. Original credits go to [Mark Jaquith][mj]. + +### Stage WP Multisite Uploads + +The way WordPress Multisite serves uploads is not ideal. It streams them through a PHP file. Professional sites should not do this. This plugin allows one NGINX rewrite rule to handle all uploads, eliminating the need for PHP streaming. It uses the following URL scheme for uploads: `{scheme}://{domain}/wp-files/{blog_id}/`. By inserting the `$blog_id`, one rewrite rule can make sure file requests go to the correct blog. Original credits go to [Mark Jaquith][mj]. + +**Note:** You will need to implement this NGINX rewrite rule for this to work: + +`rewrite ^/wp-files/([0-9]+)/(.*)$ /wp-content/blogs.dir/$1/files/$2;` -To sync from production to staging (DB and files), run `cap staging db:sync`. +### Stage WP Manual DB Upgrades + +Normally, WordPress redirects `/wp-admin/` requests to the WordPress database upgrade screen. On large sites, or sites with a lot of active authors, this may not be desired. This drop-in prevents the automatic redirect and instead lets you manually go to `/wp-admin/upgrade.php` to upgrade a site. ## Assumptions made about WordPress -If you're not using [WordPress Skeleton](https://github.com/markjaquith/WordPress-Skeleton), you should be aware of these assumptions: +If you're not using [Wordpress Bareboner][wpbareboner], you should be aware of these assumptions: -1. Your `wp-config.php` file exists in your web root. So put it there. -2. WP Stack replaces the following "stubs": +1. Your application path is defined in `:application_path`, inside `/config/config.rb` +2. Your `wp-config.php` file must exist in the root of your application path. +3. Stage WP replaces the following "stubs": * `%%DB_NAME%%` — Database name. * `%%DB_HOST%%` — Database host. * `%%DB_USER%%` — Database username. * `%%DB_PASSWORD%%` — Database password. * `%%WP_STAGE%%` – will be `production` or `staging` after deploy. -3. WP Stack uses the constants `WP_STAGE` (which should be set to `'%%WP_STAGE%%'`) and `STAGING_DOMAIN`, which should be set to the domain you want to use for staging (something like `staging.example.com`). +4. Stage WP uses the constants `WP_STAGE` (which should be set to `'%%WP_STAGE%%'`) and `STAGING_DOMAIN`, which should be set to the domain you want to use for staging (something like `staging.example.com`). + +## Extending + +You have the following options to add your own functionlity without altering the flow of the repository: + +* Add your custom configurations to `/config/config.rb`, `/config/local-config.rb`, `/config/production-config.rb` and `/config/staging-config.rb`, since they won't be tracked by Git. +* Rename `/Customfile-sample` to `/Customfile`, if you want to hook `/Capfile`. +* Rename `/lib/custom-tasks-sample.rb` to `/lib/custom-tasks.rb`, if you want to add extra tasks. +* Rename `/lib/custom-hooks-sample.rb` to `/lib/custom-hooks.rb`, if you want to add extra hooks. +* Put anything you want into `/custom`. Git won't track those files. + +### Contributing +If you feel like you want to help this project by adding something you think useful, you can make your pull request against the master branch :) + +[wp]: http://wordpress.org/ +[wpstack]: http://github.com/markjaquith/WP-Stack +[wpbareboner]: http://github.com/andrezrv/wordpress-bareboner/ +[mj]: http://github.com/markjaquith +[cap]: https://github.com/capistrano/capistrano +[rubygems]: http://rubygems.org/pages/download From 281cceab9f18ebe26970c74193d736dd68b81234 Mon Sep 17 00:00:00 2001 From: andrezrv Date: Sat, 1 Feb 2014 01:39:06 +0000 Subject: [PATCH 26/52] Updated documentation. --- README.md | 20 ++++++++++++++++++-- lib/tasks.rb | 2 +- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index c8b4098..2cb125a 100644 --- a/README.md +++ b/README.md @@ -40,7 +40,7 @@ Capistrano is a code deployment tool. When you have code that is ready to go "li * `sudo gem install capistrano -v 2.15.5` * `sudo gem install capistrano-ext railsless-deploy` -### Setting Up Stage WP +### Setting Up Stage WP 1. Check out Stage WP somewhere on your local system. * `git clone git@github.com:andrezrv/Stage-WP.git /srv/www/website/stage-wp` @@ -91,6 +91,22 @@ You can synchronize your shared files both from local to remote stages and from You can synchronize both database and shared files from production to staging or local using `cap {local|staging} db:sync`. +### Some Other Useful Tasks + +If you're using [WordPress Bareboner][wpbareboner], you can perform remote backup and maintenance tasks with the following commands: + +* `cap {staging|production} util:backup_application`: Zips and saves all application files to `:application_backup_path`. +* `cap {staging|production} util:backup_db`: Performs a mysqldump of the WordPress database and save it to `:wpdb[stage][:backups_dir]`. +* `cap {staging|production} util:switch`: Switches the state of your site from active to maintenance and vice versa. +* `cap {staging|production} util:full_backup`: Performs a full backup (files and database). + +Yet more useful tasks: + +* `cap {local|staging|production} nginx:restart`: Restarts NGINX. +* `cap {local|staging|production} phpfpm:restart`: Restarts PHP-FPM. +* `cap {local|staging|production} memcached:restart`: Restarts Memcached. +* `cap {local|staging|production} memcached:upload`: Updates the pool of Memcached servers. + ## WordPress Must Use Plugins Must Use plugins are WordPress plugins that usually live into the `mu-plugins` directory. They are autoloaded — no need to activate them. Stage WP comes with a number of these plugins for your use: @@ -111,7 +127,7 @@ The way WordPress Multisite serves uploads is not ideal. It streams them through Normally, WordPress redirects `/wp-admin/` requests to the WordPress database upgrade screen. On large sites, or sites with a lot of active authors, this may not be desired. This drop-in prevents the automatic redirect and instead lets you manually go to `/wp-admin/upgrade.php` to upgrade a site. -## Assumptions made about WordPress +## Assumptions Made About WordPress If you're not using [Wordpress Bareboner][wpbareboner], you should be aware of these assumptions: diff --git a/lib/tasks.rb b/lib/tasks.rb index a594b77..9ef884b 100644 --- a/lib/tasks.rb +++ b/lib/tasks.rb @@ -323,7 +323,7 @@ task :backup_db do run "sudo bash #{deploy_to}/current#{tasks_path}/website-backup-database.sh" end - desc "Switches the state of your site from live to maintenance and vice versa" + desc "Switches the state of your site from active to maintenance and vice versa" task :switch do run "sudo bash #{deploy_to}/current#{tasks_path}/website-switch.sh" end From 4ed4290494cfa097660ee671788e720e80bcb31b Mon Sep 17 00:00:00 2001 From: andrezrv Date: Fri, 31 Jan 2014 22:44:02 -0300 Subject: [PATCH 27/52] Fixed typo. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 2cb125a..7e9a57d 100644 --- a/README.md +++ b/README.md @@ -96,7 +96,7 @@ You can synchronize both database and shared files from production to staging or If you're using [WordPress Bareboner][wpbareboner], you can perform remote backup and maintenance tasks with the following commands: * `cap {staging|production} util:backup_application`: Zips and saves all application files to `:application_backup_path`. -* `cap {staging|production} util:backup_db`: Performs a mysqldump of the WordPress database and save it to `:wpdb[stage][:backups_dir]`. +* `cap {staging|production} util:backup_db`: Performs a mysqldump of the WordPress database and saves it to `:wpdb[stage][:backups_dir]`. * `cap {staging|production} util:switch`: Switches the state of your site from active to maintenance and vice versa. * `cap {staging|production} util:full_backup`: Performs a full backup (files and database). From 6e545488070c962806409ec36c1e5d25c9e92d06 Mon Sep 17 00:00:00 2001 From: andrezrv Date: Mon, 3 Feb 2014 20:08:17 +0000 Subject: [PATCH 28/52] Protocol relative URLs. --- wordpress-mu-plugins/stage-wp-cdn.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/wordpress-mu-plugins/stage-wp-cdn.php b/wordpress-mu-plugins/stage-wp-cdn.php index 6a0fa50..7c59e38 100644 --- a/wordpress-mu-plugins/stage-wp-cdn.php +++ b/wordpress-mu-plugins/stage-wp-cdn.php @@ -22,7 +22,7 @@ * Description: This is a very simple CDN plugin. Simply configure the constant WP_STACK_CDN_DOMAIN in your wp-config.php or hook in and override the wp_stack_cdn_domain option. Provide a domain name only, like static.example.com. The plugin will look for static file URLs on your domain and repoint them to the CDN domain. Original credits go to Mark Jaquith. * Author: Andrés Villarreal * Author URI: http://about.me/andrezrv - * Version: 1.0 + * Version: 1.1 * License: GPL2 */ // Load required class. @@ -95,12 +95,12 @@ public function filter_uploads_only( $content ) { $preg_path = preg_quote( $path, '#' ); // Targeted replace just on uploads URLs - return preg_replace( "#=([\"'])(https?://{$domain})?$preg_path/((?:(?!\\1]).)+)\.(" . implode( '|', $this->extensions ) . ")(\?((?:(?!\\1).)+))?\\1#", '=$1http://' . $this->cdn_domain . $path . '/$3.$4$5$1', $content ); + return preg_replace( "#=([\"'])(https?://{$domain})?$preg_path/((?:(?!\\1]).)+)\.(" . implode( '|', $this->extensions ) . ")(\?((?:(?!\\1).)+))?\\1#", '=$1//' . $this->cdn_domain . $path . '/$3.$4$5$1', $content ); } public function filter( $content ) { - return preg_replace( "#=([\"'])(https?://{$this->site_domain})?/([^/](?:(?!\\1).)+)\.(" . implode( '|', $this->extensions ) . ")(\?((?:(?!\\1).)+))?\\1#", '=$1http://' . $this->cdn_domain . '/$3.$4$5$1', $content ); + return preg_replace( "#=([\"'])(https?://{$this->site_domain})?/([^/](?:(?!\\1).)+)\.(" . implode( '|', $this->extensions ) . ")(\?((?:(?!\\1).)+))?\\1#", '=$1//' . $this->cdn_domain . '/$3.$4$5$1', $content ); } public function template_redirect() { From 1d8d036ae8ac7276928b0c6c7a288131af78fe03 Mon Sep 17 00:00:00 2001 From: andrezrv Date: Mon, 3 Feb 2014 20:08:17 +0000 Subject: [PATCH 29/52] Solved #1. --- wordpress-mu-plugins/stage-wp-cdn.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/wordpress-mu-plugins/stage-wp-cdn.php b/wordpress-mu-plugins/stage-wp-cdn.php index 6a0fa50..7c59e38 100644 --- a/wordpress-mu-plugins/stage-wp-cdn.php +++ b/wordpress-mu-plugins/stage-wp-cdn.php @@ -22,7 +22,7 @@ * Description: This is a very simple CDN plugin. Simply configure the constant WP_STACK_CDN_DOMAIN in your wp-config.php or hook in and override the wp_stack_cdn_domain option. Provide a domain name only, like static.example.com. The plugin will look for static file URLs on your domain and repoint them to the CDN domain. Original credits go to Mark Jaquith. * Author: Andrés Villarreal * Author URI: http://about.me/andrezrv - * Version: 1.0 + * Version: 1.1 * License: GPL2 */ // Load required class. @@ -95,12 +95,12 @@ public function filter_uploads_only( $content ) { $preg_path = preg_quote( $path, '#' ); // Targeted replace just on uploads URLs - return preg_replace( "#=([\"'])(https?://{$domain})?$preg_path/((?:(?!\\1]).)+)\.(" . implode( '|', $this->extensions ) . ")(\?((?:(?!\\1).)+))?\\1#", '=$1http://' . $this->cdn_domain . $path . '/$3.$4$5$1', $content ); + return preg_replace( "#=([\"'])(https?://{$domain})?$preg_path/((?:(?!\\1]).)+)\.(" . implode( '|', $this->extensions ) . ")(\?((?:(?!\\1).)+))?\\1#", '=$1//' . $this->cdn_domain . $path . '/$3.$4$5$1', $content ); } public function filter( $content ) { - return preg_replace( "#=([\"'])(https?://{$this->site_domain})?/([^/](?:(?!\\1).)+)\.(" . implode( '|', $this->extensions ) . ")(\?((?:(?!\\1).)+))?\\1#", '=$1http://' . $this->cdn_domain . '/$3.$4$5$1', $content ); + return preg_replace( "#=([\"'])(https?://{$this->site_domain})?/([^/](?:(?!\\1).)+)\.(" . implode( '|', $this->extensions ) . ")(\?((?:(?!\\1).)+))?\\1#", '=$1//' . $this->cdn_domain . '/$3.$4$5$1', $content ); } public function template_redirect() { From 609fc8a00ee0194e7cdaf108c288c6ef51ea58a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Villarreal?= Date: Tue, 25 Feb 2014 18:51:10 -0200 Subject: [PATCH 30/52] Changed names for constants and options. --- wordpress-mu-plugins/stage-wp-cdn.php | 32 +++++++++++++-------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/wordpress-mu-plugins/stage-wp-cdn.php b/wordpress-mu-plugins/stage-wp-cdn.php index 7c59e38..8092e71 100644 --- a/wordpress-mu-plugins/stage-wp-cdn.php +++ b/wordpress-mu-plugins/stage-wp-cdn.php @@ -3,8 +3,8 @@ * Stage WP CDN * * This is a very simple CDN plugin. Simply configure the constant - * WP_STACK_CDN_DOMAIN in your wp-config.php or hook in and override the - * wp_stack_cdn_domain option. Provide a domain name only, like + * STAGE_WP_CDN_DOMAIN in your wp-config.php or hook in and override the + * stage_wp_cdn_domain option. Provide a domain name only, like * static.example.com. The plugin will look for static file URLs on your domain * and repoint them to the CDN domain. * @@ -19,7 +19,7 @@ * @wordpress-plugin * Plugin name: Stage WP CDN * Plugin URI: http://github.com/andrezrv/stage-wp/ - * Description: This is a very simple CDN plugin. Simply configure the constant WP_STACK_CDN_DOMAIN in your wp-config.php or hook in and override the wp_stack_cdn_domain option. Provide a domain name only, like static.example.com. The plugin will look for static file URLs on your domain and repoint them to the CDN domain. Original credits go to Mark Jaquith. + * Description: This is a very simple CDN plugin. Simply configure the constant STAGE_WP_CDN_DOMAIN in your wp-config.php or hook in and override the stage_wp_cdn_domain option. Provide a domain name only, like static.example.com. The plugin will look for static file URLs on your domain and repoint them to the CDN domain. Original credits go to Mark Jaquith. * Author: Andrés Villarreal * Author URI: http://about.me/andrezrv * Version: 1.1 @@ -53,10 +53,10 @@ public function __construct() { public function plugins_loaded() { - $domain_set_up = get_option( 'wp_stack_cdn_domain' ) || ( defined( 'WP_STACK_CDN_DOMAIN' ) && WP_STACK_CDN_DOMAIN ); + $domain_set_up = get_option( 'stage_wp_cdn_domain' ) || ( defined( 'STAGE_WP_CDN_DOMAIN' ) && STAGE_WP_CDN_DOMAIN ); $production = defined( 'WP_STAGE' ) && WP_STAGE === 'production'; $staging = defined( 'WP_STAGE' ) && WP_STAGE === 'staging'; - $uploads_only = defined( 'WP_STACK_CDN_UPLOADS_ONLY' ) && WP_STACK_CDN_UPLOADS_ONLY; + $uploads_only = defined( 'STAGE_WP_CDN_UPLOADS_ONLY' ) && STAGE_WP_CDN_UPLOADS_ONLY; if ( $domain_set_up && !$staging && ( $production || $uploads_only ) ) { $this->hook( 'init' ); @@ -65,22 +65,22 @@ public function plugins_loaded() { } public function init() { - - $this->uploads_only = apply_filters( 'wp_stack_cdn_uploads_only', defined( 'WP_STACK_CDN_UPLOADS_ONLY' ) ? WP_STACK_CDN_UPLOADS_ONLY : false ); - $this->extensions = apply_filters( 'wp_stack_cdn_extensions', array( 'jpe?g', 'gif', 'png', 'css', 'bmp', 'js', 'ico' ) ); - + + $this->uploads_only = apply_filters( 'stage_wp_cdn_uploads_only', defined( 'STAGE_WP_CDN_UPLOADS_ONLY' ) ? STAGE_WP_CDN_UPLOADS_ONLY : false ); + $this->extensions = apply_filters( 'stage_wp_cdn_extensions', array( 'jpe?g', 'gif', 'png', 'css', 'bmp', 'js', 'ico' ) ); + if ( !is_admin() ) { - + $this->hook( 'template_redirect' ); - + if ( $this->uploads_only ) { - $this->hook( 'wp_stack_cdn_content', 'filter_uploads_only' ); + $this->hook( 'stage_wp_cdn_content', 'filter_uploads_only' ); } else { - $this->hook( 'wp_stack_cdn_content', 'filter' ); + $this->hook( 'stage_wp_cdn_content', 'filter' ); } $this->site_domain = parse_url( get_bloginfo( 'url' ), PHP_URL_HOST ); - $this->cdn_domain = defined( 'WP_STACK_CDN_DOMAIN' ) ? WP_STACK_CDN_DOMAIN : get_option( 'wp_stack_cdn_domain' ); + $this->cdn_domain = defined( 'STAGE_WP_CDN_DOMAIN' ) ? STAGE_WP_CDN_DOMAIN : get_option( 'stage_wp_cdn_domain' ); } @@ -96,7 +96,7 @@ public function filter_uploads_only( $content ) { // Targeted replace just on uploads URLs return preg_replace( "#=([\"'])(https?://{$domain})?$preg_path/((?:(?!\\1]).)+)\.(" . implode( '|', $this->extensions ) . ")(\?((?:(?!\\1).)+))?\\1#", '=$1//' . $this->cdn_domain . $path . '/$3.$4$5$1', $content ); - + } public function filter( $content ) { @@ -108,7 +108,7 @@ public function template_redirect() { } public function ob( $contents ) { - return apply_filters( 'wp_stack_cdn_content', $contents, $this ); + return apply_filters( 'stage_wp_cdn_content', $contents, $this ); } } From 6e6233e6d57e35ecedec5445e2ffd06f7247dc4f Mon Sep 17 00:00:00 2001 From: andrezrv Date: Thu, 27 Feb 2014 18:57:55 +0000 Subject: [PATCH 31/52] Remove unnecessary hooks. --- lib/deploy.rb | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/deploy.rb b/lib/deploy.rb index f725e88..c20047e 100644 --- a/lib/deploy.rb +++ b/lib/deploy.rb @@ -14,8 +14,6 @@ after "deploy:update_code", "shared:make_shared_dir" after "deploy:update_code", "shared:make_symlinks" after "deploy:update_code", "db:make_config" -after "deploy:update_code", "util:make_config" -after "util:make_config", "util:make_commands" after "deploy", "memcached:update" # Put some hooks after deploy tasks From 1f936a99f50c7e479a6b3176e1242dbb495313f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Villarreal?= Date: Thu, 27 Feb 2014 17:39:08 -0300 Subject: [PATCH 32/52] Fix issues when parsing default backup file name. --- lib/tasks.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/tasks.rb b/lib/tasks.rb index 9ef884b..7cd50f5 100644 --- a/lib/tasks.rb +++ b/lib/tasks.rb @@ -211,7 +211,7 @@ # List contents from dumps folder backups = capture("ls -1 #{env[:backups_dir]}").split("\n") # Define default backup - default_backup = backups.last + default_backup = backups.last.scan(/[a-zA-Z0-9_.\-]+/i) puts "Available backups: " puts backups backup = Capistrano::CLI.ui.ask "Which backup would you like to restore? [#{default_backup}] " @@ -240,7 +240,7 @@ # List contents from dumps folder backups = capture("ls -1 #{env[:backups_dir]}").split("\n") # Define default backup - default_backup = backups.last + default_backup = backups.last.scan(/[a-zA-Z0-9_.\-]+/i) puts "Available backups: " puts backups backup = Capistrano::CLI.ui.ask "Which backup would you like to pull? [#{default_backup}] " From 0bebe9603d2a33d7b12b49db3bda2f9a6da212c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Villarreal?= Date: Thu, 6 Mar 2014 02:11:07 -0200 Subject: [PATCH 33/52] Fix for #2. --- lib/tasks.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/tasks.rb b/lib/tasks.rb index 7cd50f5..b915a0d 100644 --- a/lib/tasks.rb +++ b/lib/tasks.rb @@ -28,7 +28,7 @@ puts "[Error] You must run shared:pull from staging or production with cap staging shared:pull or cap production shared:pull" else current_host = capture("echo $CAPISTRANO:HOST$").strip - system "rsync -avz --delete #{local_shared_folder}/ #{user}@#{current_host}:#{deploy_to}/shared/files/" + system "rsync -avz #{local_shared_folder}/ #{user}@#{current_host}:#{deploy_to}/shared/files/" end end end From 1efd758222019ef98414b9010121b044fff45f2f Mon Sep 17 00:00:00 2001 From: andrezrv Date: Wed, 9 Apr 2014 13:06:10 +0000 Subject: [PATCH 34/52] Create symlink for uploads folder. --- lib/tasks.rb | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/lib/tasks.rb b/lib/tasks.rb index b915a0d..127bb03 100644 --- a/lib/tasks.rb +++ b/lib/tasks.rb @@ -1,5 +1,5 @@ # tasks.rb -# +# # This file contains the core tasks for Stage WP. You can override any of these # tasks and add your own into custom-tasks.rb. @@ -8,9 +8,10 @@ task :make_shared_dir do run "if [ ! -d #{shared_path}/files ]; then mkdir #{shared_path}/files; fi" end - desc "Create symlinks to shared folder" + desc "Create symlinks to shared and uploads folder" task :make_symlinks do run "if [ ! -h #{release_path}/shared ]; then ln -s #{shared_path}/files/ #{release_path}/shared; fi" + run "if [ -h #{release_path}#{application_path}/content/uploads ]; then rm #{release_path}#{application_path}/content/uploads; ln -s #{shared_path}/files/content/uploads #{release_path}#{application_path}/content/uploads; fi" run "for p in `find -L #{release_path} -type l`; do t=`readlink $p | grep -o 'shared/.*$'`; sudo mkdir -p #{release_path}/$t; sudo chown www-data:www-data #{release_path}/$t; done" end desc "Pulls shared files from remote location" @@ -44,9 +45,9 @@ desc "Restart PHP-FPM" task :restart do begin # For non-Ubuntu systems - run "sudo /etc/init.d/php-fpm restart" + run "sudo /etc/init.d/php-fpm restart" rescue Exception => e # For Ubuntu systems - run "sudo /etc/init.d/php5-fpm restart" + run "sudo /etc/init.d/php5-fpm restart" end end end @@ -91,7 +92,7 @@ # Initialize output output = "" # Check if database already exists - run "mysql -u #{admin_name} -p -e \"#{show}\"" do |channel, stream, data| + run "mysql -u #{admin_name} -p -e \"#{show}\"" do |channel, stream, data| if data =~ /^Enter password: / # Securely pass admin password channel.send_data "#{admin_password}\n" @@ -103,7 +104,7 @@ else # In case database does not exist ... output = "" # Try to create database - run "mysql -u #{admin_name} -p -e \"#{create} #{grant} #{show}\"" do |channel, stream, data| + run "mysql -u #{admin_name} -p -e \"#{create} #{grant} #{show}\"" do |channel, stream, data| if data =~ /^Enter password: / # Securely pass admin password channel.send_data "#{admin_password}\n" @@ -175,7 +176,7 @@ # Create folder for dumps, in case that it doesn't exist run "mkdir -p #{s[:backups_dir]}" begin - run "mysqldump -u #{s[:user]} -p #{s[:name]} > #{filename}" do |channel, stream, data| + run "mysqldump -u #{s[:user]} -p #{s[:name]} > #{filename}" do |channel, stream, data| if data =~ /^Enter password: / channel.send_data "#{s[:password]}\n" end @@ -218,7 +219,7 @@ backup_file = default_backup if backup.empty? backup_file = "#{env[:backups_dir]}/#{backup_file}" begin - run "mysql -u #{env[:user]} -p#{env[:password]} #{env[:name]} < #{backup_file}" do |channel, stream, data| + run "mysql -u #{env[:user]} -p#{env[:password]} #{env[:name]} < #{backup_file}" do |channel, stream, data| if data =~ /^Enter password: / channel.send_data "#{p[:password]}\n" end From 55b592fec9380cc764eb9d85c33b48c4400698f9 Mon Sep 17 00:00:00 2001 From: andrezrv Date: Wed, 9 Apr 2014 13:06:56 +0000 Subject: [PATCH 35/52] Exclude vvv folder from deploy. --- lib/deploy.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/deploy.rb b/lib/deploy.rb index c20047e..e11f1e9 100644 --- a/lib/deploy.rb +++ b/lib/deploy.rb @@ -1,12 +1,12 @@ # deploy.rb -# +# # This file includes default settings and hooks for the deployment process. # Set some default values set :user, "deploy" set :use_sudo, false set :deploy_via, :remote_cache -set :copy_exclude, [".git", ".gitmodules", ".DS_Store", ".gitignore"] +set :copy_exclude, [".git", ".gitmodules", ".DS_Store", ".gitignore", "vvv"] set :keep_releases, 5 # Put some hooks before deploy tasks From 9459f5e36e43c5282c0f1f4d83a4e27fb474e0bd Mon Sep 17 00:00:00 2001 From: andrezrv Date: Wed, 9 Apr 2014 10:26:56 -0300 Subject: [PATCH 36/52] Remove utils. --- config/config-sample-placeholded.rb | 31 +++------------------- config/config-sample.rb | 31 +++------------------- config/production-sample.rb | 4 --- config/staging-sample.rb | 4 --- lib/tasks.rb | 41 ----------------------------- 5 files changed, 8 insertions(+), 103 deletions(-) diff --git a/config/config-sample-placeholded.rb b/config/config-sample-placeholded.rb index 0094012..75b27c8 100644 --- a/config/config-sample-placeholded.rb +++ b/config/config-sample-placeholded.rb @@ -21,13 +21,6 @@ # // "#{release_path}" should do the trick and this value should be left empty. set :application_path, "/app" -# Where are your shell tasks located within #{release_path}? -# // If you're using WordPress Bareboner, the tasks should be by default into -# // /app/tasks. If you are using another WordPress starting repo, you should -# // adjust this value to your own configuration. However, all tasks related to -# // this setting will not be executed if following path does'n t exist. -set :tasks_path, "/app/tasks" - # Repository settings # // Location of your remote repository. @@ -61,19 +54,9 @@ # // Path to your local shared folder. set :local_shared_folder, "%%LOCAL_SHARED_FOLDER%%" -# Backup settings - -# // Where do you want to save your application remote backups? -set :production_backup_path, "%%PRODUCTION_BACKUP_PATH%%" -set :staging_backup_path, "%%STAGING_BACKUP_PATH%%" - -# // How many application backups do you want to save? -set :production_max_backups, "3" -set :staging_max_backups, "3" - # WordPress database settings. # -# Set the values for host, user, pass, and name for production, staging and +# Set the values for host, user, pass, and name for production, staging and # local stages. You can also specify a backup directory where your mysqldumps # should be saved. Note that placeholders like %%DB_NAME%% and %%DB_PASSWORD%% # in your wp-config.php file will be automatically replaced when `cap deploy` is @@ -85,27 +68,21 @@ :user => "%%PRODUCTION_USER%%", :password => "%%PRODUCTION_PASSWORD%%", :name => "%%PRODUCTION_DB%%", - :backups_dir => "%%PRODUCTION_BACKUPS_DIR%%", - :max_backups => "%%PRODUCTION_MAX_BACKUPS%%", - :dump_suffix => "%%PRODUCTION_DUMP_SUFFIX%%", # A string to differentiate mysqldumps + :dump_suffix => "%%PRODUCTION_DUMP_SUFFIX%%", # A string to differentiate mysqldumps }, :staging => { :host => "%%STAGING_HOST%%", :user => "%%STAGING_USER%%", :password => "%%STAGING_PASSWORD%%", :name => "%%STAGING_DB%%", - :backups_dir => "%%STAGING_BACKUPS_DIR%%", - :max_backups => "%%STAGING_MAX_BACKUPS%%", - :dump_suffix => "%%STAGING_DUMP_SUFFIX%%", # A string to differentiate mysqldumps + :dump_suffix => "%%STAGING_DUMP_SUFFIX%%", # A string to differentiate mysqldumps }, :local => { :host => "%%LOCAL_HOST%%", :user => "%%LOCAL_USER%%", :password => "%%LOCAL_PASSWORD%%", :name => "%%LOCAL_DB%%", - :backups_dir => "%%LOCAL_BACKUPS_DIR%%", - :max_backups => "%%LOCAL_MAX_BACKUPS%%", - :dump_suffix => "%%LOCAL_DUMP_SUFFIX%%", # A string to differentiate mysqldumps + :dump_suffix => "%%LOCAL_DUMP_SUFFIX%%", # A string to differentiate mysqldumps } } end diff --git a/config/config-sample.rb b/config/config-sample.rb index 104f058..a127993 100644 --- a/config/config-sample.rb +++ b/config/config-sample.rb @@ -21,13 +21,6 @@ # // "#{release_path}" should do the trick and this value should be left empty. set :application_path, "/app" -# Where are your shell tasks located within #{release_path}? -# // If you're using WordPress Bareboner, the tasks should be by default into -# // /app/tasks. If you are using another WordPress starting repo, you should -# // adjust this value to your own configuration. However, all tasks related to -# // this setting will not be executed if following path does'n t exist. -set :tasks_path, "/app/tasks" - # Repository settings # // Location of your remote repository. @@ -61,19 +54,9 @@ # // Path to your local shared folder. set :local_shared_folder, "/srv/www/website/application/shared" -# Backup settings - -# // Where do you want to save your application remote backups? -set :production_backup_path, '/srv/www/website/backups/app' -set :staging_backup_path, '/srv/www/website/backups/app' - -# // How many application backups do you want to save? -set :production_max_backups, '3' -set :staging_max_backups, '3' - # WordPress database settings. # -# Set the values for host, user, pass, and name for production, staging and +# Set the values for host, user, pass, and name for production, staging and # local stages. You can also specify a backup directory where your mysqldumps # should be saved. Note that placeholders like %%DB_NAME%% and %%DB_PASSWORD%% # in your wp-config.php file will be automatically replaced when `cap deploy` is @@ -85,27 +68,21 @@ :user => "root", :password => "root", :name => "production_db", - :backups_dir => "/srv/www/website/backups/dumps", - :max_backups => "3", - :dump_suffix => "production", # A string to differentiate mysqldumps + :dump_suffix => "production", # A string to differentiate mysqldumps }, :staging => { :host => "localhost", :user => "root", :password => "root", :name => "staging_db", - :backups_dir => "/srv/www/website/backups/dumps", - :max_backups => "3", - :dump_suffix => "staging", # A string to differentiate mysqldumps + :dump_suffix => "staging", # A string to differentiate mysqldumps }, :local => { :host => "localhost", :user => "root", :password => "root", :name => "local_db", - :backups_dir => "/srv/www/website/backups/dumps", - :max_backups => "3", - :dump_suffix => "local", # A string to differentiate mysqldumps + :dump_suffix => "local", # A string to differentiate mysqldumps } } end diff --git a/config/production-sample.rb b/config/production-sample.rb index 031107c..e8ded66 100644 --- a/config/production-sample.rb +++ b/config/production-sample.rb @@ -8,10 +8,6 @@ # Where should the site deploy to? set :deploy_to, production_deploy_to -# Backup settings -set :application_backup_path, production_backup_path -set :application_max_backups, production_max_backups - # Now configure the servers for this environment # OPTION 1 diff --git a/config/staging-sample.rb b/config/staging-sample.rb index 0562fbc..0061af3 100644 --- a/config/staging-sample.rb +++ b/config/staging-sample.rb @@ -8,10 +8,6 @@ # Where should the site deploy to? set :deploy_to, staging_deploy_to -# Backup settings -set :application_backup_path, staging_backup_path -set :application_max_backups, staging_max_backups - # Now configure the servers for this environment # OPTION 1 diff --git a/lib/tasks.rb b/lib/tasks.rb index 127bb03..f138204 100644 --- a/lib/tasks.rb +++ b/lib/tasks.rb @@ -292,44 +292,3 @@ end end end - -namespace :util do - desc "Set the database credentials (and other settings) in config.sh" - task :make_config do - run "sudo rm -f #{release_path}#{tasks_path}/config.sh" - run "sudo cp #{release_path}#{tasks_path}/config-sample.sh #{release_path}#{tasks_path}/config.sh" - {:'%%DB_NAME%%' => wpdb[stage][:name], - :'%%DB_USER%%' => wpdb[stage][:user], - :'%%DB_PASSWORD%%' => wpdb[stage][:password], - :'%%DB_BACKUP_PATH%%' => wpdb[stage][:backups_dir], - :'%%DB_MAX_BACKUPS%%' => wpdb[stage][:max_backups], - :'%%PROJECT_PATH%%' => "#{deploy_to}", - :'%%USR_BIN_PREFIX%%' => application_id, - :'%%APPLICATION_PATH%%' => "#{deploy_to}/current#{application_path}", - :'%%APPLICATION_BACKUP_PATH%%' => application_backup_path, - :'%%APPLICATION_MAX_BACKUPS%%' => application_max_backups, - }.each do |k, v| - run "sed -i 's|#{k}|#{v}|' #{release_path}#{tasks_path}/config.sh", :roles => :web - end - end - desc "Add tasks commands to /usr/bin" - task :make_commands do - run "sudo bash #{deploy_to}/current#{tasks_path}/add-to-bin.sh" - end - desc "Zip and save all application files to ${application_backup_path}" - task :backup_application do - run "sudo bash #{deploy_to}/current#{tasks_path}/website-backup-application.sh" - end - desc "Perform a mysqldump of the WordPress database and save it to wpdb[stage][:backups_dir]" - task :backup_db do - run "sudo bash #{deploy_to}/current#{tasks_path}/website-backup-database.sh" - end - desc "Switches the state of your site from active to maintenance and vice versa" - task :switch do - run "sudo bash #{deploy_to}/current#{tasks_path}/website-switch.sh" - end - desc "Perform a full backup (files and database)" - task :full_backup do - run "sudo bash #{deploy_to}/current#{tasks_path}/website-full-backup.sh" - end -end From 6d685ae5ecb02691dbfb3e7c1a53d8b0359312ad Mon Sep 17 00:00:00 2001 From: andrezrv Date: Thu, 10 Apr 2014 13:06:05 -0300 Subject: [PATCH 37/52] Rollback for MySQL backups. --- config/config-sample-placeholded.rb | 130 ++++++++++++++++++++++++++++ config/config-sample.rb | 6 ++ 2 files changed, 136 insertions(+) diff --git a/config/config-sample-placeholded.rb b/config/config-sample-placeholded.rb index 75b27c8..4f84a83 100644 --- a/config/config-sample-placeholded.rb +++ b/config/config-sample-placeholded.rb @@ -54,6 +54,130 @@ # // Path to your local shared folder. set :local_shared_folder, "%%LOCAL_SHARED_FOLDER%%" +# WordPress database settings. +# +# Set the values for host, user, pass, and name for production, staging and +# local stages. You can also specify a backup directory where your mysqldumps +# should be saved. Note that placeholders like %%DB_NAME%% and %%DB_PASSWORD%% +# in your wp-config.php file will be automatically replaced when `cap deploy` is +# executed, so you only have to configure these values here. + +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +# Stage WP configuration file. +# +# This is a sample config file. It manages settings for your remote repository, +# your default domains and your database values. Copy it to config.rb and +# customize it to your own needs. + + +# Application settings. + +# // The name of your application. It can be any string. +set :application, "%%APPLICATION%%" + +# // A shortname to identify your application. +set :application_id, "%%APPLICATION_ID%%" + +# Where is your wp-config.php file located within #{release_path}? +# // Your release path points to the newer copy of your repository, so you must +# // specify where your wp-config.php file is located within your remore repo. +# // WordPress Bareboner puts the file in the "app" subfolder, so it needs to +# // be "#{release_path}/app", but if you are using WordPress-Skeleton, just +# // "#{release_path}" should do the trick and this value should be left empty. +set :application_path, "/app" + +# Where are your shell tasks located within #{release_path}? +# // If you're using WordPress Bareboner, the tasks should be by default into +# // /app/tasks. If you are using another WordPress starting repo, you should +# // adjust this value to your own configuration. However, all tasks related to +# // this setting will not be executed if following path does'n t exist. +set :tasks_path, "/app/tasks" + +# Repository settings + +# // Location of your remote repository. +set :repository, "%%REPOSITORY%%" + +# // Your preferred method for source control. Supports :accurev, :bzr, :cvs, +# // :darcs, :git, :mercurial, :perforce, :subversion or :none. +set :scm, :git + +# // Using Git submodules? +set :git_enable_submodules, 1 + +# Default deploy directories. + +# // :deploy_to in production.rb will use this value as default +set :production_deploy_to, "%%PRODUCTION_DEPLOY_TO%%" + +# // :deploy_to in staging.rb will use this value as default +set :staging_deploy_to, "%%STAGING_DEPLOY_TO%%" + +# Default domains. + +# // :deploy_to in production.rb will use this value as default +set :production_domain, "%%PRODUCTION_DOMAIN%%" + +# // :deploy_to in staging.rb will use this value as default +set :staging_domain, "%%STAGING_DOMAIN%%" + +# Local stage default settings. + +# // Path to your local shared folder. +set :local_shared_folder, "%%LOCAL_SHARED_FOLDER%%" + +# Backup settings + +# // Where do you want to save your application remote backups? +set :production_backup_path, "%%PRODUCTION_BACKUP_PATH%%" +set :staging_backup_path, "%%STAGING_BACKUP_PATH%%" + +# // How many application backups do you want to save? +set :production_max_backups, "3" +set :staging_max_backups, "3" + # WordPress database settings. # # Set the values for host, user, pass, and name for production, staging and @@ -68,6 +192,8 @@ :user => "%%PRODUCTION_USER%%", :password => "%%PRODUCTION_PASSWORD%%", :name => "%%PRODUCTION_DB%%", + :backups_dir => "%%PRODUCTION_BACKUPS_DIR%%", + :max_backups => "%%PRODUCTION_MAX_BACKUPS%%", :dump_suffix => "%%PRODUCTION_DUMP_SUFFIX%%", # A string to differentiate mysqldumps }, :staging => { @@ -75,6 +201,8 @@ :user => "%%STAGING_USER%%", :password => "%%STAGING_PASSWORD%%", :name => "%%STAGING_DB%%", + :backups_dir => "%%STAGING_BACKUPS_DIR%%", + :max_backups => "%%STAGING_MAX_BACKUPS%%", :dump_suffix => "%%STAGING_DUMP_SUFFIX%%", # A string to differentiate mysqldumps }, :local => { @@ -82,6 +210,8 @@ :user => "%%LOCAL_USER%%", :password => "%%LOCAL_PASSWORD%%", :name => "%%LOCAL_DB%%", + :backups_dir => "%%LOCAL_BACKUPS_DIR%%", + :max_backups => "%%LOCAL_MAX_BACKUPS%%", :dump_suffix => "%%LOCAL_DUMP_SUFFIX%%", # A string to differentiate mysqldumps } } diff --git a/config/config-sample.rb b/config/config-sample.rb index a127993..68cd1a7 100644 --- a/config/config-sample.rb +++ b/config/config-sample.rb @@ -68,6 +68,8 @@ :user => "root", :password => "root", :name => "production_db", + :backups_dir => "/srv/www/website/backups/dumps", + :max_backups => "3", :dump_suffix => "production", # A string to differentiate mysqldumps }, :staging => { @@ -75,6 +77,8 @@ :user => "root", :password => "root", :name => "staging_db", + :backups_dir => "/srv/www/website/backups/dumps", + :max_backups => "3", :dump_suffix => "staging", # A string to differentiate mysqldumps }, :local => { @@ -82,6 +86,8 @@ :user => "root", :password => "root", :name => "local_db", + :backups_dir => "/srv/www/website/backups/dumps", + :max_backups => "3", :dump_suffix => "local", # A string to differentiate mysqldumps } } From ba9e34df74b2468fd950b4557c66635c393ad6d2 Mon Sep 17 00:00:00 2001 From: andrezrv Date: Thu, 10 Apr 2014 13:55:14 -0300 Subject: [PATCH 38/52] Ignore shared folder. --- lib/deploy.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/deploy.rb b/lib/deploy.rb index e11f1e9..84e1526 100644 --- a/lib/deploy.rb +++ b/lib/deploy.rb @@ -6,7 +6,7 @@ set :user, "deploy" set :use_sudo, false set :deploy_via, :remote_cache -set :copy_exclude, [".git", ".gitmodules", ".DS_Store", ".gitignore", "vvv"] +set :copy_exclude, [".git", ".gitmodules", ".DS_Store", ".gitignore", "shared", "vvv"] set :keep_releases, 5 # Put some hooks before deploy tasks From 3e4257dcc2062a2b3d77af4d14e1859bffee4131 Mon Sep 17 00:00:00 2001 From: andrezrv Date: Thu, 10 Apr 2014 13:55:42 -0300 Subject: [PATCH 39/52] Improve sync tasks. --- lib/tasks.rb | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/lib/tasks.rb b/lib/tasks.rb index f138204..f3e0482 100644 --- a/lib/tasks.rb +++ b/lib/tasks.rb @@ -8,10 +8,9 @@ task :make_shared_dir do run "if [ ! -d #{shared_path}/files ]; then mkdir #{shared_path}/files; fi" end - desc "Create symlinks to shared and uploads folder" + desc "Create symlink to shared folder" task :make_symlinks do - run "if [ ! -h #{release_path}/shared ]; then ln -s #{shared_path}/files/ #{release_path}/shared; fi" - run "if [ -h #{release_path}#{application_path}/content/uploads ]; then rm #{release_path}#{application_path}/content/uploads; ln -s #{shared_path}/files/content/uploads #{release_path}#{application_path}/content/uploads; fi" + run "if [ ! -h #{release_path}/shared ]; then ln -s #{shared_path} #{release_path}/shared; fi" run "for p in `find -L #{release_path} -type l`; do t=`readlink $p | grep -o 'shared/.*$'`; sudo mkdir -p #{release_path}/$t; sudo chown www-data:www-data #{release_path}/$t; done" end desc "Pulls shared files from remote location" @@ -20,7 +19,7 @@ puts "[Error] You must run shared:pull from staging or production with cap staging shared:pull or cap production shared:pull" else current_host = capture("echo $CAPISTRANO:HOST$").strip - system "rsync -avz --delete #{user}@#{current_host}:#{deploy_to}/shared/files/ #{local_shared_folder}/" + system "rsync -avz --delete #{user}@#{current_host}:#{shared_path}/files/ #{local_shared_folder}/files/" end end desc "Pushes shared files to remote location" @@ -29,7 +28,7 @@ puts "[Error] You must run shared:pull from staging or production with cap staging shared:pull or cap production shared:pull" else current_host = capture("echo $CAPISTRANO:HOST$").strip - system "rsync -avz #{local_shared_folder}/ #{user}@#{current_host}:#{deploy_to}/shared/files/" + system "rsync -avz #{local_shared_folder}/files/ #{user}@#{current_host}:#{shared_path}/shared/files/" end end end From fba8fcec9b139249a92ee79e9523418676f40dab Mon Sep 17 00:00:00 2001 From: andrezrv Date: Sat, 24 May 2014 15:48:48 -0300 Subject: [PATCH 40/52] Close #4. --- vvv/vvv-init.sh | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 vvv/vvv-init.sh diff --git a/vvv/vvv-init.sh b/vvv/vvv-init.sh new file mode 100644 index 0000000..80a8278 --- /dev/null +++ b/vvv/vvv-init.sh @@ -0,0 +1,46 @@ +#!/bin/bash +# +# vvv-init.sh +# +# This file will install Capistrano in VVV virtual machines. + +# Capture a basic ping result to Google's primary DNS server to determine if +# outside access is available to us. If this does not reply after 2 attempts, +# we try one of Level3's DNS servers as well. If neither IP replies to a ping, +# then we'll skip a few things further in provisioning rather than creating a +# bunch of errors. +echo -e "\nStarting Capistrano installation process..." +ping_result="$(ping -c 2 8.8.4.4 2>&1)" +if [[ $ping_result != *bytes?from* ]]; then + ping_result="$(ping -c 2 4.2.2.2 2>&1)" +fi + +if [[ $ping_result == *bytes?from* ]]; then + + # rubygems install, required by Capistrano + if [[ ! -d /opt/vagrant_ruby/lib/ruby/gems ]]; then + sudo apt-get install rubygems + # Clean up apt caches + apt-get clean + else + echo " * rubygems is already installed." + fi + + # Capistrano install + if [[ -d /opt/vagrant_ruby/lib/ruby/gems ]]; then + if [[ ! -d /var/lib/gems/1.8/gems/capistrano-2.15.5/lib/capistrano ]]; then + # We're specifying an older Capistrano version, because recent versions + # may cause errors running some cap commands. + sudo gem install capistrano -v 2.15.5 + # Install Capistrano friends + sudo gem install capistrano-ext railsless-deploy + else + echo " * Capistrano is already installed." + fi + else + echo -e " * Capistrano requires rubygems to work." + fi + +else + echo -e "\nNo network connection available, skipping package installation" +fi From 470c8f93e92b12ceed93e18f6b2416bbb8d26a18 Mon Sep 17 00:00:00 2001 From: andrezrv Date: Sat, 24 May 2014 16:05:49 -0300 Subject: [PATCH 41/52] Close #3. --- .gitmodules | 3 ++ wordpress-mu-plugins/stage-wp-plugin-manager | 1 + .../stage-wp-plugin-manager.php | 30 +++++++++++++++++++ 3 files changed, 34 insertions(+) create mode 100644 .gitmodules create mode 160000 wordpress-mu-plugins/stage-wp-plugin-manager create mode 100644 wordpress-mu-plugins/stage-wp-plugin-manager.php diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..751b424 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "wordpress-mu-plugins/stage-wp-plugin-manager"] + path = wordpress-mu-plugins/stage-wp-plugin-manager + url = git@github.com:andrezrv/stage-wp-plugin-manager.git diff --git a/wordpress-mu-plugins/stage-wp-plugin-manager b/wordpress-mu-plugins/stage-wp-plugin-manager new file mode 160000 index 0000000..cb80cd1 --- /dev/null +++ b/wordpress-mu-plugins/stage-wp-plugin-manager @@ -0,0 +1 @@ +Subproject commit cb80cd1edb9e8aeb51ef3b9b98a391d7a22d9729 diff --git a/wordpress-mu-plugins/stage-wp-plugin-manager.php b/wordpress-mu-plugins/stage-wp-plugin-manager.php new file mode 100644 index 0000000..36ccf3e --- /dev/null +++ b/wordpress-mu-plugins/stage-wp-plugin-manager.php @@ -0,0 +1,30 @@ + + * @license GPL-2.0 + * @link http://github.com/andrezrv/stage-wp-plugin-manager + * @copyright 2014 Andrés Villarreal + * + * @wordpress-plugin + * Plugin Name: Stage WP Plugin Manager + * Plugin URI: http://wordpress.org/extend/plugins/stage-wp-plugin-manager/ + * Description: Gives you the option to define which plugins must be active for a particular stage only. You can activate plugins separatedly for local, staging and production stages. To use this plugin, you need to add a constant named WP_ENV_PLUGINS to your wp-config.php file, with one of the following values: local, staging, production. This plugin supports WordPress Multisite, and can manage network activated plugins. + * Author: Andrés Villarreal + * Author URI: http://www.andrezrv.com + * Version: 1.0 + */ +require dirname( __FILE__ ) . '/stage-wp-plugin-manager/stage-wp-plugin-manager.php'; From 362502df99a2abc1daa38e436a2bc9715ceb7ccb Mon Sep 17 00:00:00 2001 From: andrezrv Date: Sat, 24 May 2014 16:07:56 -0300 Subject: [PATCH 42/52] Update version notice. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 7e9a57d..05dd7eb 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ A toolkit for creating professional [WordPress][wp] deployments, forked from Mark Jaquith's [WP-Stack][wpstack]. It uses Capistrano as a code deployment system, and offers a complete set of tasks for you to scale your WordPress project to different servers, both from local and remote environments. -**Current stable version**: [1.0](https://github.com/andrezrv/stage-wp/tree/1.0) +**Current stable version**: [1.1](https://github.com/andrezrv/stage-wp/tree/1.1) ## Why do you need this? From 33c3f550af07225233a86cca55a052bdd4246d44 Mon Sep 17 00:00:00 2001 From: andrezrv Date: Sat, 24 May 2014 16:08:09 -0300 Subject: [PATCH 43/52] Tag 1.1. From fac6e255f306e4afc41be7286e8cff6354dadb44 Mon Sep 17 00:00:00 2001 From: andrezrv Date: Sun, 9 Nov 2014 19:32:13 -0300 Subject: [PATCH 44/52] Update Capistrano installation for VVV. --- vvv/vvv-init.sh | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/vvv/vvv-init.sh b/vvv/vvv-init.sh index 80a8278..77732c1 100644 --- a/vvv/vvv-init.sh +++ b/vvv/vvv-init.sh @@ -16,29 +16,27 @@ if [[ $ping_result != *bytes?from* ]]; then fi if [[ $ping_result == *bytes?from* ]]; then + gem_exists="$(which gem)" # check if rubygems is installed + cap_exists="$(which cap)" # check if capistrano is installed - # rubygems install, required by Capistrano - if [[ ! -d /opt/vagrant_ruby/lib/ruby/gems ]]; then - sudo apt-get install rubygems + # ruby install, required by Capistrano + if [[ ! $gem_exists ]]; then + sudo apt-get -y install ruby # Clean up apt caches - apt-get clean + sudo apt-get clean else - echo " * rubygems is already installed." + echo " * ruby is already installed." fi # Capistrano install - if [[ -d /opt/vagrant_ruby/lib/ruby/gems ]]; then - if [[ ! -d /var/lib/gems/1.8/gems/capistrano-2.15.5/lib/capistrano ]]; then - # We're specifying an older Capistrano version, because recent versions - # may cause errors running some cap commands. - sudo gem install capistrano -v 2.15.5 - # Install Capistrano friends - sudo gem install capistrano-ext railsless-deploy - else - echo " * Capistrano is already installed." - fi + if [[ ! $cap_exists ]]; then + # We're specifying an older Capistrano version, because recent versions + # may cause errors running some cap commands. + sudo gem install capistrano -v 2.15.5 + # Install Capistrano friends + sudo gem install capistrano-ext railsless-deploy else - echo -e " * Capistrano requires rubygems to work." + echo " * Capistrano is already installed." fi else From 488d11e5fd82c612d354ac608523b2027c57dae4 Mon Sep 17 00:00:00 2001 From: andrezrv Date: Sun, 9 Nov 2014 19:37:21 -0300 Subject: [PATCH 45/52] Update documentation about Capistrano and Ruby installation. --- README.md | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 05dd7eb..9cde6a4 100644 --- a/README.md +++ b/README.md @@ -34,12 +34,14 @@ Capistrano is a code deployment tool. When you have code that is ready to go "li 3. Create (if you don't have one) and upload an SSH key to the list of authorized keys for the `deploy` user in each of your web servers. * `ssh-keygen` * `cat ~/.ssh/id_rsa.pub | ssh deploy@$your_server "cat - >> ~/.ssh/authorized_keys"` -3. [Install RubyGems][rubygems]. - * `sudo apt-get install rubygems` +3. [Install Ruby][ruby]. + * `sudo apt-get install ruby` 4. Install Capistrano and extras. * `sudo gem install capistrano -v 2.15.5` * `sudo gem install capistrano-ext railsless-deploy` +If you're using [VVV][vvv], steps 3 and 4 will run automatically upon `vagrant up --provision`. + ### Setting Up Stage WP 1. Check out Stage WP somewhere on your local system. @@ -159,4 +161,5 @@ If you feel like you want to help this project by adding something you think use [wpbareboner]: http://github.com/andrezrv/wordpress-bareboner/ [mj]: http://github.com/markjaquith [cap]: https://github.com/capistrano/capistrano -[rubygems]: http://rubygems.org/pages/download +[ruby]: https://www.ruby-lang.org/en/installation/#ruby-install +[vvv]: https://github.com/Varying-Vagrant-Vagrants/VVV From a38a57937d5226e7c81c962091e75d6de2050bdb Mon Sep 17 00:00:00 2001 From: andrezrv Date: Sun, 9 Nov 2014 19:39:31 -0300 Subject: [PATCH 46/52] Close #5. --- lib/tasks.rb | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/tasks.rb b/lib/tasks.rb index f3e0482..87cc59b 100644 --- a/lib/tasks.rb +++ b/lib/tasks.rb @@ -128,9 +128,9 @@ random = rand(10 ** 5).to_s.rjust(5, '0') p = wpdb[:production] s = wpdb[:staging] - run "ssh #{user}@#{production_domain} \"mysqldump -u #{p[:user]} --result-file=/tmp/wpstack-#{random}.sql -h #{p[:host]} -p#{p[:password]} #{p[:name]}\"" - run "scp #{user}@#{production_domain}:/tmp/wpstack-#{random}.sql /tmp/" - run "mysql -u #{s[:user]} -h #{s[:host]} -p#{s[:password]} #{s[:name]} < /tmp/wpstack-#{random}.sql && rm /tmp/wpstack-#{random}.sql" + run "ssh #{user}@#{production_domain} \"mysqldump -u #{p[:user]} --result-file=/tmp/stagewp-#{random}.sql -h #{p[:host]} -p#{p[:password]} #{p[:name]}\"" + run "scp #{user}@#{production_domain}:/tmp/stagewp-#{random}.sql /tmp/" + run "mysql -u #{s[:user]} -h #{s[:host]} -p#{s[:password]} #{s[:name]} < /tmp/stagewp-#{random}.sql && rm /tmp/stagewp-#{random}.sql" puts "Database synced to staging" # Now to copy files find_servers( :roles => :web ).each do |server| @@ -142,9 +142,9 @@ random = rand(10 ** 5).to_s.rjust(5, '0') p = wpdb[:production] l = wpdb[:local] - system "ssh #{user}@#{production_domain} \"mysqldump -u #{p[:user]} --result-file=/tmp/wpstack-#{random}.sql -h #{p[:host]} -p#{p[:password]} #{p[:name]}\"" - system "scp #{user}@#{production_domain}:/tmp/wpstack-#{random}.sql /tmp/" - system "mysql -u #{l[:user]} -h #{l[:host]} -p#{l[:password]} #{l[:name]} < /tmp/wpstack-#{random}.sql && rm /tmp/wpstack-#{random}.sql" + system "ssh #{user}@#{production_domain} \"mysqldump -u #{p[:user]} --result-file=/tmp/stagewp-#{random}.sql -h #{p[:host]} -p#{p[:password]} #{p[:name]}\"" + system "scp #{user}@#{production_domain}:/tmp/stagewp-#{random}.sql /tmp/" + system "mysql -u #{l[:user]} -h #{l[:host]} -p#{l[:password]} #{l[:name]} < /tmp/stagewp-#{random}.sql && rm /tmp/stagewp-#{random}.sql" puts "Database synced to local" # memcached.restart puts "Memcached flushed" From 6e8482d7e5fdaa9f36420c573efd0944158074be Mon Sep 17 00:00:00 2001 From: andrezrv Date: Sun, 9 Nov 2014 19:43:17 -0300 Subject: [PATCH 47/52] Tag 1.1.1. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 9cde6a4..d462528 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ A toolkit for creating professional [WordPress][wp] deployments, forked from Mark Jaquith's [WP-Stack][wpstack]. It uses Capistrano as a code deployment system, and offers a complete set of tasks for you to scale your WordPress project to different servers, both from local and remote environments. -**Current stable version**: [1.1](https://github.com/andrezrv/stage-wp/tree/1.1) +**Current stable version**: [1.1.1](https://github.com/andrezrv/stage-wp/tree/1.1.1) ## Why do you need this? From 86670bb95b3989f818fbd7116812d237baa03629 Mon Sep 17 00:00:00 2001 From: andrezrv Date: Sun, 18 Jan 2015 21:27:00 -0300 Subject: [PATCH 48/52] Add Bitbucket Connector plugin. --- .../stage-wp-bitbucket-connector.php | 399 ++++++++++++++++++ 1 file changed, 399 insertions(+) create mode 100644 wordpress-mu-plugins/stage-wp-bitbucket-connector.php diff --git a/wordpress-mu-plugins/stage-wp-bitbucket-connector.php b/wordpress-mu-plugins/stage-wp-bitbucket-connector.php new file mode 100644 index 0000000..c045e48 --- /dev/null +++ b/wordpress-mu-plugins/stage-wp-bitbucket-connector.php @@ -0,0 +1,399 @@ + + * @license GPL2 + * @link http://github.com/andrezrv/stage-wp-bitbucket-connector/ + * @copyright 2015 Andrés Villarreal + * + * @wordpress-plugin + * Plugin name: Stage WP Bitbucket Connector + * Plugin URI: http://github.com/andrezrv/stage-wp/ + * Description: Connect the current site with Bitbucket through a POST hook and deploy using Stage WP. + * Author: Andrés Villarreal + * Author URI: http://about.me/andrezrv + * Version: 1.0.0 + * License: GPL2 + */ + +if ( ! class_exists( 'Stage_WP_Bitbucket_Connector' ) ) : +/** + * Class Stage_WP_Bitbucket_Connector + * + * Setup connection between this WordPress website and Bitbucket POST hook. + * + * @since 1.0.0 + */ +final class Stage_WP_Bitbucket_Connector { + /** + * Internal options for this class. + * + * @var array|mixed|void + * @since 1.0.0 + */ + private $options = array(); + + /** + * Option ID to retrieve an array of options using the Options API. + * + * @var string + * @since 1.0.0 + */ + private static $options_id = 'stage_wp_bitbucket_connector_options'; + + /** + * ID used to initialize and retrieve results when interacting with the + * Settings API. + * + * @var string + * @since 1.0.0 + */ + private $settings_id = 'stage-wp-bitbucket-connector-settings'; + + /** + * Text domain for this plugin. + * + * @var string + * @since 1.0.0 + */ + private $text_domain = 'stage_wp'; + + /** + * Initialize internal options and plugin hooks. + * + * @since 1.0.0 + */ + private function __construct() { + // Return early if running in AJAX context. + if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) { + return; + } + + // Obtain internal options. + $this->options = self::get_options(); + + // Schedule internal hooks. + $this->setup_hooks(); + } + + /** + * Make sure this class is instantiated only once. + * + * @return Stage_WP_Bitbucket_Connector Self instance of this class. + * @since 1.0 + */ + final public static function get_instance() { + static $instances = array(); + + // PHP >= 5.3 required. + $called_class = get_called_class(); + + if ( ! isset( $instances[$called_class] ) ) { + $instances[$called_class] = new $called_class(); + } + + return $instances[$called_class]; + } + + /** + * Schedule plugin hooks. + * + * @since 1.0.0 + */ + private function setup_hooks() { + // Register a sub-menu page. + add_action( 'admin_menu', array( $this, 'add_submenu_page' ) ); + + // Register plugin settings. + add_action( 'admin_init', array( $this, 'register_settings' ) ); + } + + /** + * Initialize internal options. + * + * @since 1.0.0 + */ + private static function initialize_options() { + $options = array( + 'key' => md5( time() ), + 'log' => '', + 'branch' => 'master', + 'stage_wp_path' => '', + ); + + update_option( self::$options_id, $options ); + } + + /** + * Obtain internal options. + * + * @since 1.0.0 + * @return mixed|void + */ + private static function get_options() { + $options = get_option( self::$options_id ); + + // If we don't have any options, initialize them and get back here again. + if ( ! $options ) { + self::initialize_options(); + $options = self::get_options(); + } + + return $options; + } + + /** + * Perform deployment process. + * + * @since 1.0.0 + */ + public function deploy() { + // Return early if the deployment can't be authorized. + if ( ! $this->allow_deployment() ) { + return; + } + + // Fire deployment process through Stage WP. + $this->prepare_deployment(); + + // Set a message with the date and time of the process. + $message = sprintf( __( 'Deployment performed at %s', $this->text_domain ), date( 'Y-m-d H:i:s' ) ); + + // Log previous message. + $this->log( $message ); + + // Die showing message. + die( $message ); + } + + /** + * Check if the deployment process can be fired. + * + * @since 1.0.0 + * @return bool + */ + private function allow_deployment() { + if ( ! $this->requested_deployment() || ! $this->request_has_valid_key() || ! $this->request_has_valid_branch() ) { + return false; + } + + return true; + } + + /** + * Check if the deployment process was correctly requested. + * + * @since 1.0.0 + * @return bool + */ + private function requested_deployment() { + if ( empty( $_REQUEST['deploy'] ) || 'true' != $_REQUEST['deploy'] ) { + return false; + } + + return true; + } + + /** + * Check if the deployment process was requested using a valid key. + * + * @since 1.0.0 + * @return bool + */ + private function request_has_valid_key() { + if ( empty( $_REQUEST['key'] ) || $this->options['key'] != urldecode( $_REQUEST['key'] ) ) { + return false; + } + + return true; + } + + /** + * Check if at least one of the pushed commits belongs to the deployment branch. + * + * @since 1.0.0 + * @return bool + */ + private function request_has_valid_branch() { + if ( empty( $_REQUEST['payload'] ) ) { + return false; + } + + $payload = json_decode( $_REQUEST['payload'], true ); + + if ( empty( $payload['commits'] ) ) { + return false; + } + + $has_allowed_branch = false; + foreach ( $payload['commits'] as $commit ) { + if ( $this->options['branch'] == $commit['branch'] ) { + $has_allowed_branch = true; + break; + } + } + + return $has_allowed_branch; + } + + private function prepare_deployment() { + // Log received data. + $this->log( 'Preparing deployment with the following data: ' . serialize( $_REQUEST ) ); + + // Construct command to run through Stage WP. + $cmd = 'cd ' . $this->options['stage_wp_path'] . '; cap deploy 2>&1'; + + // Execute command. + exec( $cmd, $output, $return_var ); + + // Log results of deployment process. + $this->log( 'Deployment results: ' . "\n" . implode( "\n", $output ) ); + } + + /** + * Add a submenu page to WP admin. + * + * @since 1.0.0 + */ + public function add_submenu_page() { + // Avoid this function from running inside any other action. + if ( 'admin_menu' != current_action() ) { + return false; + } + + add_submenu_page( + 'options-general.php', + __( 'Stage WP Bitbucket Connector' ), + __( 'Deployment Settings' ), + 'manage_options', + 'stage-wp-bitbucket-connector', + array( $this, 'settings_page' ) + ); + } + + /** + * Output HTML for settings page. + * + * @since 1.0.0 + */ + public function settings_page() { + // Avoid this function from running inside any other action. + if ( 'settings_page_stage-wp-bitbucket-connector' != current_action() ) { + return false; + } + + // Check that the user is allowed to update options. + if ( ! current_user_can( 'manage_options' ) ) { + wp_die( 'You do not have sufficient permissions to access this page.' ); + } + + $options = self::get_options(); + ?> +
+ +

+
+ settings_id ); ?> + settings_id ); ?> + + + + + + + + + + + + + + + + + + +
text_domain ); ?>
text_domain ); ?>
text_domain ); ?>
text_domain ); ?>
+ + +
+
+ settings_id, 'stage_wp_bitbucket_connector_options' ); + } + + /** + * Writes a message to the log file. + * + * @since 1.0.0 + * + * @param string $message The message to write + * @param string $type The type of log message (e.g. INFO, DEBUG, ERROR, etc.) + */ + private function log( $message, $type = 'INFO' ) { + if ( $this->options['log'] ) { + // Set the name of the log file + $filename = $this->options['log']; + + if ( ! file_exists( $filename ) ) { + // Create the log file + file_put_contents( $filename, '' ); + + // Allow anyone to write to log files + chmod( $filename, 0666 ); + } + + // Write the message into the log file + // Format: time --- type: message + file_put_contents( $filename, date( 'Y-m-d H:i:s' ) . ' --- ' . $type . ': ' . $message . PHP_EOL, FILE_APPEND ); + } + } +} +endif; + +if ( ! function_exists( 'stage_wp_bitbucket_connector_init' ) ) : +add_action( 'plugins_loaded', 'stage_wp_bitbucket_connector_init' ); +/** + * Initialize Bitbucket connector and deploy when requested. + * + * @since 1.0.0 + */ +function stage_wp_bitbucket_connector_init() { + // Avoid this function from running inside any other action. + if ( 'plugins_loaded' != current_action() ) { + return false; + } + + global $stage_wp_bitbucket_connector; + + if ( ! $stage_wp_bitbucket_connector ) { + $stage_wp_bitbucket_connector = Stage_WP_Bitbucket_Connector::get_instance(); + + if ( ! empty( $_REQUEST['deploy'] ) ) { + $stage_wp_bitbucket_connector->deploy(); + } + } +} +endif; From 81024161cfb6be84057d65976bcdd9d53bf9d4a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andre=CC=81s=20Villarreal?= Date: Fri, 15 May 2015 02:19:43 -0300 Subject: [PATCH 49/52] Set staging domain correctly when before performing string replacements. --- lib/tasks.rb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/tasks.rb b/lib/tasks.rb index 87cc59b..fb14c16 100644 --- a/lib/tasks.rb +++ b/lib/tasks.rb @@ -279,8 +279,7 @@ end desc "Set the database credentials (and other settings) in wp-config.php" task :make_config do - set :staging_domain, '' unless defined? staging_domain - {:'%%WP_STAGING_DOMAIN%%' => staging_domain, + {:'%%WP_STAGING_DOMAIN%%' => (stage == :production) ? production_domain : staging_domain, :'%%WP_STAGE%%' => stage, :'%%DB_NAME%%' => wpdb[stage][:name], :'%%DB_USER%%' => wpdb[stage][:user], From 10b2c200ddd2b10aba9e5102c886e8b3788ba9e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andre=CC=81s=20Villarreal?= Date: Fri, 15 May 2015 02:24:48 -0300 Subject: [PATCH 50/52] Remove `chown`- Ownership changes should be performed via after-hooks. --- lib/tasks.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/tasks.rb b/lib/tasks.rb index fb14c16..5d3105f 100644 --- a/lib/tasks.rb +++ b/lib/tasks.rb @@ -11,7 +11,7 @@ desc "Create symlink to shared folder" task :make_symlinks do run "if [ ! -h #{release_path}/shared ]; then ln -s #{shared_path} #{release_path}/shared; fi" - run "for p in `find -L #{release_path} -type l`; do t=`readlink $p | grep -o 'shared/.*$'`; sudo mkdir -p #{release_path}/$t; sudo chown www-data:www-data #{release_path}/$t; done" + run "for p in `find -L #{release_path} -type l`; do t=`readlink $p | grep -o 'shared/.*$'`; sudo mkdir -p #{release_path}/$t; done" end desc "Pulls shared files from remote location" task :pull do From ccca7c5655fc566b2284aed3aeede3dcb24eeb64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andre=CC=81s=20Villarreal?= Date: Mon, 12 Feb 2018 17:52:05 -0300 Subject: [PATCH 51/52] Update README.txt. --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index d462528..9ab6fc5 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ Because WordPress runs professional sites, and you should have a professional de ### Assumptions about your workflow -* You mantain your code under a version control system (like [Git](http://git-scm.com/)). Stage WP works specially well with [WordPress Bareboner][wpbareboner]. +* You mantain your code under a version control system (like [Git](http://git-scm.com/)). Stage WP works specially well with [WordPress Barebones][wpbarebones]. * You develop locally before deploying your code. * Ideally, you have a staging environment to test changes before they go to production. * Ideally, you use a CDN for static assets. @@ -44,10 +44,10 @@ If you're using [VVV][vvv], steps 3 and 4 will run automatically upon `vagrant u ### Setting Up Stage WP -1. Check out Stage WP somewhere on your local system. +1. Check out Stage WP somewhere on your local system. * `git clone git@github.com:andrezrv/Stage-WP.git /srv/www/website/stage-wp` 2. Customize and rename `/config/{config|local|production|staging}-sample.rb` -3. Make sure your remote `:production_deploy_to` and `:staging_deploy_to` paths exist and are owned by the deploy user. +3. Make sure your remote `:production_deploy_to` and `:staging_deploy_to` paths exist and are owned by the deploy user. * `chown -R deploy:deploy /path/to/your/deployment` 4. Go to your Stage WP directory and run `cap deploy:setup` to setup the initial `shared` and `releases` directories. @@ -158,7 +158,7 @@ If you feel like you want to help this project by adding something you think use [wp]: http://wordpress.org/ [wpstack]: http://github.com/markjaquith/WP-Stack -[wpbareboner]: http://github.com/andrezrv/wordpress-bareboner/ +[wpbareboner]: http://github.com/andrezrv/wordpress-barebones/ [mj]: http://github.com/markjaquith [cap]: https://github.com/capistrano/capistrano [ruby]: https://www.ruby-lang.org/en/installation/#ruby-install From 08964782d240291336a95651f17cd9e99c52878a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andre=CC=81s=20Villarreal?= Date: Mon, 12 Feb 2018 17:59:35 -0300 Subject: [PATCH 52/52] Update some internal docs. --- README.md | 6 +- config/config-sample-placeholded.rb | 111 +----------------- config/config-sample.rb | 2 +- .../stage-wp-plugin.class.php | 2 +- 4 files changed, 7 insertions(+), 114 deletions(-) diff --git a/README.md b/README.md index 9ab6fc5..ce64e0e 100644 --- a/README.md +++ b/README.md @@ -95,7 +95,7 @@ You can synchronize both database and shared files from production to staging or ### Some Other Useful Tasks -If you're using [WordPress Bareboner][wpbareboner], you can perform remote backup and maintenance tasks with the following commands: +If you're using [WordPress Barebones][wpbarebones], you can perform remote backup and maintenance tasks with the following commands: * `cap {staging|production} util:backup_application`: Zips and saves all application files to `:application_backup_path`. * `cap {staging|production} util:backup_db`: Performs a mysqldump of the WordPress database and saves it to `:wpdb[stage][:backups_dir]`. @@ -131,7 +131,7 @@ Normally, WordPress redirects `/wp-admin/` requests to the WordPress database up ## Assumptions Made About WordPress -If you're not using [Wordpress Bareboner][wpbareboner], you should be aware of these assumptions: +If you're not using [WordPress Barebones][wpbarebones], you should be aware of these assumptions: 1. Your application path is defined in `:application_path`, inside `/config/config.rb` 2. Your `wp-config.php` file must exist in the root of your application path. @@ -158,7 +158,7 @@ If you feel like you want to help this project by adding something you think use [wp]: http://wordpress.org/ [wpstack]: http://github.com/markjaquith/WP-Stack -[wpbareboner]: http://github.com/andrezrv/wordpress-barebones/ +[wpbarebones]: http://github.com/andrezrv/wordpress-barebones/ [mj]: http://github.com/markjaquith [cap]: https://github.com/capistrano/capistrano [ruby]: https://www.ruby-lang.org/en/installation/#ruby-install diff --git a/config/config-sample-placeholded.rb b/config/config-sample-placeholded.rb index 4f84a83..d43006a 100644 --- a/config/config-sample-placeholded.rb +++ b/config/config-sample-placeholded.rb @@ -16,120 +16,13 @@ # Where is your wp-config.php file located within #{release_path}? # // Your release path points to the newer copy of your repository, so you must # // specify where your wp-config.php file is located within your remore repo. -# // WordPress Bareboner puts the file in the "app" subfolder, so it needs to -# // be "#{release_path}/app", but if you are using WordPress-Skeleton, just -# // "#{release_path}" should do the trick and this value should be left empty. -set :application_path, "/app" - -# Repository settings - -# // Location of your remote repository. -set :repository, "%%REPOSITORY%%" - -# // Your preferred method for source control. Supports :accurev, :bzr, :cvs, -# // :darcs, :git, :mercurial, :perforce, :subversion or :none. -set :scm, :git - -# // Using Git submodules? -set :git_enable_submodules, 1 - -# Default deploy directories. - -# // :deploy_to in production.rb will use this value as default -set :production_deploy_to, "%%PRODUCTION_DEPLOY_TO%%" - -# // :deploy_to in staging.rb will use this value as default -set :staging_deploy_to, "%%STAGING_DEPLOY_TO%%" - -# Default domains. - -# // :deploy_to in production.rb will use this value as default -set :production_domain, "%%PRODUCTION_DOMAIN%%" - -# // :deploy_to in staging.rb will use this value as default -set :staging_domain, "%%STAGING_DOMAIN%%" - -# Local stage default settings. - -# // Path to your local shared folder. -set :local_shared_folder, "%%LOCAL_SHARED_FOLDER%%" - -# WordPress database settings. -# -# Set the values for host, user, pass, and name for production, staging and -# local stages. You can also specify a backup directory where your mysqldumps -# should be saved. Note that placeholders like %%DB_NAME%% and %%DB_PASSWORD%% -# in your wp-config.php file will be automatically replaced when `cap deploy` is -# executed, so you only have to configure these values here. - -82 -83 -84 -85 -86 -87 -88 -89 -90 -91 -92 -93 -94 -95 -96 -97 -98 -99 -100 -101 -102 -103 -104 -105 -106 -107 -108 -109 -110 -111 -112 -113 -114 -115 -116 -117 -118 -119 -120 -121 -122 -123 -124 -# Stage WP configuration file. -# -# This is a sample config file. It manages settings for your remote repository, -# your default domains and your database values. Copy it to config.rb and -# customize it to your own needs. - - -# Application settings. - -# // The name of your application. It can be any string. -set :application, "%%APPLICATION%%" - -# // A shortname to identify your application. -set :application_id, "%%APPLICATION_ID%%" - -# Where is your wp-config.php file located within #{release_path}? -# // Your release path points to the newer copy of your repository, so you must -# // specify where your wp-config.php file is located within your remore repo. -# // WordPress Bareboner puts the file in the "app" subfolder, so it needs to +# // WordPress Barebones puts the file in the "app" subfolder, so it needs to # // be "#{release_path}/app", but if you are using WordPress-Skeleton, just # // "#{release_path}" should do the trick and this value should be left empty. set :application_path, "/app" # Where are your shell tasks located within #{release_path}? -# // If you're using WordPress Bareboner, the tasks should be by default into +# // If you're using WordPress Barebones, the tasks should be by default into # // /app/tasks. If you are using another WordPress starting repo, you should # // adjust this value to your own configuration. However, all tasks related to # // this setting will not be executed if following path does'n t exist. diff --git a/config/config-sample.rb b/config/config-sample.rb index 68cd1a7..2ac52f5 100644 --- a/config/config-sample.rb +++ b/config/config-sample.rb @@ -16,7 +16,7 @@ # Where is your wp-config.php file located within #{release_path}? # // Your release path points to the newer copy of your repository, so you must # // specify where your wp-config.php file is located within your remore repo. -# // WordPress Bareboner puts the file in the "app" subfolder, so it needs to +# // WordPress Barebones puts the file in the "app" subfolder, so it needs to # // be "#{release_path}/app", but if you are using WordPress-Skeleton, just # // "#{release_path}" should do the trick and this value should be left empty. set :application_path, "/app" diff --git a/wordpress-mu-plugins/stage-wp-plugin.class.php b/wordpress-mu-plugins/stage-wp-plugin.class.php index f2e7b6a..77b11ae 100644 --- a/wordpress-mu-plugins/stage-wp-plugin.class.php +++ b/wordpress-mu-plugins/stage-wp-plugin.class.php @@ -14,7 +14,7 @@ * * @wordpress-plugin * Plugin name: Stage WP Plugin Class - * Plugin URI: http://github.com/andrezrv/wordpress-bareboner/ + * Plugin URI: http://github.com/andrezrv/wordpress-barebones/ * Description: Just a helper class for Stage WP must-use plugins. Original credits go to Mark Jaquith. * Author: Andrés Villarreal * Author URI: http://about.me/andrezrv