WordPress Development: Consistency and Deployments

WordPress Development: VVV, Consistency and Automated Deployments

At Y-Designs, as with other firms in our industry, we are often forced to develop client websites using WordPress.  Wordpress is like Windows in the late 90s, early 2000s; many tools are available, even though the operating system itself is kind of questionable.

One of the biggest issues with WordPress Development is the fact that it stores many of its configurations (root URL, etc) in its database instead of storing it as part of a config file.  Because of this, it becomes very difficult to keep things in sync with other developers who are working on the same project.  Most version control systems only account for files anyway.

So, we came up with a plan (Its definitely not a perfect one, but it seems to be working for us!).

What the Plan involves

  • Create a script that let’s us deploy to our staging environment with a single command (yd_stage_up)
  • Create scripts that let’s us push and pull databases between local wordpress development systems using Git (yd_git_push and yd_git_pull)
  • Create a script that automates most of the setup per WordPress instance for pushing to the staging environment and database version control systems. (yd_setup)
  • Create a script that initializes all the above scripts into a Vagrant box for ease. (yd_init)

Our Tools for WordPress Development (or a combination of tools)

Before we introduce you to the scripts and the tools we created, let’s talk about the vagrant/VVV and other tools we use.  Below are the tools we use for our WordPress Development.

VVV - Varying Vagrant Vagrants

A mouthful as VVV is, it is awesome. Because we like some consistency and because we value having an easy to use solution, we installed VVV to be our WordPress Virtual Machine. In plain form, VVV is a Vagrant box with a couple of different WordPress instances, memcached, MySQL, NGINX, and PhpMyAdmin.   Key Features: Host Matching and File Mirroring VVV is also smart enough to match a hostname on the host OS.  For eample, if you go to “vvv.dev” while VVV is running, it will map against the installed VVV components accessible.  To accomplish this, VVV edits the host’s “/etc/hosts” file and matches its internal IP against the hostnames that is serving (all VVV host names finish with a “.dev” so it won’t ever have a conflict with sites you’re trying to visit). VVV matches its “www” directory on the host against its own “/srv/www” directory which is used to serve the content via PHP-FPM/NGINX.  This is particularly handy since it allows us to work on on the local file without having to create an SSH mount.  You can directly open the local copies of the file via a text-editor/IDE and get to work! For installation instructions, check out VVV’s github page here: https://github.com/Varying-Vagrant-Vagrants/VVV Note that you’ll definitely need VirtualBox, Vagrant and other tools.  All of it should be explained at VVV’s docs.  If not, checkout this article too: webdevstudios VVV

VV

What is VV? Don’t we already have enough Vs?  VV is another tool which works on top of VVV.  VV allows you to create more WordPress development instances on top of the VVV vagrant box.  While it is a relatively simple looking set of bash functions, VV does a whole lot of awesome.   Key Feature: Consistent WordPress Provisioning on top of VVV Once in the vagrant directory for VV, issue this command: “vv create” It asks you all the right questions about how you want your WP install setup (Multi-site, debug enabled, etc).  After that, it takes its time to provision a new WordPress instance within the VVV vagrant box for you.  If you named your site “test”, after VV is done with VVV, you will be able to access a new WP installation at “test.dev”.  Its important to keep the name consistent here so I suggest you keep the name of the url and the project identical. You can get your VV here: https://github.com/bradp/vv (To install it on Linux, you can just put the vv script in your /usr/local/bin/ directory or in your home directory’s bin directory) Also, if you want to go one step further and install a nice front-end to VV, you can get that here: https://github.com/leogopal/VVV-Dashboard

Going Beyond Local Development: Grunt, WordPress Deploy and our yd_wp scripts

So far the above two VVV/VVs have helped us setup sites so they run on our local virtual machines very well.  This is where the issue of “transportability” comes in.  Let’s say that you want to export a site to a staging area so you can share it with your client before it is deployed to production.  What can you do? TL;DR: Skip below to get our yd_wp script and it’ll do all the grunt/wordpress-deploy magic for you once you configure it right. Grunt Grunt is a Node based tool that allows us to run specific tasks.  You can install it on any machine with node/npm installed on it by running “npm install -g grunt-cli”  Remember, its grunt-cli and not just grunt!  I believe this is installed globally by default, but you can install it yourself also. WordPress Deploy This is a Node/Grunt package that allows you to deploy your existing WordPress installation to somewhere in the cloud.  It can be installed like this “npm install grunt-wordpress-deploy”.   The most important aspect of this grunt plugin is that it transports only the changed files to the otherside using rsync.  Another important aspect of this plugin is that it replaces all of the strings within the SQL file before loading it to the other side. Below is an example configuration file for what the Gruntfile.js might look like for your site.
module.exports = function(grunt) {

  "use strict";

  grunt.initConfig({
    wordpressdeploy: {
      options: {
        backup_dir: "backups/",
        rsync_args: ['--verbose', '--progress', '-rlpt', '--compress', '--omit-dir-times', '--delete'],
        exclusions: ['Gruntfile.js', '.git/', 'tmp/*', 'backups/', 'local-config.php', 'composer.json', 'composer.lock', 'README.md', '.gitignore', 'package.json', 'node_modules']
      },
      local: {
        "title": "local",
        "database": "SITENAME",
        "user": "wp",
        "pass": "wp",
        "host": "localhost",
        "url": "http://SITENAME.dev",
        "path": "/srv/www/SITENAME/htdocs/"//Trailing slash is super important here.
      },
      staging: {//Also known to us as Devshed
        "title": "staging",
        "database": "SITENAME",//We have to set this up manually since our host doesn't have an API
        "user": "mysql_user_stage",
        "pass": "mysql_pass_stage",
        "host": "localhost",
        "url": "http://site.com/stage/SITENAME",
        "path": "/home/user/stage/SITENAME/",
        "ssh_host": "stageuser@site.com"
      },
      production: {
        "title": "production",
        "database": "prod",
        "user": "prod",
        "pass": "prod",
        "host": "prod",
        "url": "http://prod.com.dev",
        "path": "/home/prod/webapps/site/",
        "ssh_host": "user@prod.com.dev"
      }
    },
  });

  // Load tasks
  grunt.loadNpmTasks('grunt-wordpress-deploy');

  // Register tasks
  grunt.registerTask('default', [
    'wordpressdeploy'
  ]);

};
You can setup a shared database user specifically for this staging use and setup a shared directory on your hosting account for a similar purpose.

The YD_WP scripts

So, we again like some sense of consistency.  We created a short script that we used to setup every new WordPress installation.  It’s our “yd_wp” scripts.  TBH, we’re not super proud of it, but it works well.  You can get it here. Installation
  1. First, you should clone the directory to your VVV vagrant directory (it should be in the same directory as the www directory).
    1. Here’s how you might do that “git clone https://github.com/YD-Seattle/yd_wp.git yd_wp”
    2. You can always clone from inside or outside of the vagrant instance as long as its in the VVV vagrant directory.
  2. You should now log into the VVV vagrant instance (vagrant ssh) and change directory into the “/vagrant” directory.
  3. Now you can go into the directory ”yd_wp”.  You’ll have to execute the “yd_init.sh” script.
    1. Its a bash script  that generates symbolic link between “/usr/local/bin/” and the yd_wp directory.  It will also make sure that all of the commands are executable.
    2. Please note that it will sudo to do the above command
  Initial Configuration for the yd_setup Command The yd_setup command installs the necessary components to push each WordPress installation into a shared staging environment (like a staging directory on a web host). There are some default settings that need to be set.  Note that these configurations carry over to every project you setup using the yd_setup command.  We suggest that you setup a SSH user for stage deployment as well as a MySQL (shared or otherwise) for the staging purposes also prior to below configuration.
  1. Before you can use the system fully, you’ll want to configure the available scripts to your use.  There are two configuration files you’ll need to modify
    1. “configs/stage-config.php”: This is where the stage-configurations are stored for WordPress (MySQL, etc).
      1. This should just store the MySQL information for the staging.  This may have to be manually edited per project.
    2. “yd_gruntfile.js”: This is where the grunt stage deployment information is stored (SSH user/host, MySQL login, etc).  You should be editing the “staging” part of this file.  The local part of the system shouldn’t really need change as long as you didn’t disable the “wp” MySQL user.  Note that what you edit here will apply to every site you setup later.
      1. In this file, be sure that you do not replace the “SITENAME” strings as it is used by a later process to fill in the blanks
      2. User: mysql user name for the staging
      3. Pass: mysql password for staging
      4. URL: This should be setup against your stage’s deployment path.  We have our deployment path setup against a shared staging directory.  An example would be a shared directory at http://example.com/stage/ which all of your sites would deploy to.  If your site was called oranges, it would deploy the site to http://example.com/stage/oranges/
      5. Path: Similar concept to above, except that this would be the absolute path on your hosting environment.  So, it could be something like “/home/myusername/stage/oranges”
      6. SSH_host: this would be the full “myusername@myhost.com”. Later, when issuing the command, it’ll prompt you for the user’s password. We suggest you use SSH keys if possible.
  2. Generally speaking, the stage environment should be setup for easy of use and not for production.  We suggest that you have a separate deployment mechanism for production use.
  Setting up individual WordPress Installations with yd_setup Command This is where each WordPress installation is setup after VV is done with them.
  1. After VV has created a new WP installation, you can go into the installation directory.
    1. Note, you should be in the vagrant instance itself.  To get in, you should use “vagrant ssh”
    2. The default location for the WP installations from VV are located at “/srv/www/site-name/htdocs”
  2. Once you’re in the “htdocs” part of the installation, you’ll want to issue the “yd_setup” command. This command performs the below tasks:
    1. Copy over the configuration system from the yd_wp directory for stage systems.
    2. Install grunt-wordpress-deploy package
    3. Copy over the configuration for the grunt wordpress deploy system
    4. Modify the copied grunt configuration file to reflect the current site’s configurations. (Usually this shouldn’t be a major issue as long as you have a shared host that you can configure against.  This is configuration is mentioned in our configuration section 1.b. earlier)
    5. Copy over the “stage-config.php”
  Using the Stage Up Command You can use the “yd_stage_up” command to push up all of the code to a shared staging environment.
  1. What the command does:
    1. Makes a backup copy of the remote database and copies it to your local system
    2. Makes a backup copy of the local database and puts into the remote stage system (the script also replaces the current url with the stage URL specified in the gruntfile)
    3. Rsyncs the directory over to the remote stage host.
  2. Notes:
    1. If you don’t have an SSH key setup, it will ask for the remote password 3 times (backup remote db, push local db to remote, push local files to remote)
    2. Don’t make DB/file changes while this command is running
  Setting up GIT and using the YD_GIT_PUSH/PULL commands So, aside from being able to push to stage as a whole, the yd_wp command’s greater useage for us is with the “yd_git_push” and “yd_git_pull” commands.  These commands, like the stage up command incorporate the database as part of the “git push/pull” systems.  We assume that the two systems are setup identically for these two commands (between two local systems for instance between developer and designer).  We intentionally left this part of the setup loose and didn’t write a script to automate since there are different scenarios even within our usecase.
  1. First, you’ll need to initialize and push the project directory (say /srv/www/test-site/htdocs) using the below commands:
    1. git init
    2. git add -A
    3. git commit -m ‘initial commit’
    4. git remote add origin git@git.gitserver.com:user/test-site.git
    5. git push -u origin master
  2. After all of the above commands go through without a hitch you can issue a “yd_git_push” command.  The command will do the following:
    1. Backup a copy of the database as part of the directories which are tracked by git
    2. Asks you for a comment
    3. Pushes the change up.
  3. If the other local worker pushes a change to the system, you can issue a “yd_git_pull” command. Keep in mind that this command will overwrite your database with their copy of the database.
    1. This command will save the local database in a non-tracked directory sibling to the htdocs directory (basically one directory below)
    2. This command will then put the latest version of the tracked SQL file into the database.
One major caveat as mentioned in the 3rd section is that databases are tracked in GIT and therefore cannot be affected by multiple users.  This is not an issue if the project and its files are the only parts being worked on.  That said, this feature does make these scripts worthwhile for most non-super-heavy-duty use cases.  Wordpress Problems!   Notes on setting up an already GIT tracked project on another local machine using VVV and VV As assumed by the above section on yd_git_push/pull commands, you can have another person with an identical setup work on the project with you. To do this, you will need to setup the WP instance using VVV and VV as normal (mentioned a couple sections up) prior to issuing the yd_setup command.  Here’s what you should do to setup a pre-existing GIT tracked project on another local VVV based development system:
  1. First, make sure that you names both projects on both local machines identically.  This will allow the scripts to work correctly.
  2. Once that’s done, go to “/srv/www/example-site” (Assuming example-site as the name).
    1. cd /srv/www/example-site
  3. Remove everything in the example-site’s htdocs directory
    1. rm -rf htdocs/*
  4. Now, let’s clone in the GIT repo straight into the htdocs directory
    1. git clone git@git.gitserver.com:user/example-site.git htdocs
  5. Now go into the htdocs directory:
    1. cd htdocs
  6. You should issue the yd_git_pull command to initialize the local database.
    1. yd_git_pull
    2. Note: this will erase the default database that VVV/VV setup for the install.
  Below is a diagram showing how the entire system works.

Conclusion

This system should allow you to manage WordPress across multiple systems.  Its tailored towards our specific use, but I’m sure many have the same problem.  It would be nice if we could rewrite it into something more substantial, but that’s for another day. Hope this is of some help to someone!  Let us know in the comments. Let us know if you’re looking for web development and/or design services.