وردپرس‌کالاوردپرس رو ساده‌تر توسعه بده
عضویت VIP

دیپلوی وردپرس با Git و GitHub Actions روی هاست ایرانی (راهنمای کامل)

هر تغییر کد با یک git push به صورت خودکار، تست‌شده و قابل بازگشت روی سرور بنشیند. در این راهنما یک پایپ‌لاین کامل GitHub Actions برای وردپرس می‌سازید: ساختار ریپو، کلید دیپلوی، بیلد قالب و بلاک، rsync، WP-CLI، استقرار اتمیک، staging با تأیید انسانی و سه استراتژی مخصوص هاست‌های ایرانی.

دیپلوی وردپرس با Git و GitHub Actions روی هاست ایرانی

دیپلوی وردپرس با Git یعنی هر تغییر کد با یک git push به صورت خودکار، تست‌شده و قابل بازگشت روی سرور می‌نشیند؛ بدون FTP، بدون فایل جامانده و بدون «روی سیستم من کار می‌کرد». این راهنما یک پایپ‌لاین کامل با GitHub Actions می‌سازد که قالب و افزونه‌های اختصاصی را بیلد می‌کند، با rsync منتقل می‌کند، با WP-CLI کش را خالی می‌کند و سلامت سایت را می‌سنجد. چون رانرهای GitHub خارج از ایران‌اند، سه استراتژی مختلف برای VPS خارجی، VPS ایرانی و هاست اشتراکی ایرانی ارائه شده است.

آنچه در این آموزش یاد می‌گیرید

  • ساختار درست ریپوی وردپرس و فایل .gitignore کامل

  • آماده‌سازی سرور: کاربر محدود deploy، کلید SSH و پوشه‌بندی اتمیک

  • workflow کامل GitHub Actions با بیلد قالب و بلاک، Composer، rsync، WP-CLI و سلامت‌سنجی

  • استقرار اتمیک با پوشه‌ی releases و بازگشت یک‌ثانیه‌ای

  • سه استراتژی برای هاست ایرانی: رانر ابری، رانر self-hosted و استقرار pull با کران‌جاب

  • محیط staging، تأیید انسانی قبل از production و همگام‌سازی دیتابیس

  • امنیت، خطاهای رایج و چیزهایی که هرگز نباید وارد گیت شوند

چرا FTP کافی نیست

با FTP هیچ‌کس نمی‌داند چه فایلی کی و توسط چه کسی تغییر کرده. یک آپلود ناقص سایت را می‌شکند و برگشت یعنی پیدا کردن نسخه‌ی قبلی روی لپ‌تاپ کسی. گیت این سه مشکل را یک‌جا حل می‌کند: تاریخچه‌ی کامل، بازبینی کد قبل از انتشار و بازگشت به هر نقطه. GitHub Actions این را یک قدم جلوتر می‌برد: بیلد و تست روی ماشین تمیز انجام می‌شود، نه روی سرور زنده، و هیچ فایلی دستی جابه‌جا نمی‌شود.

معیار

FTP دستی

Git + GitHub Actions

چه کسی چه چیزی را تغییر داد

نامشخص

هر خط با کامیت و نویسنده

بازگشت بعد از خرابی

جست‌وجوی بکاپ

یک دستور یا کلیک Re-run

بیلد قالب (Sass، JS)

روی لپ‌تاپ هر نفر

روی رانر، یکسان برای همه

خطر آپلود ناقص

زیاد

صفر؛ تعویض اتمیک

کار تیمی

تداخل فایل‌ها

شاخه، Pull Request، بازبینی

زمان هر انتشار

۱۰ تا ۳۰ دقیقه

۱ تا ۳ دقیقه خودکار

ساختار ریپو: چه چیزی در گیت باشد

چه فایل‌هایی از وردپرس در گیت باشد و چه فایل‌هایی در gitignore: قالب و افزونه‌های اختصاصی در برابر هسته، آپلودها و wp-config

فقط کد اختصاصی شما در گیت است. هسته و افزونه‌های مخزن در دیپلوی نصب می‌شوند و داده‌ها جداگانه مدیریت می‌شوند.

اشتباه رایج این است که کل پوشه‌ی وردپرس را commit کنند. نتیجه ریپویی چند صد مگابایتی با هزاران فایل هسته است که هر به‌روزرسانی وردپرس آن را به‌هم می‌ریزد. قاعده‌ی ساده: هر چیزی که خودتان ننوشته‌اید یا داده‌ی کاربر است، بیرون از گیت. این فایل .gitignore را در ریشه‌ی پروژه بگذارید و نام قالب و افزونه‌هایتان را جایگزین کنید:

# هسته‌ی وردپرس (با wp-cli یا composer نصب می‌شود)
/wp-admin/
/wp-includes/
/wp-*.php
/index.php
/license.txt
/readme.html
/xmlrpc.php

# رمزها و تنظیمات محیط
wp-config.php
.env
.env.*

# محتوای کاربر و فایل‌های موقت
/wp-content/uploads/
/wp-content/cache/
/wp-content/upgrade/
/wp-content/backup*/
/wp-content/debug.log

# افزونه‌ها و قالب‌های مخزن وردپرس (در deploy نصب می‌شوند)
/wp-content/plugins/*
!/wp-content/plugins/wpkala-*/
/wp-content/themes/*
!/wp-content/themes/wpkala-theme/

# خروجی بیلد و وابستگی‌ها
node_modules/
vendor/
/wp-content/themes/wpkala-theme/build/
/wp-content/plugins/wpkala-blocks/build/

# فایل‌های سیستم و ویرایشگر
.DS_Store
Thumbs.db
.idea/
.vscode/

افزونه‌های مخزن وردپرس را یا با Composer و بسته‌ی wpackagist مدیریت کنید یا در مرحله‌ی دیپلوی با wp plugin install نصب کنید. هر دو راه نسخه‌ی دقیق افزونه را در کد ثبت می‌کنند و سرور را از لوکال و staging یکسان نگه می‌دارند. اگر به سراغ Composer می‌روید، ساختار Bedrock از Roots همین کارها را با استاندارد آماده انجام می‌دهد، اما برای هاست اشتراکی ساختار ساده‌ی این مقاله کافی است.

آماده‌سازی سرور

استقرار اتمیک وردپرس با پوشه releases و symlink current برای بازگشت فوری

ساختار پوشه‌ها برای استقرار اتمیک. وب‌سرور همیشه به current اشاره می‌کند و هر دیپلوی فقط این لینک را عوض می‌کند.

ایده‌ی استقرار اتمیک این است که هیچ‌وقت روی فایل‌های سایت زنده نمی‌نویسیم. هر دیپلوی در پوشه‌ی جدیدی داخل releases ساخته می‌شود، فایل‌های مشترک (wp-config، آپلودها و هسته) از shared به آن لینک می‌شوند و در پایان symlink به نام current به نسخه‌ی جدید می‌چرخد. وب‌سرور در تمام مدت یا نسخه‌ی قبلی را می‌بیند یا نسخه‌ی کامل جدید را؛ هرگز حالت نیمه‌کاره وجود ندارد. بازگشت هم فقط برگرداندن همین لینک است.

# روی سرور، یک بار با کاربر دارای sudo
sudo adduser --disabled-password --gecos "" deploy
sudo mkdir -p /var/www/site/{releases,shared/uploads}
sudo chown -R deploy:www-data /var/www/site
sudo chmod -R 2775 /var/www/site

# کلید عمومی دیپلوی را برای کاربر deploy ثبت کنید
sudo -u deploy mkdir -p /home/deploy/.ssh
sudo -u deploy tee -a /home/deploy/.ssh/authorized_keys < deploy_key.pub
sudo chmod 700 /home/deploy/.ssh && sudo chmod 600 /home/deploy/.ssh/authorized_keys

# هسته‌ی وردپرس و wp-config در shared می‌مانند
cd /var/www/site/shared
sudo -u deploy wp core download --locale=fa_IR --skip-content
sudo -u deploy wp config create --dbname=site --dbuser=site --dbpass='رمز' --dbhost=localhost

ریشه‌ی وب‌سرور را روی /var/www/site/current تنظیم کنید. در nginx یعنی root /var/www/site/current; و در آپاچی DocumentRoot /var/www/site/current. گزینه‌ی --skip-content هسته را بدون قالب‌ها و افزونه‌های پیش‌فرض دانلود می‌کند، چون آن‌ها از گیت می‌آیند.

کلید دیپلوی و Secrets

جریان کلید دیپلوی و Secrets در GitHub Actions: کلید خصوصی در Secrets و کلید عمومی در authorized_keys سرور

کلید خصوصی فقط در Secrets ریپو، کلید عمومی فقط روی سرور. کاربر deploy به چیزی جز پوشه‌ی سایت دسترسی ندارد.

# روی لپ‌تاپ خودتان: کلید فقط برای دیپلوی، بدون passphrase
ssh-keygen -t ed25519 -C "github-deploy" -f deploy_key -N ""

# محتوای deploy_key (خصوصی)  →  GitHub › Settings › Secrets › SSH_PRIVATE_KEY
# محتوای deploy_key.pub (عمومی) →  روی سرور در authorized_keys کاربر deploy
cat deploy_key
cat deploy_key.pub

در GitHub به Settings › Environments بروید، محیط production را بسازید و این Secrets را در آن تعریف کنید: SSH_PRIVATE_KEY، DEPLOY_HOST، DEPLOY_USER (deploy)، DEPLOY_PORT (معمولاً ۲۲) و DEPLOY_PATH (/var/www/site). یک Variable به نام SITE_URL هم برای سلامت‌سنجی بگذارید. تعریف در سطح Environment به جای ریپو اجازه می‌دهد بعداً برای staging مقادیر جداگانه داشته باشید و برای production تأییدکننده تعیین کنید.

workflow کامل GitHub Actions

مسیر دیپلوی خودکار وردپرس: git push، GitHub Actions، rsync، WP-CLI و سلامت‌سنجی

پنج مرحله‌ی پایپ‌لاین. شکست در هر مرحله اجرای مراحل بعد را متوقف می‌کند و سایت دست‌نخورده می‌ماند.

این فایل را در مسیر .github/workflows/deploy.yml بگذارید. با هر push به شاخه‌ی main اجرا می‌شود و با workflow_dispatch می‌توانید دستی هم اجرایش کنید:

# .github/workflows/deploy.yml
name: Deploy to production

on:
  push:
    branches: [main]
  workflow_dispatch:

concurrency:
  group: production
  cancel-in-progress: false

jobs:
  deploy:
    runs-on: ubuntu-latest
    environment: production
    timeout-minutes: 15

    steps:
      - name: Checkout
        uses: actions/checkout@v7

      - name: Setup Node
        uses: actions/setup-node@v4
        with:
          node-version: 22
          cache: npm
          cache-dependency-path: wp-content/themes/wpkala-theme/package-lock.json

      - name: Build theme assets
        working-directory: wp-content/themes/wpkala-theme
        run: |
          npm ci
          npm run build

      - name: Build blocks plugin
        working-directory: wp-content/plugins/wpkala-blocks
        run: |
          npm ci
          npm run build

      - name: Setup PHP and Composer
        uses: shivammathur/setup-php@v2
        with:
          php-version: '8.3'
          tools: composer

      - name: Install PHP dependencies (production only)
        run: composer install --no-dev --optimize-autoloader --no-interaction

      - name: Start SSH agent
        uses: webfactory/ssh-agent@v0.9.1
        with:
          ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }}

      - name: Trust server host key
        run: ssh-keyscan -p ${{ secrets.DEPLOY_PORT }} -H ${{ secrets.DEPLOY_HOST }} >> ~/.ssh/known_hosts

      - name: Upload release
        env:
          HOST: ${{ secrets.DEPLOY_HOST }}
          USER: ${{ secrets.DEPLOY_USER }}
          PORT: ${{ secrets.DEPLOY_PORT }}
          BASE: ${{ secrets.DEPLOY_PATH }}
        run: |
          RELEASE=$(date +%Y%m%d-%H%M%S)-${GITHUB_SHA::7}
          echo "RELEASE=$RELEASE" >> "$GITHUB_ENV"
          rsync -az --delete \
            --exclude='.git' --exclude='.github' --exclude='node_modules' \
            --exclude='**/src' --exclude='*.map' \
            -e "ssh -p $PORT" \
            ./ "$USER@$HOST:$BASE/releases/$RELEASE/"

      - name: Activate release and run WP-CLI
        env:
          HOST: ${{ secrets.DEPLOY_HOST }}
          USER: ${{ secrets.DEPLOY_USER }}
          PORT: ${{ secrets.DEPLOY_PORT }}
          BASE: ${{ secrets.DEPLOY_PATH }}
        run: |
          ssh -p "$PORT" "$USER@$HOST" "bash -s" <<EOF
            set -euo pipefail
            cd "$BASE"
            R="releases/$RELEASE"
            # فایل‌های مشترک به نسخه‌ی جدید لینک می‌شوند
            ln -sfn "$BASE/shared/wp-config.php" "$R/wp-config.php"
            ln -sfn "$BASE/shared/uploads" "$R/wp-content/uploads"
            for f in wp-admin wp-includes index.php wp-*.php; do ln -sfn "$BASE/shared/\$f" "$R/\$f"; done
            # تعویض اتمیک
            ln -sfn "$BASE/$R" "$BASE/current"
            cd "$BASE/current"
            wp core update-db --quiet
            wp cache flush --quiet
            wp rewrite flush --hard --quiet
            # فقط ۵ نسخه‌ی آخر را نگه دار
            cd "$BASE/releases" && ls -1dt */ | tail -n +6 | xargs -r rm -rf
          EOF

      - name: Health check
        run: |
          for i in 1 2 3; do
            curl -fsS -o /dev/null "https://${{ vars.SITE_URL }}/" && exit 0
            sleep 5
          done
          echo "Site did not respond with 200" && exit 1

چند تصمیم در این workflow عمدی است:

  • concurrency نمی‌گذارد دو دیپلوی هم‌زمان اجرا شوند. اگر دو کامیت پشت سر هم push شود، دومی صبر می‌کند.

  • بیلد روی رانر انجام می‌شود نه روی سرور. سرور به Node نیاز ندارد و پوشه‌های src و node_modules هرگز منتقل نمی‌شوند.

  • rsync با --delete فایل‌های حذف‌شده از ریپو را از نسخه‌ی جدید هم حذف می‌کند. چون هر نسخه پوشه‌ی جداگانه دارد، این پرچم خطری برای آپلودها ندارد.

  • WP-CLI بعد از تعویض اجرا می‌شود: به‌روزرسانی ساختار دیتابیس، خالی کردن کش و بازسازی پیوندها. دستورهای بیشتر را در مقاله‌ی WP-CLI وردپرس کالا ببینید.

  • سلامت‌سنجی سه بار کد ۲۰۰ را می‌خواهد. اگر نگرفت workflow قرمز می‌شود و شما بلافاصله می‌فهمید، نه کاربر.

  • فقط پنج نسخه‌ی آخر نگه داشته می‌شود تا دیسک پر نشود؛ عدد را به دلخواه تغییر دهید.

تنظیمات محیط در wp-config

// wp-config.php (در shared): مقادیر از متغیر محیطی یا فایل .env خوانده می‌شوند
define( 'WP_ENVIRONMENT_TYPE', getenv( 'WP_ENV' ) ?: 'production' );
define( 'DISALLOW_FILE_MODS', WP_ENVIRONMENT_TYPE === 'production' ); // نصب افزونه فقط از طریق گیت
define( 'DISABLE_WP_CRON', true );                                     // کران واقعی با WP-CLI
define( 'WP_DEBUG', WP_ENVIRONMENT_TYPE !== 'production' );
define( 'AUTOMATIC_UPDATER_DISABLED', true );                          // به‌روزرسانی‌ها هم از مسیر دیپلوی

ثابت DISALLOW_FILE_MODS مهم‌ترین خط است: در production هیچ‌کس نمی‌تواند از پیشخوان افزونه نصب یا فایل ویرایش کند. تنها راه تغییر کد همان گیت است و این یعنی سرور همیشه با ریپو یکی است.

سه استراتژی برای هاست‌های ایرانی

سه استراتژی استقرار وردپرس برای هاست ایرانی: رانر ابری GitHub، رانر self-hosted و استقرار pull روی سرور

انتخاب استراتژی به این بستگی دارد که فایروال هاست SSH ورودی از IP خارجی را می‌پذیرد یا نه.

رانرهای رایگان GitHub روی سرورهای مایکروسافت خارج از ایران اجرا می‌شوند. workflow بالا از همان‌جا به سرور شما SSH می‌زند. بسیاری از هاست‌های ایرانی SSH ورودی از IP خارجی را می‌بندند یا فقط با درخواست باز می‌کنند. اگر در لاگ workflow پیام Connection timed out دیدید، همین است. دو راه‌حل دارید:

استراتژی ۲: رانر self-hosted روی سرور ایرانی

رانر یک سرویس کوچک است که روی سرور خودتان نصب می‌شود و خودش به GitHub وصل می‌شود تا job بگیرد. ارتباط همیشه از سرور به بیرون است، پس هیچ پورتی باز نمی‌شود و فایروال مشکلی ندارد. بیلد و کپی فایل‌ها هم روی همان سرور انجام می‌شود و دیگر rsync از راه دور لازم نیست:

# روی VPS ایرانی با کاربر deploy (دستور دقیق را GitHub در Settings › Actions › Runners می‌دهد)
mkdir -p ~/actions-runner && cd ~/actions-runner
curl -o actions-runner-linux-x64.tar.gz -L https://github.com/actions/runner/releases/latest/download/actions-runner-linux-x64.tar.gz
tar xzf actions-runner-linux-x64.tar.gz
./config.sh --url https://github.com/USER/REPO --token TOKEN --labels iran-prod --unattended
sudo ./svc.sh install deploy && sudo ./svc.sh start
jobs:
  deploy:
    runs-on: [self-hosted, iran-prod]
    environment: production
    steps:
      - uses: actions/checkout@v7
      - name: Build
        run: |
          cd wp-content/themes/wpkala-theme && npm ci && npm run build
      - name: Release (local copy, no SSH needed)
        run: |
          RELEASE=$(date +%Y%m%d-%H%M%S)
          rsync -az --delete --exclude='.git' ./ /var/www/site/releases/$RELEASE/
          /var/www/site/deploy/activate.sh "$RELEASE"

رانر را با کاربر deploy نصب کنید نه root، و برچسب (label) اختصاصی بدهید تا job های دیگر روی آن اجرا نشوند. برای ریپوهای عمومی رانر self-hosted نگذارید؛ هر کسی با یک Pull Request می‌تواند روی سرور شما کد اجرا کند. نیاز به Node روی سرور دارید که روی VPS ساده است.

استراتژی ۳: استقرار pull برای هاست اشتراکی

هاست اشتراکی نه Node دارد نه اجازه‌ی نصب سرویس. اما اگر SSH و git داشته باشد (بیشتر هاست‌های ایرانی دارند) سرور می‌تواند خودش هر چند دقیقه ریپو را بررسی کند و در صورت تغییر، نسخه‌ی جدید را بگیرد. در این حالت خروجی بیلد (پوشه‌ی build) را در ریپو commit می‌کنید یا در یک شاخه‌ی جداگانه‌ی deploy با Actions می‌سازید و push می‌کنید:

#!/usr/bin/env bash
# /var/www/site/deploy/pull.sh : استقرار pull برای هاست اشتراکی (اجرا با کران‌جاب)
set -euo pipefail
cd /home/USER/public_html/wp-content/themes/wpkala-theme

# فقط اگر کامیت جدیدی روی main هست
git fetch --quiet origin main
if [ "$(git rev-parse HEAD)" = "$(git rev-parse origin/main)" ]; then
  exit 0
fi

git reset --hard origin/main
# بیلد از قبل در ریپو کامیت شده (پوشه‌ی build) چون هاست اشتراکی Node ندارد
wp cache flush --path=/home/USER/public_html --quiet
echo "$(date) deployed $(git rev-parse --short HEAD)" >> /home/USER/deploy.log
# crontab -e : هر پنج دقیقه بررسی کن
*/5 * * * * /home/USER/deploy/pull.sh >> /home/USER/deploy-cron.log 2>&1

برای اینکه هاست بتواند ریپوی خصوصی را بخواند، یک Deploy Key فقط‌خواندنی در Settings › Deploy keys ریپو بسازید و کلید خصوصی‌اش را در ~/.ssh هاست بگذارید. این روش اتمیک نیست و بیلد را روی رانر انجام نمی‌دهد، اما از FTP هزار بار بهتر است و برای سایت‌های کوچک کاملاً کافی است.

محیط staging و تأیید قبل از production

یک شاخه‌ی staging بسازید که به زیردامنه‌ی staging دیپلوی شود. همان workflow با یک خط تغییر هر دو محیط را پوشش می‌دهد و Secrets هر محیط جداگانه خوانده می‌شود:

on:
  push:
    branches: [main, staging]

jobs:
  deploy:
    runs-on: ubuntu-latest
    # شاخه‌ی staging به محیط staging و main به production
    environment: ${{ github.ref_name == 'main' && 'production' || 'staging' }}
    steps:
      - uses: actions/checkout@v7
      # ... همان مراحل؛ Secrets هر محیط جداگانه تعریف می‌شود

در Settings › Environments › production گزینه‌ی Required reviewers را فعال کنید. از این به بعد هر push به main منتظر می‌ماند تا یکی از تأییدکننده‌ها در صفحه‌ی Actions روی Approve بزند. برای تیم‌های دو سه نفره همین یک قدم بیشتر حوادث را حذف می‌کند.

همگام‌سازی دیتابیس و آپلودها

جهت داده همیشه از production به staging است، هرگز برعکس. دیتابیس زنده را روی staging کپی کنید تا با داده‌ی واقعی تست کنید، و آپلودها را با rsync بیاورید یا در staging به آدرس production وصل کنید:

# کپی دیتابیس production روی staging (هرگز برعکس)
ssh deploy@prod "cd /var/www/site/current && wp db export - | gzip" | gunzip | \
  ssh deploy@staging "cd /var/www/staging/current && wp db import -"
ssh deploy@staging "cd /var/www/staging/current && \
  wp search-replace 'https://site.ir' 'https://staging.site.ir' --all-tables --skip-columns=guid && \
  wp option update blog_public 0"

خط آخر staging را از ایندکس گوگل پنهان می‌کند. اگر بخواهید staging را با رمز هم ببندید، یک Basic Auth در nginx کافی است.

امنیت در پایپ‌لاین

  • کلید دیپلوی فقط برای همین کار ساخته می‌شود و با کاربر deploy که sudo ندارد وارد می‌شود. کلید شخصی خودتان هرگز در Secrets نمی‌رود.

  • اکشن‌های شخص ثالث را به نسخه‌ی مشخص (یا SHA کامیت) پین کنید. در این مقاله فقط اکشن‌های رسمی GitHub و دو اکشن پرکاربرد با نسخه‌ی ثابت استفاده شده‌اند.

  • Secrets در لاگ نمایش داده نمی‌شوند اما اگر آن‌ها را با echo چاپ کنید، GitHub فقط بخشی را ماسک می‌کند. هیچ‌وقت چاپشان نکنید.

  • wp-config و .env خارج از گیت و خارج از پوشه‌ی هر نسخه در shared می‌مانند؛ هیچ دیپلویی آن‌ها را بازنویسی نمی‌کند.

  • با DISALLOW_FILE_MODS پیشخوان را از ویرایش فایل محروم کنید تا کد سرور همیشه برابر ریپو باشد و هک از طریق ویرایشگر قالب غیرممکن شود.

  • برای ریپوی عمومی هرگز رانر self-hosted نگذارید و workflow را فقط روی push به main (نه pull_request) اجرا کنید.

خطاهای رایج و راه‌حل

نشانه

علت

راه‌حل

Connection timed out در مرحله‌ی rsync

فایروال هاست IP خارجی را می‌بندد

رانر self-hosted یا استقرار pull؛ یا از پشتیبانی هاست بخواهید IP رانرها را باز کند

Permission denied (publickey)

کلید عمومی در authorized_keys نیست یا مجوز فایل‌ها اشتباه است

مجوز ۷۰۰ برای .ssh و ۶۰۰ برای authorized_keys؛ کلید را بدون passphrase بسازید

Host key verification failed

known_hosts خالی است

مرحله‌ی ssh-keyscan را قبل از rsync بگذارید

سایت بعد از دیپلوی خطای ۵۰۰ می‌دهد

symlink هسته یا wp-config ساخته نشده

لاگ مرحله‌ی Activate را ببینید؛ با ln -sfn دستی تست کنید

تصاویر بعد از دیپلوی ۴۰۴ شدند

uploads داخل نسخه است نه shared

پوشه‌ی uploads را به shared منتقل و symlink کنید

Permission denied هنگام نوشتن کش

مالک فایل‌ها deploy است و PHP با www-data اجرا می‌شود

گروه www-data و chmod 2775 روی پوشه‌ها؛ یا PHP-FPM را با همان کاربر اجرا کنید

workflow موفق ولی تغییرات دیده نمی‌شود

کش سرور یا CDN

wp cache flush در workflow هست؛ کش nginx یا کلودفلر را هم پاک کنید

دیپلوی دوم با rsync خیلی کند است

node_modules یا src منتقل می‌شود

exclude ها را بررسی کنید؛ فقط خروجی build باید برود

جمع‌بندی

پایپ‌لاین این مقاله چهار قول می‌دهد: هر تغییر کد ردیابی‌شده است، بیلد همیشه یکسان است، هیچ دیپلویی سایت را نیمه‌کاره نمی‌گذارد و بازگشت یک دستور است. اگر VPS دارید، همان workflow اصلی را با رانر self-hosted راه بیندازید و از اولین دیپلوی موفق به بعد دیگر سراغ FTP نخواهید رفت. اگر روی هاست اشتراکی هستید، اسکریپت pull با کران‌جاب همین امروز قابل راه‌اندازی است.

سه قدم برای شروع: فایل .gitignore این مقاله را در پروژه بگذارید و ریپو را بسازید، کاربر deploy و کلید اختصاصی را روی سرور آماده کنید، و workflow را اول روی staging امتحان کنید. وقتی سبز شد، Required reviewers را برای production فعال کنید و بعد سراغ main بروید. دستورهای WP-CLI داخل workflow در مقاله‌ی آموزش WP-CLI وردپرس کالا توضیح داده شده‌اند.

سؤال‌های متداول

آیا باید کل وردپرس را در گیت بگذارم؟

خیر. فقط قالب، افزونه‌های اختصاصی و فایل‌های پیکربندی دیپلوی در گیت هستند. هسته با WP-CLI نصب می‌شود، افزونه‌های مخزن با Composer یا در دیپلوی، و آپلودها و دیتابیس جداگانه مدیریت می‌شوند. ریپو کوچک می‌ماند و به‌روزرسانی وردپرس آن را به‌هم نمی‌ریزد.

GitHub Actions برای ایران کار می‌کند؟

بله، خود GitHub و Actions از ایران قابل استفاده‌اند. مشکل سمت سرور است: رانرهای ابری IP خارجی دارند و بعضی هاست‌های ایرانی SSH ورودی خارجی را می‌بندند. راه‌حل، رانر self-hosted روی سرور خودتان یا استقرار pull با کران‌جاب است که در مقاله توضیح داده شده.

دیتابیس را هم با گیت منتقل کنم؟

هرگز. دیتابیس داده‌ی زنده است و با هر سفارش و دیدگاه تغییر می‌کند. ساختار دیتابیس را با کد (مهاجرت در افزونه و wp core update-db) مدیریت کنید و داده را فقط از production به staging کپی کنید، نه برعکس.

استقرار اتمیک یعنی چه و چرا مهم است؟

یعنی نسخه‌ی جدید در پوشه‌ی جداگانه ساخته می‌شود و فقط یک symlink به آن می‌چرخد. وب‌سرور هیچ‌وقت نسخه‌ی نیمه‌کپی‌شده نمی‌بیند و بازگشت فقط برگرداندن همان لینک است. با FTP یا rsync مستقیم روی پوشه‌ی زنده، در فاصله‌ی چند ثانیه‌ی کپی، سایت می‌تواند خطا بدهد.

اگر هاست اشتراکی SSH ندارد چه کنم؟

بدون SSH نه گیت روی سرور ممکن است و نه WP-CLI. می‌توانید در GitHub Actions بیلد بگیرید و خروجی را با FTP از داخل workflow منتقل کنید، اما اتمیک نیست و امن‌تر این است که به هاستی با SSH مهاجرت کنید؛ تقریباً همه‌ی هاست‌های ایرانی در پلن‌های میانی SSH می‌دهند.

آیا به Composer و Bedrock نیاز دارم؟

نه الزاماً. ساختار این مقاله با وردپرس استاندارد کار می‌کند. Composer وقتی ارزش دارد که افزونه‌های مخزن یا کتابخانه‌های PHP زیادی دارید و می‌خواهید نسخه‌ی دقیقشان در کد ثبت شود. Bedrock همین کار را با قرارداد آماده انجام می‌دهد و برای پروژه‌های بزرگ انتخاب خوبی است.

چطور دیپلوی را به عقب برگردانم؟

در ساختار اتمیک، symlink به نام current را به پوشه‌ی نسخه‌ی قبلی در releases برگردانید و کش را خالی کنید؛ کمتر از یک ثانیه طول می‌کشد. در GitHub هم می‌توانید workflow کامیت قبلی را دوباره اجرا کنید تا همان نسخه از نو دیپلوی شود.

  • ۱۲ دقیقه مطالعه
نویسندهمدیریت

نظرات کاربران

ثبت نظر و امتیاز

هنوز نظری ثبت نشده؛ اولین نظر را شما بنویسید.

نظر و امتیاز خود را بنویسید

ایمیل شما منتشر نمی‌شود. نظرها پس از بازبینی منتشر می‌شوند.

با ارسال نظر، قوانین انتشار نظرات سایت را می‌پذیرید.

مطالب مرتبط

اگر این مقاله برایتان مفید بود، این‌ها را هم بخوانید

محیط توسعه لوکال وردپرس در ۱۴۰۵ با wp-env، Docker، Playground، Studio و LocalWP
توسعه و کدنویسی وردپرس

محیط توسعه‌ی لوکال وردپرس در ۱۴۰۵: wp-env، Docker، Playground، Studio و LocalWP

جایگزین‌های امروزی XAMPP برای توسعه‌ی وردپرس: wp-env ابزار رسمی، Docker Compose برای تیم، Playground برای اجرا داخل مرورگر و Studio و LocalWP برای طراحان. با فایل‌های پیکربندی آماده، Blueprint برای دمو و نکته‌های مخصوص اینترنت ایران.

۹ دقیقه مطالعه
REST API وردپرس: اندپوینت سفارشی، احراز هویت با Application Password، کش و امنیت
توسعه و کدنویسی وردپرس

REST API وردپرس: ساخت اندپوینت سفارشی، احراز هویت با Application Password، کش و امنیت

REST API راه استاندارد اتصال اپ موبایل، سایت هدلس، سرویس‌های اتوماسیون و هوش مصنوعی به وردپرس است. در این راهنما یک API واقعی محصولات می‌سازید، چهار روش احراز هویت را مقایسه می‌کنید، کش را در چهار لایه می‌چینید و با چک‌لیست امنیت API را آماده‌ی انتشار می‌کنید.

۱۲ دقیقه مطالعه
هوک‌های وردپرس به زبان ساده: اکشن، فیلتر و ۲۰ مثال واقعی بدون افزونه
توسعه و کدنویسی وردپرس

هوک‌های وردپرس به زبان ساده: اکشن، فیلتر و ۲۰ مثال واقعی بدون افزونه

هوک‌ها راه رسمی تغییر رفتار وردپرس بدون دست زدن به هسته و افزونه‌ها هستند. در این راهنما اکشن و فیلتر را با تصویر یاد می‌گیرید، چهار پارامتر add_action را باز می‌کنیم، جای درست کد و ترتیب اجرای هوک‌ها را می‌بینید و ۲۰ مثال آماده‌ی کپی برای محتوا، امنیت، ورود، پیشخوان، ووکامرس و کرون می‌گیرید.

۱۳ دقیقه مطالعه
آموزش WP-CLI: ۳۰ دستور کاربردی برای مدیریت، مهاجرت و عیب‌یابی وردپرس
توسعه و کدنویسی وردپرس

آموزش WP-CLI: ۳۰ دستور کاربردی برای مدیریت، مهاجرت و عیب‌یابی وردپرس

WP-CLI رابط خط فرمان رسمی وردپرس است. در این راهنما ۳۰ دستوری را که در کار روزمره بیشترین استفاده را دارند با مثال واقعی یاد می‌گیرید: از نصب و به‌روزرسانی تا پشتیبان دیتابیس، تغییر دامنه، مهاجرت کامل سایت، عیب‌یابی بدون پیشخوان و دستورهای جدید نسخه‌ی ۳ برای وردپرس ۷.