المُشغِّلون وبيئة التنفيذ
المُشغِّلون وبيئة التنفيذ
في الدرس الأول تعلّمت أن الـ workflow هو ملف YAML مؤلف من jobs وsteps تُطلَق بواسطة أحداث. لكن من الذي يُنفّذ تلك الخطوات فعلياً؟ الجواب هو المُشغِّل (runner) — خادم (مادي أو افتراضي أو حاوية) يستمع للعمل من GitHub Actions، وينفّذ كل خطوة داخل job، ويُرسل النتيجة إلى GitHub. كل قرار تتخذه بشأن الـ runners — أي نوع، أي نظام تشغيل، كم عدده، كيفية اتصاله بالشبكة — له عواقب مباشرة على سرعة الـ pipeline وتكلفته وأمانه وامتثاله.
المُشغِّلون المستضافون لدى GitHub
تحتفظ GitHub بأسطول عالمي من الأجهزة الافتراضية المؤقتة (ephemeral). كل job يعمل على مُشغِّل مستضاف يبدأ من VM منشأ حديثاً — لا يوجد أي حالة متبقية من job سابق، لأي فريق أو أي مستودع. هذه هي خاصية الأمان الأساسية للمُشغِّلين المستضافين: كل تشغيل يبدأ من صفحة نظيفة.
ثلاث عائلات رئيسية ومواصفاتها الحالية:
ubuntu-24.04/ubuntu-22.04— Linux (x64). 4 vCPU، 16 GB RAM، 14 GB SSD. الحصان الأقوى لمعظم أحمال CI. أسرع إقلاع، أرخص سعراً في الدقيقة، أفضل أدوات مثبتة مسبقاً.windows-2022/windows-2025— Windows Server (x64). 4 vCPU، 16 GB RAM. مطلوب لأهداف .NET Framework وMSBuild واختبارات Windows المحددة. يُفاتَر بمعدل ضعفين من معدل Linux.macos-15/macos-14— macOS (arm64 على أجهزة M1). مطلوب لبناء تطبيقات iOS وmacOS (Xcode). يُفاتَر بمعدل عشرة أضعاف من معدل Linux — أغلى خيار مستضاف بكثير.
تقدّم GitHub أيضاً مُشغِّلين أكبر حجماً — 8 أو 16 أو 32 أو 64 vCPU — للمؤسسات التي تحتاجها. تتطلب خطة تنظيم أو مؤسسة وتُكوَّن تحت Settings > Actions > Runner groups.
ubuntu-latest هو مؤشر متغير تقوم GitHub بتحديثه عند صدور نسخة LTS جديدة. في الماضي، انتقلت GitHub بـ ubuntu-latest من 20.04 إلى 22.04 وكسرت pipelines تعتمد على إصدارات حزم النظام. ثبّت دائماً على إصدار صريح (ubuntu-24.04) في workflows الإنتاج حتى تكون الترقيات مقصودة لا عرضية.تأتي بيئة الـ runner مع قائمة برامج كبيرة — Node.js وPython وJava وDocker وkubectl وTerraform وعشرات غيرها — لكن الإصدارات المثبتة تتغير مع كل إصدار صورة جديدة. لأي أداة يعتمد عليها الـ pipeline، ثبّتها صراحةً في خطوة (باستخدام action من نوع actions/setup-*) بدلاً من الاعتماد على ما قد يكون مثبتاً مسبقاً.
المُشغِّلون المستضافون ذاتياً
المُشغِّل المستضاف ذاتياً هو أي جهاز تقوم بتوفيره وتسجيله مع GitHub وصيانته بنفسك. وكيل runner الخاص بـ GitHub Actions هو برنامج ثنائي صغير مفتوح المصدر مكتوب بـ Go يستمع لـ API الخاصة بـ GitHub للوظائف المخصصة له. يعمل على Linux وWindows وmacOS وARM.
ثلاثة أسباب جوهرية تدفع الفرق للانتقال إلى مُشغِّلين مستضافين ذاتياً:
- الوصول إلى الشبكة. اختبارات التكامل أو نصوص النشر أو فحوصات الأمان يجب أن تصل إلى موارد خاصة — قاعدة بيانات داخلية، سجل حزم artifacts داخلي، مجموعة Kubernetes مستضافة في VPC — لا يمكن الوصول إليها من نطاقات IP العامة لـ GitHub.
- التكلفة على نطاق واسع. عند الحجم الكبير (آلاف دقائق CI يومياً)، تتجاوز تكلفة الدقيقة للمُشغِّلين المستضافين التكلفة المستهلكة لامتلاك أو استئجار حوسبة مخصصة. كثير من المؤسسات الهندسية الكبيرة تُشغّل مُشغِّليها على VMs spot/preemptible لخفض التكلفة أكثر.
- أجهزة مخصصة. تدريب ML بتسريع GPU، أجهزة Apple Silicon لبناء iOS، أهداف FPGA، أو اختبار الأجهزة الحقيقية — كل هذه تتطلب أجهزة تحضرها بنفسك.
تسجيل مُشغِّل ذاتي يستغرق أقل من خمس دقائق:
في الإنتاج، لا تسجّل مُشغِّلاً واحداً أبداً. سجّل أسطولاً خلف وسم واترك GitHub يوزّع الـ jobs عبر الأسطول. استخدم مجموعات الـ runner للتحكم في أي مستودعات يمكنها الوصول إلى أي مُشغِّلين — حدود عزل حرجة في المؤسسات متعددة الفرق.
مجموعات الـ Runner: التحكم في الوصول على نطاق واسع
مجموعات الـ runner هي بنية على مستوى المؤسسة (أو المشروع) تتيح لك تعيين مُشغِّلين لمجموعات ثم منح مستودعات محددة الوصول إلى تلك المجموعات. هكذا تمنع مؤسسات الهندسة الكبيرة مستودع فريق من جدولة jobs عن طريق الخطأ على مُشغِّلي فريق آخر الباهظة الثمن أو، الأسوأ، على مُشغِّلين تحمل أوراق اعتماد الإنتاج.
--ephemeral (متاح منذ إصدار runner v2.293). في الوضع المؤقت، يُلغي الـ runner تسجيل نفسه بعد إكمال job واحد، وتُوفّر البنية التحتية كـ كود (Terraform أو Pulumi أو متحكم مخصص) VM جديداً للـ job التالي. هذا يمنحك خاصية الأمان للمُشغِّلين المستضافين (لا حالة مشتركة بين الـ jobs) مع الاحتفاظ بمزايا الذاتي الاستضافة (الوصول للشبكة، الأجهزة المخصصة). أدوات مثل actions-runner-controller (ARC) لـ Kubernetes تؤتمت هذا النمط على نطاق واسع.الحاويات كـ Jobs: مفتاح container
تدعم GitHub Actions تشغيل job كامل داخل حاوية Docker، بدلاً من تشغيله مباشرة على مضيف الـ runner. هذا يختلف عن خطوة تُشغّل أمر Docker بالصدفة — كامل الـ job يُنفَّذ داخل الصورة المحددة، مما يمنحك بيئة قابلة للتكرار تماماً تطابق حاوية الإنتاج.
مفتاح container على مستوى الـ job يلفّ كل خطوة في حاوية Docker. الخطوات لا تعمل على نظام التشغيل المضيف — بل تعمل داخل الحاوية مع مساحة العمل مثبّتة فيها. هذا يعني إن استخدمت صورة python:3.12-slim، كل خطوة لها تلك النسخة بالضبط من Python، بغض النظر عما ثُبّت على نظام تشغيل الـ runner الأساسي. لا حاجة لـ actions/setup-python.
حاويات الخدمة تُشغَّل جنباً إلى جنب مع حاوية الـ job وتكون متاحة باسم الخادم (postgres، redis) عبر شبكة Docker الداخلية. خيارات --health-* تضمن أن Actions تنتظر حتى تكون الخدمة جاهزة قبل تشغيل خطواتك — تفصيل حرج يمنع الاختبارات المتذبذبة الناجمة عن تسابق بين كود التطبيق وقاعدة بيانات لم تقبل الاتصالات بعد.
إطار قرار اختيار الـ Runner
في الإنتاج، يتبع اختيار الـ runner شجرة قرار واضحة:
- ابدأ بالمستضاف من GitHub (
ubuntu-24.04) لكل شيء. هذا هو الافتراضي الصحيح. التكلفة متوقعة، عبء الصيانة صفر، ونموذج الأمان قوي. - انتقل للذاتي الاستضافة فقط عند وجود متطلب ملموس لا يمكن للمُشغِّلين المستضافين الوفاء به: الوصول للشبكة الخاصة، الأجهزة المخصصة، أو توفير التكاليف المدفوع بالحجم. استخدم مُشغِّلين مؤقتين (ARC أو متحكم مخصص) للحفاظ على خصائص أمان المُشغِّلين المستضافين.
- أضف
container:عندما يجب أن تطابق بيئة الاختبار بيئة تشغيل محددة بدقة، أو عندما تحتاج خدمات sidecar (قواعد بيانات، وسطاء رسائل، خوادم SMTP) يكلّف محاكاتها الصحيحة الكثير. - استخدم مجموعات الـ runner فور وجود أكثر من فريق أو أكثر من مستوى حساسية للـ runner (مثلاً مُشغِّلون بأوراق اعتماد سحابية للإنتاج مقابل مُشغِّلون بدون أوراق اعتماد).
فهم الـ runners بعمق هو أساس كل ما يلي في هذا الدرس التعليمي — استراتيجيات التخزين المؤقت وبناءات المصفوفة والمصادقة OIDC مع السحابة وتحديد نطاق الأسرار — كل هذه تتفاعل مباشرة مع أين وكيف تُنفَّذ الـ jobs. في الدرس 3 ننتقل إلى التعبيرات والسياقات — لغة القوالب التي تتيح لمنطق الـ workflow التكيّف ديناميكياً مع الحدث والفرع وبيئة الـ runner في وقت التشغيل.