<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Real-World WP-CLI Projects Archives - WP-CLI Mastery</title>
	<atom:link href="https://wpclimastery.com/blog/category/real-world-wp-cli-projects/feed/" rel="self" type="application/rss+xml" />
	<link>https://wpclimastery.com/blog/category/real-world-wp-cli-projects/</link>
	<description>Automate WordPress Like a DevOps Pro.</description>
	<lastBuildDate>Mon, 24 Nov 2025 11:16:47 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	

<image>
	<url>https://wpclimastery.com/wp-content/uploads/2025/11/cropped-favicon-32x32.webp</url>
	<title>Real-World WP-CLI Projects Archives - WP-CLI Mastery</title>
	<link>https://wpclimastery.com/blog/category/real-world-wp-cli-projects/</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>Building a Complete WordPress Deployment System with WP-CLI (Real Project)</title>
		<link>https://wpclimastery.com/blog/building-a-complete-wordpress-deployment-system-with-wp-cli-real-project/</link>
		
		<dc:creator><![CDATA[Krasen]]></dc:creator>
		<pubDate>Fri, 30 Jan 2026 09:00:00 +0000</pubDate>
				<category><![CDATA[Real-World WP-CLI Projects]]></category>
		<category><![CDATA[complete deployment automation]]></category>
		<category><![CDATA[devops wordpress]]></category>
		<category><![CDATA[wordpress automation project]]></category>
		<category><![CDATA[wordpress deployment system]]></category>
		<category><![CDATA[wp-cli project]]></category>
		<guid isPermaLink="false">https://wpclimastery.com/?p=160</guid>

					<description><![CDATA[<p>Professional WordPress deployments require coordinating server provisioning, WordPress installation, plugin configuration, database migrations, zero-downtime releases, automated backups, health monitoring, and rollback capabilities. Managing these manually across development, staging, and production...</p>
<p>The post <a href="https://wpclimastery.com/blog/building-a-complete-wordpress-deployment-system-with-wp-cli-real-project/">Building a Complete WordPress Deployment System with WP-CLI (Real Project)</a> appeared first on <a href="https://wpclimastery.com">WP-CLI Mastery</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>Professional WordPress deployments require coordinating server provisioning, WordPress installation, plugin configuration, database migrations, zero-downtime releases, automated backups, health monitoring, and rollback capabilities. Managing these manually across development, staging, and production environments is error-prone and time-consuming.</p>



<p>A complete WordPress deployment system automates the entire lifecycle—provision servers, install WordPress, deploy code changes, run migrations, monitor health, and rollback failures—all with single commands executed by WP-CLI and Bash scripts.</p>



<p>In this guide, you’ll build a production-ready WordPress deployment system used by professional development teams, integrating server provisioning, automated deployments, monitoring, and disaster recovery into one cohesive system.</p>



<h3 class="wp-block-heading" id="architecture">System Architecture Overview</h3>



<p>Understand the complete deployment system components and workflow.</p>



<h4 class="wp-block-heading" id="deployment-system-components">Deployment System Components</h4>



<div class="sourceCode" id="cb1">
<pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true"></a>┌─────────────────────┐</span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true"></a>│  <span class="ex">Version</span> Control    │  ← Git repository (source of truth)</span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true"></a>│      <span class="kw">(</span><span class="ex">Git</span><span class="kw">)</span>          │</span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true"></a>└──────────┬──────────┘</span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true"></a>           │</span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true"></a>           ▼</span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true"></a>┌─────────────────────┐</span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true"></a>│  <span class="ex">CI/CD</span> Pipeline     │  ← GitHub Actions/GitLab CI</span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true"></a>│   <span class="kw">(</span><span class="ex">Automated</span><span class="kw">)</span>       │</span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true"></a>└──────────┬──────────┘</span>
<span id="cb1-11"><a href="#cb1-11" aria-hidden="true"></a>           │</span>
<span id="cb1-12"><a href="#cb1-12" aria-hidden="true"></a>           ▼</span>
<span id="cb1-13"><a href="#cb1-13" aria-hidden="true"></a>┌─────────────────────┐</span>
<span id="cb1-14"><a href="#cb1-14" aria-hidden="true"></a>│ <span class="ex">Deployment</span> Scripts  │  ← WP-CLI + Bash automation</span>
<span id="cb1-15"><a href="#cb1-15" aria-hidden="true"></a>│    <span class="kw">(</span><span class="ex">This</span> System<span class="kw">)</span>    │</span>
<span id="cb1-16"><a href="#cb1-16" aria-hidden="true"></a>└──────────┬──────────┘</span>
<span id="cb1-17"><a href="#cb1-17" aria-hidden="true"></a>           │</span>
<span id="cb1-18"><a href="#cb1-18" aria-hidden="true"></a>    ┌──────┴──────┐</span>
<span id="cb1-19"><a href="#cb1-19" aria-hidden="true"></a>    │             │</span>
<span id="cb1-20"><a href="#cb1-20" aria-hidden="true"></a>    ▼             ▼</span>
<span id="cb1-21"><a href="#cb1-21" aria-hidden="true"></a>┌────────┐   ┌────────┐</span>
<span id="cb1-22"><a href="#cb1-22" aria-hidden="true"></a>│<span class="ex">Staging</span> │   │  Prod  │  ← WordPress environments</span>
<span id="cb1-23"><a href="#cb1-23" aria-hidden="true"></a>└────────┘   └────────┘</span></code></pre>
</div>



<h4 class="wp-block-heading" id="system-features">System Features</h4>



<p><strong>Server provisioning</strong>: Automated WordPress server setup from scratch.</p>



<p><strong>Zero-downtime deploys</strong>: Release code without taking site offline.</p>



<p><strong>Database migrations</strong>: Automatic schema changes with rollback.</p>



<p><strong>Health monitoring</strong>: Continuous uptime and performance checks.</p>



<p><strong>Automatic backups</strong>: Pre-deployment snapshots with retention policies.</p>



<p><strong>One-command rollback</strong>: Instantly revert failed deployments.</p>



<p>Learn about <a href="https://aws.amazon.com/devops/what-is-devops/">DevOps deployment patterns</a>.</p>



<h3 class="wp-block-heading" id="project-structure">Project Structure and Setup</h3>



<p>Organize the deployment system codebase.</p>



<h4 class="wp-block-heading" id="directory-structure">Directory Structure</h4>



<div class="sourceCode" id="cb2">
<pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true"></a><span class="ex">wordpress-deploy-system/</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true"></a>├── <span class="ex">bin/</span>                      # Executable scripts</span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true"></a>│   ├── <span class="ex">deploy</span>                # Main deployment command</span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true"></a>│   ├── <span class="ex">provision</span>             # Server provisioning</span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true"></a>│   ├── <span class="ex">backup</span>                # Backup management</span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true"></a>│   ├── <span class="ex">rollback</span>              # Rollback deployments</span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true"></a>│   └── <span class="ex">monitor</span>               # Health monitoring</span>
<span id="cb2-8"><a href="#cb2-8" aria-hidden="true"></a>├── <span class="ex">lib/</span>                      # Reusable functions</span>
<span id="cb2-9"><a href="#cb2-9" aria-hidden="true"></a>│   ├── <span class="ex">common.sh</span>             # Shared utilities</span>
<span id="cb2-10"><a href="#cb2-10" aria-hidden="true"></a>│   ├── <span class="ex">deploy.sh</span>             # Deployment logic</span>
<span id="cb2-11"><a href="#cb2-11" aria-hidden="true"></a>│   ├── <span class="ex">database.sh</span>           # DB operations</span>
<span id="cb2-12"><a href="#cb2-12" aria-hidden="true"></a>│   └── <span class="ex">wordpress.sh</span>          # WordPress operations</span>
<span id="cb2-13"><a href="#cb2-13" aria-hidden="true"></a>├── <span class="ex">config/</span>                   # Configuration files</span>
<span id="cb2-14"><a href="#cb2-14" aria-hidden="true"></a>│   ├── <span class="ex">environments/</span>         # Environment-specific configs</span>
<span id="cb2-15"><a href="#cb2-15" aria-hidden="true"></a>│   │   ├── <span class="ex">development.conf</span></span>
<span id="cb2-16"><a href="#cb2-16" aria-hidden="true"></a>│   │   ├── <span class="ex">staging.conf</span></span>
<span id="cb2-17"><a href="#cb2-17" aria-hidden="true"></a>│   │   └── <span class="ex">production.conf</span></span>
<span id="cb2-18"><a href="#cb2-18" aria-hidden="true"></a>│   └── <span class="ex">deploy.conf</span>           # Global deployment config</span>
<span id="cb2-19"><a href="#cb2-19" aria-hidden="true"></a>├── <span class="ex">migrations/</span>               # Database migrations</span>
<span id="cb2-20"><a href="#cb2-20" aria-hidden="true"></a>│   ├── <span class="ex">001-initial-schema.sql</span></span>
<span id="cb2-21"><a href="#cb2-21" aria-hidden="true"></a>│   └── <span class="ex">002-add-custom-tables.sql</span></span>
<span id="cb2-22"><a href="#cb2-22" aria-hidden="true"></a>├── <span class="ex">hooks/</span>                    # Deployment hooks</span>
<span id="cb2-23"><a href="#cb2-23" aria-hidden="true"></a>│   ├── <span class="ex">pre-deploy.sh</span></span>
<span id="cb2-24"><a href="#cb2-24" aria-hidden="true"></a>│   ├── <span class="ex">post-deploy.sh</span></span>
<span id="cb2-25"><a href="#cb2-25" aria-hidden="true"></a>│   └── <span class="ex">health-check.sh</span></span>
<span id="cb2-26"><a href="#cb2-26" aria-hidden="true"></a>├── <span class="ex">logs/</span>                     # Deployment logs</span>
<span id="cb2-27"><a href="#cb2-27" aria-hidden="true"></a>└── <span class="ex">backups/</span>                  # Backup storage</span></code></pre>
</div>



<h4 class="wp-block-heading" id="installation-script">Installation Script</h4>



<div class="sourceCode" id="cb3">
<pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true"></a><span class="co">#!/bin/bash</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true"></a><span class="co"># install.sh - Set up deployment system</span></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true"></a></span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true"></a><span class="va">INSTALL_DIR=</span><span class="st">"/opt/wordpress-deploy"</span></span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true"></a></span>
<span id="cb3-6"><a href="#cb3-6" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"Installing WordPress Deployment System"</span></span>
<span id="cb3-7"><a href="#cb3-7" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"======================================="</span></span>
<span id="cb3-8"><a href="#cb3-8" aria-hidden="true"></a></span>
<span id="cb3-9"><a href="#cb3-9" aria-hidden="true"></a><span class="co"># Create directory structure</span></span>
<span id="cb3-10"><a href="#cb3-10" aria-hidden="true"></a><span class="fu">sudo</span> mkdir -p <span class="st">"</span><span class="va">$INSTALL_DIR</span><span class="st">"</span>/<span class="dt">{bin,lib,config/environments,migrations,hooks,logs,backups}</span></span>
<span id="cb3-11"><a href="#cb3-11" aria-hidden="true"></a></span>
<span id="cb3-12"><a href="#cb3-12" aria-hidden="true"></a><span class="co"># Copy files</span></span>
<span id="cb3-13"><a href="#cb3-13" aria-hidden="true"></a><span class="fu">sudo</span> cp -r bin/* <span class="st">"</span><span class="va">$INSTALL_DIR</span><span class="st">/bin/"</span></span>
<span id="cb3-14"><a href="#cb3-14" aria-hidden="true"></a><span class="fu">sudo</span> cp -r lib/* <span class="st">"</span><span class="va">$INSTALL_DIR</span><span class="st">/lib/"</span></span>
<span id="cb3-15"><a href="#cb3-15" aria-hidden="true"></a><span class="fu">sudo</span> cp -r config/* <span class="st">"</span><span class="va">$INSTALL_DIR</span><span class="st">/config/"</span></span>
<span id="cb3-16"><a href="#cb3-16" aria-hidden="true"></a></span>
<span id="cb3-17"><a href="#cb3-17" aria-hidden="true"></a><span class="co"># Make scripts executable</span></span>
<span id="cb3-18"><a href="#cb3-18" aria-hidden="true"></a><span class="fu">sudo</span> chmod +x <span class="st">"</span><span class="va">$INSTALL_DIR</span><span class="st">"</span>/bin/*</span>
<span id="cb3-19"><a href="#cb3-19" aria-hidden="true"></a><span class="fu">sudo</span> chmod +x <span class="st">"</span><span class="va">$INSTALL_DIR</span><span class="st">"</span>/hooks/*</span>
<span id="cb3-20"><a href="#cb3-20" aria-hidden="true"></a></span>
<span id="cb3-21"><a href="#cb3-21" aria-hidden="true"></a><span class="co"># Add to PATH</span></span>
<span id="cb3-22"><a href="#cb3-22" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"export PATH=</span><span class="dt">\$</span><span class="st">PATH:</span><span class="va">$INSTALL_DIR</span><span class="st">/bin"</span> <span class="kw">|</span> <span class="fu">sudo</span> tee -a /etc/profile.d/wordpress-deploy.sh</span>
<span id="cb3-23"><a href="#cb3-23" aria-hidden="true"></a></span>
<span id="cb3-24"><a href="#cb3-24" aria-hidden="true"></a><span class="co"># Install WP-CLI if not present</span></span>
<span id="cb3-25"><a href="#cb3-25" aria-hidden="true"></a><span class="kw">if</span> ! <span class="bu">command</span> -v wp <span class="op">&amp;&gt;</span> /dev/null<span class="kw">;</span> <span class="kw">then</span></span>
<span id="cb3-26"><a href="#cb3-26" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"Installing WP-CLI..."</span></span>
<span id="cb3-27"><a href="#cb3-27" aria-hidden="true"></a>    <span class="ex">curl</span> -O https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar</span>
<span id="cb3-28"><a href="#cb3-28" aria-hidden="true"></a>    <span class="fu">sudo</span> mv wp-cli.phar /usr/local/bin/wp</span>
<span id="cb3-29"><a href="#cb3-29" aria-hidden="true"></a>    <span class="fu">sudo</span> chmod +x /usr/local/bin/wp</span>
<span id="cb3-30"><a href="#cb3-30" aria-hidden="true"></a><span class="kw">fi</span></span>
<span id="cb3-31"><a href="#cb3-31" aria-hidden="true"></a></span>
<span id="cb3-32"><a href="#cb3-32" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"✓ Installation complete"</span></span>
<span id="cb3-33"><a href="#cb3-33" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"Usage: deploy &lt;environment&gt; &lt;release&gt;"</span></span></code></pre>
</div>



<h3 class="wp-block-heading" id="provisioning">Server Provisioning Automation</h3>



<p>Automate complete WordPress server setup.</p>



<h4 class="wp-block-heading" id="provisioning-script">Provisioning Script</h4>



<div class="sourceCode" id="cb4">
<pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true"></a><span class="co">#!/bin/bash</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true"></a><span class="co"># bin/provision - Provision WordPress server</span></span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true"></a></span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true"></a><span class="kw">set</span> <span class="ex">-euo</span> pipefail</span>
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true"></a></span>
<span id="cb4-6"><a href="#cb4-6" aria-hidden="true"></a><span class="bu">source</span> <span class="st">"</span><span class="va">$(</span><span class="fu">dirname</span> <span class="st">"</span><span class="va">$0</span><span class="st">"</span><span class="va">)</span><span class="st">/../lib/common.sh"</span></span>
<span id="cb4-7"><a href="#cb4-7" aria-hidden="true"></a></span>
<span id="cb4-8"><a href="#cb4-8" aria-hidden="true"></a><span class="va">ENVIRONMENT=</span><span class="st">"</span><span class="va">${1:-</span>staging<span class="va">}</span><span class="st">"</span></span>
<span id="cb4-9"><a href="#cb4-9" aria-hidden="true"></a><span class="va">CONFIG_FILE=</span><span class="st">"</span><span class="va">$CONFIG_DIR</span><span class="st">/environments/</span><span class="va">$ENVIRONMENT</span><span class="st">.conf"</span></span>
<span id="cb4-10"><a href="#cb4-10" aria-hidden="true"></a></span>
<span id="cb4-11"><a href="#cb4-11" aria-hidden="true"></a><span class="kw">if</span><span class="bu"> [</span> <span class="ot">!</span> <span class="ot">-f</span> <span class="st">"</span><span class="va">$CONFIG_FILE</span><span class="st">"</span><span class="bu"> ]</span>; <span class="kw">then</span></span>
<span id="cb4-12"><a href="#cb4-12" aria-hidden="true"></a>    <span class="ex">error</span> <span class="st">"Configuration not found: </span><span class="va">$CONFIG_FILE</span><span class="st">"</span></span>
<span id="cb4-13"><a href="#cb4-13" aria-hidden="true"></a><span class="kw">fi</span></span>
<span id="cb4-14"><a href="#cb4-14" aria-hidden="true"></a></span>
<span id="cb4-15"><a href="#cb4-15" aria-hidden="true"></a><span class="bu">source</span> <span class="st">"</span><span class="va">$CONFIG_FILE</span><span class="st">"</span></span>
<span id="cb4-16"><a href="#cb4-16" aria-hidden="true"></a></span>
<span id="cb4-17"><a href="#cb4-17" aria-hidden="true"></a><span class="ex">log</span> <span class="st">"Provisioning WordPress server for: </span><span class="va">$ENVIRONMENT</span><span class="st">"</span></span>
<span id="cb4-18"><a href="#cb4-18" aria-hidden="true"></a></span>
<span id="cb4-19"><a href="#cb4-19" aria-hidden="true"></a><span class="co"># Update system packages</span></span>
<span id="cb4-20"><a href="#cb4-20" aria-hidden="true"></a><span class="ex">log</span> <span class="st">"Updating system packages..."</span></span>
<span id="cb4-21"><a href="#cb4-21" aria-hidden="true"></a><span class="fu">sudo</span> apt-get update</span>
<span id="cb4-22"><a href="#cb4-22" aria-hidden="true"></a><span class="fu">sudo</span> apt-get upgrade -y</span>
<span id="cb4-23"><a href="#cb4-23" aria-hidden="true"></a></span>
<span id="cb4-24"><a href="#cb4-24" aria-hidden="true"></a><span class="co"># Install LAMP stack</span></span>
<span id="cb4-25"><a href="#cb4-25" aria-hidden="true"></a><span class="ex">log</span> <span class="st">"Installing LAMP stack..."</span></span>
<span id="cb4-26"><a href="#cb4-26" aria-hidden="true"></a><span class="fu">sudo</span> apt-get install -y <span class="kw">\</span></span>
<span id="cb4-27"><a href="#cb4-27" aria-hidden="true"></a>    <span class="ex">nginx</span> <span class="kw">\</span></span>
<span id="cb4-28"><a href="#cb4-28" aria-hidden="true"></a>    <span class="ex">mysql-server</span> <span class="kw">\</span></span>
<span id="cb4-29"><a href="#cb4-29" aria-hidden="true"></a>    <span class="ex">php8.1-fpm</span> <span class="kw">\</span></span>
<span id="cb4-30"><a href="#cb4-30" aria-hidden="true"></a>    <span class="ex">php8.1-mysql</span> <span class="kw">\</span></span>
<span id="cb4-31"><a href="#cb4-31" aria-hidden="true"></a>    <span class="ex">php8.1-xml</span> <span class="kw">\</span></span>
<span id="cb4-32"><a href="#cb4-32" aria-hidden="true"></a>    <span class="ex">php8.1-mbstring</span> <span class="kw">\</span></span>
<span id="cb4-33"><a href="#cb4-33" aria-hidden="true"></a>    <span class="ex">php8.1-curl</span> <span class="kw">\</span></span>
<span id="cb4-34"><a href="#cb4-34" aria-hidden="true"></a>    <span class="ex">php8.1-zip</span> <span class="kw">\</span></span>
<span id="cb4-35"><a href="#cb4-35" aria-hidden="true"></a>    <span class="ex">php8.1-gd</span> <span class="kw">\</span></span>
<span id="cb4-36"><a href="#cb4-36" aria-hidden="true"></a>    <span class="ex">php8.1-intl</span></span>
<span id="cb4-37"><a href="#cb4-37" aria-hidden="true"></a></span>
<span id="cb4-38"><a href="#cb4-38" aria-hidden="true"></a><span class="co"># Configure Nginx</span></span>
<span id="cb4-39"><a href="#cb4-39" aria-hidden="true"></a><span class="ex">log</span> <span class="st">"Configuring Nginx..."</span></span>
<span id="cb4-40"><a href="#cb4-40" aria-hidden="true"></a><span class="fu">sudo</span> tee /etc/nginx/sites-available/wordpress <span class="op">&lt;&lt;EOF</span></span>
<span id="cb4-41"><a href="#cb4-41" aria-hidden="true"></a>server {</span>
<span id="cb4-42"><a href="#cb4-42" aria-hidden="true"></a>    listen 80;</span>
<span id="cb4-43"><a href="#cb4-43" aria-hidden="true"></a>    server_name <span class="va">$SERVER_NAME</span>;</span>
<span id="cb4-44"><a href="#cb4-44" aria-hidden="true"></a>    root <span class="va">$DEPLOY_PATH</span>/current;</span>
<span id="cb4-45"><a href="#cb4-45" aria-hidden="true"></a>    index index.php;</span>
<span id="cb4-46"><a href="#cb4-46" aria-hidden="true"></a></span>
<span id="cb4-47"><a href="#cb4-47" aria-hidden="true"></a>    location / {</span>
<span id="cb4-48"><a href="#cb4-48" aria-hidden="true"></a>        try_files <span class="dt">\$</span>uri <span class="dt">\$</span>uri/ /index.php?<span class="dt">\$</span>args;</span>
<span id="cb4-49"><a href="#cb4-49" aria-hidden="true"></a>    }</span>
<span id="cb4-50"><a href="#cb4-50" aria-hidden="true"></a></span>
<span id="cb4-51"><a href="#cb4-51" aria-hidden="true"></a>    location ~ \.php$ {</span>
<span id="cb4-52"><a href="#cb4-52" aria-hidden="true"></a>        fastcgi_pass unix:/var/run/php/php8.1-fpm.sock;</span>
<span id="cb4-53"><a href="#cb4-53" aria-hidden="true"></a>        fastcgi_index index.php;</span>
<span id="cb4-54"><a href="#cb4-54" aria-hidden="true"></a>        include fastcgi_params;</span>
<span id="cb4-55"><a href="#cb4-55" aria-hidden="true"></a>        fastcgi_param SCRIPT_FILENAME <span class="dt">\$</span>document_root<span class="dt">\$</span>fastcgi_script_name;</span>
<span id="cb4-56"><a href="#cb4-56" aria-hidden="true"></a>    }</span>
<span id="cb4-57"><a href="#cb4-57" aria-hidden="true"></a>}</span>
<span id="cb4-58"><a href="#cb4-58" aria-hidden="true"></a><span class="op">EOF</span></span>
<span id="cb4-59"><a href="#cb4-59" aria-hidden="true"></a></span>
<span id="cb4-60"><a href="#cb4-60" aria-hidden="true"></a><span class="fu">sudo</span> ln -sf /etc/nginx/sites-available/wordpress /etc/nginx/sites-enabled/</span>
<span id="cb4-61"><a href="#cb4-61" aria-hidden="true"></a><span class="fu">sudo</span> nginx -t <span class="kw">&amp;&amp;</span> <span class="fu">sudo</span> systemctl reload nginx</span>
<span id="cb4-62"><a href="#cb4-62" aria-hidden="true"></a></span>
<span id="cb4-63"><a href="#cb4-63" aria-hidden="true"></a><span class="co"># Create deployment directories</span></span>
<span id="cb4-64"><a href="#cb4-64" aria-hidden="true"></a><span class="ex">log</span> <span class="st">"Creating deployment directories..."</span></span>
<span id="cb4-65"><a href="#cb4-65" aria-hidden="true"></a><span class="fu">sudo</span> mkdir -p <span class="st">"</span><span class="va">$DEPLOY_PATH</span><span class="st">"</span>/<span class="dt">{releases,shared}</span></span>
<span id="cb4-66"><a href="#cb4-66" aria-hidden="true"></a><span class="fu">sudo</span> mkdir -p <span class="st">"</span><span class="va">$DEPLOY_PATH</span><span class="st">/shared"</span>/<span class="dt">{wp-content/uploads,logs}</span></span>
<span id="cb4-67"><a href="#cb4-67" aria-hidden="true"></a></span>
<span id="cb4-68"><a href="#cb4-68" aria-hidden="true"></a><span class="co"># Set permissions</span></span>
<span id="cb4-69"><a href="#cb4-69" aria-hidden="true"></a><span class="fu">sudo</span> chown -R www-data:www-data <span class="st">"</span><span class="va">$DEPLOY_PATH</span><span class="st">"</span></span>
<span id="cb4-70"><a href="#cb4-70" aria-hidden="true"></a><span class="fu">sudo</span> chmod -R 755 <span class="st">"</span><span class="va">$DEPLOY_PATH</span><span class="st">"</span></span>
<span id="cb4-71"><a href="#cb4-71" aria-hidden="true"></a></span>
<span id="cb4-72"><a href="#cb4-72" aria-hidden="true"></a><span class="co"># Create MySQL database</span></span>
<span id="cb4-73"><a href="#cb4-73" aria-hidden="true"></a><span class="ex">log</span> <span class="st">"Creating WordPress database..."</span></span>
<span id="cb4-74"><a href="#cb4-74" aria-hidden="true"></a><span class="fu">sudo</span> mysql <span class="op">&lt;&lt;EOF</span></span>
<span id="cb4-75"><a href="#cb4-75" aria-hidden="true"></a>CREATE DATABASE IF NOT EXISTS <span class="va">$DB_NAME</span>;</span>
<span id="cb4-76"><a href="#cb4-76" aria-hidden="true"></a>CREATE USER IF NOT EXISTS '<span class="va">$DB_USER</span>'@'localhost' IDENTIFIED BY '<span class="va">$DB_PASS</span>';</span>
<span id="cb4-77"><a href="#cb4-77" aria-hidden="true"></a>GRANT ALL PRIVILEGES ON <span class="va">$DB_NAME</span>.* TO '<span class="va">$DB_USER</span>'@'localhost';</span>
<span id="cb4-78"><a href="#cb4-78" aria-hidden="true"></a>FLUSH PRIVILEGES;</span>
<span id="cb4-79"><a href="#cb4-79" aria-hidden="true"></a><span class="op">EOF</span></span>
<span id="cb4-80"><a href="#cb4-80" aria-hidden="true"></a></span>
<span id="cb4-81"><a href="#cb4-81" aria-hidden="true"></a><span class="co"># Install WordPress</span></span>
<span id="cb4-82"><a href="#cb4-82" aria-hidden="true"></a><span class="ex">log</span> <span class="st">"Installing WordPress..."</span></span>
<span id="cb4-83"><a href="#cb4-83" aria-hidden="true"></a><span class="bu">cd</span> <span class="st">"</span><span class="va">$DEPLOY_PATH</span><span class="st">"</span></span>
<span id="cb4-84"><a href="#cb4-84" aria-hidden="true"></a></span>
<span id="cb4-85"><a href="#cb4-85" aria-hidden="true"></a><span class="ex">wp</span> core download --path=initial-install</span>
<span id="cb4-86"><a href="#cb4-86" aria-hidden="true"></a><span class="bu">cd</span> initial-install</span>
<span id="cb4-87"><a href="#cb4-87" aria-hidden="true"></a></span>
<span id="cb4-88"><a href="#cb4-88" aria-hidden="true"></a><span class="ex">wp</span> config create <span class="kw">\</span></span>
<span id="cb4-89"><a href="#cb4-89" aria-hidden="true"></a>    <span class="ex">--dbname</span>=<span class="st">"</span><span class="va">$DB_NAME</span><span class="st">"</span> <span class="kw">\</span></span>
<span id="cb4-90"><a href="#cb4-90" aria-hidden="true"></a>    <span class="ex">--dbuser</span>=<span class="st">"</span><span class="va">$DB_USER</span><span class="st">"</span> <span class="kw">\</span></span>
<span id="cb4-91"><a href="#cb4-91" aria-hidden="true"></a>    <span class="ex">--dbpass</span>=<span class="st">"</span><span class="va">$DB_PASS</span><span class="st">"</span> <span class="kw">\</span></span>
<span id="cb4-92"><a href="#cb4-92" aria-hidden="true"></a>    <span class="ex">--dbhost</span>=localhost</span>
<span id="cb4-93"><a href="#cb4-93" aria-hidden="true"></a></span>
<span id="cb4-94"><a href="#cb4-94" aria-hidden="true"></a><span class="ex">wp</span> core install <span class="kw">\</span></span>
<span id="cb4-95"><a href="#cb4-95" aria-hidden="true"></a>    <span class="ex">--url</span>=<span class="st">"</span><span class="va">$SITE_URL</span><span class="st">"</span> <span class="kw">\</span></span>
<span id="cb4-96"><a href="#cb4-96" aria-hidden="true"></a>    <span class="ex">--title</span>=<span class="st">"</span><span class="va">$SITE_TITLE</span><span class="st">"</span> <span class="kw">\</span></span>
<span id="cb4-97"><a href="#cb4-97" aria-hidden="true"></a>    <span class="ex">--admin_user</span>=<span class="st">"</span><span class="va">$ADMIN_USER</span><span class="st">"</span> <span class="kw">\</span></span>
<span id="cb4-98"><a href="#cb4-98" aria-hidden="true"></a>    <span class="ex">--admin_password</span>=<span class="st">"</span><span class="va">$ADMIN_PASS</span><span class="st">"</span> <span class="kw">\</span></span>
<span id="cb4-99"><a href="#cb4-99" aria-hidden="true"></a>    <span class="ex">--admin_email</span>=<span class="st">"</span><span class="va">$ADMIN_EMAIL</span><span class="st">"</span></span>
<span id="cb4-100"><a href="#cb4-100" aria-hidden="true"></a></span>
<span id="cb4-101"><a href="#cb4-101" aria-hidden="true"></a><span class="co"># Move to shared directory</span></span>
<span id="cb4-102"><a href="#cb4-102" aria-hidden="true"></a><span class="fu">mv</span> wp-content/uploads/* <span class="st">"</span><span class="va">$DEPLOY_PATH</span><span class="st">/shared/wp-content/uploads/"</span></span>
<span id="cb4-103"><a href="#cb4-103" aria-hidden="true"></a><span class="fu">mv</span> wp-config.php <span class="st">"</span><span class="va">$DEPLOY_PATH</span><span class="st">/shared/"</span></span>
<span id="cb4-104"><a href="#cb4-104" aria-hidden="true"></a></span>
<span id="cb4-105"><a href="#cb4-105" aria-hidden="true"></a><span class="co"># Install SSL certificate (Let's Encrypt)</span></span>
<span id="cb4-106"><a href="#cb4-106" aria-hidden="true"></a><span class="kw">if</span><span class="bu"> [</span> <span class="st">"</span><span class="va">$SSL_ENABLED</span><span class="st">"</span> <span class="ot">=</span> <span class="st">"true"</span><span class="bu"> ]</span>; <span class="kw">then</span></span>
<span id="cb4-107"><a href="#cb4-107" aria-hidden="true"></a>    <span class="ex">log</span> <span class="st">"Installing SSL certificate..."</span></span>
<span id="cb4-108"><a href="#cb4-108" aria-hidden="true"></a>    <span class="fu">sudo</span> apt-get install -y certbot python3-certbot-nginx</span>
<span id="cb4-109"><a href="#cb4-109" aria-hidden="true"></a>    <span class="fu">sudo</span> certbot --nginx -d <span class="st">"</span><span class="va">$SERVER_NAME</span><span class="st">"</span> --non-interactive --agree-tos -m <span class="st">"</span><span class="va">$ADMIN_EMAIL</span><span class="st">"</span></span>
<span id="cb4-110"><a href="#cb4-110" aria-hidden="true"></a><span class="kw">fi</span></span>
<span id="cb4-111"><a href="#cb4-111" aria-hidden="true"></a></span>
<span id="cb4-112"><a href="#cb4-112" aria-hidden="true"></a><span class="ex">log</span> <span class="st">"✓ Server provisioning complete"</span></span>
<span id="cb4-113"><a href="#cb4-113" aria-hidden="true"></a><span class="ex">log</span> <span class="st">"WordPress URL: </span><span class="va">$SITE_URL</span><span class="st">"</span></span>
<span id="cb4-114"><a href="#cb4-114" aria-hidden="true"></a><span class="ex">log</span> <span class="st">"Admin user: </span><span class="va">$ADMIN_USER</span><span class="st">"</span></span></code></pre>
</div>



<h4 class="wp-block-heading" id="environment-configuration-template">Environment Configuration Template</h4>



<div class="sourceCode" id="cb5">
<pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true"></a><span class="co"># config/environments/production.conf</span></span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true"></a></span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true"></a><span class="co"># Server settings</span></span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true"></a><span class="va">SERVER_NAME=</span><span class="st">"example.com"</span></span>
<span id="cb5-5"><a href="#cb5-5" aria-hidden="true"></a><span class="va">SITE_URL=</span><span class="st">"https://example.com"</span></span>
<span id="cb5-6"><a href="#cb5-6" aria-hidden="true"></a><span class="va">SITE_TITLE=</span><span class="st">"Production Site"</span></span>
<span id="cb5-7"><a href="#cb5-7" aria-hidden="true"></a></span>
<span id="cb5-8"><a href="#cb5-8" aria-hidden="true"></a><span class="co"># Deployment paths</span></span>
<span id="cb5-9"><a href="#cb5-9" aria-hidden="true"></a><span class="va">DEPLOY_PATH=</span><span class="st">"/var/www/production"</span></span>
<span id="cb5-10"><a href="#cb5-10" aria-hidden="true"></a><span class="va">RELEASE_DIR=</span><span class="st">"</span><span class="va">$DEPLOY_PATH</span><span class="st">/releases"</span></span>
<span id="cb5-11"><a href="#cb5-11" aria-hidden="true"></a><span class="va">SHARED_DIR=</span><span class="st">"</span><span class="va">$DEPLOY_PATH</span><span class="st">/shared"</span></span>
<span id="cb5-12"><a href="#cb5-12" aria-hidden="true"></a><span class="va">CURRENT_LINK=</span><span class="st">"</span><span class="va">$DEPLOY_PATH</span><span class="st">/current"</span></span>
<span id="cb5-13"><a href="#cb5-13" aria-hidden="true"></a></span>
<span id="cb5-14"><a href="#cb5-14" aria-hidden="true"></a><span class="co"># Database credentials</span></span>
<span id="cb5-15"><a href="#cb5-15" aria-hidden="true"></a><span class="va">DB_NAME=</span><span class="st">"wp_production"</span></span>
<span id="cb5-16"><a href="#cb5-16" aria-hidden="true"></a><span class="va">DB_USER=</span><span class="st">"wp_user"</span></span>
<span id="cb5-17"><a href="#cb5-17" aria-hidden="true"></a><span class="va">DB_PASS=</span><span class="st">"strong-password-here"</span></span>
<span id="cb5-18"><a href="#cb5-18" aria-hidden="true"></a><span class="va">DB_HOST=</span><span class="st">"localhost"</span></span>
<span id="cb5-19"><a href="#cb5-19" aria-hidden="true"></a></span>
<span id="cb5-20"><a href="#cb5-20" aria-hidden="true"></a><span class="co"># WordPress admin</span></span>
<span id="cb5-21"><a href="#cb5-21" aria-hidden="true"></a><span class="va">ADMIN_USER=</span><span class="st">"admin"</span></span>
<span id="cb5-22"><a href="#cb5-22" aria-hidden="true"></a><span class="va">ADMIN_PASS=</span><span class="st">"admin-password-here"</span></span>
<span id="cb5-23"><a href="#cb5-23" aria-hidden="true"></a><span class="va">ADMIN_EMAIL=</span><span class="st">"admin@example.com"</span></span>
<span id="cb5-24"><a href="#cb5-24" aria-hidden="true"></a></span>
<span id="cb5-25"><a href="#cb5-25" aria-hidden="true"></a><span class="co"># Git repository</span></span>
<span id="cb5-26"><a href="#cb5-26" aria-hidden="true"></a><span class="va">GIT_REPO=</span><span class="st">"git@github.com:yourcompany/wordpress-site.git"</span></span>
<span id="cb5-27"><a href="#cb5-27" aria-hidden="true"></a><span class="va">GIT_BRANCH=</span><span class="st">"main"</span></span>
<span id="cb5-28"><a href="#cb5-28" aria-hidden="true"></a></span>
<span id="cb5-29"><a href="#cb5-29" aria-hidden="true"></a><span class="co"># Deployment settings</span></span>
<span id="cb5-30"><a href="#cb5-30" aria-hidden="true"></a><span class="va">KEEP_RELEASES=</span>5</span>
<span id="cb5-31"><a href="#cb5-31" aria-hidden="true"></a><span class="va">BACKUP_RETENTION_DAYS=</span>30</span>
<span id="cb5-32"><a href="#cb5-32" aria-hidden="true"></a><span class="va">SSL_ENABLED=</span>true</span>
<span id="cb5-33"><a href="#cb5-33" aria-hidden="true"></a></span>
<span id="cb5-34"><a href="#cb5-34" aria-hidden="true"></a><span class="co"># Notifications</span></span>
<span id="cb5-35"><a href="#cb5-35" aria-hidden="true"></a><span class="va">SLACK_WEBHOOK=</span><span class="st">"https://hooks.slack.com/services/YOUR/WEBHOOK/URL"</span></span>
<span id="cb5-36"><a href="#cb5-36" aria-hidden="true"></a><span class="va">EMAIL_NOTIFICATIONS=</span><span class="st">"team@example.com"</span></span></code></pre>
</div>



<p>Learn about <a href="https://wordpress.org/about/requirements/">WordPress server requirements</a>.</p>



<h3 class="wp-block-heading" id="zero-downtime">Zero-Downtime Deployment Implementation</h3>



<p>Deploy code changes without taking site offline.</p>



<h4 class="wp-block-heading" id="main-deployment-script">Main Deployment Script</h4>



<div class="sourceCode" id="cb6">
<pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true"></a><span class="co">#!/bin/bash</span></span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true"></a><span class="co"># bin/deploy - Main deployment command</span></span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true"></a></span>
<span id="cb6-4"><a href="#cb6-4" aria-hidden="true"></a><span class="kw">set</span> <span class="ex">-euo</span> pipefail</span>
<span id="cb6-5"><a href="#cb6-5" aria-hidden="true"></a></span>
<span id="cb6-6"><a href="#cb6-6" aria-hidden="true"></a><span class="bu">source</span> <span class="st">"</span><span class="va">$(</span><span class="fu">dirname</span> <span class="st">"</span><span class="va">$0</span><span class="st">"</span><span class="va">)</span><span class="st">/../lib/common.sh"</span></span>
<span id="cb6-7"><a href="#cb6-7" aria-hidden="true"></a><span class="bu">source</span> <span class="st">"</span><span class="va">$(</span><span class="fu">dirname</span> <span class="st">"</span><span class="va">$0</span><span class="st">"</span><span class="va">)</span><span class="st">/../lib/deploy.sh"</span></span>
<span id="cb6-8"><a href="#cb6-8" aria-hidden="true"></a></span>
<span id="cb6-9"><a href="#cb6-9" aria-hidden="true"></a><span class="va">ENVIRONMENT=</span><span class="st">"</span><span class="va">${1:-</span>staging<span class="va">}</span><span class="st">"</span></span>
<span id="cb6-10"><a href="#cb6-10" aria-hidden="true"></a><span class="va">RELEASE_TAG=</span><span class="st">"</span><span class="va">${2:-</span>HEAD<span class="va">}</span><span class="st">"</span></span>
<span id="cb6-11"><a href="#cb6-11" aria-hidden="true"></a><span class="va">CONFIG_FILE=</span><span class="st">"</span><span class="va">$CONFIG_DIR</span><span class="st">/environments/</span><span class="va">$ENVIRONMENT</span><span class="st">.conf"</span></span>
<span id="cb6-12"><a href="#cb6-12" aria-hidden="true"></a></span>
<span id="cb6-13"><a href="#cb6-13" aria-hidden="true"></a><span class="kw">if</span><span class="bu"> [</span> <span class="ot">!</span> <span class="ot">-f</span> <span class="st">"</span><span class="va">$CONFIG_FILE</span><span class="st">"</span><span class="bu"> ]</span>; <span class="kw">then</span></span>
<span id="cb6-14"><a href="#cb6-14" aria-hidden="true"></a>    <span class="ex">error</span> <span class="st">"Configuration not found: </span><span class="va">$CONFIG_FILE</span><span class="st">"</span></span>
<span id="cb6-15"><a href="#cb6-15" aria-hidden="true"></a><span class="kw">fi</span></span>
<span id="cb6-16"><a href="#cb6-16" aria-hidden="true"></a></span>
<span id="cb6-17"><a href="#cb6-17" aria-hidden="true"></a><span class="bu">source</span> <span class="st">"</span><span class="va">$CONFIG_FILE</span><span class="st">"</span></span>
<span id="cb6-18"><a href="#cb6-18" aria-hidden="true"></a></span>
<span id="cb6-19"><a href="#cb6-19" aria-hidden="true"></a><span class="ex">log</span> <span class="st">"=== WordPress Deployment Started ==="</span></span>
<span id="cb6-20"><a href="#cb6-20" aria-hidden="true"></a><span class="ex">log</span> <span class="st">"Environment: </span><span class="va">$ENVIRONMENT</span><span class="st">"</span></span>
<span id="cb6-21"><a href="#cb6-21" aria-hidden="true"></a><span class="ex">log</span> <span class="st">"Release: </span><span class="va">$RELEASE_TAG</span><span class="st">"</span></span>
<span id="cb6-22"><a href="#cb6-22" aria-hidden="true"></a><span class="ex">log</span> <span class="st">"Time: </span><span class="va">$(</span><span class="fu">date</span><span class="va">)</span><span class="st">"</span></span>
<span id="cb6-23"><a href="#cb6-23" aria-hidden="true"></a></span>
<span id="cb6-24"><a href="#cb6-24" aria-hidden="true"></a><span class="co"># Pre-deployment checks</span></span>
<span id="cb6-25"><a href="#cb6-25" aria-hidden="true"></a><span class="ex">log</span> <span class="st">"Running pre-deployment checks..."</span></span>
<span id="cb6-26"><a href="#cb6-26" aria-hidden="true"></a><span class="ex">run_hook</span> <span class="st">"pre-deploy"</span> <span class="kw">||</span> <span class="ex">error</span> <span class="st">"Pre-deployment checks failed"</span></span>
<span id="cb6-27"><a href="#cb6-27" aria-hidden="true"></a></span>
<span id="cb6-28"><a href="#cb6-28" aria-hidden="true"></a><span class="co"># Create backup</span></span>
<span id="cb6-29"><a href="#cb6-29" aria-hidden="true"></a><span class="ex">log</span> <span class="st">"Creating pre-deployment backup..."</span></span>
<span id="cb6-30"><a href="#cb6-30" aria-hidden="true"></a><span class="st">"</span><span class="va">$BIN_DIR</span><span class="st">/backup"</span> <span class="st">"</span><span class="va">$ENVIRONMENT</span><span class="st">"</span> <span class="kw">||</span> <span class="ex">error</span> <span class="st">"Backup failed"</span></span>
<span id="cb6-31"><a href="#cb6-31" aria-hidden="true"></a></span>
<span id="cb6-32"><a href="#cb6-32" aria-hidden="true"></a><span class="co"># Prepare new release</span></span>
<span id="cb6-33"><a href="#cb6-33" aria-hidden="true"></a><span class="va">RELEASE_ID=$(</span><span class="fu">date</span> +%Y%m%d_%H%M%S<span class="va">)</span></span>
<span id="cb6-34"><a href="#cb6-34" aria-hidden="true"></a><span class="va">RELEASE_PATH=</span><span class="st">"</span><span class="va">$RELEASE_DIR</span><span class="st">/</span><span class="va">$RELEASE_ID</span><span class="st">"</span></span>
<span id="cb6-35"><a href="#cb6-35" aria-hidden="true"></a></span>
<span id="cb6-36"><a href="#cb6-36" aria-hidden="true"></a><span class="ex">log</span> <span class="st">"Creating release: </span><span class="va">$RELEASE_ID</span><span class="st">"</span></span>
<span id="cb6-37"><a href="#cb6-37" aria-hidden="true"></a><span class="fu">mkdir</span> -p <span class="st">"</span><span class="va">$RELEASE_PATH</span><span class="st">"</span></span>
<span id="cb6-38"><a href="#cb6-38" aria-hidden="true"></a></span>
<span id="cb6-39"><a href="#cb6-39" aria-hidden="true"></a><span class="co"># Clone code from Git</span></span>
<span id="cb6-40"><a href="#cb6-40" aria-hidden="true"></a><span class="ex">log</span> <span class="st">"Cloning repository..."</span></span>
<span id="cb6-41"><a href="#cb6-41" aria-hidden="true"></a><span class="fu">git</span> clone --depth 1 --branch <span class="st">"</span><span class="va">$GIT_BRANCH</span><span class="st">"</span> <span class="st">"</span><span class="va">$GIT_REPO</span><span class="st">"</span> <span class="st">"</span><span class="va">$RELEASE_PATH</span><span class="st">"</span></span>
<span id="cb6-42"><a href="#cb6-42" aria-hidden="true"></a><span class="bu">cd</span> <span class="st">"</span><span class="va">$RELEASE_PATH</span><span class="st">"</span></span>
<span id="cb6-43"><a href="#cb6-43" aria-hidden="true"></a></span>
<span id="cb6-44"><a href="#cb6-44" aria-hidden="true"></a><span class="co"># Install dependencies</span></span>
<span id="cb6-45"><a href="#cb6-45" aria-hidden="true"></a><span class="ex">log</span> <span class="st">"Installing dependencies..."</span></span>
<span id="cb6-46"><a href="#cb6-46" aria-hidden="true"></a><span class="kw">if</span><span class="bu"> [</span> <span class="ot">-f</span> composer.json<span class="bu"> ]</span>; <span class="kw">then</span></span>
<span id="cb6-47"><a href="#cb6-47" aria-hidden="true"></a>    <span class="ex">composer</span> install --no-dev --optimize-autoloader</span>
<span id="cb6-48"><a href="#cb6-48" aria-hidden="true"></a><span class="kw">fi</span></span>
<span id="cb6-49"><a href="#cb6-49" aria-hidden="true"></a></span>
<span id="cb6-50"><a href="#cb6-50" aria-hidden="true"></a><span class="kw">if</span><span class="bu"> [</span> <span class="ot">-f</span> package.json<span class="bu"> ]</span>; <span class="kw">then</span></span>
<span id="cb6-51"><a href="#cb6-51" aria-hidden="true"></a>    <span class="ex">npm</span> ci --production</span>
<span id="cb6-52"><a href="#cb6-52" aria-hidden="true"></a>    <span class="ex">npm</span> run build</span>
<span id="cb6-53"><a href="#cb6-53" aria-hidden="true"></a><span class="kw">fi</span></span>
<span id="cb6-54"><a href="#cb6-54" aria-hidden="true"></a></span>
<span id="cb6-55"><a href="#cb6-55" aria-hidden="true"></a><span class="co"># Link shared directories</span></span>
<span id="cb6-56"><a href="#cb6-56" aria-hidden="true"></a><span class="ex">log</span> <span class="st">"Linking shared resources..."</span></span>
<span id="cb6-57"><a href="#cb6-57" aria-hidden="true"></a><span class="fu">ln</span> -nfs <span class="st">"</span><span class="va">$SHARED_DIR</span><span class="st">/wp-content/uploads"</span> <span class="st">"</span><span class="va">$RELEASE_PATH</span><span class="st">/wp-content/uploads"</span></span>
<span id="cb6-58"><a href="#cb6-58" aria-hidden="true"></a><span class="fu">ln</span> -nfs <span class="st">"</span><span class="va">$SHARED_DIR</span><span class="st">/wp-config.php"</span> <span class="st">"</span><span class="va">$RELEASE_PATH</span><span class="st">/wp-config.php"</span></span>
<span id="cb6-59"><a href="#cb6-59" aria-hidden="true"></a></span>
<span id="cb6-60"><a href="#cb6-60" aria-hidden="true"></a><span class="co"># Run database migrations</span></span>
<span id="cb6-61"><a href="#cb6-61" aria-hidden="true"></a><span class="ex">log</span> <span class="st">"Running database migrations..."</span></span>
<span id="cb6-62"><a href="#cb6-62" aria-hidden="true"></a><span class="ex">run_migrations</span> <span class="st">"</span><span class="va">$RELEASE_PATH</span><span class="st">"</span> <span class="kw">||</span> <span class="kw">{</span></span>
<span id="cb6-63"><a href="#cb6-63" aria-hidden="true"></a>    <span class="ex">error</span> <span class="st">"Database migration failed"</span></span>
<span id="cb6-64"><a href="#cb6-64" aria-hidden="true"></a>    <span class="ex">rollback_deployment</span> <span class="st">"</span><span class="va">$ENVIRONMENT</span><span class="st">"</span> <span class="st">"</span><span class="va">$RELEASE_ID</span><span class="st">"</span></span>
<span id="cb6-65"><a href="#cb6-65" aria-hidden="true"></a>    <span class="bu">exit</span> 1</span>
<span id="cb6-66"><a href="#cb6-66" aria-hidden="true"></a><span class="kw">}</span></span>
<span id="cb6-67"><a href="#cb6-67" aria-hidden="true"></a></span>
<span id="cb6-68"><a href="#cb6-68" aria-hidden="true"></a><span class="co"># Health check on new release</span></span>
<span id="cb6-69"><a href="#cb6-69" aria-hidden="true"></a><span class="ex">log</span> <span class="st">"Running health checks..."</span></span>
<span id="cb6-70"><a href="#cb6-70" aria-hidden="true"></a><span class="ex">test_release</span> <span class="st">"</span><span class="va">$RELEASE_PATH</span><span class="st">"</span> <span class="kw">||</span> <span class="kw">{</span></span>
<span id="cb6-71"><a href="#cb6-71" aria-hidden="true"></a>    <span class="ex">error</span> <span class="st">"Health checks failed"</span></span>
<span id="cb6-72"><a href="#cb6-72" aria-hidden="true"></a>    <span class="ex">rollback_deployment</span> <span class="st">"</span><span class="va">$ENVIRONMENT</span><span class="st">"</span> <span class="st">"</span><span class="va">$RELEASE_ID</span><span class="st">"</span></span>
<span id="cb6-73"><a href="#cb6-73" aria-hidden="true"></a>    <span class="bu">exit</span> 1</span>
<span id="cb6-74"><a href="#cb6-74" aria-hidden="true"></a><span class="kw">}</span></span>
<span id="cb6-75"><a href="#cb6-75" aria-hidden="true"></a></span>
<span id="cb6-76"><a href="#cb6-76" aria-hidden="true"></a><span class="co"># Atomic switch to new release</span></span>
<span id="cb6-77"><a href="#cb6-77" aria-hidden="true"></a><span class="ex">log</span> <span class="st">"Switching to new release..."</span></span>
<span id="cb6-78"><a href="#cb6-78" aria-hidden="true"></a><span class="fu">ln</span> -nfs <span class="st">"</span><span class="va">$RELEASE_PATH</span><span class="st">"</span> <span class="st">"</span><span class="va">$CURRENT_LINK</span><span class="st">"</span></span>
<span id="cb6-79"><a href="#cb6-79" aria-hidden="true"></a></span>
<span id="cb6-80"><a href="#cb6-80" aria-hidden="true"></a><span class="co"># Post-deployment tasks</span></span>
<span id="cb6-81"><a href="#cb6-81" aria-hidden="true"></a><span class="ex">log</span> <span class="st">"Running post-deployment tasks..."</span></span>
<span id="cb6-82"><a href="#cb6-82" aria-hidden="true"></a><span class="bu">cd</span> <span class="st">"</span><span class="va">$CURRENT_LINK</span><span class="st">"</span></span>
<span id="cb6-83"><a href="#cb6-83" aria-hidden="true"></a><span class="ex">wp</span> cache flush</span>
<span id="cb6-84"><a href="#cb6-84" aria-hidden="true"></a><span class="ex">wp</span> rewrite flush</span>
<span id="cb6-85"><a href="#cb6-85" aria-hidden="true"></a></span>
<span id="cb6-86"><a href="#cb6-86" aria-hidden="true"></a><span class="ex">run_hook</span> <span class="st">"post-deploy"</span></span>
<span id="cb6-87"><a href="#cb6-87" aria-hidden="true"></a></span>
<span id="cb6-88"><a href="#cb6-88" aria-hidden="true"></a><span class="co"># Cleanup old releases</span></span>
<span id="cb6-89"><a href="#cb6-89" aria-hidden="true"></a><span class="ex">log</span> <span class="st">"Cleaning up old releases..."</span></span>
<span id="cb6-90"><a href="#cb6-90" aria-hidden="true"></a><span class="ex">cleanup_releases</span> <span class="st">"</span><span class="va">$RELEASE_DIR</span><span class="st">"</span> <span class="st">"</span><span class="va">$KEEP_RELEASES</span><span class="st">"</span></span>
<span id="cb6-91"><a href="#cb6-91" aria-hidden="true"></a></span>
<span id="cb6-92"><a href="#cb6-92" aria-hidden="true"></a><span class="co"># Send notifications</span></span>
<span id="cb6-93"><a href="#cb6-93" aria-hidden="true"></a><span class="ex">notify_deployment</span> <span class="st">"success"</span> <span class="st">"</span><span class="va">$ENVIRONMENT</span><span class="st">"</span> <span class="st">"</span><span class="va">$RELEASE_ID</span><span class="st">"</span></span>
<span id="cb6-94"><a href="#cb6-94" aria-hidden="true"></a></span>
<span id="cb6-95"><a href="#cb6-95" aria-hidden="true"></a><span class="ex">log</span> <span class="st">"=== Deployment Complete ==="</span></span>
<span id="cb6-96"><a href="#cb6-96" aria-hidden="true"></a><span class="ex">log</span> <span class="st">"Active release: </span><span class="va">$RELEASE_ID</span><span class="st">"</span></span>
<span id="cb6-97"><a href="#cb6-97" aria-hidden="true"></a><span class="ex">log</span> <span class="st">"Site URL: </span><span class="va">$SITE_URL</span><span class="st">"</span></span></code></pre>
</div>



<h4 class="wp-block-heading" id="shared-functions-library">Shared Functions Library</h4>



<div class="sourceCode" id="cb7">
<pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true"></a><span class="co"># lib/common.sh - Common utilities</span></span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true"></a></span>
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true"></a><span class="va">LOG_FILE=</span><span class="st">"</span><span class="va">$LOG_DIR</span><span class="st">/deploy-</span><span class="va">$(</span><span class="fu">date</span> +%Y%m%d<span class="va">)</span><span class="st">.log"</span></span>
<span id="cb7-4"><a href="#cb7-4" aria-hidden="true"></a></span>
<span id="cb7-5"><a href="#cb7-5" aria-hidden="true"></a><span class="fu">log()</span> <span class="kw">{</span></span>
<span id="cb7-6"><a href="#cb7-6" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"[</span><span class="va">$(</span><span class="fu">date</span> <span class="st">'+%Y-%m-%d %H:%M:%S'</span><span class="va">)</span><span class="st">] </span><span class="va">$@</span><span class="st">"</span> <span class="kw">|</span> <span class="fu">tee</span> -a <span class="st">"</span><span class="va">$LOG_FILE</span><span class="st">"</span></span>
<span id="cb7-7"><a href="#cb7-7" aria-hidden="true"></a><span class="kw">}</span></span>
<span id="cb7-8"><a href="#cb7-8" aria-hidden="true"></a></span>
<span id="cb7-9"><a href="#cb7-9" aria-hidden="true"></a><span class="fu">error()</span> <span class="kw">{</span></span>
<span id="cb7-10"><a href="#cb7-10" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"[ERROR] </span><span class="va">$@</span><span class="st">"</span> <span class="kw">|</span> <span class="fu">tee</span> -a <span class="st">"</span><span class="va">$LOG_FILE</span><span class="st">"</span> <span class="op">&gt;&amp;2</span></span>
<span id="cb7-11"><a href="#cb7-11" aria-hidden="true"></a>    <span class="ex">notify_deployment</span> <span class="st">"failure"</span> <span class="st">"</span><span class="va">$ENVIRONMENT</span><span class="st">"</span> <span class="st">"</span><span class="va">$RELEASE_ID</span><span class="st">"</span></span>
<span id="cb7-12"><a href="#cb7-12" aria-hidden="true"></a>    <span class="bu">exit</span> 1</span>
<span id="cb7-13"><a href="#cb7-13" aria-hidden="true"></a><span class="kw">}</span></span>
<span id="cb7-14"><a href="#cb7-14" aria-hidden="true"></a></span>
<span id="cb7-15"><a href="#cb7-15" aria-hidden="true"></a><span class="fu">run_hook()</span> <span class="kw">{</span></span>
<span id="cb7-16"><a href="#cb7-16" aria-hidden="true"></a>    <span class="bu">local</span> <span class="va">hook_name=</span><span class="st">"</span><span class="va">$1</span><span class="st">"</span></span>
<span id="cb7-17"><a href="#cb7-17" aria-hidden="true"></a>    <span class="bu">local</span> <span class="va">hook_script=</span><span class="st">"</span><span class="va">$HOOKS_DIR</span><span class="st">/</span><span class="va">${hook_name}</span><span class="st">.sh"</span></span>
<span id="cb7-18"><a href="#cb7-18" aria-hidden="true"></a></span>
<span id="cb7-19"><a href="#cb7-19" aria-hidden="true"></a>    <span class="kw">if</span><span class="bu"> [</span> <span class="ot">-f</span> <span class="st">"</span><span class="va">$hook_script</span><span class="st">"</span><span class="bu"> ]</span>; <span class="kw">then</span></span>
<span id="cb7-20"><a href="#cb7-20" aria-hidden="true"></a>        <span class="ex">log</span> <span class="st">"Running hook: </span><span class="va">$hook_name</span><span class="st">"</span></span>
<span id="cb7-21"><a href="#cb7-21" aria-hidden="true"></a>        <span class="fu">bash</span> <span class="st">"</span><span class="va">$hook_script</span><span class="st">"</span> <span class="st">"</span><span class="va">$ENVIRONMENT</span><span class="st">"</span></span>
<span id="cb7-22"><a href="#cb7-22" aria-hidden="true"></a>    <span class="kw">fi</span></span>
<span id="cb7-23"><a href="#cb7-23" aria-hidden="true"></a><span class="kw">}</span></span>
<span id="cb7-24"><a href="#cb7-24" aria-hidden="true"></a></span>
<span id="cb7-25"><a href="#cb7-25" aria-hidden="true"></a><span class="fu">notify_deployment()</span> <span class="kw">{</span></span>
<span id="cb7-26"><a href="#cb7-26" aria-hidden="true"></a>    <span class="bu">local</span> <span class="va">status=</span><span class="st">"</span><span class="va">$1</span><span class="st">"</span></span>
<span id="cb7-27"><a href="#cb7-27" aria-hidden="true"></a>    <span class="bu">local</span> <span class="va">environment=</span><span class="st">"</span><span class="va">$2</span><span class="st">"</span></span>
<span id="cb7-28"><a href="#cb7-28" aria-hidden="true"></a>    <span class="bu">local</span> <span class="va">release=</span><span class="st">"</span><span class="va">$3</span><span class="st">"</span></span>
<span id="cb7-29"><a href="#cb7-29" aria-hidden="true"></a></span>
<span id="cb7-30"><a href="#cb7-30" aria-hidden="true"></a>    <span class="co"># Slack notification</span></span>
<span id="cb7-31"><a href="#cb7-31" aria-hidden="true"></a>    <span class="kw">if</span><span class="bu"> [</span> <span class="ot">-n</span> <span class="st">"</span><span class="va">$SLACK_WEBHOOK</span><span class="st">"</span><span class="bu"> ]</span>; <span class="kw">then</span></span>
<span id="cb7-32"><a href="#cb7-32" aria-hidden="true"></a>        <span class="ex">curl</span> -X POST <span class="st">"</span><span class="va">$SLACK_WEBHOOK</span><span class="st">"</span> <span class="kw">\</span></span>
<span id="cb7-33"><a href="#cb7-33" aria-hidden="true"></a>            <span class="ex">-H</span> <span class="st">'Content-Type: application/json'</span> <span class="kw">\</span></span>
<span id="cb7-34"><a href="#cb7-34" aria-hidden="true"></a>            <span class="ex">-d</span> <span class="st">"{</span><span class="dt">\"</span><span class="st">text</span><span class="dt">\"</span><span class="st">:</span><span class="dt">\"</span><span class="st">Deployment </span><span class="va">$status</span><span class="st">: </span><span class="va">$environment</span><span class="st"> (</span><span class="va">$release</span><span class="st">)</span><span class="dt">\"</span><span class="st">}"</span></span>
<span id="cb7-35"><a href="#cb7-35" aria-hidden="true"></a>    <span class="kw">fi</span></span>
<span id="cb7-36"><a href="#cb7-36" aria-hidden="true"></a></span>
<span id="cb7-37"><a href="#cb7-37" aria-hidden="true"></a>    <span class="co"># Email notification</span></span>
<span id="cb7-38"><a href="#cb7-38" aria-hidden="true"></a>    <span class="kw">if</span><span class="bu"> [</span> <span class="ot">-n</span> <span class="st">"</span><span class="va">$EMAIL_NOTIFICATIONS</span><span class="st">"</span><span class="bu"> ]</span>; <span class="kw">then</span></span>
<span id="cb7-39"><a href="#cb7-39" aria-hidden="true"></a>        <span class="bu">echo</span> <span class="st">"Deployment </span><span class="va">$status</span><span class="st"> on </span><span class="va">$environment</span><span class="st"> (Release: </span><span class="va">$release</span><span class="st">)"</span> <span class="kw">|</span> <span class="kw">\</span></span>
<span id="cb7-40"><a href="#cb7-40" aria-hidden="true"></a>            <span class="ex">mail</span> -s <span class="st">"WordPress Deployment </span><span class="va">$status</span><span class="st">"</span> <span class="st">"</span><span class="va">$EMAIL_NOTIFICATIONS</span><span class="st">"</span></span>
<span id="cb7-41"><a href="#cb7-41" aria-hidden="true"></a>    <span class="kw">fi</span></span>
<span id="cb7-42"><a href="#cb7-42" aria-hidden="true"></a><span class="kw">}</span></span>
<span id="cb7-43"><a href="#cb7-43" aria-hidden="true"></a></span>
<span id="cb7-44"><a href="#cb7-44" aria-hidden="true"></a><span class="fu">cleanup_releases()</span> <span class="kw">{</span></span>
<span id="cb7-45"><a href="#cb7-45" aria-hidden="true"></a>    <span class="bu">local</span> <span class="va">release_dir=</span><span class="st">"</span><span class="va">$1</span><span class="st">"</span></span>
<span id="cb7-46"><a href="#cb7-46" aria-hidden="true"></a>    <span class="bu">local</span> <span class="va">keep_count=</span><span class="st">"</span><span class="va">$2</span><span class="st">"</span></span>
<span id="cb7-47"><a href="#cb7-47" aria-hidden="true"></a></span>
<span id="cb7-48"><a href="#cb7-48" aria-hidden="true"></a>    <span class="bu">cd</span> <span class="st">"</span><span class="va">$release_dir</span><span class="st">"</span></span>
<span id="cb7-49"><a href="#cb7-49" aria-hidden="true"></a>    <span class="fu">ls</span> -t <span class="kw">|</span> <span class="fu">tail</span> -n +<span class="va">$((</span>keep_count + 1<span class="va">))</span> <span class="kw">|</span> <span class="fu">xargs</span> rm -rf</span>
<span id="cb7-50"><a href="#cb7-50" aria-hidden="true"></a><span class="kw">}</span></span></code></pre>
</div>



<h3 class="wp-block-heading" id="migrations">Database Migration System</h3>



<p>Manage database schema changes safely.</p>



<h4 class="wp-block-heading" id="migration-runner">Migration Runner</h4>



<div class="sourceCode" id="cb8">
<pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true"></a><span class="co"># lib/database.sh - Database migration functions</span></span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true"></a></span>
<span id="cb8-3"><a href="#cb8-3" aria-hidden="true"></a><span class="fu">run_migrations()</span> <span class="kw">{</span></span>
<span id="cb8-4"><a href="#cb8-4" aria-hidden="true"></a>    <span class="bu">local</span> <span class="va">release_path=</span><span class="st">"</span><span class="va">$1</span><span class="st">"</span></span>
<span id="cb8-5"><a href="#cb8-5" aria-hidden="true"></a>    <span class="bu">local</span> <span class="va">migration_dir=</span><span class="st">"</span><span class="va">$MIGRATIONS_DIR</span><span class="st">"</span></span>
<span id="cb8-6"><a href="#cb8-6" aria-hidden="true"></a>    <span class="bu">local</span> <span class="va">applied_file=</span><span class="st">"</span><span class="va">$SHARED_DIR</span><span class="st">/.applied-migrations"</span></span>
<span id="cb8-7"><a href="#cb8-7" aria-hidden="true"></a></span>
<span id="cb8-8"><a href="#cb8-8" aria-hidden="true"></a>    <span class="fu">touch</span> <span class="st">"</span><span class="va">$applied_file</span><span class="st">"</span></span>
<span id="cb8-9"><a href="#cb8-9" aria-hidden="true"></a></span>
<span id="cb8-10"><a href="#cb8-10" aria-hidden="true"></a>    <span class="ex">log</span> <span class="st">"Checking for pending migrations..."</span></span>
<span id="cb8-11"><a href="#cb8-11" aria-hidden="true"></a></span>
<span id="cb8-12"><a href="#cb8-12" aria-hidden="true"></a>    <span class="kw">for</span> <span class="ex">migration</span> in <span class="va">$(</span><span class="fu">ls</span> <span class="st">"</span><span class="va">$migration_dir</span><span class="st">"</span>/*.sql <span class="kw">|</span> <span class="fu">sort</span><span class="va">)</span><span class="kw">;</span> <span class="kw">do</span></span>
<span id="cb8-13"><a href="#cb8-13" aria-hidden="true"></a>        <span class="bu">local</span> <span class="va">migration_name=$(</span><span class="fu">basename</span> <span class="st">"</span><span class="va">$migration</span><span class="st">"</span><span class="va">)</span></span>
<span id="cb8-14"><a href="#cb8-14" aria-hidden="true"></a></span>
<span id="cb8-15"><a href="#cb8-15" aria-hidden="true"></a>        <span class="co"># Check if already applied</span></span>
<span id="cb8-16"><a href="#cb8-16" aria-hidden="true"></a>        <span class="kw">if</span> <span class="fu">grep</span> -q <span class="st">"</span><span class="va">$migration_name</span><span class="st">"</span> <span class="st">"</span><span class="va">$applied_file</span><span class="st">"</span><span class="kw">;</span> <span class="kw">then</span></span>
<span id="cb8-17"><a href="#cb8-17" aria-hidden="true"></a>            <span class="ex">log</span> <span class="st">"  ⊘ Skipping: </span><span class="va">$migration_name</span><span class="st"> (already applied)"</span></span>
<span id="cb8-18"><a href="#cb8-18" aria-hidden="true"></a>            <span class="bu">continue</span></span>
<span id="cb8-19"><a href="#cb8-19" aria-hidden="true"></a>        <span class="kw">fi</span></span>
<span id="cb8-20"><a href="#cb8-20" aria-hidden="true"></a></span>
<span id="cb8-21"><a href="#cb8-21" aria-hidden="true"></a>        <span class="ex">log</span> <span class="st">"  → Applying: </span><span class="va">$migration_name</span><span class="st">"</span></span>
<span id="cb8-22"><a href="#cb8-22" aria-hidden="true"></a></span>
<span id="cb8-23"><a href="#cb8-23" aria-hidden="true"></a>        <span class="co"># Run migration</span></span>
<span id="cb8-24"><a href="#cb8-24" aria-hidden="true"></a>        <span class="kw">if</span> <span class="ex">wp</span> db query <span class="op">&lt;</span> <span class="st">"</span><span class="va">$migration</span><span class="st">"</span> --path=<span class="st">"</span><span class="va">$release_path</span><span class="st">"</span><span class="kw">;</span> <span class="kw">then</span></span>
<span id="cb8-25"><a href="#cb8-25" aria-hidden="true"></a>            <span class="bu">echo</span> <span class="st">"</span><span class="va">$migration_name</span><span class="st">"</span> <span class="op">&gt;&gt;</span> <span class="st">"</span><span class="va">$applied_file</span><span class="st">"</span></span>
<span id="cb8-26"><a href="#cb8-26" aria-hidden="true"></a>            <span class="ex">log</span> <span class="st">"  ✓ Applied: </span><span class="va">$migration_name</span><span class="st">"</span></span>
<span id="cb8-27"><a href="#cb8-27" aria-hidden="true"></a>        <span class="kw">else</span></span>
<span id="cb8-28"><a href="#cb8-28" aria-hidden="true"></a>            <span class="ex">error</span> <span class="st">"Migration failed: </span><span class="va">$migration_name</span><span class="st">"</span></span>
<span id="cb8-29"><a href="#cb8-29" aria-hidden="true"></a>        <span class="kw">fi</span></span>
<span id="cb8-30"><a href="#cb8-30" aria-hidden="true"></a>    <span class="kw">done</span></span>
<span id="cb8-31"><a href="#cb8-31" aria-hidden="true"></a></span>
<span id="cb8-32"><a href="#cb8-32" aria-hidden="true"></a>    <span class="ex">log</span> <span class="st">"✓ All migrations applied"</span></span>
<span id="cb8-33"><a href="#cb8-33" aria-hidden="true"></a><span class="kw">}</span></span>
<span id="cb8-34"><a href="#cb8-34" aria-hidden="true"></a></span>
<span id="cb8-35"><a href="#cb8-35" aria-hidden="true"></a><span class="fu">rollback_migration()</span> <span class="kw">{</span></span>
<span id="cb8-36"><a href="#cb8-36" aria-hidden="true"></a>    <span class="bu">local</span> <span class="va">migration_name=</span><span class="st">"</span><span class="va">$1</span><span class="st">"</span></span>
<span id="cb8-37"><a href="#cb8-37" aria-hidden="true"></a>    <span class="bu">local</span> <span class="va">rollback_file=</span><span class="st">"</span><span class="va">$MIGRATIONS_DIR</span><span class="st">/</span><span class="va">${migration_name%</span>.sql<span class="va">}</span><span class="st">-rollback.sql"</span></span>
<span id="cb8-38"><a href="#cb8-38" aria-hidden="true"></a></span>
<span id="cb8-39"><a href="#cb8-39" aria-hidden="true"></a>    <span class="kw">if</span><span class="bu"> [</span> <span class="ot">-f</span> <span class="st">"</span><span class="va">$rollback_file</span><span class="st">"</span><span class="bu"> ]</span>; <span class="kw">then</span></span>
<span id="cb8-40"><a href="#cb8-40" aria-hidden="true"></a>        <span class="ex">log</span> <span class="st">"Rolling back migration: </span><span class="va">$migration_name</span><span class="st">"</span></span>
<span id="cb8-41"><a href="#cb8-41" aria-hidden="true"></a>        <span class="ex">wp</span> db query <span class="op">&lt;</span> <span class="st">"</span><span class="va">$rollback_file</span><span class="st">"</span></span>
<span id="cb8-42"><a href="#cb8-42" aria-hidden="true"></a>    <span class="kw">else</span></span>
<span id="cb8-43"><a href="#cb8-43" aria-hidden="true"></a>        <span class="ex">error</span> <span class="st">"Rollback file not found: </span><span class="va">$rollback_file</span><span class="st">"</span></span>
<span id="cb8-44"><a href="#cb8-44" aria-hidden="true"></a>    <span class="kw">fi</span></span>
<span id="cb8-45"><a href="#cb8-45" aria-hidden="true"></a><span class="kw">}</span></span></code></pre>
</div>



<h4 class="wp-block-heading" id="example-migration-files">Example Migration Files</h4>



<div class="sourceCode" id="cb9">
<pre class="sourceCode sql"><code class="sourceCode sql"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true"></a><span class="co">-- migrations/001-add-custom-tables.sql</span></span>
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true"></a></span>
<span id="cb9-3"><a href="#cb9-3" aria-hidden="true"></a><span class="kw">CREATE</span> <span class="kw">TABLE</span> <span class="cf">IF</span> <span class="kw">NOT</span> <span class="kw">EXISTS</span> wp_custom_data (</span>
<span id="cb9-4"><a href="#cb9-4" aria-hidden="true"></a>    <span class="kw">id</span> BIGINT(<span class="dv">20</span>) UNSIGNED <span class="kw">NOT</span> <span class="kw">NULL</span> AUTO_INCREMENT,</span>
<span id="cb9-5"><a href="#cb9-5" aria-hidden="true"></a>    user_id BIGINT(<span class="dv">20</span>) UNSIGNED <span class="kw">NOT</span> <span class="kw">NULL</span>,</span>
<span id="cb9-6"><a href="#cb9-6" aria-hidden="true"></a>    data_key <span class="dt">VARCHAR</span>(<span class="dv">255</span>) <span class="kw">NOT</span> <span class="kw">NULL</span>,</span>
<span id="cb9-7"><a href="#cb9-7" aria-hidden="true"></a>    data_value LONGTEXT,</span>
<span id="cb9-8"><a href="#cb9-8" aria-hidden="true"></a>    created_at DATETIME <span class="kw">DEFAULT</span> <span class="fu">CURRENT_TIMESTAMP</span>,</span>
<span id="cb9-9"><a href="#cb9-9" aria-hidden="true"></a>    <span class="kw">PRIMARY</span> <span class="kw">KEY</span> (<span class="kw">id</span>),</span>
<span id="cb9-10"><a href="#cb9-10" aria-hidden="true"></a>    <span class="kw">KEY</span> user_id (user_id)</span>
<span id="cb9-11"><a href="#cb9-11" aria-hidden="true"></a>) ENGINE<span class="op">=</span>InnoDB <span class="kw">DEFAULT</span> CHARSET<span class="op">=</span>utf8mb4;</span>
<span id="cb9-12"><a href="#cb9-12" aria-hidden="true"></a></span>
<span id="cb9-13"><a href="#cb9-13" aria-hidden="true"></a><span class="co">-- migrations/001-add-custom-tables-rollback.sql</span></span>
<span id="cb9-14"><a href="#cb9-14" aria-hidden="true"></a></span>
<span id="cb9-15"><a href="#cb9-15" aria-hidden="true"></a><span class="kw">DROP</span> <span class="kw">TABLE</span> <span class="cf">IF</span> <span class="kw">EXISTS</span> wp_custom_data;</span></code></pre>
</div>



<h3 class="wp-block-heading" id="rollback">Rollback System</h3>



<p>Instantly revert failed deployments.</p>



<h4 class="wp-block-heading" id="rollback-script">Rollback Script</h4>



<div class="sourceCode" id="cb10">
<pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true"></a><span class="co">#!/bin/bash</span></span>
<span id="cb10-2"><a href="#cb10-2" aria-hidden="true"></a><span class="co"># bin/rollback - Rollback to previous release</span></span>
<span id="cb10-3"><a href="#cb10-3" aria-hidden="true"></a></span>
<span id="cb10-4"><a href="#cb10-4" aria-hidden="true"></a><span class="kw">set</span> <span class="ex">-euo</span> pipefail</span>
<span id="cb10-5"><a href="#cb10-5" aria-hidden="true"></a></span>
<span id="cb10-6"><a href="#cb10-6" aria-hidden="true"></a><span class="bu">source</span> <span class="st">"</span><span class="va">$(</span><span class="fu">dirname</span> <span class="st">"</span><span class="va">$0</span><span class="st">"</span><span class="va">)</span><span class="st">/../lib/common.sh"</span></span>
<span id="cb10-7"><a href="#cb10-7" aria-hidden="true"></a></span>
<span id="cb10-8"><a href="#cb10-8" aria-hidden="true"></a><span class="va">ENVIRONMENT=</span><span class="st">"</span><span class="va">${1:-</span>staging<span class="va">}</span><span class="st">"</span></span>
<span id="cb10-9"><a href="#cb10-9" aria-hidden="true"></a><span class="va">CONFIG_FILE=</span><span class="st">"</span><span class="va">$CONFIG_DIR</span><span class="st">/environments/</span><span class="va">$ENVIRONMENT</span><span class="st">.conf"</span></span>
<span id="cb10-10"><a href="#cb10-10" aria-hidden="true"></a></span>
<span id="cb10-11"><a href="#cb10-11" aria-hidden="true"></a><span class="bu">source</span> <span class="st">"</span><span class="va">$CONFIG_FILE</span><span class="st">"</span></span>
<span id="cb10-12"><a href="#cb10-12" aria-hidden="true"></a></span>
<span id="cb10-13"><a href="#cb10-13" aria-hidden="true"></a><span class="ex">log</span> <span class="st">"=== Starting Rollback ==="</span></span>
<span id="cb10-14"><a href="#cb10-14" aria-hidden="true"></a></span>
<span id="cb10-15"><a href="#cb10-15" aria-hidden="true"></a><span class="co"># Get current release</span></span>
<span id="cb10-16"><a href="#cb10-16" aria-hidden="true"></a><span class="va">CURRENT=$(</span><span class="fu">readlink</span> <span class="st">"</span><span class="va">$CURRENT_LINK</span><span class="st">"</span><span class="va">)</span></span>
<span id="cb10-17"><a href="#cb10-17" aria-hidden="true"></a><span class="va">CURRENT_NAME=$(</span><span class="fu">basename</span> <span class="st">"</span><span class="va">$CURRENT</span><span class="st">"</span><span class="va">)</span></span>
<span id="cb10-18"><a href="#cb10-18" aria-hidden="true"></a></span>
<span id="cb10-19"><a href="#cb10-19" aria-hidden="true"></a><span class="ex">log</span> <span class="st">"Current release: </span><span class="va">$CURRENT_NAME</span><span class="st">"</span></span>
<span id="cb10-20"><a href="#cb10-20" aria-hidden="true"></a></span>
<span id="cb10-21"><a href="#cb10-21" aria-hidden="true"></a><span class="co"># Get previous release</span></span>
<span id="cb10-22"><a href="#cb10-22" aria-hidden="true"></a><span class="va">PREVIOUS=$(</span><span class="fu">ls</span> -t <span class="st">"</span><span class="va">$RELEASE_DIR</span><span class="st">"</span> <span class="kw">|</span> <span class="fu">grep</span> -v <span class="st">"^</span><span class="va">$CURRENT_NAME</span><span class="st"><pre wp-pre-tag-9=""></pre>quot;</span> <span class="kw">|</span> <span class="fu">head</span> -n 1<span class="va">)</span></span>
<span id="cb10-23"><a href="#cb10-23" aria-hidden="true"></a></span>
<span id="cb10-24"><a href="#cb10-24" aria-hidden="true"></a><span class="kw">if</span><span class="bu"> [</span> <span class="ot">-z</span> <span class="st">"</span><span class="va">$PREVIOUS</span><span class="st">"</span><span class="bu"> ]</span>; <span class="kw">then</span></span>
<span id="cb10-25"><a href="#cb10-25" aria-hidden="true"></a>    <span class="ex">error</span> <span class="st">"No previous release found for rollback"</span></span>
<span id="cb10-26"><a href="#cb10-26" aria-hidden="true"></a><span class="kw">fi</span></span>
<span id="cb10-27"><a href="#cb10-27" aria-hidden="true"></a></span>
<span id="cb10-28"><a href="#cb10-28" aria-hidden="true"></a><span class="va">PREVIOUS_PATH=</span><span class="st">"</span><span class="va">$RELEASE_DIR</span><span class="st">/</span><span class="va">$PREVIOUS</span><span class="st">"</span></span>
<span id="cb10-29"><a href="#cb10-29" aria-hidden="true"></a></span>
<span id="cb10-30"><a href="#cb10-30" aria-hidden="true"></a><span class="ex">log</span> <span class="st">"Rolling back to: </span><span class="va">$PREVIOUS</span><span class="st">"</span></span>
<span id="cb10-31"><a href="#cb10-31" aria-hidden="true"></a></span>
<span id="cb10-32"><a href="#cb10-32" aria-hidden="true"></a><span class="co"># Backup current state (in case rollback fails)</span></span>
<span id="cb10-33"><a href="#cb10-33" aria-hidden="true"></a><span class="va">ROLLBACK_BACKUP=</span><span class="st">"</span><span class="va">$BACKUP_DIR</span><span class="st">/pre-rollback-</span><span class="va">$(</span><span class="fu">date</span> +%Y%m%d_%H%M%S<span class="va">)</span><span class="st">"</span></span>
<span id="cb10-34"><a href="#cb10-34" aria-hidden="true"></a><span class="fu">mkdir</span> -p <span class="st">"</span><span class="va">$ROLLBACK_BACKUP</span><span class="st">"</span></span>
<span id="cb10-35"><a href="#cb10-35" aria-hidden="true"></a><span class="ex">wp</span> db export <span class="st">"</span><span class="va">$ROLLBACK_BACKUP</span><span class="st">/database.sql.gz"</span> --path=<span class="st">"</span><span class="va">$CURRENT</span><span class="st">"</span></span>
<span id="cb10-36"><a href="#cb10-36" aria-hidden="true"></a></span>
<span id="cb10-37"><a href="#cb10-37" aria-hidden="true"></a><span class="co"># Switch to previous release</span></span>
<span id="cb10-38"><a href="#cb10-38" aria-hidden="true"></a><span class="fu">ln</span> -nfs <span class="st">"</span><span class="va">$PREVIOUS_PATH</span><span class="st">"</span> <span class="st">"</span><span class="va">$CURRENT_LINK</span><span class="st">"</span></span>
<span id="cb10-39"><a href="#cb10-39" aria-hidden="true"></a></span>
<span id="cb10-40"><a href="#cb10-40" aria-hidden="true"></a><span class="co"># Clear caches</span></span>
<span id="cb10-41"><a href="#cb10-41" aria-hidden="true"></a><span class="bu">cd</span> <span class="st">"</span><span class="va">$CURRENT_LINK</span><span class="st">"</span></span>
<span id="cb10-42"><a href="#cb10-42" aria-hidden="true"></a><span class="ex">wp</span> cache flush</span>
<span id="cb10-43"><a href="#cb10-43" aria-hidden="true"></a><span class="ex">wp</span> rewrite flush</span>
<span id="cb10-44"><a href="#cb10-44" aria-hidden="true"></a></span>
<span id="cb10-45"><a href="#cb10-45" aria-hidden="true"></a><span class="co"># Verify rollback</span></span>
<span id="cb10-46"><a href="#cb10-46" aria-hidden="true"></a><span class="kw">if</span> <span class="ex">wp</span> core is-installed --path=<span class="st">"</span><span class="va">$CURRENT_LINK</span><span class="st">"</span><span class="kw">;</span> <span class="kw">then</span></span>
<span id="cb10-47"><a href="#cb10-47" aria-hidden="true"></a>    <span class="ex">log</span> <span class="st">"✓ Rollback successful"</span></span>
<span id="cb10-48"><a href="#cb10-48" aria-hidden="true"></a>    <span class="ex">notify_deployment</span> <span class="st">"rollback-success"</span> <span class="st">"</span><span class="va">$ENVIRONMENT</span><span class="st">"</span> <span class="st">"</span><span class="va">$PREVIOUS</span><span class="st">"</span></span>
<span id="cb10-49"><a href="#cb10-49" aria-hidden="true"></a><span class="kw">else</span></span>
<span id="cb10-50"><a href="#cb10-50" aria-hidden="true"></a>    <span class="ex">error</span> <span class="st">"Rollback verification failed"</span></span>
<span id="cb10-51"><a href="#cb10-51" aria-hidden="true"></a><span class="kw">fi</span></span>
<span id="cb10-52"><a href="#cb10-52" aria-hidden="true"></a></span>
<span id="cb10-53"><a href="#cb10-53" aria-hidden="true"></a><span class="ex">log</span> <span class="st">"=== Rollback Complete ==="</span></span>
<span id="cb10-54"><a href="#cb10-54" aria-hidden="true"></a><span class="ex">log</span> <span class="st">"Active release: </span><span class="va">$PREVIOUS</span><span class="st">"</span></span></code></pre>
</div>



<h3 class="wp-block-heading" id="monitoring">Health Monitoring System</h3>



<p>Continuous uptime and performance monitoring.</p>



<h4 class="wp-block-heading" id="monitoring-script">Monitoring Script</h4>



<div class="sourceCode" id="cb11">
<pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true"></a><span class="co">#!/bin/bash</span></span>
<span id="cb11-2"><a href="#cb11-2" aria-hidden="true"></a><span class="co"># bin/monitor - WordPress health monitoring</span></span>
<span id="cb11-3"><a href="#cb11-3" aria-hidden="true"></a></span>
<span id="cb11-4"><a href="#cb11-4" aria-hidden="true"></a><span class="kw">set</span> <span class="ex">-euo</span> pipefail</span>
<span id="cb11-5"><a href="#cb11-5" aria-hidden="true"></a></span>
<span id="cb11-6"><a href="#cb11-6" aria-hidden="true"></a><span class="bu">source</span> <span class="st">"</span><span class="va">$(</span><span class="fu">dirname</span> <span class="st">"</span><span class="va">$0</span><span class="st">"</span><span class="va">)</span><span class="st">/../lib/common.sh"</span></span>
<span id="cb11-7"><a href="#cb11-7" aria-hidden="true"></a></span>
<span id="cb11-8"><a href="#cb11-8" aria-hidden="true"></a><span class="va">ENVIRONMENT=</span><span class="st">"</span><span class="va">${1:-</span>production<span class="va">}</span><span class="st">"</span></span>
<span id="cb11-9"><a href="#cb11-9" aria-hidden="true"></a><span class="va">CONFIG_FILE=</span><span class="st">"</span><span class="va">$CONFIG_DIR</span><span class="st">/environments/</span><span class="va">$ENVIRONMENT</span><span class="st">.conf"</span></span>
<span id="cb11-10"><a href="#cb11-10" aria-hidden="true"></a></span>
<span id="cb11-11"><a href="#cb11-11" aria-hidden="true"></a><span class="bu">source</span> <span class="st">"</span><span class="va">$CONFIG_FILE</span><span class="st">"</span></span>
<span id="cb11-12"><a href="#cb11-12" aria-hidden="true"></a></span>
<span id="cb11-13"><a href="#cb11-13" aria-hidden="true"></a><span class="fu">check_site_health()</span> <span class="kw">{</span></span>
<span id="cb11-14"><a href="#cb11-14" aria-hidden="true"></a>    <span class="bu">local</span> <span class="va">url=</span><span class="st">"</span><span class="va">$1</span><span class="st">"</span></span>
<span id="cb11-15"><a href="#cb11-15" aria-hidden="true"></a>    <span class="bu">local</span> <span class="va">response=$(</span><span class="ex">curl</span> -s -o /dev/null -w <span class="st">"%{http_code}"</span> <span class="st">"</span><span class="va">$url</span><span class="st">"</span><span class="va">)</span></span>
<span id="cb11-16"><a href="#cb11-16" aria-hidden="true"></a></span>
<span id="cb11-17"><a href="#cb11-17" aria-hidden="true"></a>    <span class="kw">if</span><span class="bu"> [</span> <span class="st">"</span><span class="va">$response</span><span class="st">"</span> <span class="ot">=</span> <span class="st">"200"</span><span class="bu"> ]</span>; <span class="kw">then</span></span>
<span id="cb11-18"><a href="#cb11-18" aria-hidden="true"></a>        <span class="ex">log</span> <span class="st">"✓ Site accessible: </span><span class="va">$url</span><span class="st">"</span></span>
<span id="cb11-19"><a href="#cb11-19" aria-hidden="true"></a>        <span class="bu">return</span> 0</span>
<span id="cb11-20"><a href="#cb11-20" aria-hidden="true"></a>    <span class="kw">else</span></span>
<span id="cb11-21"><a href="#cb11-21" aria-hidden="true"></a>        <span class="ex">error</span> <span class="st">"✗ Site down: </span><span class="va">$url</span><span class="st"> (HTTP </span><span class="va">$response</span><span class="st">)"</span></span>
<span id="cb11-22"><a href="#cb11-22" aria-hidden="true"></a>        <span class="bu">return</span> 1</span>
<span id="cb11-23"><a href="#cb11-23" aria-hidden="true"></a>    <span class="kw">fi</span></span>
<span id="cb11-24"><a href="#cb11-24" aria-hidden="true"></a><span class="kw">}</span></span>
<span id="cb11-25"><a href="#cb11-25" aria-hidden="true"></a></span>
<span id="cb11-26"><a href="#cb11-26" aria-hidden="true"></a><span class="fu">check_database_connection()</span> <span class="kw">{</span></span>
<span id="cb11-27"><a href="#cb11-27" aria-hidden="true"></a>    <span class="kw">if</span> <span class="ex">wp</span> db check --path=<span class="st">"</span><span class="va">$CURRENT_LINK</span><span class="st">"</span><span class="kw">;</span> <span class="kw">then</span></span>
<span id="cb11-28"><a href="#cb11-28" aria-hidden="true"></a>        <span class="ex">log</span> <span class="st">"✓ Database connection OK"</span></span>
<span id="cb11-29"><a href="#cb11-29" aria-hidden="true"></a>        <span class="bu">return</span> 0</span>
<span id="cb11-30"><a href="#cb11-30" aria-hidden="true"></a>    <span class="kw">else</span></span>
<span id="cb11-31"><a href="#cb11-31" aria-hidden="true"></a>        <span class="ex">error</span> <span class="st">"✗ Database connection failed"</span></span>
<span id="cb11-32"><a href="#cb11-32" aria-hidden="true"></a>        <span class="bu">return</span> 1</span>
<span id="cb11-33"><a href="#cb11-33" aria-hidden="true"></a>    <span class="kw">fi</span></span>
<span id="cb11-34"><a href="#cb11-34" aria-hidden="true"></a><span class="kw">}</span></span>
<span id="cb11-35"><a href="#cb11-35" aria-hidden="true"></a></span>
<span id="cb11-36"><a href="#cb11-36" aria-hidden="true"></a><span class="fu">check_disk_space()</span> <span class="kw">{</span></span>
<span id="cb11-37"><a href="#cb11-37" aria-hidden="true"></a>    <span class="bu">local</span> <span class="va">usage=$(</span><span class="fu">df</span> -h <span class="st">"</span><span class="va">$DEPLOY_PATH</span><span class="st">"</span> <span class="kw">|</span> <span class="fu">awk</span> <span class="st">'NR==2 {print $5}'</span> <span class="kw">|</span> <span class="fu">sed</span> <span class="st">'s/%//'</span><span class="va">)</span></span>
<span id="cb11-38"><a href="#cb11-38" aria-hidden="true"></a></span>
<span id="cb11-39"><a href="#cb11-39" aria-hidden="true"></a>    <span class="kw">if</span><span class="bu"> [</span> <span class="st">"</span><span class="va">$usage</span><span class="st">"</span> <span class="ot">-lt</span> 80<span class="bu"> ]</span>; <span class="kw">then</span></span>
<span id="cb11-40"><a href="#cb11-40" aria-hidden="true"></a>        <span class="ex">log</span> <span class="st">"✓ Disk space OK (</span><span class="va">$usage</span><span class="st">%)"</span></span>
<span id="cb11-41"><a href="#cb11-41" aria-hidden="true"></a>        <span class="bu">return</span> 0</span>
<span id="cb11-42"><a href="#cb11-42" aria-hidden="true"></a>    <span class="kw">else</span></span>
<span id="cb11-43"><a href="#cb11-43" aria-hidden="true"></a>        <span class="ex">log</span> <span class="st">"⚠ Disk space warning: </span><span class="va">$usage</span><span class="st">%"</span></span>
<span id="cb11-44"><a href="#cb11-44" aria-hidden="true"></a>        <span class="bu">return</span> 1</span>
<span id="cb11-45"><a href="#cb11-45" aria-hidden="true"></a>    <span class="kw">fi</span></span>
<span id="cb11-46"><a href="#cb11-46" aria-hidden="true"></a><span class="kw">}</span></span>
<span id="cb11-47"><a href="#cb11-47" aria-hidden="true"></a></span>
<span id="cb11-48"><a href="#cb11-48" aria-hidden="true"></a><span class="fu">check_plugin_updates()</span> <span class="kw">{</span></span>
<span id="cb11-49"><a href="#cb11-49" aria-hidden="true"></a>    <span class="bu">local</span> <span class="va">updates=$(</span><span class="ex">wp</span> plugin list --update=available --format=count --path=<span class="st">"</span><span class="va">$CURRENT_LINK</span><span class="st">"</span><span class="va">)</span></span>
<span id="cb11-50"><a href="#cb11-50" aria-hidden="true"></a></span>
<span id="cb11-51"><a href="#cb11-51" aria-hidden="true"></a>    <span class="kw">if</span><span class="bu"> [</span> <span class="st">"</span><span class="va">$updates</span><span class="st">"</span> <span class="ot">-eq</span> 0<span class="bu"> ]</span>; <span class="kw">then</span></span>
<span id="cb11-52"><a href="#cb11-52" aria-hidden="true"></a>        <span class="ex">log</span> <span class="st">"✓ All plugins up to date"</span></span>
<span id="cb11-53"><a href="#cb11-53" aria-hidden="true"></a>    <span class="kw">else</span></span>
<span id="cb11-54"><a href="#cb11-54" aria-hidden="true"></a>        <span class="ex">log</span> <span class="st">"⚠ </span><span class="va">$updates</span><span class="st"> plugin updates available"</span></span>
<span id="cb11-55"><a href="#cb11-55" aria-hidden="true"></a>    <span class="kw">fi</span></span>
<span id="cb11-56"><a href="#cb11-56" aria-hidden="true"></a><span class="kw">}</span></span>
<span id="cb11-57"><a href="#cb11-57" aria-hidden="true"></a></span>
<span id="cb11-58"><a href="#cb11-58" aria-hidden="true"></a><span class="co"># Run all checks</span></span>
<span id="cb11-59"><a href="#cb11-59" aria-hidden="true"></a><span class="ex">log</span> <span class="st">"=== Health Check: </span><span class="va">$ENVIRONMENT</span><span class="st"> ==="</span></span>
<span id="cb11-60"><a href="#cb11-60" aria-hidden="true"></a></span>
<span id="cb11-61"><a href="#cb11-61" aria-hidden="true"></a><span class="va">FAILED=</span>0</span>
<span id="cb11-62"><a href="#cb11-62" aria-hidden="true"></a></span>
<span id="cb11-63"><a href="#cb11-63" aria-hidden="true"></a><span class="ex">check_site_health</span> <span class="st">"</span><span class="va">$SITE_URL</span><span class="st">"</span> <span class="kw">||</span> <span class="va">FAILED=$((</span>FAILED + 1<span class="va">))</span></span>
<span id="cb11-64"><a href="#cb11-64" aria-hidden="true"></a><span class="ex">check_database_connection</span> <span class="kw">||</span> <span class="va">FAILED=$((</span>FAILED + 1<span class="va">))</span></span>
<span id="cb11-65"><a href="#cb11-65" aria-hidden="true"></a><span class="ex">check_disk_space</span> <span class="kw">||</span> <span class="va">FAILED=$((</span>FAILED + 1<span class="va">))</span></span>
<span id="cb11-66"><a href="#cb11-66" aria-hidden="true"></a><span class="ex">check_plugin_updates</span></span>
<span id="cb11-67"><a href="#cb11-67" aria-hidden="true"></a></span>
<span id="cb11-68"><a href="#cb11-68" aria-hidden="true"></a><span class="kw">if</span><span class="bu"> [</span> <span class="st">"</span><span class="va">$FAILED</span><span class="st">"</span> <span class="ot">-gt</span> 0<span class="bu"> ]</span>; <span class="kw">then</span></span>
<span id="cb11-69"><a href="#cb11-69" aria-hidden="true"></a>    <span class="ex">error</span> <span class="st">"</span><span class="va">$FAILED</span><span class="st"> health checks failed"</span></span>
<span id="cb11-70"><a href="#cb11-70" aria-hidden="true"></a><span class="kw">else</span></span>
<span id="cb11-71"><a href="#cb11-71" aria-hidden="true"></a>    <span class="ex">log</span> <span class="st">"✓ All health checks passed"</span></span>
<span id="cb11-72"><a href="#cb11-72" aria-hidden="true"></a><span class="kw">fi</span></span></code></pre>
</div>



<h4 class="wp-block-heading" id="scheduled-monitoring">Scheduled Monitoring</h4>



<div class="sourceCode" id="cb12">
<pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb12-1"><a href="#cb12-1" aria-hidden="true"></a><span class="co"># Add to crontab: crontab -e</span></span>
<span id="cb12-2"><a href="#cb12-2" aria-hidden="true"></a></span>
<span id="cb12-3"><a href="#cb12-3" aria-hidden="true"></a><span class="co"># Health check every 5 minutes</span></span>
<span id="cb12-4"><a href="#cb12-4" aria-hidden="true"></a><span class="ex">*/5</span> * * * * /opt/wordpress-deploy/bin/monitor production <span class="op">&gt;&gt;</span> /var/log/wp-monitor.log <span class="op">2&gt;&amp;1</span></span>
<span id="cb12-5"><a href="#cb12-5" aria-hidden="true"></a></span>
<span id="cb12-6"><a href="#cb12-6" aria-hidden="true"></a><span class="co"># Daily deployment report</span></span>
<span id="cb12-7"><a href="#cb12-7" aria-hidden="true"></a><span class="ex">0</span> 9 * * * /opt/wordpress-deploy/bin/report production <span class="kw">|</span> <span class="ex">mail</span> -s <span class="st">"Daily WordPress Report"</span> team@example.com</span></code></pre>
</div>



<h3 class="wp-block-heading" id="next-steps">Next Steps</h3>



<p>You now have a complete production-ready WordPress deployment system.</p>



<h4 class="wp-block-heading" id="recommended-learning-path">Recommended Learning Path</h4>



<p><strong>Week 1</strong>: System setup</p>



<ul class="wp-block-list">
<li>Install deployment system</li>



<li>Configure environments</li>



<li>Test provisioning</li>
</ul>



<p><strong>Week 2</strong>: Deployment workflow</p>



<ul class="wp-block-list">
<li>Practice deployments</li>



<li>Test rollback procedures</li>



<li>Configure notifications</li>
</ul>



<p><strong>Week 3</strong>: CI/CD integration</p>



<ul class="wp-block-list">
<li>Connect to GitHub Actions</li>



<li>Automate testing</li>



<li>Deploy on merge</li>
</ul>



<p><strong>Week 4</strong>: Production hardening</p>



<ul class="wp-block-list">
<li>Implement monitoring</li>



<li>Optimize performance</li>



<li>Document procedures</li>
</ul>



<h4 class="wp-block-heading" id="advanced-topics">Advanced Topics</h4>



<ol class="wp-block-list">
<li><strong><a href="#">Multi-Server Deployments</a></strong> &#8211; Load-balanced WordPress</li>



<li><strong><a href="#">Container-Based Deployments</a></strong> &#8211; Docker/Kubernetes</li>



<li><strong><a href="#">GitOps Workflows</a></strong> &#8211; Infrastructure as code</li>
</ol>



<h4 class="wp-block-heading" id="get-more-resources">Get More Resources</h4>



<p><strong><a href="#">Download complete system</a></strong> including:</p>



<ul class="wp-block-list">
<li>Full deployment scripts</li>



<li>Configuration templates</li>



<li>Documentation</li>
</ul>



<p><strong><a href="/#get-started">Join our email course</a></strong> for:</p>



<ul class="wp-block-list">
<li>Weekly WP-CLI tutorials</li>



<li>DevOps best practices</li>



<li>Production war stories</li>
</ul>



<h3 class="wp-block-heading" id="conclusion">Conclusion</h3>



<p>A complete WordPress deployment system automates the entire lifecycle from server provisioning to zero-downtime deployments, monitoring, and rollback—enabling professional DevOps workflows for WordPress sites.</p>



<p>What we covered:</p>



<p>✅ Complete system architecture and project structure <br>✅ Automated server provisioning from scratch <br>✅ Zero-downtime deployment implementation <br>✅ Database migration system with rollback <br>✅ Instant rollback for failed deployments <br>✅ Continuous health monitoring and alerting</p>



<p>Build this system, and you’ll deploy WordPress professionally—automated provisioning, zero-downtime releases, instant rollbacks, and comprehensive monitoring for production-grade WordPress operations.</p>



<p><strong>Ready for more?</strong> Learn <a href="#">high-availability WordPress</a> or <a href="#">enterprise DevOps</a>.</p>



<p><strong>Questions about WordPress deployment systems?</strong> Drop a comment below!</p>



<p><strong>Found this helpful?</strong> Share with other DevOps engineers.</p>
<p>The post <a href="https://wpclimastery.com/blog/building-a-complete-wordpress-deployment-system-with-wp-cli-real-project/">Building a Complete WordPress Deployment System with WP-CLI (Real Project)</a> appeared first on <a href="https://wpclimastery.com">WP-CLI Mastery</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>WordPress Site Cloning and Migration Automation with WP-CLI</title>
		<link>https://wpclimastery.com/blog/wordpress-site-cloning-and-migration-automation-with-wp-cli/</link>
		
		<dc:creator><![CDATA[Krasen]]></dc:creator>
		<pubDate>Thu, 15 Jan 2026 09:00:00 +0000</pubDate>
				<category><![CDATA[Real-World WP-CLI Projects]]></category>
		<category><![CDATA[automated wordpress migration]]></category>
		<category><![CDATA[clone wordpress site]]></category>
		<category><![CDATA[wordpress migration automation]]></category>
		<category><![CDATA[wordpress site cloning]]></category>
		<category><![CDATA[wp-cli migration]]></category>
		<guid isPermaLink="false">https://wpclimastery.com/?p=143</guid>

					<description><![CDATA[<p>Cloning WordPress sites manually means exporting databases through phpMyAdmin, FTPing thousands of files, running search-replace SQL queries that break serialized data, and spending hours fixing broken configurations. One mistake destroys...</p>
<p>The post <a href="https://wpclimastery.com/blog/wordpress-site-cloning-and-migration-automation-with-wp-cli/">WordPress Site Cloning and Migration Automation with WP-CLI</a> appeared first on <a href="https://wpclimastery.com">WP-CLI Mastery</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>Cloning WordPress sites manually means exporting databases through phpMyAdmin, FTPing thousands of files, running search-replace SQL queries that break serialized data, and spending hours fixing broken configurations. One mistake destroys the entire clone.</p>



<p>WP-CLI transforms WordPress cloning and migration into a fast, automated process—clone production to staging in minutes, migrate sites between hosts reliably, and replicate environments for testing without manual intervention or data corruption.</p>



<p>In this guide, you’ll build a complete WordPress site cloning and migration system using WP-CLI, with automated scripts, safety checks, and verification procedures used by professional WordPress agencies.</p>



<h3 class="wp-block-heading" id="why-automate">Why Automate WordPress Cloning and Migration?</h3>



<p><a href="https://wordpress.org/support/article/moving-wordpress/">WordPress site migration</a> manually is error-prone and doesn’t scale.</p>



<h4 class="wp-block-heading" id="problems-with-manual-cloningmigration">Problems with Manual Cloning/Migration</h4>



<p><strong>Time-consuming</strong>: Manual cloning takes 2-4 hours for medium sites.</p>



<p><strong>Error-prone</strong>: Database exports fail, files get missed, URLs break.</p>



<p><strong>Serialized data corruption</strong>: Manual search-replace destroys widget settings and options.</p>



<p><strong>No validation</strong>: Can’t verify clone completeness or data integrity.</p>



<p><strong>Not repeatable</strong>: Each clone requires same tedious manual steps.</p>



<h4 class="wp-block-heading" id="wp-cli-cloningmigration-advantages">WP-CLI Cloning/Migration Advantages</h4>



<p><strong>Fast</strong>: Clone complete sites in 5-10 minutes instead of hours.</p>



<p><strong>Safe</strong>: WordPress-aware operations preserve serialized data.</p>



<p><strong>Scriptable</strong>: One-command cloning for any site at any time.</p>



<p><strong>Verifiable</strong>: Automated checks ensure complete, accurate clones.</p>



<p><strong>Consistent</strong>: Same process every time guarantees reliability.</p>



<p>According to <a href="https://wpengine.com/">WordPress development surveys</a>, agencies save 20+ hours monthly by automating site cloning for staging and development.</p>



<h3 class="wp-block-heading" id="basic-cloning">Basic Site Cloning</h3>



<p>Clone a WordPress site locally with essential components.</p>



<h4 class="wp-block-heading" id="complete-local-clone-script">Complete Local Clone Script</h4>



<div class="sourceCode" id="cb1">
<pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true"></a><span class="co">#!/bin/bash</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true"></a><span class="co"># clone-wordpress-site.sh - Clone WordPress site locally</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true"></a></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true"></a><span class="kw">set</span> <span class="ex">-euo</span> pipefail</span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true"></a></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true"></a><span class="va">SOURCE_PATH=</span><span class="st">"</span><span class="va">$1</span><span class="st">"</span></span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true"></a><span class="va">DEST_PATH=</span><span class="st">"</span><span class="va">$2</span><span class="st">"</span></span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true"></a></span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true"></a><span class="kw">if</span><span class="bu"> [</span> <span class="ot">-z</span> <span class="st">"</span><span class="va">$SOURCE_PATH</span><span class="st">"</span><span class="bu"> ]</span> <span class="kw">||</span><span class="bu"> [</span> <span class="ot">-z</span> <span class="st">"</span><span class="va">$DEST_PATH</span><span class="st">"</span><span class="bu"> ]</span>; <span class="kw">then</span></span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"Usage: </span><span class="va">$0</span><span class="st"> &lt;source_path&gt; &lt;dest_path&gt;"</span></span>
<span id="cb1-11"><a href="#cb1-11" aria-hidden="true"></a>    <span class="bu">exit</span> 1</span>
<span id="cb1-12"><a href="#cb1-12" aria-hidden="true"></a><span class="kw">fi</span></span>
<span id="cb1-13"><a href="#cb1-13" aria-hidden="true"></a></span>
<span id="cb1-14"><a href="#cb1-14" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"Cloning WordPress site..."</span></span>
<span id="cb1-15"><a href="#cb1-15" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"Source: </span><span class="va">$SOURCE_PATH</span><span class="st">"</span></span>
<span id="cb1-16"><a href="#cb1-16" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"Destination: </span><span class="va">$DEST_PATH</span><span class="st">"</span></span>
<span id="cb1-17"><a href="#cb1-17" aria-hidden="true"></a></span>
<span id="cb1-18"><a href="#cb1-18" aria-hidden="true"></a><span class="co"># Create destination directory</span></span>
<span id="cb1-19"><a href="#cb1-19" aria-hidden="true"></a><span class="fu">mkdir</span> -p <span class="st">"</span><span class="va">$DEST_PATH</span><span class="st">"</span></span>
<span id="cb1-20"><a href="#cb1-20" aria-hidden="true"></a></span>
<span id="cb1-21"><a href="#cb1-21" aria-hidden="true"></a><span class="co"># Copy WordPress files</span></span>
<span id="cb1-22"><a href="#cb1-22" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"Copying files..."</span></span>
<span id="cb1-23"><a href="#cb1-23" aria-hidden="true"></a><span class="fu">rsync</span> -av --exclude=<span class="st">'wp-content/cache'</span> <span class="kw">\</span></span>
<span id="cb1-24"><a href="#cb1-24" aria-hidden="true"></a>    <span class="ex">--exclude</span>=<span class="st">'wp-content/backup*'</span> <span class="kw">\</span></span>
<span id="cb1-25"><a href="#cb1-25" aria-hidden="true"></a>    <span class="st">"</span><span class="va">$SOURCE_PATH</span><span class="st">/"</span> <span class="st">"</span><span class="va">$DEST_PATH</span><span class="st">/"</span></span>
<span id="cb1-26"><a href="#cb1-26" aria-hidden="true"></a></span>
<span id="cb1-27"><a href="#cb1-27" aria-hidden="true"></a><span class="co"># Export database from source</span></span>
<span id="cb1-28"><a href="#cb1-28" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"Exporting database..."</span></span>
<span id="cb1-29"><a href="#cb1-29" aria-hidden="true"></a><span class="bu">cd</span> <span class="st">"</span><span class="va">$SOURCE_PATH</span><span class="st">"</span></span>
<span id="cb1-30"><a href="#cb1-30" aria-hidden="true"></a><span class="ex">wp</span> db export /tmp/clone-db.sql</span>
<span id="cb1-31"><a href="#cb1-31" aria-hidden="true"></a></span>
<span id="cb1-32"><a href="#cb1-32" aria-hidden="true"></a><span class="co"># Create new database config for destination</span></span>
<span id="cb1-33"><a href="#cb1-33" aria-hidden="true"></a><span class="bu">cd</span> <span class="st">"</span><span class="va">$DEST_PATH</span><span class="st">"</span></span>
<span id="cb1-34"><a href="#cb1-34" aria-hidden="true"></a></span>
<span id="cb1-35"><a href="#cb1-35" aria-hidden="true"></a><span class="co"># Get source database details</span></span>
<span id="cb1-36"><a href="#cb1-36" aria-hidden="true"></a><span class="va">SOURCE_DB=$(</span><span class="ex">wp</span> config get DB_NAME<span class="va">)</span></span>
<span id="cb1-37"><a href="#cb1-37" aria-hidden="true"></a><span class="va">SOURCE_USER=$(</span><span class="ex">wp</span> config get DB_USER<span class="va">)</span></span>
<span id="cb1-38"><a href="#cb1-38" aria-hidden="true"></a><span class="va">SOURCE_PASS=$(</span><span class="ex">wp</span> config get DB_PASSWORD<span class="va">)</span></span>
<span id="cb1-39"><a href="#cb1-39" aria-hidden="true"></a></span>
<span id="cb1-40"><a href="#cb1-40" aria-hidden="true"></a><span class="co"># Create new database</span></span>
<span id="cb1-41"><a href="#cb1-41" aria-hidden="true"></a><span class="va">NEW_DB=</span><span class="st">"cloned_</span><span class="va">${SOURCE_DB}</span><span class="st">"</span></span>
<span id="cb1-42"><a href="#cb1-42" aria-hidden="true"></a><span class="ex">mysql</span> -u<span class="st">"</span><span class="va">$SOURCE_USER</span><span class="st">"</span> -p<span class="st">"</span><span class="va">$SOURCE_PASS</span><span class="st">"</span> -e <span class="st">"CREATE DATABASE IF NOT EXISTS </span><span class="va">${NEW_DB}</span><span class="st">;"</span></span>
<span id="cb1-43"><a href="#cb1-43" aria-hidden="true"></a></span>
<span id="cb1-44"><a href="#cb1-44" aria-hidden="true"></a><span class="co"># Update wp-config.php</span></span>
<span id="cb1-45"><a href="#cb1-45" aria-hidden="true"></a><span class="ex">wp</span> config set DB_NAME <span class="st">"</span><span class="va">$NEW_DB</span><span class="st">"</span></span>
<span id="cb1-46"><a href="#cb1-46" aria-hidden="true"></a></span>
<span id="cb1-47"><a href="#cb1-47" aria-hidden="true"></a><span class="co"># Import database</span></span>
<span id="cb1-48"><a href="#cb1-48" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"Importing database..."</span></span>
<span id="cb1-49"><a href="#cb1-49" aria-hidden="true"></a><span class="ex">wp</span> db import /tmp/clone-db.sql</span>
<span id="cb1-50"><a href="#cb1-50" aria-hidden="true"></a></span>
<span id="cb1-51"><a href="#cb1-51" aria-hidden="true"></a><span class="co"># Cleanup</span></span>
<span id="cb1-52"><a href="#cb1-52" aria-hidden="true"></a><span class="fu">rm</span> /tmp/clone-db.sql</span>
<span id="cb1-53"><a href="#cb1-53" aria-hidden="true"></a></span>
<span id="cb1-54"><a href="#cb1-54" aria-hidden="true"></a><span class="co"># Update URLs if needed</span></span>
<span id="cb1-55"><a href="#cb1-55" aria-hidden="true"></a><span class="va">SOURCE_URL=$(</span><span class="ex">wp</span> option get siteurl<span class="va">)</span></span>
<span id="cb1-56"><a href="#cb1-56" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"Current site URL: </span><span class="va">$SOURCE_URL</span><span class="st">"</span></span>
<span id="cb1-57"><a href="#cb1-57" aria-hidden="true"></a><span class="bu">read</span> -p <span class="st">"Enter new site URL (or press Enter to keep same): "</span> <span class="va">NEW_URL</span></span>
<span id="cb1-58"><a href="#cb1-58" aria-hidden="true"></a></span>
<span id="cb1-59"><a href="#cb1-59" aria-hidden="true"></a><span class="kw">if</span><span class="bu"> [</span> <span class="ot">-n</span> <span class="st">"</span><span class="va">$NEW_URL</span><span class="st">"</span><span class="bu"> ]</span>; <span class="kw">then</span></span>
<span id="cb1-60"><a href="#cb1-60" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"Updating URLs..."</span></span>
<span id="cb1-61"><a href="#cb1-61" aria-hidden="true"></a>    <span class="ex">wp</span> search-replace <span class="st">"</span><span class="va">$SOURCE_URL</span><span class="st">"</span> <span class="st">"</span><span class="va">$NEW_URL</span><span class="st">"</span></span>
<span id="cb1-62"><a href="#cb1-62" aria-hidden="true"></a>    <span class="ex">wp</span> option update home <span class="st">"</span><span class="va">$NEW_URL</span><span class="st">"</span></span>
<span id="cb1-63"><a href="#cb1-63" aria-hidden="true"></a>    <span class="ex">wp</span> option update siteurl <span class="st">"</span><span class="va">$NEW_URL</span><span class="st">"</span></span>
<span id="cb1-64"><a href="#cb1-64" aria-hidden="true"></a><span class="kw">fi</span></span>
<span id="cb1-65"><a href="#cb1-65" aria-hidden="true"></a></span>
<span id="cb1-66"><a href="#cb1-66" aria-hidden="true"></a><span class="co"># Clear caches</span></span>
<span id="cb1-67"><a href="#cb1-67" aria-hidden="true"></a><span class="ex">wp</span> cache flush</span>
<span id="cb1-68"><a href="#cb1-68" aria-hidden="true"></a><span class="ex">wp</span> rewrite flush</span>
<span id="cb1-69"><a href="#cb1-69" aria-hidden="true"></a></span>
<span id="cb1-70"><a href="#cb1-70" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"✓ Clone complete: </span><span class="va">$DEST_PATH</span><span class="st">"</span></span></code></pre>
</div>



<p>Run it:</p>



<div class="sourceCode" id="cb2">
<pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true"></a><span class="fu">chmod</span> +x clone-wordpress-site.sh</span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true"></a><span class="ex">./clone-wordpress-site.sh</span> /var/www/production /var/www/staging</span></code></pre>
</div>



<p>Learn about <a href="https://wordpress.org/support/article/wordpress-files/">WordPress directory structure</a>.</p>



<h3 class="wp-block-heading" id="remote-migration">Remote Site Migration</h3>



<p>Migrate WordPress sites between servers or hosting providers.</p>



<h4 class="wp-block-heading" id="complete-remote-migration-script">Complete Remote Migration Script</h4>



<div class="sourceCode" id="cb3">
<pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true"></a><span class="co">#!/bin/bash</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true"></a><span class="co"># migrate-wordpress-remote.sh - Migrate between servers</span></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true"></a></span>
<span id="cb3-4"><a href="#cb3-4" aria-hidden="true"></a><span class="kw">set</span> <span class="ex">-euo</span> pipefail</span>
<span id="cb3-5"><a href="#cb3-5" aria-hidden="true"></a></span>
<span id="cb3-6"><a href="#cb3-6" aria-hidden="true"></a><span class="va">SOURCE_HOST=</span><span class="st">"</span><span class="va">$1</span><span class="st">"</span></span>
<span id="cb3-7"><a href="#cb3-7" aria-hidden="true"></a><span class="va">SOURCE_PATH=</span><span class="st">"</span><span class="va">$2</span><span class="st">"</span></span>
<span id="cb3-8"><a href="#cb3-8" aria-hidden="true"></a><span class="va">DEST_PATH=</span><span class="st">"</span><span class="va">$3</span><span class="st">"</span></span>
<span id="cb3-9"><a href="#cb3-9" aria-hidden="true"></a><span class="va">OLD_URL=</span><span class="st">"</span><span class="va">$4</span><span class="st">"</span></span>
<span id="cb3-10"><a href="#cb3-10" aria-hidden="true"></a><span class="va">NEW_URL=</span><span class="st">"</span><span class="va">$5</span><span class="st">"</span></span>
<span id="cb3-11"><a href="#cb3-11" aria-hidden="true"></a></span>
<span id="cb3-12"><a href="#cb3-12" aria-hidden="true"></a><span class="kw">if</span><span class="bu"> [</span> <span class="ot">-z</span> <span class="st">"</span><span class="va">$NEW_URL</span><span class="st">"</span><span class="bu"> ]</span>; <span class="kw">then</span></span>
<span id="cb3-13"><a href="#cb3-13" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"Usage: </span><span class="va">$0</span><span class="st"> &lt;source_host&gt; &lt;source_path&gt; &lt;dest_path&gt; &lt;old_url&gt; &lt;new_url&gt;"</span></span>
<span id="cb3-14"><a href="#cb3-14" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"Example: </span><span class="va">$0</span><span class="st"> user@old-server.com /var/www/html /var/www/html https://oldsite.com https://newsite.com"</span></span>
<span id="cb3-15"><a href="#cb3-15" aria-hidden="true"></a>    <span class="bu">exit</span> 1</span>
<span id="cb3-16"><a href="#cb3-16" aria-hidden="true"></a><span class="kw">fi</span></span>
<span id="cb3-17"><a href="#cb3-17" aria-hidden="true"></a></span>
<span id="cb3-18"><a href="#cb3-18" aria-hidden="true"></a><span class="va">TEMP_DIR=</span><span class="st">"/tmp/wp-migration-</span><span class="va">$</span><span class="st">"</span></span>
<span id="cb3-19"><a href="#cb3-19" aria-hidden="true"></a><span class="va">DATE=$(</span><span class="fu">date</span> +%Y%m%d_%H%M%S<span class="va">)</span></span>
<span id="cb3-20"><a href="#cb3-20" aria-hidden="true"></a></span>
<span id="cb3-21"><a href="#cb3-21" aria-hidden="true"></a><span class="fu">mkdir</span> -p <span class="st">"</span><span class="va">$TEMP_DIR</span><span class="st">"</span></span>
<span id="cb3-22"><a href="#cb3-22" aria-hidden="true"></a></span>
<span id="cb3-23"><a href="#cb3-23" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"=== WordPress Remote Migration Started ==="</span></span>
<span id="cb3-24"><a href="#cb3-24" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"From: </span><span class="va">$SOURCE_HOST</span><span class="st">:</span><span class="va">$SOURCE_PATH</span><span class="st">"</span></span>
<span id="cb3-25"><a href="#cb3-25" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"To: </span><span class="va">$DEST_PATH</span><span class="st">"</span></span>
<span id="cb3-26"><a href="#cb3-26" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"URL: </span><span class="va">$OLD_URL</span><span class="st"> → </span><span class="va">$NEW_URL</span><span class="st">"</span></span>
<span id="cb3-27"><a href="#cb3-27" aria-hidden="true"></a></span>
<span id="cb3-28"><a href="#cb3-28" aria-hidden="true"></a><span class="co"># Step 1: Export database from source</span></span>
<span id="cb3-29"><a href="#cb3-29" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"Step 1/6: Exporting database from source..."</span></span>
<span id="cb3-30"><a href="#cb3-30" aria-hidden="true"></a><span class="fu">ssh</span> <span class="st">"</span><span class="va">$SOURCE_HOST</span><span class="st">"</span> <span class="st">"cd </span><span class="va">$SOURCE_PATH</span><span class="st"> &amp;&amp; wp db export - | gzip"</span> <span class="op">&gt;</span> <span class="st">"</span><span class="va">$TEMP_DIR</span><span class="st">/database.sql.gz"</span></span>
<span id="cb3-31"><a href="#cb3-31" aria-hidden="true"></a></span>
<span id="cb3-32"><a href="#cb3-32" aria-hidden="true"></a><span class="co"># Verify database export</span></span>
<span id="cb3-33"><a href="#cb3-33" aria-hidden="true"></a><span class="va">DB_SIZE=$(</span><span class="fu">stat</span> -c%s <span class="st">"</span><span class="va">$TEMP_DIR</span><span class="st">/database.sql.gz"</span><span class="va">)</span></span>
<span id="cb3-34"><a href="#cb3-34" aria-hidden="true"></a><span class="kw">if</span><span class="bu"> [</span> <span class="st">"</span><span class="va">$DB_SIZE</span><span class="st">"</span> <span class="ot">-lt</span> 1000<span class="bu"> ]</span>; <span class="kw">then</span></span>
<span id="cb3-35"><a href="#cb3-35" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"✗ Database export too small, aborting"</span></span>
<span id="cb3-36"><a href="#cb3-36" aria-hidden="true"></a>    <span class="bu">exit</span> 1</span>
<span id="cb3-37"><a href="#cb3-37" aria-hidden="true"></a><span class="kw">fi</span></span>
<span id="cb3-38"><a href="#cb3-38" aria-hidden="true"></a></span>
<span id="cb3-39"><a href="#cb3-39" aria-hidden="true"></a><span class="co"># Step 2: Transfer files from source</span></span>
<span id="cb3-40"><a href="#cb3-40" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"Step 2/6: Transferring files from source..."</span></span>
<span id="cb3-41"><a href="#cb3-41" aria-hidden="true"></a><span class="fu">rsync</span> -avz --progress <span class="kw">\</span></span>
<span id="cb3-42"><a href="#cb3-42" aria-hidden="true"></a>    <span class="ex">--exclude</span>=<span class="st">'wp-content/cache/*'</span> <span class="kw">\</span></span>
<span id="cb3-43"><a href="#cb3-43" aria-hidden="true"></a>    <span class="ex">--exclude</span>=<span class="st">'wp-content/backup*'</span> <span class="kw">\</span></span>
<span id="cb3-44"><a href="#cb3-44" aria-hidden="true"></a>    <span class="st">"</span><span class="va">$SOURCE_HOST</span><span class="st">:</span><span class="va">$SOURCE_PATH</span><span class="st">/"</span> <span class="st">"</span><span class="va">$DEST_PATH</span><span class="st">/"</span></span>
<span id="cb3-45"><a href="#cb3-45" aria-hidden="true"></a></span>
<span id="cb3-46"><a href="#cb3-46" aria-hidden="true"></a><span class="co"># Step 3: Backup destination (if exists)</span></span>
<span id="cb3-47"><a href="#cb3-47" aria-hidden="true"></a><span class="kw">if</span><span class="bu"> [</span> <span class="ot">-d</span> <span class="st">"</span><span class="va">$DEST_PATH</span><span class="st">"</span><span class="bu"> ]</span>; <span class="kw">then</span></span>
<span id="cb3-48"><a href="#cb3-48" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"Step 3/6: Backing up destination..."</span></span>
<span id="cb3-49"><a href="#cb3-49" aria-hidden="true"></a>    <span class="bu">cd</span> <span class="st">"</span><span class="va">$DEST_PATH</span><span class="st">"</span></span>
<span id="cb3-50"><a href="#cb3-50" aria-hidden="true"></a>    <span class="kw">if</span> <span class="ex">wp</span> core is-installed <span class="op">2&gt;</span>/dev/null<span class="kw">;</span> <span class="kw">then</span></span>
<span id="cb3-51"><a href="#cb3-51" aria-hidden="true"></a>        <span class="ex">wp</span> db export <span class="st">"/backups/dest-before-migration-</span><span class="va">$DATE</span><span class="st">.sql.gz"</span> <span class="kw">||</span> <span class="fu">true</span></span>
<span id="cb3-52"><a href="#cb3-52" aria-hidden="true"></a>    <span class="kw">fi</span></span>
<span id="cb3-53"><a href="#cb3-53" aria-hidden="true"></a><span class="kw">fi</span></span>
<span id="cb3-54"><a href="#cb3-54" aria-hidden="true"></a></span>
<span id="cb3-55"><a href="#cb3-55" aria-hidden="true"></a><span class="co"># Step 4: Import database</span></span>
<span id="cb3-56"><a href="#cb3-56" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"Step 4/6: Importing database..."</span></span>
<span id="cb3-57"><a href="#cb3-57" aria-hidden="true"></a><span class="bu">cd</span> <span class="st">"</span><span class="va">$DEST_PATH</span><span class="st">"</span></span>
<span id="cb3-58"><a href="#cb3-58" aria-hidden="true"></a><span class="ex">wp</span> db import <span class="st">"</span><span class="va">$TEMP_DIR</span><span class="st">/database.sql.gz"</span></span>
<span id="cb3-59"><a href="#cb3-59" aria-hidden="true"></a></span>
<span id="cb3-60"><a href="#cb3-60" aria-hidden="true"></a><span class="co"># Step 5: Update URLs</span></span>
<span id="cb3-61"><a href="#cb3-61" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"Step 5/6: Updating URLs..."</span></span>
<span id="cb3-62"><a href="#cb3-62" aria-hidden="true"></a><span class="ex">wp</span> search-replace <span class="st">"</span><span class="va">$OLD_URL</span><span class="st">"</span> <span class="st">"</span><span class="va">$NEW_URL</span><span class="st">"</span> --dry-run --report</span>
<span id="cb3-63"><a href="#cb3-63" aria-hidden="true"></a><span class="ex">wp</span> search-replace <span class="st">"</span><span class="va">$OLD_URL</span><span class="st">"</span> <span class="st">"</span><span class="va">$NEW_URL</span><span class="st">"</span></span>
<span id="cb3-64"><a href="#cb3-64" aria-hidden="true"></a><span class="ex">wp</span> search-replace <span class="st">"//</span><span class="va">$(</span><span class="bu">echo</span> <span class="va">$OLD_URL</span> <span class="kw">|</span> <span class="fu">sed</span> <span class="st">'s~http[s]*://~~'</span><span class="va">)</span><span class="st">"</span> <span class="st">"//</span><span class="va">$(</span><span class="bu">echo</span> <span class="va">$NEW_URL</span> <span class="kw">|</span> <span class="fu">sed</span> <span class="st">'s~http[s]*://~~'</span><span class="va">)</span><span class="st">"</span></span>
<span id="cb3-65"><a href="#cb3-65" aria-hidden="true"></a></span>
<span id="cb3-66"><a href="#cb3-66" aria-hidden="true"></a><span class="co"># Update WordPress options</span></span>
<span id="cb3-67"><a href="#cb3-67" aria-hidden="true"></a><span class="ex">wp</span> option update home <span class="st">"</span><span class="va">$NEW_URL</span><span class="st">"</span></span>
<span id="cb3-68"><a href="#cb3-68" aria-hidden="true"></a><span class="ex">wp</span> option update siteurl <span class="st">"</span><span class="va">$NEW_URL</span><span class="st">"</span></span>
<span id="cb3-69"><a href="#cb3-69" aria-hidden="true"></a></span>
<span id="cb3-70"><a href="#cb3-70" aria-hidden="true"></a><span class="co"># Step 6: Verify and cleanup</span></span>
<span id="cb3-71"><a href="#cb3-71" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"Step 6/6: Verifying migration..."</span></span>
<span id="cb3-72"><a href="#cb3-72" aria-hidden="true"></a><span class="kw">if</span> <span class="ex">wp</span> core is-installed<span class="kw">;</span> <span class="kw">then</span></span>
<span id="cb3-73"><a href="#cb3-73" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"✓ WordPress installation verified"</span></span>
<span id="cb3-74"><a href="#cb3-74" aria-hidden="true"></a><span class="kw">else</span></span>
<span id="cb3-75"><a href="#cb3-75" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"✗ WordPress verification failed"</span></span>
<span id="cb3-76"><a href="#cb3-76" aria-hidden="true"></a>    <span class="bu">exit</span> 1</span>
<span id="cb3-77"><a href="#cb3-77" aria-hidden="true"></a><span class="kw">fi</span></span>
<span id="cb3-78"><a href="#cb3-78" aria-hidden="true"></a></span>
<span id="cb3-79"><a href="#cb3-79" aria-hidden="true"></a><span class="kw">if</span> <span class="ex">wp</span> db check<span class="kw">;</span> <span class="kw">then</span></span>
<span id="cb3-80"><a href="#cb3-80" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"✓ Database healthy"</span></span>
<span id="cb3-81"><a href="#cb3-81" aria-hidden="true"></a><span class="kw">else</span></span>
<span id="cb3-82"><a href="#cb3-82" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"✗ Database issues detected"</span></span>
<span id="cb3-83"><a href="#cb3-83" aria-hidden="true"></a>    <span class="bu">exit</span> 1</span>
<span id="cb3-84"><a href="#cb3-84" aria-hidden="true"></a><span class="kw">fi</span></span>
<span id="cb3-85"><a href="#cb3-85" aria-hidden="true"></a></span>
<span id="cb3-86"><a href="#cb3-86" aria-hidden="true"></a><span class="co"># Clear caches</span></span>
<span id="cb3-87"><a href="#cb3-87" aria-hidden="true"></a><span class="ex">wp</span> cache flush</span>
<span id="cb3-88"><a href="#cb3-88" aria-hidden="true"></a><span class="ex">wp</span> rewrite flush</span>
<span id="cb3-89"><a href="#cb3-89" aria-hidden="true"></a></span>
<span id="cb3-90"><a href="#cb3-90" aria-hidden="true"></a><span class="co"># Cleanup</span></span>
<span id="cb3-91"><a href="#cb3-91" aria-hidden="true"></a><span class="fu">rm</span> -rf <span class="st">"</span><span class="va">$TEMP_DIR</span><span class="st">"</span></span>
<span id="cb3-92"><a href="#cb3-92" aria-hidden="true"></a></span>
<span id="cb3-93"><a href="#cb3-93" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"=== Migration Complete ==="</span></span>
<span id="cb3-94"><a href="#cb3-94" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"Site URL: </span><span class="va">$NEW_URL</span><span class="st">"</span></span>
<span id="cb3-95"><a href="#cb3-95" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"Backup: /backups/dest-before-migration-</span><span class="va">$DATE</span><span class="st">.sql.gz"</span></span></code></pre>
</div>



<h4 class="wp-block-heading" id="push-to-production">Push to Production</h4>



<div class="sourceCode" id="cb4">
<pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true"></a><span class="co">#!/bin/bash</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true"></a><span class="co"># push-to-production.sh - Push staging to production</span></span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true"></a></span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true"></a><span class="va">STAGING_PATH=</span><span class="st">"/var/www/staging"</span></span>
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true"></a><span class="va">PROD_PATH=</span><span class="st">"/var/www/production"</span></span>
<span id="cb4-6"><a href="#cb4-6" aria-hidden="true"></a><span class="va">STAGING_URL=</span><span class="st">"https://staging.example.com"</span></span>
<span id="cb4-7"><a href="#cb4-7" aria-hidden="true"></a><span class="va">PROD_URL=</span><span class="st">"https://example.com"</span></span>
<span id="cb4-8"><a href="#cb4-8" aria-hidden="true"></a></span>
<span id="cb4-9"><a href="#cb4-9" aria-hidden="true"></a><span class="bu">read</span> -p <span class="st">"This will overwrite production. Continue? (y/n) "</span> -n 1 -r</span>
<span id="cb4-10"><a href="#cb4-10" aria-hidden="true"></a><span class="bu">echo</span></span>
<span id="cb4-11"><a href="#cb4-11" aria-hidden="true"></a><span class="kw">if [[</span> <span class="ot">!</span> <span class="va">$REPLY</span> =~ ^[Yy]$<span class="kw"> ]]</span>; <span class="kw">then</span></span>
<span id="cb4-12"><a href="#cb4-12" aria-hidden="true"></a>    <span class="bu">exit</span> 0</span>
<span id="cb4-13"><a href="#cb4-13" aria-hidden="true"></a><span class="kw">fi</span></span>
<span id="cb4-14"><a href="#cb4-14" aria-hidden="true"></a></span>
<span id="cb4-15"><a href="#cb4-15" aria-hidden="true"></a><span class="co"># Backup production first</span></span>
<span id="cb4-16"><a href="#cb4-16" aria-hidden="true"></a><span class="bu">cd</span> <span class="st">"</span><span class="va">$PROD_PATH</span><span class="st">"</span></span>
<span id="cb4-17"><a href="#cb4-17" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"Backing up production..."</span></span>
<span id="cb4-18"><a href="#cb4-18" aria-hidden="true"></a><span class="ex">wp</span> db export <span class="st">"/backups/prod-</span><span class="va">$(</span><span class="fu">date</span> +%Y%m%d_%H%M%S<span class="va">)</span><span class="st">.sql.gz"</span></span>
<span id="cb4-19"><a href="#cb4-19" aria-hidden="true"></a></span>
<span id="cb4-20"><a href="#cb4-20" aria-hidden="true"></a><span class="co"># Export from staging</span></span>
<span id="cb4-21"><a href="#cb4-21" aria-hidden="true"></a><span class="bu">cd</span> <span class="st">"</span><span class="va">$STAGING_PATH</span><span class="st">"</span></span>
<span id="cb4-22"><a href="#cb4-22" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"Exporting staging..."</span></span>
<span id="cb4-23"><a href="#cb4-23" aria-hidden="true"></a><span class="ex">wp</span> db export /tmp/staging-push.sql.gz</span>
<span id="cb4-24"><a href="#cb4-24" aria-hidden="true"></a></span>
<span id="cb4-25"><a href="#cb4-25" aria-hidden="true"></a><span class="co"># Copy files</span></span>
<span id="cb4-26"><a href="#cb4-26" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"Copying files..."</span></span>
<span id="cb4-27"><a href="#cb4-27" aria-hidden="true"></a><span class="fu">rsync</span> -av --delete <span class="kw">\</span></span>
<span id="cb4-28"><a href="#cb4-28" aria-hidden="true"></a>    <span class="ex">--exclude</span>=<span class="st">'wp-config.php'</span> <span class="kw">\</span></span>
<span id="cb4-29"><a href="#cb4-29" aria-hidden="true"></a>    <span class="st">"</span><span class="va">$STAGING_PATH</span><span class="st">/"</span> <span class="st">"</span><span class="va">$PROD_PATH</span><span class="st">/"</span></span>
<span id="cb4-30"><a href="#cb4-30" aria-hidden="true"></a></span>
<span id="cb4-31"><a href="#cb4-31" aria-hidden="true"></a><span class="co"># Import to production</span></span>
<span id="cb4-32"><a href="#cb4-32" aria-hidden="true"></a><span class="bu">cd</span> <span class="st">"</span><span class="va">$PROD_PATH</span><span class="st">"</span></span>
<span id="cb4-33"><a href="#cb4-33" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"Importing database..."</span></span>
<span id="cb4-34"><a href="#cb4-34" aria-hidden="true"></a><span class="ex">wp</span> db import /tmp/staging-push.sql.gz</span>
<span id="cb4-35"><a href="#cb4-35" aria-hidden="true"></a></span>
<span id="cb4-36"><a href="#cb4-36" aria-hidden="true"></a><span class="co"># Update URLs</span></span>
<span id="cb4-37"><a href="#cb4-37" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"Updating URLs for production..."</span></span>
<span id="cb4-38"><a href="#cb4-38" aria-hidden="true"></a><span class="ex">wp</span> search-replace <span class="st">"</span><span class="va">$STAGING_URL</span><span class="st">"</span> <span class="st">"</span><span class="va">$PROD_URL</span><span class="st">"</span></span>
<span id="cb4-39"><a href="#cb4-39" aria-hidden="true"></a><span class="ex">wp</span> option update home <span class="st">"</span><span class="va">$PROD_URL</span><span class="st">"</span></span>
<span id="cb4-40"><a href="#cb4-40" aria-hidden="true"></a><span class="ex">wp</span> option update siteurl <span class="st">"</span><span class="va">$PROD_URL</span><span class="st">"</span></span>
<span id="cb4-41"><a href="#cb4-41" aria-hidden="true"></a></span>
<span id="cb4-42"><a href="#cb4-42" aria-hidden="true"></a><span class="co"># Clear caches</span></span>
<span id="cb4-43"><a href="#cb4-43" aria-hidden="true"></a><span class="ex">wp</span> cache flush</span>
<span id="cb4-44"><a href="#cb4-44" aria-hidden="true"></a><span class="ex">wp</span> rewrite flush</span>
<span id="cb4-45"><a href="#cb4-45" aria-hidden="true"></a></span>
<span id="cb4-46"><a href="#cb4-46" aria-hidden="true"></a><span class="co"># Cleanup</span></span>
<span id="cb4-47"><a href="#cb4-47" aria-hidden="true"></a><span class="fu">rm</span> /tmp/staging-push.sql.gz</span>
<span id="cb4-48"><a href="#cb4-48" aria-hidden="true"></a></span>
<span id="cb4-49"><a href="#cb4-49" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"✓ Staging pushed to production"</span></span></code></pre>
</div>



<h3 class="wp-block-heading" id="advanced-cloning">Advanced Cloning Features</h3>



<p>Add professional features to cloning automation.</p>



<h4 class="wp-block-heading" id="selective-cloning">Selective Cloning</h4>



<div class="sourceCode" id="cb5">
<pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true"></a><span class="co">#!/bin/bash</span></span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true"></a><span class="co"># selective-clone.sh - Clone only specific components</span></span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true"></a></span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true"></a><span class="va">SOURCE_PATH=</span><span class="st">"</span><span class="va">$1</span><span class="st">"</span></span>
<span id="cb5-5"><a href="#cb5-5" aria-hidden="true"></a><span class="va">DEST_PATH=</span><span class="st">"</span><span class="va">$2</span><span class="st">"</span></span>
<span id="cb5-6"><a href="#cb5-6" aria-hidden="true"></a><span class="va">CLONE_TYPE=</span><span class="st">"</span><span class="va">$3</span><span class="st">"</span>  # <span class="ex">database</span>, files, plugins, themes, uploads</span>
<span id="cb5-7"><a href="#cb5-7" aria-hidden="true"></a></span>
<span id="cb5-8"><a href="#cb5-8" aria-hidden="true"></a><span class="kw">case</span> <span class="st">"</span><span class="va">$CLONE_TYPE</span><span class="st">"</span><span class="kw"> in</span></span>
<span id="cb5-9"><a href="#cb5-9" aria-hidden="true"></a>    database<span class="kw">)</span></span>
<span id="cb5-10"><a href="#cb5-10" aria-hidden="true"></a>        <span class="bu">echo</span> <span class="st">"Cloning database only..."</span></span>
<span id="cb5-11"><a href="#cb5-11" aria-hidden="true"></a>        <span class="bu">cd</span> <span class="st">"</span><span class="va">$SOURCE_PATH</span><span class="st">"</span></span>
<span id="cb5-12"><a href="#cb5-12" aria-hidden="true"></a>        <span class="ex">wp</span> db export /tmp/db-clone.sql.gz</span>
<span id="cb5-13"><a href="#cb5-13" aria-hidden="true"></a>        <span class="bu">cd</span> <span class="st">"</span><span class="va">$DEST_PATH</span><span class="st">"</span></span>
<span id="cb5-14"><a href="#cb5-14" aria-hidden="true"></a>        <span class="ex">wp</span> db import /tmp/db-clone.sql.gz</span>
<span id="cb5-15"><a href="#cb5-15" aria-hidden="true"></a>        <span class="fu">rm</span> /tmp/db-clone.sql.gz</span>
<span id="cb5-16"><a href="#cb5-16" aria-hidden="true"></a>        <span class="kw">;;</span></span>
<span id="cb5-17"><a href="#cb5-17" aria-hidden="true"></a></span>
<span id="cb5-18"><a href="#cb5-18" aria-hidden="true"></a>    files<span class="kw">)</span></span>
<span id="cb5-19"><a href="#cb5-19" aria-hidden="true"></a>        <span class="bu">echo</span> <span class="st">"Cloning files only..."</span></span>
<span id="cb5-20"><a href="#cb5-20" aria-hidden="true"></a>        <span class="fu">rsync</span> -av <span class="st">"</span><span class="va">$SOURCE_PATH</span><span class="st">/"</span> <span class="st">"</span><span class="va">$DEST_PATH</span><span class="st">/"</span></span>
<span id="cb5-21"><a href="#cb5-21" aria-hidden="true"></a>        <span class="kw">;;</span></span>
<span id="cb5-22"><a href="#cb5-22" aria-hidden="true"></a></span>
<span id="cb5-23"><a href="#cb5-23" aria-hidden="true"></a>    plugins<span class="kw">)</span></span>
<span id="cb5-24"><a href="#cb5-24" aria-hidden="true"></a>        <span class="bu">echo</span> <span class="st">"Cloning plugins..."</span></span>
<span id="cb5-25"><a href="#cb5-25" aria-hidden="true"></a>        <span class="fu">rsync</span> -av <span class="st">"</span><span class="va">$SOURCE_PATH</span><span class="st">/wp-content/plugins/"</span> <span class="st">"</span><span class="va">$DEST_PATH</span><span class="st">/wp-content/plugins/"</span></span>
<span id="cb5-26"><a href="#cb5-26" aria-hidden="true"></a>        <span class="kw">;;</span></span>
<span id="cb5-27"><a href="#cb5-27" aria-hidden="true"></a></span>
<span id="cb5-28"><a href="#cb5-28" aria-hidden="true"></a>    themes<span class="kw">)</span></span>
<span id="cb5-29"><a href="#cb5-29" aria-hidden="true"></a>        <span class="bu">echo</span> <span class="st">"Cloning themes..."</span></span>
<span id="cb5-30"><a href="#cb5-30" aria-hidden="true"></a>        <span class="fu">rsync</span> -av <span class="st">"</span><span class="va">$SOURCE_PATH</span><span class="st">/wp-content/themes/"</span> <span class="st">"</span><span class="va">$DEST_PATH</span><span class="st">/wp-content/themes/"</span></span>
<span id="cb5-31"><a href="#cb5-31" aria-hidden="true"></a>        <span class="kw">;;</span></span>
<span id="cb5-32"><a href="#cb5-32" aria-hidden="true"></a></span>
<span id="cb5-33"><a href="#cb5-33" aria-hidden="true"></a>    uploads<span class="kw">)</span></span>
<span id="cb5-34"><a href="#cb5-34" aria-hidden="true"></a>        <span class="bu">echo</span> <span class="st">"Cloning uploads..."</span></span>
<span id="cb5-35"><a href="#cb5-35" aria-hidden="true"></a>        <span class="fu">rsync</span> -av <span class="st">"</span><span class="va">$SOURCE_PATH</span><span class="st">/wp-content/uploads/"</span> <span class="st">"</span><span class="va">$DEST_PATH</span><span class="st">/wp-content/uploads/"</span></span>
<span id="cb5-36"><a href="#cb5-36" aria-hidden="true"></a>        <span class="kw">;;</span></span>
<span id="cb5-37"><a href="#cb5-37" aria-hidden="true"></a></span>
<span id="cb5-38"><a href="#cb5-38" aria-hidden="true"></a>    *<span class="kw">)</span></span>
<span id="cb5-39"><a href="#cb5-39" aria-hidden="true"></a>        <span class="bu">echo</span> <span class="st">"Usage: </span><span class="va">$0</span><span class="st"> &lt;source&gt; &lt;dest&gt; &lt;database|files|plugins|themes|uploads&gt;"</span></span>
<span id="cb5-40"><a href="#cb5-40" aria-hidden="true"></a>        <span class="bu">exit</span> 1</span>
<span id="cb5-41"><a href="#cb5-41" aria-hidden="true"></a>        <span class="kw">;;</span></span>
<span id="cb5-42"><a href="#cb5-42" aria-hidden="true"></a><span class="kw">esac</span></span>
<span id="cb5-43"><a href="#cb5-43" aria-hidden="true"></a></span>
<span id="cb5-44"><a href="#cb5-44" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"✓ Selective clone complete"</span></span></code></pre>
</div>



<h4 class="wp-block-heading" id="clone-with-sanitization">Clone with Sanitization</h4>



<div class="sourceCode" id="cb6">
<pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true"></a><span class="co">#!/bin/bash</span></span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true"></a><span class="co"># clone-sanitized.sh - Clone for development, remove sensitive data</span></span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true"></a></span>
<span id="cb6-4"><a href="#cb6-4" aria-hidden="true"></a><span class="va">SOURCE_PATH=</span><span class="st">"</span><span class="va">$1</span><span class="st">"</span></span>
<span id="cb6-5"><a href="#cb6-5" aria-hidden="true"></a><span class="va">DEST_PATH=</span><span class="st">"</span><span class="va">$2</span><span class="st">"</span></span>
<span id="cb6-6"><a href="#cb6-6" aria-hidden="true"></a></span>
<span id="cb6-7"><a href="#cb6-7" aria-hidden="true"></a><span class="co"># Clone site</span></span>
<span id="cb6-8"><a href="#cb6-8" aria-hidden="true"></a><span class="fu">bash</span> /usr/local/bin/clone-wordpress-site.sh <span class="st">"</span><span class="va">$SOURCE_PATH</span><span class="st">"</span> <span class="st">"</span><span class="va">$DEST_PATH</span><span class="st">"</span></span>
<span id="cb6-9"><a href="#cb6-9" aria-hidden="true"></a></span>
<span id="cb6-10"><a href="#cb6-10" aria-hidden="true"></a><span class="bu">cd</span> <span class="st">"</span><span class="va">$DEST_PATH</span><span class="st">"</span></span>
<span id="cb6-11"><a href="#cb6-11" aria-hidden="true"></a></span>
<span id="cb6-12"><a href="#cb6-12" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"Sanitizing clone for development..."</span></span>
<span id="cb6-13"><a href="#cb6-13" aria-hidden="true"></a></span>
<span id="cb6-14"><a href="#cb6-14" aria-hidden="true"></a><span class="co"># Deactivate security plugins</span></span>
<span id="cb6-15"><a href="#cb6-15" aria-hidden="true"></a><span class="ex">wp</span> plugin deactivate wordfence sucuri-scanner --quiet</span>
<span id="cb6-16"><a href="#cb6-16" aria-hidden="true"></a></span>
<span id="cb6-17"><a href="#cb6-17" aria-hidden="true"></a><span class="co"># Remove sensitive data</span></span>
<span id="cb6-18"><a href="#cb6-18" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"Removing sensitive user data..."</span></span>
<span id="cb6-19"><a href="#cb6-19" aria-hidden="true"></a></span>
<span id="cb6-20"><a href="#cb6-20" aria-hidden="true"></a><span class="co"># Anonymize user emails</span></span>
<span id="cb6-21"><a href="#cb6-21" aria-hidden="true"></a><span class="kw">for</span> <span class="ex">user_id</span> in <span class="va">$(</span><span class="ex">wp</span> user list --field=ID<span class="va">)</span><span class="kw">;</span> <span class="kw">do</span></span>
<span id="cb6-22"><a href="#cb6-22" aria-hidden="true"></a>    <span class="va">USERNAME=$(</span><span class="ex">wp</span> user get <span class="va">$user_id</span> --field=user_login<span class="va">)</span></span>
<span id="cb6-23"><a href="#cb6-23" aria-hidden="true"></a>    <span class="ex">wp</span> user update <span class="va">$user_id</span> --user_email=<span class="st">"</span><span class="va">${USERNAME}</span><span class="st">@example.test"</span></span>
<span id="cb6-24"><a href="#cb6-24" aria-hidden="true"></a><span class="kw">done</span></span>
<span id="cb6-25"><a href="#cb6-25" aria-hidden="true"></a></span>
<span id="cb6-26"><a href="#cb6-26" aria-hidden="true"></a><span class="co"># Remove real passwords (force password reset)</span></span>
<span id="cb6-27"><a href="#cb6-27" aria-hidden="true"></a><span class="kw">for</span> <span class="ex">user_id</span> in <span class="va">$(</span><span class="ex">wp</span> user list --field=ID<span class="va">)</span><span class="kw">;</span> <span class="kw">do</span></span>
<span id="cb6-28"><a href="#cb6-28" aria-hidden="true"></a>    <span class="ex">wp</span> user update <span class="va">$user_id</span> --user_pass=<span class="st">"development"</span></span>
<span id="cb6-29"><a href="#cb6-29" aria-hidden="true"></a><span class="kw">done</span></span>
<span id="cb6-30"><a href="#cb6-30" aria-hidden="true"></a></span>
<span id="cb6-31"><a href="#cb6-31" aria-hidden="true"></a><span class="co"># Remove payment gateway credentials</span></span>
<span id="cb6-32"><a href="#cb6-32" aria-hidden="true"></a><span class="ex">wp</span> option update woocommerce_stripe_settings <span class="st">'{"enabled":"no"}'</span></span>
<span id="cb6-33"><a href="#cb6-33" aria-hidden="true"></a><span class="ex">wp</span> option update woocommerce_paypal_settings <span class="st">'{"enabled":"no"}'</span></span>
<span id="cb6-34"><a href="#cb6-34" aria-hidden="true"></a></span>
<span id="cb6-35"><a href="#cb6-35" aria-hidden="true"></a><span class="co"># Disable external services</span></span>
<span id="cb6-36"><a href="#cb6-36" aria-hidden="true"></a><span class="ex">wp</span> plugin deactivate google-analytics mailchimp --quiet</span>
<span id="cb6-37"><a href="#cb6-37" aria-hidden="true"></a></span>
<span id="cb6-38"><a href="#cb6-38" aria-hidden="true"></a><span class="co"># Enable debug mode</span></span>
<span id="cb6-39"><a href="#cb6-39" aria-hidden="true"></a><span class="ex">wp</span> config set WP_DEBUG true --raw</span>
<span id="cb6-40"><a href="#cb6-40" aria-hidden="true"></a><span class="ex">wp</span> config set WP_DEBUG_LOG true --raw</span>
<span id="cb6-41"><a href="#cb6-41" aria-hidden="true"></a></span>
<span id="cb6-42"><a href="#cb6-42" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"✓ Clone sanitized for development"</span></span></code></pre>
</div>



<h3 class="wp-block-heading" id="multi-environment">Multi-Environment Sync</h3>



<p>Synchronize WordPress across development, staging, and production.</p>



<h4 class="wp-block-heading" id="environment-sync-system">Environment Sync System</h4>



<div class="sourceCode" id="cb7">
<pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true"></a><span class="co">#!/bin/bash</span></span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true"></a><span class="co"># sync-environments.sh - Sync between dev/staging/prod</span></span>
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true"></a></span>
<span id="cb7-4"><a href="#cb7-4" aria-hidden="true"></a><span class="va">OPERATION=</span><span class="st">"</span><span class="va">$1</span><span class="st">"</span>  # <span class="ex">pull</span> or push</span>
<span id="cb7-5"><a href="#cb7-5" aria-hidden="true"></a><span class="va">ENV_FROM=</span><span class="st">"</span><span class="va">$2</span><span class="st">"</span>   # <span class="ex">dev</span>, staging, prod</span>
<span id="cb7-6"><a href="#cb7-6" aria-hidden="true"></a><span class="va">ENV_TO=</span><span class="st">"</span><span class="va">$3</span><span class="st">"</span>     # <span class="ex">dev</span>, staging, prod</span>
<span id="cb7-7"><a href="#cb7-7" aria-hidden="true"></a></span>
<span id="cb7-8"><a href="#cb7-8" aria-hidden="true"></a><span class="co"># Environment paths</span></span>
<span id="cb7-9"><a href="#cb7-9" aria-hidden="true"></a><span class="bu">declare</span> -A <span class="va">PATHS=(</span></span>
<span id="cb7-10"><a href="#cb7-10" aria-hidden="true"></a>    [<span class="st">"dev"</span>]=<span class="st">"/var/www/dev"</span></span>
<span id="cb7-11"><a href="#cb7-11" aria-hidden="true"></a>    [<span class="st">"staging"</span>]=<span class="st">"/var/www/staging"</span></span>
<span id="cb7-12"><a href="#cb7-12" aria-hidden="true"></a>    [<span class="st">"prod"</span>]=<span class="st">"/var/www/production"</span></span>
<span id="cb7-13"><a href="#cb7-13" aria-hidden="true"></a>)</span>
<span id="cb7-14"><a href="#cb7-14" aria-hidden="true"></a></span>
<span id="cb7-15"><a href="#cb7-15" aria-hidden="true"></a><span class="co"># Environment URLs</span></span>
<span id="cb7-16"><a href="#cb7-16" aria-hidden="true"></a><span class="bu">declare</span> -A <span class="va">URLS=(</span></span>
<span id="cb7-17"><a href="#cb7-17" aria-hidden="true"></a>    [<span class="st">"dev"</span>]=<span class="st">"http://dev.local"</span></span>
<span id="cb7-18"><a href="#cb7-18" aria-hidden="true"></a>    [<span class="st">"staging"</span>]=<span class="st">"https://staging.example.com"</span></span>
<span id="cb7-19"><a href="#cb7-19" aria-hidden="true"></a>    [<span class="st">"prod"</span>]=<span class="st">"https://example.com"</span></span>
<span id="cb7-20"><a href="#cb7-20" aria-hidden="true"></a>)</span>
<span id="cb7-21"><a href="#cb7-21" aria-hidden="true"></a></span>
<span id="cb7-22"><a href="#cb7-22" aria-hidden="true"></a><span class="kw">if</span><span class="bu"> [</span> <span class="ot">-z</span> <span class="st">"</span><span class="va">$ENV_TO</span><span class="st">"</span><span class="bu"> ]</span>; <span class="kw">then</span></span>
<span id="cb7-23"><a href="#cb7-23" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"Usage: </span><span class="va">$0</span><span class="st"> &lt;pull|push&gt; &lt;from_env&gt; &lt;to_env&gt;"</span></span>
<span id="cb7-24"><a href="#cb7-24" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"Environments: dev, staging, prod"</span></span>
<span id="cb7-25"><a href="#cb7-25" aria-hidden="true"></a>    <span class="bu">exit</span> 1</span>
<span id="cb7-26"><a href="#cb7-26" aria-hidden="true"></a><span class="kw">fi</span></span>
<span id="cb7-27"><a href="#cb7-27" aria-hidden="true"></a></span>
<span id="cb7-28"><a href="#cb7-28" aria-hidden="true"></a><span class="va">SOURCE_PATH=</span><span class="st">"</span><span class="va">${PATHS[$ENV_FROM]}</span><span class="st">"</span></span>
<span id="cb7-29"><a href="#cb7-29" aria-hidden="true"></a><span class="va">DEST_PATH=</span><span class="st">"</span><span class="va">${PATHS[$ENV_TO]}</span><span class="st">"</span></span>
<span id="cb7-30"><a href="#cb7-30" aria-hidden="true"></a><span class="va">SOURCE_URL=</span><span class="st">"</span><span class="va">${URLS[$ENV_FROM]}</span><span class="st">"</span></span>
<span id="cb7-31"><a href="#cb7-31" aria-hidden="true"></a><span class="va">DEST_URL=</span><span class="st">"</span><span class="va">${URLS[$ENV_TO]}</span><span class="st">"</span></span>
<span id="cb7-32"><a href="#cb7-32" aria-hidden="true"></a></span>
<span id="cb7-33"><a href="#cb7-33" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"Syncing </span><span class="va">$ENV_FROM</span><span class="st"> → </span><span class="va">$ENV_TO</span><span class="st">"</span></span>
<span id="cb7-34"><a href="#cb7-34" aria-hidden="true"></a></span>
<span id="cb7-35"><a href="#cb7-35" aria-hidden="true"></a><span class="co"># Confirmation for production</span></span>
<span id="cb7-36"><a href="#cb7-36" aria-hidden="true"></a><span class="kw">if</span><span class="bu"> [</span> <span class="st">"</span><span class="va">$ENV_TO</span><span class="st">"</span> <span class="ot">==</span> <span class="st">"prod"</span><span class="bu"> ]</span>; <span class="kw">then</span></span>
<span id="cb7-37"><a href="#cb7-37" aria-hidden="true"></a>    <span class="bu">read</span> -p <span class="st">"WARNING: Syncing to production. Continue? (y/n) "</span> -n 1 -r</span>
<span id="cb7-38"><a href="#cb7-38" aria-hidden="true"></a>    <span class="bu">echo</span></span>
<span id="cb7-39"><a href="#cb7-39" aria-hidden="true"></a>    <span class="kw">if [[</span> <span class="ot">!</span> <span class="va">$REPLY</span> =~ ^[Yy]$<span class="kw"> ]]</span>; <span class="kw">then</span></span>
<span id="cb7-40"><a href="#cb7-40" aria-hidden="true"></a>        <span class="bu">exit</span> 0</span>
<span id="cb7-41"><a href="#cb7-41" aria-hidden="true"></a>    <span class="kw">fi</span></span>
<span id="cb7-42"><a href="#cb7-42" aria-hidden="true"></a><span class="kw">fi</span></span>
<span id="cb7-43"><a href="#cb7-43" aria-hidden="true"></a></span>
<span id="cb7-44"><a href="#cb7-44" aria-hidden="true"></a><span class="co"># Backup destination</span></span>
<span id="cb7-45"><a href="#cb7-45" aria-hidden="true"></a><span class="bu">cd</span> <span class="st">"</span><span class="va">$DEST_PATH</span><span class="st">"</span></span>
<span id="cb7-46"><a href="#cb7-46" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"Backing up </span><span class="va">$ENV_TO</span><span class="st">..."</span></span>
<span id="cb7-47"><a href="#cb7-47" aria-hidden="true"></a><span class="ex">wp</span> db export <span class="st">"/backups/</span><span class="va">${ENV_TO}</span><span class="st">-before-sync-</span><span class="va">$(</span><span class="fu">date</span> +%Y%m%d<span class="va">)</span><span class="st">.sql.gz"</span></span>
<span id="cb7-48"><a href="#cb7-48" aria-hidden="true"></a></span>
<span id="cb7-49"><a href="#cb7-49" aria-hidden="true"></a><span class="co"># Clone</span></span>
<span id="cb7-50"><a href="#cb7-50" aria-hidden="true"></a><span class="bu">cd</span> <span class="st">"</span><span class="va">$SOURCE_PATH</span><span class="st">"</span></span>
<span id="cb7-51"><a href="#cb7-51" aria-hidden="true"></a><span class="ex">wp</span> db export /tmp/env-sync.sql.gz</span>
<span id="cb7-52"><a href="#cb7-52" aria-hidden="true"></a></span>
<span id="cb7-53"><a href="#cb7-53" aria-hidden="true"></a><span class="fu">rsync</span> -av <span class="kw">\</span></span>
<span id="cb7-54"><a href="#cb7-54" aria-hidden="true"></a>    <span class="ex">--exclude</span>=<span class="st">'wp-config.php'</span> <span class="kw">\</span></span>
<span id="cb7-55"><a href="#cb7-55" aria-hidden="true"></a>    <span class="ex">--exclude</span>=<span class="st">'wp-content/cache'</span> <span class="kw">\</span></span>
<span id="cb7-56"><a href="#cb7-56" aria-hidden="true"></a>    <span class="st">"</span><span class="va">$SOURCE_PATH</span><span class="st">/"</span> <span class="st">"</span><span class="va">$DEST_PATH</span><span class="st">/"</span></span>
<span id="cb7-57"><a href="#cb7-57" aria-hidden="true"></a></span>
<span id="cb7-58"><a href="#cb7-58" aria-hidden="true"></a><span class="bu">cd</span> <span class="st">"</span><span class="va">$DEST_PATH</span><span class="st">"</span></span>
<span id="cb7-59"><a href="#cb7-59" aria-hidden="true"></a><span class="ex">wp</span> db import /tmp/env-sync.sql.gz</span>
<span id="cb7-60"><a href="#cb7-60" aria-hidden="true"></a></span>
<span id="cb7-61"><a href="#cb7-61" aria-hidden="true"></a><span class="co"># Update URLs</span></span>
<span id="cb7-62"><a href="#cb7-62" aria-hidden="true"></a><span class="ex">wp</span> search-replace <span class="st">"</span><span class="va">$SOURCE_URL</span><span class="st">"</span> <span class="st">"</span><span class="va">$DEST_URL</span><span class="st">"</span></span>
<span id="cb7-63"><a href="#cb7-63" aria-hidden="true"></a><span class="ex">wp</span> option update home <span class="st">"</span><span class="va">$DEST_URL</span><span class="st">"</span></span>
<span id="cb7-64"><a href="#cb7-64" aria-hidden="true"></a><span class="ex">wp</span> option update siteurl <span class="st">"</span><span class="va">$DEST_URL</span><span class="st">"</span></span>
<span id="cb7-65"><a href="#cb7-65" aria-hidden="true"></a></span>
<span id="cb7-66"><a href="#cb7-66" aria-hidden="true"></a><span class="co"># Clear caches</span></span>
<span id="cb7-67"><a href="#cb7-67" aria-hidden="true"></a><span class="ex">wp</span> cache flush</span>
<span id="cb7-68"><a href="#cb7-68" aria-hidden="true"></a><span class="ex">wp</span> rewrite flush</span>
<span id="cb7-69"><a href="#cb7-69" aria-hidden="true"></a></span>
<span id="cb7-70"><a href="#cb7-70" aria-hidden="true"></a><span class="fu">rm</span> /tmp/env-sync.sql.gz</span>
<span id="cb7-71"><a href="#cb7-71" aria-hidden="true"></a></span>
<span id="cb7-72"><a href="#cb7-72" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"✓ Environment sync complete: </span><span class="va">$ENV_FROM</span><span class="st"> → </span><span class="va">$ENV_TO</span><span class="st">"</span></span></code></pre>
</div>



<h3 class="wp-block-heading" id="verification">Clone Verification</h3>



<p>Validate clones are complete and functional.</p>



<h4 class="wp-block-heading" id="complete-verification-script">Complete Verification Script</h4>



<div class="sourceCode" id="cb8">
<pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true"></a><span class="co">#!/bin/bash</span></span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true"></a><span class="co"># verify-clone.sh - Verify WordPress clone</span></span>
<span id="cb8-3"><a href="#cb8-3" aria-hidden="true"></a></span>
<span id="cb8-4"><a href="#cb8-4" aria-hidden="true"></a><span class="va">CLONE_PATH=</span><span class="st">"</span><span class="va">$1</span><span class="st">"</span></span>
<span id="cb8-5"><a href="#cb8-5" aria-hidden="true"></a></span>
<span id="cb8-6"><a href="#cb8-6" aria-hidden="true"></a><span class="kw">if</span><span class="bu"> [</span> <span class="ot">-z</span> <span class="st">"</span><span class="va">$CLONE_PATH</span><span class="st">"</span><span class="bu"> ]</span>; <span class="kw">then</span></span>
<span id="cb8-7"><a href="#cb8-7" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"Usage: </span><span class="va">$0</span><span class="st"> &lt;clone_path&gt;"</span></span>
<span id="cb8-8"><a href="#cb8-8" aria-hidden="true"></a>    <span class="bu">exit</span> 1</span>
<span id="cb8-9"><a href="#cb8-9" aria-hidden="true"></a><span class="kw">fi</span></span>
<span id="cb8-10"><a href="#cb8-10" aria-hidden="true"></a></span>
<span id="cb8-11"><a href="#cb8-11" aria-hidden="true"></a><span class="bu">cd</span> <span class="st">"</span><span class="va">$CLONE_PATH</span><span class="st">"</span></span>
<span id="cb8-12"><a href="#cb8-12" aria-hidden="true"></a></span>
<span id="cb8-13"><a href="#cb8-13" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"Verifying WordPress clone..."</span></span>
<span id="cb8-14"><a href="#cb8-14" aria-hidden="true"></a></span>
<span id="cb8-15"><a href="#cb8-15" aria-hidden="true"></a><span class="co"># Check WordPress is installed</span></span>
<span id="cb8-16"><a href="#cb8-16" aria-hidden="true"></a><span class="kw">if</span> ! <span class="ex">wp</span> core is-installed <span class="op">2&gt;</span>/dev/null<span class="kw">;</span> <span class="kw">then</span></span>
<span id="cb8-17"><a href="#cb8-17" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"✗ WordPress not properly installed"</span></span>
<span id="cb8-18"><a href="#cb8-18" aria-hidden="true"></a>    <span class="bu">exit</span> 1</span>
<span id="cb8-19"><a href="#cb8-19" aria-hidden="true"></a><span class="kw">fi</span></span>
<span id="cb8-20"><a href="#cb8-20" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"✓ WordPress installed"</span></span>
<span id="cb8-21"><a href="#cb8-21" aria-hidden="true"></a></span>
<span id="cb8-22"><a href="#cb8-22" aria-hidden="true"></a><span class="co"># Check database connection</span></span>
<span id="cb8-23"><a href="#cb8-23" aria-hidden="true"></a><span class="kw">if</span> ! <span class="ex">wp</span> db check <span class="op">2&gt;</span>/dev/null<span class="kw">;</span> <span class="kw">then</span></span>
<span id="cb8-24"><a href="#cb8-24" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"✗ Database connection failed"</span></span>
<span id="cb8-25"><a href="#cb8-25" aria-hidden="true"></a>    <span class="bu">exit</span> 1</span>
<span id="cb8-26"><a href="#cb8-26" aria-hidden="true"></a><span class="kw">fi</span></span>
<span id="cb8-27"><a href="#cb8-27" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"✓ Database connected"</span></span>
<span id="cb8-28"><a href="#cb8-28" aria-hidden="true"></a></span>
<span id="cb8-29"><a href="#cb8-29" aria-hidden="true"></a><span class="co"># Verify post count matches</span></span>
<span id="cb8-30"><a href="#cb8-30" aria-hidden="true"></a><span class="co"># (Would need original count passed in for real comparison)</span></span>
<span id="cb8-31"><a href="#cb8-31" aria-hidden="true"></a><span class="va">POST_COUNT=$(</span><span class="ex">wp</span> post list --format=count<span class="va">)</span></span>
<span id="cb8-32"><a href="#cb8-32" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"✓ Posts: </span><span class="va">$POST_COUNT</span><span class="st">"</span></span>
<span id="cb8-33"><a href="#cb8-33" aria-hidden="true"></a></span>
<span id="cb8-34"><a href="#cb8-34" aria-hidden="true"></a><span class="co"># Verify user count</span></span>
<span id="cb8-35"><a href="#cb8-35" aria-hidden="true"></a><span class="va">USER_COUNT=$(</span><span class="ex">wp</span> user list --format=count<span class="va">)</span></span>
<span id="cb8-36"><a href="#cb8-36" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"✓ Users: </span><span class="va">$USER_COUNT</span><span class="st">"</span></span>
<span id="cb8-37"><a href="#cb8-37" aria-hidden="true"></a></span>
<span id="cb8-38"><a href="#cb8-38" aria-hidden="true"></a><span class="co"># Verify plugins</span></span>
<span id="cb8-39"><a href="#cb8-39" aria-hidden="true"></a><span class="va">PLUGIN_COUNT=$(</span><span class="ex">wp</span> plugin list --format=count<span class="va">)</span></span>
<span id="cb8-40"><a href="#cb8-40" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"✓ Plugins: </span><span class="va">$PLUGIN_COUNT</span><span class="st">"</span></span>
<span id="cb8-41"><a href="#cb8-41" aria-hidden="true"></a></span>
<span id="cb8-42"><a href="#cb8-42" aria-hidden="true"></a><span class="co"># Check for broken URLs</span></span>
<span id="cb8-43"><a href="#cb8-43" aria-hidden="true"></a><span class="va">SITE_URL=$(</span><span class="ex">wp</span> option get siteurl<span class="va">)</span></span>
<span id="cb8-44"><a href="#cb8-44" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"Site URL: </span><span class="va">$SITE_URL</span><span class="st">"</span></span>
<span id="cb8-45"><a href="#cb8-45" aria-hidden="true"></a></span>
<span id="cb8-46"><a href="#cb8-46" aria-hidden="true"></a><span class="co"># Test site accessibility</span></span>
<span id="cb8-47"><a href="#cb8-47" aria-hidden="true"></a><span class="kw">if</span> <span class="ex">curl</span> -f -s <span class="st">"</span><span class="va">$SITE_URL</span><span class="st">"</span> <span class="op">&gt;</span> /dev/null<span class="kw">;</span> <span class="kw">then</span></span>
<span id="cb8-48"><a href="#cb8-48" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"✓ Site accessible"</span></span>
<span id="cb8-49"><a href="#cb8-49" aria-hidden="true"></a><span class="kw">else</span></span>
<span id="cb8-50"><a href="#cb8-50" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"✗ Site not accessible"</span></span>
<span id="cb8-51"><a href="#cb8-51" aria-hidden="true"></a>    <span class="bu">exit</span> 1</span>
<span id="cb8-52"><a href="#cb8-52" aria-hidden="true"></a><span class="kw">fi</span></span>
<span id="cb8-53"><a href="#cb8-53" aria-hidden="true"></a></span>
<span id="cb8-54"><a href="#cb8-54" aria-hidden="true"></a><span class="co"># Verify file permissions</span></span>
<span id="cb8-55"><a href="#cb8-55" aria-hidden="true"></a><span class="kw">if</span><span class="bu"> [</span> <span class="ot">-w</span> wp-content<span class="bu"> ]</span>; <span class="kw">then</span></span>
<span id="cb8-56"><a href="#cb8-56" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"✓ wp-content writable"</span></span>
<span id="cb8-57"><a href="#cb8-57" aria-hidden="true"></a><span class="kw">else</span></span>
<span id="cb8-58"><a href="#cb8-58" aria-hidden="true"></a>    <span class="bu">echo</span> <span class="st">"✗ wp-content not writable"</span></span>
<span id="cb8-59"><a href="#cb8-59" aria-hidden="true"></a><span class="kw">fi</span></span>
<span id="cb8-60"><a href="#cb8-60" aria-hidden="true"></a></span>
<span id="cb8-61"><a href="#cb8-61" aria-hidden="true"></a><span class="bu">echo</span> <span class="st">"✓ Clone verification complete"</span></span></code></pre>
</div>



<h3 class="wp-block-heading" id="next-steps">Next Steps</h3>



<p>You now have complete WordPress site cloning and migration automation capabilities.</p>



<h4 class="wp-block-heading" id="recommended-learning-path">Recommended Learning Path</h4>



<p><strong>Week 1</strong>: Basic cloning</p>



<ul class="wp-block-list">
<li>Practice local clones</li>



<li>Test database operations</li>



<li>Master URL replacement</li>
</ul>



<p><strong>Week 2</strong>: Remote migrations</p>



<ul class="wp-block-list">
<li>Set up SSH access</li>



<li>Transfer between servers</li>



<li>Handle production pushes</li>
</ul>



<p><strong>Week 3</strong>: Advanced features</p>



<ul class="wp-block-list">
<li>Selective cloning</li>



<li>Data sanitization</li>



<li>Multi-environment sync</li>
</ul>



<p><strong>Week 4</strong>: Production deployment</p>



<ul class="wp-block-list">
<li>Build verification systems</li>



<li>Automate complete workflows</li>



<li>Document procedures</li>
</ul>



<h4 class="wp-block-heading" id="advanced-topics">Advanced Topics</h4>



<ol class="wp-block-list">
<li><strong><a href="#">Blue-Green Deployments</a></strong> &#8211; Zero-downtime migrations</li>



<li><strong><a href="#">Database Sync Strategies</a></strong> &#8211; Incremental updates</li>



<li><strong><a href="#">Large Site Optimization</a></strong> &#8211; Handle massive WordPress sites</li>
</ol>



<h4 class="wp-block-heading" id="get-more-resources">Get More Resources</h4>



<p><strong><a href="#">Download cloning scripts</a></strong> including:</p>



<ul class="wp-block-list">
<li>Complete automation system</li>



<li>Verification tools</li>



<li>Multi-environment management</li>
</ul>



<p><strong><a href="/#get-started">Join our email course</a></strong> for:</p>



<ul class="wp-block-list">
<li>Weekly WP-CLI tutorials</li>



<li>Migration best practices</li>



<li>DevOps workflows</li>
</ul>



<h3 class="wp-block-heading" id="conclusion">Conclusion</h3>



<p>WordPress site cloning and migration automation with WP-CLI transforms hours of manual work into fast, reliable, one-command operations you can trust.</p>



<p>What we covered:</p>



<p>✅ Complete local site cloning automation <br>✅ Remote migration between servers <br>✅ Advanced selective and sanitized cloning <br>✅ Multi-environment synchronization <br>✅ Clone verification and validation <br>✅ Production-ready workflows</p>



<p>Master these techniques, and you’ll clone WordPress sites effortlessly—whether creating staging environments, migrating to new hosts, or replicating sites for development.</p>



<p><strong>Ready for more?</strong> Learn <a href="#">WordPress backup automation</a> or <a href="#">deployment pipelines</a>.</p>



<p><strong>Questions about WordPress cloning and migration?</strong> Drop a comment below!</p>



<p><strong>Found this helpful?</strong> Share with other WordPress developers and agencies.</p>
<p>The post <a href="https://wpclimastery.com/blog/wordpress-site-cloning-and-migration-automation-with-wp-cli/">WordPress Site Cloning and Migration Automation with WP-CLI</a> appeared first on <a href="https://wpclimastery.com">WP-CLI Mastery</a>.</p>
]]></content:encoded>
					
		
		
			</item>
	</channel>
</rss>
