Leveraging WP-CLI Aliases in Your WordPress Development Workflow

Makes sense, appreciate the reply :slight_smile:

WP-CLI supports a global config file! Per the docs you can have a global config in ~/.wp-cli/config.yml - I just set it up with aliases, and now I can use my aliases from any folder :grin:

1 Like

I just noticed the last case doesn’t match up with the last usage example - I added in production <> staging and updated the usage text. I also made the site URLs root relative, just for compatibility reasons.

The first case also has ; after DIR="up" whereas the others don’t; I added to make consistent though I’m not sure it actually matters since each statement is just a variable declaration.

#!/bin/sh

DEVDIR="web/app/uploads/"
DEVSITE="//example.dev"

PRODDIR="web@example.com:/srv/www/example.com/shared/uploads/"
PRODSITE="//example.com"

STAGDIR="web@staging.example.com:/srv/www/example.com/shared/uploads/"
STAGSITE="//staging.example.com"

FROM=$1
TO=$2

case "$1-$2" in
  development-production) DIR="up";  FROMSITE=$DEVSITE;  FROMDIR=$DEVDIR;  TOSITE=$PRODSITE; TODIR=$PRODDIR; ;;
  development-staging)    DIR="up";   FROMSITE=$DEVSITE;  FROMDIR=$DEVDIR;  TOSITE=$STAGSITE; TODIR=$STAGDIR; ;;
  production-development) DIR="down"; FROMSITE=$PRODSITE; FROMDIR=$PRODDIR; TOSITE=$DEVSITE;  TODIR=$DEVDIR; ;;
  production-staging)     DIR="horizontally"; FROMSITE=$PRODSITE; FROMDIR=$PRODDIR; TOSITE=$STAGSITE; TODIR=$STAGDIR; ;;
  staging-development)    DIR="down"; FROMSITE=$STAGSITE; FROMDIR=$STAGDIR; TOSITE=$DEVSITE;  TODIR=$DEVDIR; ;;
  *) echo "usage: $0 development production | development staging | production development | production staging | staging development" && exit 1 ;;
esac

read -r -p "Would you really like to reset the $TO database and sync $DIR from $FROM? [y/N] " response

if [[ "$response" =~ ^([yY][eE][sS]|[yY])$ ]]; then
  cd ../ &&
  wp "@$TO" db export &&
  wp "@$FROM" db export - | wp "@$TO" db import - &&
  wp "@$TO" search-replace "$FROMSITE" "$TOSITE" &&
  rsync -az --progress "$FROMDIR" "$TODIR"
fi

Edit: though I’m still using WP Migrate DB, I figured I’d add in the option to skip syncing uploads, so after the case block I changed to the following:

read -r -p "Would you like to sync the uploads folder as well? [y/N] " uploads
read -r -p "Would you really like to reset the $TO database and sync $DIR from $FROM? [y/N] " response

if [[ "$response" =~ ^([yY][eE][sS]|[yY])$ ]]; then
  cd ../ &&
  wp "@$TO" db export &&
  wp "@$FROM" db export - | wp "@$TO" db import - &&
  if [[ "$uploads" =~ ^([yY][eE][sS]|[yY])$ ]]; then
    wp "@$TO" search-replace "$FROMSITE" "$TOSITE" &&
    rsync -az --progress "$FROMDIR" "$TODIR"
  else
    wp "@$TO" search-replace "$FROMSITE" "$TOSITE"
  fi
fi
1 Like

Wouldn’t this be a great candidate for a GitHub repository?

1 Like

–skip-columns=guid should be used when replacing, see
https://codex.wordpress.org/Changing_The_Site_URL#Important_GUID_Note

I am working on a repo here. Raquelle as author (@cedarstay ) as well as @ben have been mentioned for the script they made and I added there. Thanks so much for sharing this and teaching me more about aliases and shell scripts! README is not quite done yet and tweaks me be needed. Feel free to submit pull requests or clone it.

2 Likes

Also a plain backup option would be nice that dumps the database and uploads/ folder to a specific local path (for remote regular backups).

Actually another pull request by @guilro is in line for automating database and file backups using Stouts.backup Ansible role with Duplicity and is mentioned here: https://github.com/roots/trellis/pull/650 . I think that would be really good to have and can be configured in many different ways.

2 Likes

I use the --export option of wp search-replace for this and also add gzip. No wp-aliases though, but not much different. It’s basically like:

ssh $srv1 "cd $dir1; wp search-replace 'http://$srv1' 'http://$srv2'  --export | gzip" \
| ssh $srv2 "cd $dir2; gunzip | wp db import -"
1 Like

Just did a run to move stuff from a dev site to a production site. Latter is a demo so worries there. But I ran into an error

./sync-all.sh development production
Would you really like to reset the production database and sync up from development? [y/N] y
mysqldump: Can't create/write to file 'filathlos_imagewize_com_production-a822007.sql' (Errcode: 13 "Permission denied")

Must be a permissions issue. But should did not work using user web?

Well when I used the user web in the wp-cli.yml file it all worked

./sync-all.sh development production
Would you really like to reset the production database and sync up from development? [y/N] y
Success: Exported to 'filathlos_imagewize_com_production-a9ab231.sql'.
Success: Imported from '-'.

I only had a Sage error:

Error: Sage › ErrorAutoloader not found.. You must run composer install from the Sage directory.

, but when I commented out build-before.yml and ran deployment again I solved that too

Thank you for this very helpful script!

In my case, I ran sync.sh from within my Trellis-provisioned development vagrant vm and it only worked when I changed the first line from #!/bin/sh to #!/bin/bash. Otherwise it will throw the following error on line 25 of the script:

./sync.sh: 25: ./sync.sh: Syntax error: "(" unexpected (expecting "then")

I’m far from being a Unix shell expert though, so I’m wondering if anyone has encountered this?

2 Likes

Yeah, others encountered this common Bash issue too. See https://github.com/jasperf/trellis-sync/issues/3#issuecomment-291927603 where I use @ben and Raquelle’s scripts and another person @redstartinternet encountered the same POSIX issue.

I opened up a pull request to fix the upload and db syncing scripts.

2 Likes

@seraphim I’m also getting that error. Did anyone experience this and resolve the issue?

Did you try changing #!/bin/sh to #!/bin/bash at the top of the script, as he suggested?

Yes. But that didn’t change my result.

Just reading this here now, but did deal with the pull request at Github earlier on :wink:

If your wp @prod alias is not working, you need to do the same thing for your prod server. Something like adding the below to your ~/.ssh/config file:

Host example.com
HostName XXX.XXX.XXX.XXX (IP ADDRESS)
User admin
UserKnownHostsFile /dev/null
StrictHostKeyChecking no
PasswordAuthentication no
ForwardAgent yes

It looks like the vagrant-triggers plugin has been merged into Vagrant in recent versions, and this vagrant-triggers script (which I :heart:) is not working as is (at least with Vagrant 2.1.0). Anyone else experienced this?