فرض کنید شما مدیر توسعه و نگهداری از یک سایت هستید که به صلاحدید کارفرما، می‌بایست تغییراتی را در کد سایت ایجاد کنید. طبیعی‌ترین راه برای این فرآیند اینگونه است: «انجام تغییرات بر روی کدها -> بارگذاری کدها بر روی وب‌سرور -> جایگزینی فایل‌های جدید با فایل‌های قبلی». این فرآیند تعداد تغییرات زیاد باشد و برای اعمال تغییرات مجبور به بالا پایین کردن پوشه‌های مختلف بر روی این وب‌سرور با ابزارهای تحت وب یا FTP باشید، طبیعی‌ترین نتیجه کلافه‌شدن و سردرگمی خواهد بود. چاره چیست؟
در این پست قرار است یک سرور گیت به عنوان ابزار مدیریت ورژن کدها و یک وب‌سرور را به صورتی یکپارچه کنیم که هرگونه بروزشدن در سرور گیت، باعث بروزشدن فایل‌های تغییریافته‌ی متناظر در وب‌سرور شود.


مشخصات فنی

وب‌سرور: CentOS6 + Apache2 + PHP5
سرور گیت: CentOS6 + GitLab7

چاره‌ی کار

برای حل این مشکل، من از یک راه‌حل ساده، اما کارراه‌انداز استفاده کرده‌ام. کدهای وب‌سرور را از مخزن گیت کلون (Clone) می‌کنیم و با هر بار بروزشدن گیت، به وب‌سرور می‌گوئیم که پول (Pull) کند. D:

مشروح چاره‌ی کار

  1. یک مخزن گیت‌لب بسازید.
  2. حال در لوکال در پوشه‌ی پروژه -پوشه‌ای که قرار است با بروزشدنش، وب سرور شما نیز بروز شود.- گیت را راه‌اندازی کنید و فایل‌ها را به مخزن اضافه کنید.
    meysampg@freedom:~/git/sync$ git init
    Initialized empty Git repository in /home/meysampg/git/sync/.git/
    meysampg@freedom:~/git/sync$ touch index.php
    meysampg@freedom:~/git/sync$ git add index.php
    meysampg@freedom:~/git/sync$ git commit -m "first commit"
    [master (root-commit) 14cadcb] first commit
     1 file changed, 0 insertions(+), 0 deletions(-)
     create mode 100644 index.php 
  3. مقصد مخزن لوکال را به مخزن ایجادشده در گیت‌لب تغییر دهید.
    git remote add origin http://172.16.13.8/meysam/sync.git
    
    فایل‌های موجود در مخزن لوکال را به داخل گیت‌لب پوش کنید.
    meysampg@freedom:~/git/sync$ git push -u origin master
    Username for http://172.16.13.8: meysam
    Password for http://meysam@172.16.13.8:
    Counting objects: 3, done.
    Writing objects: 100% (3/3), 213 bytes | 0 bytes/s, done.
    Total 3 (delta 0), reused 0 (delta 0)
    To http://172.16.13.8/meysam/sync.git
     * [new branch]      master -> master
    Branch master set up to track remote branch master from origin. 
  4. اکنون نیاز است تا طریقه‌ی تائید هویت برای ارتباط بین وب‌سرور و گیت‌لب را مشخص کنیم. برای این منظور، یک SSH Key بر روی وب‌سرور می‌سازیم و کلید عمومی آنرا در اختیار گیت‌سرور می‌گذاریم. با این کار، می‌توانیم برای وب‌سرور، اجازه‌ی خواندن از طریق SSH از گیت‌سرور را بگیریم.
    برای این منظور ابتدا پوشه‌ی .ssh را در خانه‌ی یوزر آپاچی می‌سازیم و صاحب آن کاشانه را خود یوزر آپاچی قرار می‌دهیم:
    [root@webserver meysam]# mkdir /var/www/.ssh
    [root@webserver meysam]# chown -R apache:apache /var/www/.ssh/
    
    اکنون یک کلید از نوع rsa و با توضیحی که حاوی ایمیل یکی از دارندگان حق خواندن در مخزن گیت‌لب است را با گروه و یوزر آپاچی ایجاد می‌کنیم.
    [root@webserver meysam]# sudo -Hu apache ssh-keygen -t rsa -C "p.g.meysam@zentexcooo.cooom"
    Generating public/private rsa key pair.
    Enter file in which to save the key (/var/www/.ssh/id_rsa):
    Enter passphrase (empty for no passphrase):
    Enter same passphrase again:
    Your identification has been saved in /var/www/.ssh/id_rsa.
    Your public key has been saved in /var/www/.ssh/id_rsa.pub.
    The key fingerprint is:
    b7:e9:c2: ... :36:21 apache@webserver
    The key‍‍‍ s randomart image is:
    +--[ RSA 2048]----+
    |     E .o        |
    |      .B         |
    |    . = o        |
    |     *           |
    |  . + o S .      |
    |  .+..   . o     |
    |.... . .  o      |
    |oo    . oo       |
    |..     ..oo      |
    +-----------------+
  5. اکنون کلید عمومی را کپی می‌کنیم:
    [root@webserver meysam]# cat /var/www/.ssh/id_rsa.pub
    ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAqh ... mQy1Tlmj2qXH6ux664pamSn46OsCw== p.g.meysam@zentexcooo.cooom
    
    به مخزن گیت‌لب رفته و در بخش تنظیمات (از منوی سمت چپ، آخرین گزینه: Settings) با انتخاب گزینه‌ی Deploy Keys از منوی بغل، کلید را اضافه می‌کنیم:
  6. اکنون از روی مخزن گیت، یک نسخه از نرم‌افزار را بر روی وب‌سرور کلون می‌کنیم. دقت کنید که این کلون کردن حتما باید با استفاده از SSH صورت گیرد. امکان دارد که در اولین ارتباط بین وب‌سرور و گیت‌سرور، در خط ترمینال سوالی مبنی بر اجازه برای افزودن کلید عمومی گیت‌سرور به کلیدهای وب‌سرور پرسیده شود که به آن جواب مثبت دهید:
    [root@webserver meysam]# sudo -Hu apache git clone git@172.16.13.8:meysam/sync.git
    
    این کلون کردن برای یوزر آپاچی صورت می‌گیرد تا هم وب‌سرور اجازه‌ی تفسیر فایل‌ها را داشته باشد و هم برای بروزرسانی فایل‌ها در هنگام بروزشدن گیت، مشکلی به وجود نیاید.
    در صورتی که فایل‌های انتقالی نیاز به نصب داشته باشند -مثلا فایل‌های کلون‌شده، یک نسخه از وردپرس باشند-، قبل از رفتن به مرحله‌ی بعد، با فراخوانی آدرس پوشه‌ی مذکور در مرورگر، آنرا نصب کنید.
  7. یک فایل .gitignoreساخته و در داخل آن قرار دهید: deploy.php.
  8. [بروزرسانی: ۲۳ فروردین ۱۳۹۴] اکنون فایل بروزکردن فایل‌های موجود بر وب‌سرور با توجه به گیت‌سرور را می‌سازیم. ایده ساده است: «با استفاده از تابع shell_exec محتویات پوشه‌ی کلون‌شده را بروز می‌کنیم.». برای این منظور خط زیر را در فایلی به نام deploy.php در پوشه‌ی کلون‌شده ذخیره می‌کنیم.
    <?php
        $comms = array(
            'git fetch origin',
            'git reset --hard origin/master',
            'git checkout -f origin'
        );
    
        foreach ($comms as $comm)
        {
            shell_exec($comm);
        }
    ?>
    
    با فرض اینکه فایل‌ها در مسیر /var/www/html/meysam/sync ذخیره شده باشند، اکنون باید از طریق مروگر بتوانید به آدرس http://webserver/meysam/sync/deploy.php دست پیدا کنید.
  9. برای اینکه این فایل در هنگام بروزشدن گیت صدا زده شود، باید آنرا به عنوان یک هوک معرفی کنیم. هوک را می‌توان قلاب متصل به یک نخ که در نهایت به چوب ماهیگیری‌ای وصل شده است، تصور کرد. با کشیدن چوب، همه‌ی محل‌هایی که قلاب‌های ماهیگیری به آن متصل شده‌اند خبردار می‌شوند که اتفاقی افتاده است و عکس‌العملی فراخور با آنچه باید انجام دهند، انجام می‌دهند! :O. در اینجا سرور گیت همان چوب ماهیگیری است و آدرس http://webserver/meysam/sync/deploy.php همان قلاب ماهیگیری. زمانی که گیت‌سرور بروز می‌شود، چوب کشیده می‌شود و در نتیجه قلاب نیز کشیده خواهد شد و فایل فراخوانده شده و دستوراتی که در آن است به اجرا در خواهند آمد.
    برای معرفی لینک فوق به عنوان هوک، به قسمت تنظیمات مخزن رفته و گزینه‌ی Web Hooks را انتخاب می‌نمائیم. آدرس فوق را در قسمت URL قرار می‌دهیم و تیک Push events را می‌زنیم و هوک را با فشردن Add web hook ذخیره می‌کنیم.

  10. کار تمام است! بروی مخزن لوکال یک فایل را بروز کنید و آنرا به سرور گیت پوش کنید، خواهید دید که وب‌سرور نیز بروز خواهد شد.

بروزرسانی:

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

با کلیک بر روی دکمه‌ی Enable می‌توانید از کلید مذکور استفاده کنید ;).

۲. اگر در هنگام کلون کردن در مرحله ۶ با خطای

fatal: The remote end hung up unexpectedly
fatal: early EOF
fatal: index-pack failed

مواجه شدید، در وب‌سرور دستور زیر را وارد کنید:

git config --global http.postBuffer 5242880000


پ.ن ۱: هر وقت شروع میکنم به نوشتن، به عمق بی‌سوادی خودم پی می‌برم :|.
پ.ن ۲: هرگونه پیشنهاد برای بهتر شدن این روش، با کمال میل پذیرفته می‌شود. کچل شدیم از بس راه‌های مختلف رو رفتیم و شالاپ خوردیم به در بسته.
پ.ن ۳: داکیومنت‌های خود گیت‌لب یه مثال زده از استفاده از وب‌هوک که در اینجا میشه دیدش. به نظر میاد که بشه کارهای خیلی بیشتری را در مورد ۷ انجام داد. در این مورد ایده‌ای دارید؟
پ.ن ۴: من قبلا از تابع shell_exec برای ساختن یک نیمچه فرمول‌ساز با لاتک استفاده کرده بودم. آنجا هم ایده همین بود، محتوا را داخل یک فایل می‌نوشتم و با استفاده از تابع مذکور، لاتک و بسته‌ی زی‌پرشین آن فایل را رندر میکردم و نتیجه را تبدیل به تصویر میکردم. در ضمن این تابع معمولا روی خیلی از وب‌سرورها مسدود است و برای حل این مشکل به نظر بتوان همین ایده را با پایتون هم اجرا کرد و مشکلی پیش نیاید.