بک آپ گرفتن کدها روی فضای ابری به صورت خودکار


دیروز داشتم با دوستم صحبت میکردم در مورد اینکه الان که Gitlab اکانت های ایرانی رو داره بلاک میکنه کد هامون رو کجا بذاریم تا خیالتون تا حدودی راحت باشه که کدامون به فنا نمیره؟ گیتهاب که پارسال ایرانیا رو بلاک کرده بود، گیتلب هم که چند روز پیش این کار رو کرد، بیت باکت و سرویس های مشابه هم احتمالا در آینده همین کار رو خواهند کرد. یه طوفان فکری کوچیک داشتیم و به یه راه حلی رسیدیم که به نظر باحال میومد. من خودم اون راه رو رفتم و انجامش دادم و تصمیم گرفتم که یه جایی به اشتراک بذارم شاید به درد برنامه نویس های دیگه هم خورد.

ایده این بود که یه جوری کدهامون رو توی سرویس های فضای ابری قرار بدیم که با کمترین دردسر کدهامون سینک بشه به این صورت که نیاز نباشه هر بار که کدهامون رو کامیت میکنیم بریم دستی آپلود کنیم توی فضای ابری.

اجازه بدید اول به طور خلاصه بگم که کلیت کاری که کردم چیه بعد وارد جزئیات میشم:

  • در مرحله اول روی کامپیوترم یک دایرکتوری ساختم که همه پروژه ها به صورت git bare repository اون تو قرار می‌گیره. یه جورایی انگار دایرکتوری مربوط به ریپوزیتوریهام توی مثلا گیتلب رو روی لوکالم داشته باشم.
  • در مرحله دوم از یک ابزار برای سینک کردن دایرکتوری ریپوزیتوری ها توی فضای ابری استفاده کردم. مثلا یکی از سرویس های فضای ابری مثل گوگل درایو، دراپ باکس، مگا و سرویس های دیگه (میتونه همزمان با چند تا سرویس مختلف سینک بشه که خیالم راحت باشه اگه یکیش ایرانیارو بلاک کرد کدهام توی بقیه سرویس ها هست)
  • و در انتها یه گیت هوک نوشتم که هر وقت هر چی توی این دایرکتوری پوش شد توی فضای ابری سینک بشه

خب حالا اجازه بدید با جزئیات دقیق بگم چطور این کار رو انجام بدید:

ساخت ریپوزیتوری لوکال

گام ۱: یه دایرکتوری توی دایرکتوری هوم یا هرجای دیگه به هر اسمی میخواید درست کنید: من توی هوم به اسم repositories ساختم:

mkdir $HOME/repositories

گام ۲:فرض کنید یه پروژه دارید که توی دایرکتوری

$HOME/projects/myproject

قرار داره. توی دایرکتوری repositories که در مرحله ۱ ساختید یه دایرکتوری برای اون پروژه بسازید.

mkdir $HOME/repositories/myproject

گام ۳: برید داخل دایرکتوری ای که تو مرحله ۲ ساختید و یک git bare repository بسازید:

cd $HOME/repositories/myproject
git init --bare

خب الان شما یه ریپوزیتوری لوکال دارید. یه چیزی شبیه همون ریپوزیتوری گیتلب ولی توی لوکالتونه.

گام ۴: حالا باید آدرس ریپوزیتوری ای که ساختید رو به عنوان ریموت توی تنظیمات گیت پروژه ست کنید. فرض کردیم خود پروژه توی آدرس

$HOME/projects/myproject

قرار داشته.

برید داخل دایرکتوری پروژه و ریموت گیت رو اضافه کنید:

cd $HOME/projects/myproject
git remote add local $HOME/repositories/myproject

کلمه local اسمی هست که من گذاشتم برای این ریموتم، شما میتونید هر چی بذارید مثلا origin یا upstream یا هر چیز دیگه

گام ۵: حالا برنچ های پروژه رو پوش کنید توی ریپوزیتوری

git push local master -u

این کامند برنچ مستر رو پوش میکنه. طبیعتا اگر برنچ دیگه ای دارید که میخواید ذخیره بشه باید پوش کنید.

گام های ۲ تا ۵ رو برای همه پروژه هاتون انجام بدید.

سینک کردن ریپوزیتوری ها با فضای ابری

خب تا اینجای کار هیچ کار خاصی نکردیم که به حفظ امنیت کدهامون کمک کنه. اصل کار از اینجا به بعد قراره انجام بشه. برای ادامه کار شما ابزاری میخواید که بتونه یک دایرکتوری روی کامپیوترتون رو با فضای ابری سینک کنه. برای این کار من از Rclone استفاده کردم که سرویس های کلود زیادی رو ساپورت میکنه.

گام ۶: rclone رو نصب کنید. روش نصب rclone توی این لینک کامل توضیح داده شده

https://rclone.org/install/

گام ۷: سرویس فضای ابری مورد نظر خودتون رو توی rclone تنظیم کنید. برای اینکار اول دستور زیر رو بزنید:

rclone config

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

وقتی این دستور رو میزنید اول از همه بهتون میگه که تنظیماتی تا حالا انجام نشده و یه فایل توی مسیر پیش فرض تنظیمات خودش میسازه. بعد ازتون میپرسه چیکار کنم. شما با انتخاب گزینه New remote بهش میگید یه ریموت جدید اضافه کن. ریموت ها در واقع سرویس های فضای ابری هستن، مثل گوگل درایو، دراپ باکس و مگا (https://mega.nz). بعد ازتون میخواد یه اسم انتخاب کنید برای ریموتتون، برای مثال من mega رو وارد کردم. بعد یه لیستی از انواع ریموتی که ساپورت میکنه نشون میده که یکیش رو باید انتخاب کنید. من خودم مگا رو انتخاب کردم. انتخاب ریموت هم به این صورته که شماره ریموت مورد نظرتون که کنار اسمش نوشته وارد میکنید. سوالات بعدی هم بسته به نوع ریموتی (یا به عبارت دیگه، سرویس فضای ابری) که انتخاب میکنید متفاوته. من از تنظیماتی که انجام دادم عکس گرفتم و میذارم اینجا:

گام ۸: حالا که تنظیمات ریموت مربوط به rclone رو انجام دادید، میتونید با دستور rclone sync هر دایرکتوری ای که بخواید سینک کنید. شما چون هدفتون سینک کردن ریپوزیتوری های لوکالتون بود این دستور رو بزنید:

rclone sync $HOME/repositories mega:/repositories -P

الان اگر توی سایت مگا برید باید دایرکتوری repositories به همراه محتویاتش رو ببینید.

استفاده از هوک گیت برای سینک کردن به صورت خودکار

خب تا الان شما تونستید ریپوزیتوری هاتون رو سینک کنید اما به صورت دستی. یعنی باید هر وقت پوش کردید حتما کامند rclone sync رو بزنید تا سینک بشه. توی مراحل بعدی کاری میکنید که سینک کردن بعد از هر پوش به طور خودکار انجام بشه. این کار رو با کمک هوک های گیت انجام میدیم. هوک های گیت فایل های قابل اجرایی هستن که توی ایونت های مختلف گیت مثل «قبل از کامیت»، «بعد از کامیت»، «قبل از مرج»، «قبل از پوش» و ... اجرا میشن. هر هوک یک فایله که اسمش تعیین کننده اینه که چه زمانی اجرا میشه. مثلا فایل pre-commit اگر قابل اجرا باشه قبل از اینکه کامیت انجام بشه اجرا میشه. ما از هوک post-receive توی ریپوزیتوریمون استفاده میکنیم که بعد از اینکه کد داخلش پوش شد یه کاری انجام بده، حالا اون کار چیه؟ بله، سینک کردن دایرکتوری repositories توی فضای ابری

گام ۹: گیت به صورت پیش فرض هوک ها رو از داخل دایرکتوری

$GIT_DIR/hooks

میخونه. به این معنی که توی هر پروژه یه دایرکتوری هست به اسم .git که داخلش یه دایرکتوری دیگه هست به اسم hooks و هر فایل قابل اجرایی با یک اسم خاص که توش باشه اون رو به عنوان یک هوک برای اون پروژه در نظر میگیره. اما ما این رو نمیخوایم، چیزی که میخوایم اینه که یک هوک بسازیم که برای همه پروژه ها اجرا بشه. این کار رو میتونیم با کانفیگ گلوبال گیت به اسم core.hooksPath انجام بدیم.

کامند زیر رو بزنید:

git config --global core.hooksPath $HOME/repositories/hooks

این کامند باعث میشه که برای همه پروژه هاتون هوک ها رو از دایرکتوری

$HOME/repositories/hooks

بخونه. حتما میپرسید خوب اگر بخوایم یه پروژه، هوک های خاص خودش رو داشته باشه چیکار کنیم؟ (قاعدتا هم باید همینطور باشه)

برای اینکار باید برید داخل پروژه هایی که هوک های خودشون رو دارن کانفیگ core.hooksPath رو به صورت لوکال ست کنید. مثلا این کامند ها رو بزنید:

cd $HOME/projects/myproject
git config core.hooksPath $PWD/.git/hooks

حالا پروژه myproject هوک های خودش رو داخل دایرکتوری

$HOME/projects/myproject/.git/hooks

داره و هوک های داخل دایرکتوری

$HOME/repositories/hooks

برای همه پروژه ها (که شامل myproject هم میشه) اعمال میشه.

گام ۱۰: حالا باید هوکی که بعد از پوش شدن هر پروژه اجرا میشه تعریف کنید:

vim $HOME/repositories/hooks/post-receive

محتویات زیر رو داخل فایل کپی کنید و ذخیره کنید و ببندید:

#!/bin/bash
rclone sync $HOME/repositories mega:repositories -P

در انتها باید فایل هوک رو قابل اجرا کنید، با این کامند:

chmod +x $HOME/repositories/hooks/post-receive

حالا یه چیزی توی ریپوزیتوری myproject پوش کنید ببینید چه اتفاقی می‌افته. باحال نبود؟ من که خودم کلی حال کردم باهاش.

سوالات متداول (از نظر خودم)

سوال: چرا از سرویس های گیت دیگه مثل Bitbucket استفاده نکنیم؟

جواب: بعد از بلاک کردن اکانت های ایرانیا، پارسال توسط Github و امسال توسط Gitlab، آیا به سرویس های گیت دیگه اعتماد میکنید؟ من که نمیکنم دیگه


سوال: چرا خودمون Gitlab یا Gitea یا امثالشون رو رو سرور خودمون نیاریم بالا؟

جواب: هزینه داره. در ضمن باز هم ممکنه سروری که گرفتید بلاکتون کنه. سرور ایرانی هم دغدغه های خودش رو داره که من وارد جزئیاتش نمیشم.


سوال: حالا اگه سرویس فضای ابری که استفاده کردیم بلاکمون کرد چی؟

جواب: میتونید در لحظه با چند تا سرویس کلود سینک کنید. همشون همزمان بلاک نمیکنن که.


سوال: آیا با این کار از استفاده از سرویس هایی مثل Gitlab بی نیاز میشم؟

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

موفق باشید