deploy کردن خودکار بعد از push در مخزن git
در آخر این نوشته قراره یک وب سایت کوچیک (مثل تجربهی ئاوات) داشته باشیم که با پوش کردن روی git به صورت خودکار آپدیت میشه و لازم نیست فایلهاش رو با ssh یا ftp به سرور منتقل کنیم.
git ویژگیای به اسم hook داره که باهاش میشه شِل اسکریپتهای دلخواهمون رو وقتی که اتفاقات خاصی میفتن (مثل وقتی که کامیت میکنیم، یا بعد از push کردن) اجرا کنیم. روندی که قراره طی کنیم اینه که باید یک مخزن git سمت سرور بسازیم، hook مناسبی رو انتخاب کنیم و شل اسکریپت مربوط به دیپلوی کردن رو در اون هوک بنویسیم.
گام ۱. ساخت مخزن git
روال معمول استفاده از git اینطور هست که یک مخزن git روی کامپیوتر خودمون داریم، یک مخزن هم روی گیتهاب یا گیتلب یا… میسازیم و آدرس مخزن گیتهاب رو با git remote به مخزن لوکال میدیم. تفاوتی که الان وجود داره اینه که قراره کاری که گیتهاب انجام میده رو خودمون انجام بدیم.
بعد از ssh کردن به سرور، یک پوشه به اسم git درست کنید و داخل اون پوشه با استفاده از git init مخزن گیت رو بسازید.
mkdir git && cd git
git init --bare awat.git
بعد از این دستور پوشهای به اسمawat.git
ساخته میشه. اگر محتویات این پوشه رو نگاه کنید با بقیهی مخزنهای git متفاوت هست. این مخزن شامل کدها نمیشه و فقط فایلهای کنترلی خود مخزن git رو داره. آپشن –bare باعث به وجود آمدن این ویژگی هست.
روی کامپیوتر خودتون طبق روال عادی مخزن گیت رو بسازید و فایلها رو اضافه کنید. وقتی قراره remote رو به مخزن لوکال معرفی کنید آدرس رو با چنین قالبی وارد کنید:
username@host:path/to/awat.git
# Example:
[email protected]:/home/mjafar/git/awat.git
برای مطمئن شدن از آدرس فولدر awat.git میتونید روی سرور به اون پوشه cd کنید و دستور pwd
رو وارد کنید.
گام ۲. پیدا کردن hook مناسب
کاری که قراره انجام شه سمت سرور هست و تو مخزن لوکال قرار نیست تغییر خاصی به وجود بیاد. برای همین باید از hookهای سمت سرور استفاده کنیم. سه hook سمت سرور وجود داره: pre-receive
قبل از وارد کردن کامیتهای push شده به مخزن اجرا میشه. update
هم مثل pre-receive
هست با این تفاوت که اگر چند شاخه به صورت همزمان push بشن، به ازای هر شاخه یک بار اجرا میشه. post-receive
بعد از اتمام push اجرا میشه و برای دیپلوی کردن گزینهی مناسبیه.
برای استفاده از این hook باید داخل پوشهی hooks یک فایل به همین اسم ایجاد کنیم و داخل فایل shell script مورد نیاز برای دیپلوی شدن سایت رو بنویسیم.
cd ~/git/awat.git/hooks
touch post-receive
chmod +x post-receive
vim post-receive
گام ۳. نوشتن hook
ساده ترین اسکریپتی که میشه برای دیپلوی استفاده کرد کپی کردن فایلها در پوشهی سایت (مثل www) هست. با یک checkout ساده این کار انجام شدنیه. با متغیر محیطی (Environment variable) GIT_WORK_TREE
میشه پوشهای که checkout توش انجام میشه رو مشخص کرد.
GIT_WORK_TREE=/home/mjafar/mjafar.me/awat git checkout -f
بخش tricky کار دو گام اول بودند. وقتی hook درستی داشته باشیم، نوشتن محتویات hook خیلی روتین و سادهست. با توجه به پروژه میشه کارهای دیگهای هم بعد از جایگزینی فایلهای جدید انجام داد. مثلا برای یک پروژهی Django میشه بعد از فعال کردن virtual environment، dependency های جدید رو با pip نصب کرد و دیتابیس رو migrate کرد. یا اگر پروژه از Jekyll و jade و sass و… استفاده میکنه، کامپایل این فایلها رو میشه در همین مرحله انجام داد.
توضیحات تکمیلی (پراکنده!)
~ لزومی نداره که اسکریپت با shell نوشته شده باشه. میشه از پایتون یا ruby هم استفاده کرد. اول فایل از shebang استفاده کنید.
~ وقتی اسکریپت post-receive اجرا میشه از طریق خوندن stdin میشه متوجه شد که آخرین کامیت قبل و بعد از push چی بوده و push روی چه شاخهای داره انجام میشه. مقدار hash این دو کامیت و اسم شاخه به ترتیب روی stdin نوشته میشن. اسم شاخه به طور خاص میتونه توی نوشتن hook خیلی به درد خور باشه.
~ هرچیزی که با echo یا print و… در خروجی استاندارد hook ها نوشته شه رو کاربری که داره push میکنه روی کامپیوتر خودش میبینه. اول هر خط از خروجی عبارت remote: اضافه میشه.
~ خط checkout رو میشه به این شکل هم نوشت:
git --work-tree=/home/mjafar/mjafar.me/awat --git-dir=/home/mjafar/git/awat.git checkout -f
~ این کد که با ruby نوشته شده هم از hook استفاده میکنه و push-to-deploy تمیز و خوبی رو میتونه براتون راه بندازه. (شخصاً استفاده نکردم)