في عالم تطوير البرمجيات السريع، توصيل التطبيقات عالية الجودة بسرعة وبشكل موثوق به أمر حاسم. هنا تأتي أهمية CI/CD (التكامل المستمر والتسليم/النشر المستمر) في اللعب.
CI/CD هو مجموعة من الممارسات والأدوات المصممة لتأتيميم وتبسيط عملية دمج تغييرات الشيفرة، اختبارها، ونشرها في الإنتاج. من خلال اعتماد CI/CD، يمكن لفريقك تقليل الأخطاء اليدوية، وتسريع دورات الإصدار، وضمان أن شيفرتك دائمًا في حالة يمكن نشرها.
في هذا البرنامج التعليمي، سنركز على نهج ودود للمبتدئين لإعداد أنبوب عمل CI/CD أساسي باستخدام Bitbucket، وخادم Linux، وPython مع Flask. على وجه الخصوص، سنقوم بإنشاء عملية تلقائية تقوم بجلب أحدث التغييرات من مستودع Bitbucket إلى خادمك Linux كلما تم دفع أو دمج فرع محدد.
سيتم تشغيل هذه العملية من خلال خطافات Bitbucket وخادم Python بناءً على Flask البسيط الذي يستمع إلى أحداث الخطاف الواردة ويشغل النشر.
من المهم أن نلاحظ أن CI/CD هو مجال شاسع ومعقد، وهذا البرنامج التعليمي مصمم لتوفير فهم أساسي بدلاً من أن يكون دليل شامل.
سنغطي أساسيات إعداد أنبوب عمل CI/CD باستخدام أدوات تتوفر للمبتدئين. فقط عليك أن تضع في اعتبارك أن نظم CI/CD الحقيقية غالبًا ما تشمل أدوات وتكوينات أكثر تقدمًا، مثل التحميص، والتنظيم، وبيئات الاختبار متعددة المراحل.
بحلول نهاية هذا البرنامج التعليمي، ستمتلك مثال عملي على كيفية أتمتة عمليات النشر باستخدام Bitbucket ونظام Linux وPython، يمكنك الاستفادة منه لتطوير مهاراتك في مفهوم CI/CD.
جدول المحتويات:
لماذا هو CI/CD مهم؟
أصبح CI/CD ركيزة أساسية في تطوير البرمجيات الحديثة لعدة أسباب. أولاً وقبل كل شيء، يسرع عملية التطوير. من خلال أتمتة المهام المتكررة مثل الاختبار والنشر، يمكن للمطورين التركيز أكثر على كتابة الشفرة وأقل على العمليات اليدوية. وهذا يؤدي إلى تقديم المزيد من الميزات الجديدة وإصلاحات الأخطاء بشكل أسرع، مما يعد أمرًا مهمًا بشكل خاص في الأسواق التنافسية حيث يمكن أن يكون السرعة عاملاً مميزًا.
فائدة رئيسية أخرى لـ CI/CD هي تقليل الأخطاء وتحسين الموثوقية. يضمن الاختبار التلقائي أن يتم فحص كل تغيير في الشفرة بدقة قبل دمجه في الشفرة الرئيسية. وهذا يقلل من خطر إدخال الأخطاء التي يمكن أن تعطل التطبيق أو تتطلب إصلاحات مكلفة لاحقًا. تقلل أنابيب النشر التلقائية أيضًا من احتمالية الخطأ البشري خلال عملية النشر، مما يضمن أن تكون عمليات النشر متسقة ومتوقعة.
تعزز CI/CD أيضًا التعاون الأفضل بين أعضاء الفريق. في سير العمل التقليدي للتطوير، قد يكون دمج تغييرات الشفرة من عدة مطورين عملية تأخذ وقتًا وتكون عرضة للأخطاء. مع CI/CD، تتم دمج الشفرة واختبارها بانتظام، غالبًا مرات عديدة في اليوم. وهذا يعني اكتشاف الصراعات وحلها في وقت مبكر، ويبقى قاعدة الشفرة في حالة مستقرة. ونتيجة لذلك، يمكن للفرق العمل بكفاءة أكبر وبثقة أكبر، حتى عندما يعمل عدة مساهمين على أجزاء مختلفة من المشروع بشكل متزامن.
وأخيرًا، يدعم CI/CD التحسين المستمر والابتكار. من خلال أتمتة عملية النشر، يمكن للفرق إصدار تحديثات إلى الإنتاج بشكل أكثر تواترًا وبمخاطر أقل. وهذا يمكنهم من جمع تغذية راجعة من المستخدمين بشكل أسرع والتكرار على منتجاتهم بشكل أكثر فعالية.
ما سنغطيه في هذا البرنامج التعليمي
في هذا البرنامج التعليمي، سنقوم بشرح عملية إعداد أنبوب CI/CD بسيط يقوم بتلقيم النشر التلقائي لتغييرات الشفرة من مستودع Bitbucket إلى خادم Linux. إليك ما ستتعلمه:
-
كيفية تكوين مستودع Bitbucket لإرسال إشعارات Webhook كلما تم الدفع أو الاندماج في فرع معين.
-
كيفية إعداد خادم Python قائم على Flask على خادم Linux الخاص بك للاستماع لأحداث Webhook الواردة.
-
كيفية كتابة سكربت يستخرج أحدث التغييرات من المستودع وينشرها على الخادم.
-
كيفية اختبار وتصحيح عملية النشر التلقائي الخاصة بك.
بحلول نهاية هذا البرنامج التعليمي، ستكون لديك مثال عملي على أنبوب CI/CD الأساسي الذي يمكنك تخصيصه وتوسيعه حسب الحاجة. دعونا نبدأ!
الخطوة 1: إعداد Webhook في Bitbucket
قبل البدء في الإعداد، دعنا نشرح بإيجاز ما هو الويب هوك وكيف يندرج ضمن عملية CI/CD الخاصة بنا.
الويب هوك هو آلية تسمح لنظام بإخطار نظام آخر عن حدث في الوقت الحقيقي. في سياق Bitbucket، يمكن تكوين ويب هوك لإرسال طلب HTTP (غالبًا طلب POST مع بيانات الحمولة) إلى عنوان URL محدد كلما حدثت حدث معين في مستودعك، مثل دفع إلى فرع أو دمج طلب سحب.
في حالتنا، سيخطر الويب هوك خادم Python القائم على Flask (العامل على خادم Linux الخاص بك) كلما تم دفع أو دمج إلى فرع معين. سيؤدي هذا الإشعار إلى تشغيل سكربت على الخادم لاستخراج أحدث التغييرات من المستودع ونشرها تلقائيًا. في الأساس، يعمل الويب هوك كجسر بين Bitbucket وخادمك، مما يتيح التشغيل التلقائي لعملية النشر.
الآن بعد أن فهمت دور الويب هوك، دعنا نقوم بإعداد واحد في Bitbucket:
-
قم بتسجيل الدخول إلى Bitbucket وانتقل إلى مستودعك.
-
على الشريط الجانبي الأيسر، انقر على الإعدادات.
-
تحت قسم السير العمل، ابحث وانقر على الخطافات الويب.
-
انقر على زر إضافة خطاف.
-
أدخل اسمًا لخطافك (على سبيل المثال، “سحب تلقائي”).
-
في حقل عنوان URL، قدم عنوان URL لخادمك حيث سيُرسل الخطاف الطلب. إذا كنت تقوم بتشغيل تطبيق Flask محليًا، فسيكون شيئًا مثل
http://عنوان-آيبي-الخادم-الخاص-بك/سحب-المستودع
. (لبيئات الإنتاج، من المستحسن بشدة استخدام HTTPS لتأمين الاتصال بين Bitbucket وخادمك.) -
في قسم المُشغلات، اختر الأحداث التي ترغب في الاستماع إليها. في هذا المثال، سنختار الدفع (واختياريًا، استدعاء السحب المُدمج إذا كنت ترغب في النشر بعد الدمج أيضًا).
-
احفظ الويب هوك باسم يوضح نفسه حتى يكون من السهل التعرف عليه لاحقًا.
بمجرد إعداد الويب هوك، سيُرسل Bitbucket طلب POST إلى عنوان URL المحدد في كل مرة يحدث فيها الحدث المحدد. في الخطوات التالية، سنقوم بإعداد خادم Flask للتعامل مع هذه الطلبات الواردة وتشغيل عملية النشر.
ها هو ما يجب أن تراه عند إعداد ويب هوك Bitbucket
الخطوة 2: إعداد مُستمع Flask على خادم Linux الخاص بك
في الخطوة التالية، ستقوم بإعداد خادم ويب بسيط على جهاز Linux الخاص بك الذي سيستمع للويبهوك من Bitbucket. عندما يستلم الإشعار، سيقوم بتنفيذ git pull
أو سحب قوي (في حالة وجود تغييرات محلية) لتحديث المستودع.
قم بتثبيت Flask:
لإنشاء تطبيق Flask، قم أولاً بتثبيت Flask عن طريق تشغيل:
pip install flask
إنشاء تطبيق Flask:
أنشئ سكربت Python جديد (على سبيل المثال، app_repo_pull.py
) على خادمك وأضف الكود التالي:
from flask import Flask
import subprocess
app = Flask(__name__)
@app.route('/pull-repo', methods=['POST'])
def pull_repo():
try:
# جلب آخر التغييرات من المستودع البعيد
subprocess.run(["git", "-C", "/path/to/your/repository", "fetch"], check=True)
# قوم بإعادة ضبط الفرع المحلي بقوة ليطابق الفرع البعيد 'test'
subprocess.run(["git", "-C", "/path/to/your/repository", "reset", "--hard", "origin/test"], check=True) # استبدل 'test' باسم الفرع الخاص بك
return "Force pull successful", 200
except subprocess.CalledProcessError:
return "Failed to force pull the repository", 500
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000)
هذا ما يقوم به هذا الكود:
-
subprocess.run
(["git", "-C", "/المسار/إلى/مستودعك", "fetch"])
: هذا الأمر يجلب آخر التغييرات من المستودع البعيد دون التأثير على دليل العمل المحلي. -
subprocess.run
(["git", "-C", "/path/to/your/repository", "reset", "--hard", "origin/test"])
: تقوم هذه الأمر بإجراء إعادة تعيين قوية، مما يجبر المستودع المحلي على تطابق فرعtest
البعيد. استبدلtest
باسم فرعك.
تأكد من استبدال /path/to/your/repository
بالمسار الفعلي إلى مستودع Git المحلي الخاص بك.
الخطوة 3: عرض تطبيق Flask (اختياري)
إذا كنت ترغب في جعل تطبيق Flask يمكن الوصول إليه من خارج الخادم الخاص بك، يجب عليك عرضه علنًا. لهذا، يمكنك إعداد بروكسي عكسي مع NGINX. إليك كيفية القيام بذلك:
أولاً، قم بتثبيت NGINX إذا لم يكن مثبتًا بالفعل عن طريق تشغيل هذا الأمر:
sudo apt-get install nginx
بعد ذلك، ستحتاج إلى تكوين NGINX لتوجيه الطلبات إلى تطبيق Flask الخاص بك. افتح ملف تكوين NGINX:
sudo nano /etc/nginx/sites-available/default
قم بتعديل التكوين لتضمين هذا الكتلة:
server {
listen 80;
server_name your-server-ip;
location /pull-repo {
proxy_pass http://localhost:5000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
الآن فقط أعد تحميل NGINX لتطبيق التغييرات:
sudo systemctl reload nginx
الخطوة 4: اختبار الإعداد
الآن بعد أن تم إعداد كل شيء، قم بتشغيل تطبيق Flask عن طريق تنفيذ هذا البرنامج النصي بايثون:
python3 app_repo_pull.py
الآن لاختبار ما إذا كان كل شيء يعمل:
- أجرِ تعهدًا: ادفع تعهدًا إلى فرع
test
في مستودع Bitbucket الخاص بك. ستؤدي هذه الإجراءات إلى تنشيط الويب هوك.
-
تنشيط الويب هوك: سيرسل الويب هوك طلب POST إلى خادمك. سيتلقى تطبيق Flask هذا الطلب، وسينفذ سحبًا قويًا من فرع
test
، وسيحدث المستودع المحلي. -
التحقق من السحب: قم بفحص إخراج السجل الخاص بتطبيق Flask الخاص بك أو تفقد المستودع المحلي للتحقق من أن التغييرات قد تم سحبها وتطبيقها بنجاح.
الخطوة 5: الاعتبارات الأمنية
عند عرض تطبيق Flask على الإنترنت، يعد تأمين الخادم والتطبيق أمرًا حيويًا لحمايته من الوصول غير المصرح به، وانتهاكات البيانات، والهجمات. فيما يلي المجالات الرئيسية التي يجب التركيز عليها:
1. استخدام خادم آمن مع قواعد جدار حماية مناسبة
الخادم الآمن هو الذي تم تكوينه لتقليل التعرض للتهديدات الخارجية. وينطوي ذلك على استخدام قواعد جدار الحماية، وتقليل الخدمات غير الضرورية، وضمان فتح الفئات المطلوبة فقط للتواصل.
مثال على إعداد خادم آمن:
-
البرمجيات الأساسية: قم بتثبيت البرمجيات التي تحتاجها فقط (على سبيل المثال، Python، Flask، NGINX) وقم بإزالة الخدمات غير الضرورية.
-
تحديثات نظام التشغيل: تأكد من أن نظام تشغيل الخادم الخاص بك مُحدّث بآخر التصحيحات الأمنية.
-
تكوين جدار الحماية: استخدم جدار حماية للتحكم في حركة المرور الواردة والصادرة وتقييد الوصول إلى الخادم الخاص بك.
على سبيل المثال، يمكن أن يبدو تكوين UFW (جدار الحماية البسيط) على Ubuntu مثل هذا:
# السماح بالوصول عن بُعد عبر SSH (المنفذ 22)
sudo ufw allow ssh
# السماح بHTTP (المنفذ 80) وHTTPS (المنفذ 443) لحركة الويب
sudo ufw allow http
sudo ufw allow https
# تمكين جدار الحماية
sudo ufw enable
# التحقق من حالة جدار الحماية
sudo ufw status
في هذه الحالة:
-
يسمح جدار الحماية باتصالات SSH الواردة على المنفذ 22، HTTP على المنفذ 80، وHTTPS على المنفذ 443.
-
يجب حظر أي منافذ أو خدمات غير ضرورية افتراضيًا لتقليل التعرض للهجمات.
قواعد جدار الحماية الإضافية:
-
تقييد الوصول إلى نقطة نهاية الويب هوك: في الواقع، يجب السماح فقط بحركة المرور إلى نقطة نهاية الويب هوك من عناوين IP لـ Bitbucket لمنع الوصول الخارجي. يمكنك إعداد هذا في جدار الحماية الخاص بك أو باستخدام خادم الويب الخاص بك (على سبيل المثال، NGINX) من خلال قبول الطلبات فقط من نطاق عناوين IP لـ Bitbucket.
-
رفض جميع حركة المرور الواردة الأخرى: بالنسبة إلى أي خدمة لا تحتاج إلى تعريضها للإنترنت (على سبيل المثال، منافذ قاعدة البيانات)، تأكد من حظر تلك المنافذ.
2. إضافة المصادقة إلى تطبيق Flask
نظرًا لأن تطبيق Flask الخاص بك سيكون متاحًا علنيًا عبر رابط الويب هوك، يجب عليك النظر في إضافة المصادقة لضمان أن يمكن للمستخدمين المعتمدين فقط (مثل خوادم Bitbucket) تشغيل الاستحضار.
مثال على المصادقة الأساسية:
يمكنك استخدام المصادقة القائمة على الرمز البسيطة لتأمين نقطة نهاية الويب الخاصة بك. إليك مثال على كيفية تعديل تطبيق Flask الخاص بك لطلب رمز مصادقة:
from flask import Flask, request, abort
import subprocess
app = Flask(__name__)
# حدد رمزًا سريًا للتحقق من الويبهوك
SECRET_TOKEN = 'your-secret-token'
@app.route('/pull-repo', methods=['POST'])
def pull_repo():
# تحقق مما إذا كان الطلب يحتوي على الرمز الصحيح
token = request.headers.get('X-Hub-Signature')
if token != SECRET_TOKEN:
abort(403) # ممنوع إذا كان الرمز غير صحيح
try:
subprocess.run(["git", "-C", "/path/to/your/repository", "fetch"], check=True)
subprocess.run(["git", "-C", "/path/to/your/repository", "reset", "--hard", "origin/test"], check=True)
return "Force pull successful", 200
except subprocess.CalledProcessError:
return "Failed to force pull the repository", 500
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000)
كيف يعمل:
-
يعتبر
X-Hub-Signature
رأسًا مخصصًا تضيفه إلى الطلب عند إعداد الويبهوك في Bitbucket. -
سيُسمح فقط بالطلبات التي تحتوي على الرمز الصحيح لتنشيط السحب. إذا كان الرمز مفقودًا أو غير صحيح، سيتم رفض الطلب برد
403 ممنوع
.
يمكنك أيضًا استخدام أشكال أكثر تعقيدًا للمصادقة، مثل OAuth أو HMAC (Hash-based Message Authentication Code)، ولكن هذا النهج البسيط بالرمز يعمل للعديد من الحالات.
3. استخدام HTTPS للاتصال الآمن
من الضروري تشفير البيانات المرسلة بين تطبيق Flask الخاص بك وويبهوك Bitbucket، بالإضافة إلى أي بيانات حساسة (مثل الرموز أو كلمات المرور) المرسلة عبر الشبكة. هذا يضمن عدم قدرة المهاجمين على اعتراض أو تعديل البيانات.
لماذا HTTPS؟
-
تشفير البيانات: يُشفر HTTPS الاتصال، مما يضمن عدم تعرض البيانات الحساسة مثل رمز المصادقة الخاص بك لهجمات الوسيط الذي يقف في منتصف الاتصال.
-
الثقة والنزاهة: يساعد HTTPS في ضمان عدم تلاعب البيانات التي تصل إلى خادمك.
استخدام Let’s Encrypt لتأمين تطبيق Flask الخاص بك بشهادة SSL:
- تثبيت Certbot (الأداة للحصول على شهادات Let’s Encrypt):
sudo apt-get update
sudo apt-get install certbot python3-certbot-nginx
الحصول على شهادة SSL مجانية لنطاقك:
sudo certbot --nginx -d your-domain.com
-
سيقوم هذا الأمر تلقائيًا بتكوين Nginx لاستخدام HTTPS مع شهادة SSL مجانية من Let’s Encrypt.
-
التأكد من استخدام HTTPS: تأكد من أن تطبيق Flask الخاص بك أو تكوين Nginx يجبر كل حركة مرور على استخدام HTTPS. يمكنك القيام بذلك عن طريق إعداد قاعدة إعادة توجيه في Nginx:
server {
listen 80;
server_name your-domain.com;
# إعادة توجيه HTTP إلى HTTPS
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
server_name your-domain.com;
ssl_certificate /etc/letsencrypt/live/your-domain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/your-domain.com/privkey.pem;
# تكوين Nginx الآخر...
}
التجديد التلقائي: شهادات Let’s Encrypt صالحة لمدة 90 يومًا، لذا من المهم إعداد التجديد التلقائي:
sudo certbot renew --dry-run
يختبر هذا الأمر عملية التجديد للتأكد من أن كل شيء يعمل.
4. تسجيل ومراقبة
نفذ تسجيلًا ومراقبة لتطبيق Flask الخاص بك لتتبع أي محاولات غير مصرح بها، والأخطاء، أو النشاط الغير عادي:
-
تسجيل الطلبات: سجّل جميع الطلبات الواردة، بما في ذلك عنوان IP، رؤوس الطلب، وحالة الاستجابة، حتى تتمكن من مراقبة أي نشاط مشبوه.
-
استخدم أدوات المراقبة: قم بإعداد أدوات مثل Prometheus, Grafana, أو New Relic لمراقبة أداء الخادم وصحة التطبيق.
ختامًا
في هذا البرنامج التعليمي، استكشفنا كيفية إعداد أنبوب عمل CI/CD بسيط وصديق للمبتدئين يقوم بتوتير النشر باستخدام Bitbucket، خادوم Linux، و Python مع Flask. إليك ملخص لما تعلمته:
-
أساسيات CI/CD: تناولنا أساسيات التكامل المستمر (CI) والتسليم/النشر المستمر (CD)، وهي ممارسات أساسية لتوطين التكامل والاختبار ونشر الشفرة تلقائيًا. تعلمت كيف يساعد CI/CD في تسريع عملية التطوير، وتقليل الأخطاء، وتحسين التعاون بين المطورين.
-
إعداد خطافات Bitbucket: تعلمت كيفية تكوين خطاف Bitbucket لإعلام الخادم الخاص بك عندما يتم دفع أو دمج شيفرة في فرع معين. يعمل هذا الخطاف كزناد لبدء عملية النشر تلقائيًا.
-
إنشاء مستمع لخطافات الويب بناءً على Flask: عرضنا لك كيفية إعداد تطبيق Flask على خادم Linux الخاص بك للاستماع إلى طلبات خطاف الويب الواردة من Bitbucket. يستقبل هذا التطبيق Flask الإخطارات ويقوم بتشغيل الأوامر اللازمة من Git لجلب ونشر آخر تغييرات.
-
تأتيمة عملية النشر: باستخدام Python و Flask، قمنا بتأتيمة عملية جلب التغييرات من مستودع Bitbucket وإجراء جلب قوي لضمان نشر الشيفرة الأخيرة. كما تعلمت كيفية تكوين الخادم لتعريض تطبيق Flask وقبول الطلبات بشكل آمن.
-
اعتبارات الأمان: قمنا بتغطية خطوات الأمان الحرجة لحماية عملية النشر الخاصة بك:
-
قواعد جدار الحماية: تناولنا تكوين قواعد جدار الحماية لتقييد التعرض وضمان أن يمكن للحركة المصرح بها فقط (من Bitbucket) الوصول إلى خادمك.
-
المصادقة: قمنا بإضافة المصادقة القائمة على الرمز لضمان أن يمكن للطلبات المصرح بها فقط تشغيل عمليات النشر.
-
HTTPS: شرحنا كيفية تأمين التواصل بين خادمك و Bitbucket باستخدام شهادات SSL من Let’s Encrypt.
-
التسجيل والمراقبة: وأخيرًا، نوصي بإعداد التسجيل والمراقبة لتتبع أي نشاط غير عادي أو أخطاء.
-
الخطوات التالية
بحلول نهاية هذا البرنامج التعليمي، لديك الآن مثال عملي على أنبوب نشر آلي. على الرغم من أن هذا تنفيذ أساسي، إلا أنه يعتبر أساسًا يمكنك بناء عليه. بمجرد أن تصبح أكثر راحة مع CI/CD، يمكنك استكشاف مواضيع متقدمة مثل:
-
أنابيب نشر مرحلية متعددة
-
التكامل مع أدوات التحميل المثيلة مثل Docker
-
استراتيجيات اختبار ونشر أكثر تعقيدًا
-
استخدام أدوات التنظيم مثل Kubernetes للتوسيع
ممارسات CI/CD تتطور باستمرار، ومن خلال اتقان الأساسيات، لقد وفرت لنفسك نجاحًا بينما توسع مهاراتك في هذا المجال. نتمنى لك التوفيق في التأتير وشكرًا لك على القراءة!
يمكنك تفرع الكود من هنا.
Source:
https://www.freecodecamp.org/news/create-a-basic-cicd-pipeline-with-webhooks-on-linux/