github actions: أتمتة CI/CD والنشر باعتمادية
نُشر في · آخر تحديث
تساعد github actions في أتمتة فحوص المستودع والاختبارات والبناء والحزم والمهام المجدولة والنشر انطلاقًا من أحداث GitHub. يشرح هذا الدليل تصميم CI/CD موثوقة، وحماية Secrets، وفصل البيئات، وتسريع التنفيذ، ونشر Artifacts المختبرة، وتشخيص الفشل وصيانة Pipeline.
صمم مسار CI/CD قبل كتابة YAML
قبل كتابة أي ملف github actions، ارسم المسار الكامل الذي يجب أن يمر به الكود من التعديل إلى الإصدار. حدد الفروع المستخدمة، وفحوص Pull Request، وأوامر تثبيت الحزم، والـlint والـtype checking والاختبارات والبناء والحزم وأهداف النشر وأي خطوة تحتاج موافقة بشرية. وضوح المسار أهم من طول ملف YAML لأنه يكشف الافتراضات مبكرًا. حدد ما يجب تشغيله على كل Pull Request، وما يخص الفرع الرئيسي فقط، وما يعمل بجدول زمني أو بتشغيل يدوي. بهذه الطريقة لا تتحول الأتمتة إلى مجموعة Jobs غير مترابطة يصعب فهم سبب تشغيلها.
افصل ذهنيًا بين Continuous Integration وContinuous Delivery حتى لو كانا في نفس المستودع. CI يجيب: هل هذا التغيير صالح للدمج؟ فيشغّل التثبيت والفحص والاختبار والبناء. CD يجيب: ماذا يحدث بعد اعتماد التغيير؟ فيتعامل مع الحزمة والنشر والـmigrations والتحقق من الصحة والترقية بين البيئات. هذا الفصل يجعل رسالة الفشل أوضح؛ ففشل Unit Test ليس مثل فشل نشر Production، ولا يجب أن تبدأ عملية نشر لأن فحصًا غير مرتبط نجح.
حدد مدخلات ومخرجات كل Job. Job البناء يستهلك الكود والـlockfile ويخرج Artifact. Job النشر يستهلك Artifact الذي اجتاز الفحص ويستخدم إعدادات البيئة المستهدفة. عندما تكون هذه العقود واضحة يصبح إعادة استخدام الـJobs وتحريكها أسهل، ويصبح واضحًا أين تستخدم Cache، وما الذي يجب رفعه كـArtifact، وما الذي يجب ألا يغادر سياق التنفيذ الآمن.
- ارسم مسار الإصدار
- افصل CI عن CD
- حدد مدخلات ومخرجات Jobs
- وثق الافتراضات
اختر Triggers تناسب طريقة الإصدار
لا تشغّل كل Workflow على كل Event. Pull Request مناسب لفحوص ما قبل الدمج، وpush يمكن استخدامه لما بعد الدمج، وschedule للمهام الدورية، وworkflow_dispatch للتشغيل اليدوي المتحكم فيه. Path filters قد تقلل التنفيذ غير الضروري عندما يتغير توثيق فقط، لكنها تحتاج حذرًا حتى لا تمنع اختبارًا مهمًا عن طريق الخطأ.
فلترة الفروع مهمة جدًا للنشر. Production لا يجب أن ينشر من أي Feature Branch عشوائي. حدد الفرع أو Tag الذي يسمح بإنشاء Release، وقرر هل الـTags تمثل نسخًا غير قابلة للتغيير أم مجرد إشارات. إذا استخدمت Release Branches، وثق دورة حياتها حتى لا يتكرر النشر من فروع قديمة.
فكر في Concurrency كجزء من التصميم. إذا دفع المطور عدة Commits سريعًا، قد لا يكون من المفيد ترك كل Runs القديمة تعمل. يمكن إلغاء Builds التي أصبحت قديمة. أما في النشر فقد تحتاج العكس: Job واحد فقط يستطيع النشر على نفس البيئة في نفس الوقت. اختيار Trigger جيد يجب أن يوازن سرعة المطور مع سلامة التشغيل.
- استخدم Triggers مركزة
- احمِ فروع النشر
- اضبط Concurrency
- تجنب Runs المكررة
ابنِ CI قابلة للتكرار والاعتماد
CI الموثوقة تبدأ من بيئة قابلة لإعادة الإنتاج. ثبّت نسخة Runtime بوضوح، واستخدم Lockfile، ولا تعتمد على أدوات موجودة افتراضيًا في Runner إلا إذا كانت ضمن عقد واضح. الأفضل أن تكون أوامر CI هي نفسها أو قريبة جدًا من الأوامر التي يشغلها المطور محليًا. إذا أصبح CI نظامًا مختلفًا تمامًا عن بيئة التطوير، يصبح إعادة إنتاج الأخطاء أصعب ويزيد الوقت الضائع.
رتب الفحوص بحيث تفشل المهام السريعة أولًا. Formatting وLint وStatic Analysis غالبًا أسرع من Integration Tests أو Build كبير. تشغيلها في البداية يقلل الوقت والتكلفة. إذا كانت الاختبارات مستقلة، قسمها منطقيًا إلى Jobs أو Shards، لكن لا تبالغ في التقسيم حتى لا يصبح Workflow أكثر تعقيدًا من التطبيق نفسه.
اجعل شروط النجاح صريحة. Build يخرج Exit Code ناجحًا لكنه لم يشغّل نصف الاختبارات ليس نجاحًا حقيقيًا. يجب أن تفشل الأوامر عند وجود مشكلة فعلية، وأن تكون Coverage أو Quality Gates مقصودة وليست أرقامًا شكلية. إذا كان الإصدار يعتمد على Migration أو Schema Check، اختبره في بيئة غير Production قبل وصوله للنشر.
- ثبّت Runtime
- شغّل الفحوص السريعة أولًا
- استخدم Parallelism بوعي
- تحقق من النواتج
احمِ Secrets وافصل البيئات
لا تضع Secrets داخل YAML أو الكود أو Logs أو تعليقات Issues. استخدم Secrets المشفرة على مستوى Repository أو Organization أو Environment حسب نطاق الحاجة. Secret خاص بالنشر الإنتاجي لا يجب أن يكون متاحًا لكل Job في Pull Request. وكلما أمكن استخدام هوية قصيرة العمر أو Federation بدل مفاتيح طويلة العمر يكون ذلك أفضل من ناحية الدوران والتعرض.
استخدم Environments للفصل بين Development وStaging وProduction. البيئة ليست مجرد مجموعة Variables؛ يمكن أن تضيف Approval ومعلومات Deployment وProtection Rules. بهذه الطريقة لا يستطيع Job من Feature Branch الحصول تلقائيًا على Credentials الإنتاج. سمِّ القيم الخاصة بكل بيئة بوضوح مثل Project ID وRegion وEndpoint حتى لا تختلط الأهداف.
تعامل مع Logs كقناة محتملة لتسريب البيانات. Debug Mode أو echo لمتغيرات البيئة أو Action خارجي قد يكشف معلومات حساسة. راجع ما يطبع، وتجنب تمرير Secrets في Command Line عندما توجد طريقة أكثر أمانًا. وعند الشك في تعرض Credential، بدّله بدل الاعتماد على إخفائه لاحقًا. كذلك أزل Secrets غير المستخدمة عند تغير التكاملات أو المسؤوليات.
- قلل نطاق Secrets
- افصل البيئات
- احمِ Logs
- دوّر Credentials
سرّع التنفيذ باستخدام Cache وArtifacts
Cache تقلل وقت تثبيت Dependencies لكنها ليست مصدرًا للحقيقة. Cache Key يجب أن يرتبط بالملفات التي تحدد Dependencies، مثل lockfile. Cache قديمة قد تنتج سلوكًا محيرًا، لذلك يجب أن يكون من السهل تشغيل Job بدونها عند التشخيص. لا تجعل نجاح Build يعتمد على وجود Cache بشكل صحيح.
Artifacts مناسبة لنقل الناتج بين Jobs وحفظ أدلة التنفيذ. يمكن رفع Build Package أو Test Report أو Coverage أو Screenshots أو Logs لازمة للتشخيص. ضع Retention مقصودًا خصوصًا للملفات الكبيرة، ولا ترفع Secrets أو بيانات إنتاجية حساسة. الأفضل أن يستخدم النشر نفس Artifact الذي تم اختباره بدل إعادة بناء نسخة جديدة قد تختلف عن المختبرة.
Matrix Jobs مفيدة لاختبار أكثر من Runtime أو نظام تشغيل أو Configuration، لكنها قد تضاعف الوقت والتكلفة بسرعة. ابدأ بالتركيبات التي تمثل فعليًا البيئات المدعومة. استخدم fail-fast بوعي، وافصل التركيبات التجريبية عن Required Checks إذا كانت لا يجب أن تمنع الدمج. الهدف من التوازي هو تقليل الوقت دون فقدان وضوح Pipeline.
- استخدم Cache بحذر
- ارفع Artifacts المناسبة
- حدد Retention
- اجعل Matrix مقصودة
أتمت النشر مع الحفاظ على التحكم
النشر الآلي يجب أن يروّج Artifact معروفًا تم اختباره، لا أن يعيد بناء الكود بطريقة مختلفة في كل مرحلة. سجل Commit SHA وVersion وEnvironment ووقت النشر حتى يمكن ربط أي Incident بالإصدار الدقيق. إذا كانت عملية Build غير حتمية، فقد ينتج إعادة البناء في النشر Artifact مختلفًا عن الذي مر على CI.
ضع حواجز تناسب مستوى الخطر. Staging يمكن أن ينشر تلقائيًا بعد الدمج، بينما Production قد يحتاج Approval أو Release Tag. تعامل مع Database Migrations بحذر لأن Rollback للكود أسهل من Rollback للبيانات. التغييرات المتوافقة للخلف، والمراحل التدريجية، والنسخ الاحتياطية قبل Migrations المهمة تقلل المخاطر.
بعد النشر، شغّل Smoke Tests أو Health Checks على البيئة الحقيقية. وحدد مسبقًا ماذا يحدث إذا فشل التحقق: هل يعاد نشر الإصدار السابق، أم يتوقف Workflow وينتظر قرارًا، أم يتم إصلاح المشكلة للأمام؟ Pipeline الجيدة ليست الأسرع فقط؛ هي التي تعطي إصدارًا قابلًا للتوقع ومسار استعادة معروفًا.
- انشر Artifact مختبرة
- استخدم Approvals عند الحاجة
- نفذ Health Checks
- خطط للاستعادة
شخّص الفشل واجعل Workflow قابلًا للمراقبة
سمِّ Jobs وSteps بأسماء تصف الغرض الفعلي. الخطأ الذي يظهر في خطوة اسمها Test API أفضل كثيرًا من خطوة عامة باسم Run command. اجمع المخرجات المرتبطة واعرض Test Reports أو Annotations عندما يكون ذلك ممكنًا. إذا كان الفشل متقطعًا، سجّل Runtime وDependency State والخدمة الخارجية المتأثرة بدل إعادة التشغيل بشكل عشوائي.
فرّق بين أخطاء الكود وأخطاء البنية. Assertion فاشلة ليست مثل Registry متوقف أو Credential منتهي أو Runner ممتلئ أو Rate Limit. كل فئة تحتاج ردًا مختلفًا. Retry قد يكون مناسبًا لاتصال خارجي متذبذب، لكنه غير منطقي لخطأ deterministic في Compile. إعادة المحاولة الشاملة قد تخفي العطل الحقيقي وتزيد الزمن.
راقب مدة Workflow وQueue Time ونسبة الفشل وأكثر Jobs استهلاكًا للوقت. هذه البيانات تظهر أين ينتظر المطورون وأين توجد هشاشة في البنية. في CD احتفظ بتاريخ Deployment واربط Incidents بالإصدارات. Pipeline نفسها جزء من نظام الإنتاج وتحتاج مراقبة وتحسينًا مستمرين.
- سمِّ الخطوات بوضوح
- صنف أسباب الفشل
- استخدم Retry موجهًا
- راقب مؤشرات Workflow
راجع Pipeline وطورها باستمرار
حافظ على YAML مقروءًا. انقل المنطق المتكرر إلى Reusable Workflows أو Composite Actions أو Scripts عندما يقلل التكرار دون أن يخفي السلوك الأساسي. ثبت Third-party Actions على إصدارات موثوقة وراجع تحديثاتها؛ فهي تشغّل كودًا داخل Pipeline ويجب معاملتها كتبعيات أمنية وتقنية.
راجع Pipeline عندما تتغير بنية التطبيق. Monorepo جديد أو خدمة إضافية أو Environment جديدة قد تحتاج تقسيم Jobs مختلفًا. لا تترك Jobs قديمة وSecrets ميتة تتراكم. أزلها بعد التأكد من عدم وجود اعتماد فعلي عليها، ووثق القرارات الكبيرة حتى لا يحذف شخص لاحقًا حماية مهمة لأنه لم يفهم سبب وجودها.
اختبر مسار الاستعادة دوريًا. تأكد أن فشل Deployment يمكن تشخيصه، وأن Artifact سابقًا يمكن استعادته إذا كان Rollback مناسبًا، وأن Credentials يمكن تدويرها دون كسر النظام. setup ناضج من github actions يصبح جزءًا موثوقًا من التشغيل عندما يكون مفهومًا وقابلًا لإعادة الإنتاج والمراقبة والصيانة.
- حافظ على YAML واضحًا
- راجع Actions الخارجية
- نظف المنطق القديم بحذر
- اختبر Recovery
أسئلة
ما فائدة github actions؟
تستخدم لأتمتة فحوص المستودع والاختبارات والبناء والحزم والمهام المجدولة والنشر بناءً على أحداث أو تشغيل يدوي.
هل أنشر Production مع كل Push؟
غالبًا لا. اربط Production بفرع أو Tag أو Environment أو Approval واضح يتوافق مع طريقة الإصدار.
أين أحفظ Secrets الخاصة بالنشر؟
في Secrets مشفرة أو آلية هوية قصيرة العمر وبأضيق نطاق عملي، ويفضل ربطها بالبيئة المستهدفة.
ما الذي يجب أن تحفظه Pipeline الموثوقة؟
Commit أو Artifact التي اجتازت الاختبار، Logs واضحة، تاريخ نشر، فصل البيئات، ومسار Recovery معروف.