AICODEAgentic Programming · 67723 · 2026-7

Week 6 · video 5 of 6 · transcript

CI and GitHub Actions

ترجمة آلية لم يراجعها إنسان.AI translation, not reviewed by a person.

0:00

الفحص المحلي يعطيكم تغذية راجعة سريعة أثناء العمل. والمشروع المشترك يحتاج أيضًا إلى فحص التغييرات الآتية من أجهزة أخرى. سنتابع تغييرًا يصل إلى GitHub عبر push، من فحص فاشل إلى التصحيح، ونقرأ الـ workflow الذي يشغّل الفحص في GitHub Actions.

0:18

قد يساهم في المشروع أشخاص من بيئات مختلفة. أحدهم يستخدم الوكيل الذي أعددناه، وآخر يستخدم أداة مختلفة، وثالث يجري تغييرًا صغيرًا في المتصفح. يحتاج المشروع إلى طريقة لفحص هذه التغييرات لا تعتمد على أن يملك كل مساهم الـ hook المحلي نفسه.

0:35

التكامل المستمر، أو CI، يعني دمج التغييرات في قاعدة كود مشتركة بشكل متكرر، واستخدام عمليات بناء وفحوصات آلية لاكتشاف المشكلات مبكرًا. وخدمة فحص مشتركة تدعم هذه الممارسة. فهي تعرض النتيجة إلى جانب التغيير، فيرى الفريق أي نسخة فُحصت، ويستطيع تقصّي سبب الفشل.

0:55

وهذا يغيّر طريقة عمل الفريق. تخيّلوا عدة مطوّرين يعمل كل منهم وحده لأسابيع، ثم يجمعون كل تغييراتهم معًا في إطلاق كبير. وعندما يتعطّل شيء، تكون أمامهم تغييرات كثيرة يجب تقصّيها، وقد يكتشفون أن الكود لديهم يقوم على افتراضات غير متوافقة.

1:12

أما مع التكامل المستمر، فندمج تغييرات صغيرة في قاعدة الكود المشتركة طوال فترة التطوير. والبناء والاختبارات الآلية تعطينا تغذية راجعة عن كل تغيير، والعمل ما زال حاضرًا في أذهاننا، والكود الذي علينا تقصّيه أقل. فنستطيع إصلاح المشكلة قبل أن يُبنى عليها عمل إضافي. والتسليم المستمر يوسّع هذه الفكرة: أن يبقى البرنامج جاهزًا للإطلاق. فيستطيع الفريق إطلاق تحديثات أصغر حين تصبح جاهزة، دون تأجيل كل الدمج والاختبار إلى إطلاق كبير في النهاية. ودمج تغيير ما لا يعني أن علينا إطلاقه للمستخدمين فورًا. لنتابع تغييرًا صغيرًا واحدًا وهو يمرّ بالفحوصات التي تدعم طريقة العمل هذه.

1:50

قبل أن نجرّب ذلك، كم يكلّف؟ في GitHub، الأجهزة التي تنفّذ الـ jobs اسمها runners. الـ runners العادية التي يستضيفها GitHub مجانية للمستودعات العامة. أما للمستودعات الخاصة، فباقة GitHub Free تشمل حاليًا 2000 دقيقة كل شهر، مشتركة بين المستودعات الخاصة التابعة لمالك المستودع. وللباقات الأخرى حصص مختلفة. هذه الحصة المجانية مفيدة للمشاريع الشخصية الصغيرة. أما الـ runners الأكبر وتجاوز الحصة فلهما تكلفة إضافية.

2:19

لنفترض أننا نحدّث مشروع Python صغيرًا يجمع أعداد العناصر. يُفترض أن تُرجع الدالة المجموع، لكن تغييرنا يستبدله بالصفر عن طريق الخطأ. مع قائمة فيها 2 و3، يجب أن نحصل على 5. لنرَ ما يحدث إذا سجّلنا هذا الخطأ في commit وأجرينا push إلى GitHub. أعددنا المستودع بحيث يشغّل فحوصات المشروع كلما أجرينا push إلى main.

2:42

نسجّل الملف المعدَّل في commit ونجري push إلى main. فيبدأ GitHub Actions تشغيلًا للـ workflow على الـ commit المُرسَل. في تبويب Actions في المستودع، يمكننا فتح هذا التشغيل ورؤية الخطوات ومُخرَجاتها. وهكذا يصل كل من في المشروع إلى نتيجة الفحص نفسها.

3:00

يشغّل الـ workflow أمر فحص المشروع. الاختبار يتوقع 5 ويحصل على 0، لذلك يفشل. وهذا الفشل مرتبط بالـ commit المُرسَل. يمكننا رؤية الأمر ومُخرَجاته دون أن نطلب من المساهم نسخ رسالة من الطرفية لديه.

3:16

ما الذي بدأ هذا الفحص؟ ملف workflow في المستودع يخبر GitHub Actions متى يبدأ التشغيل وماذا ينفّذ. لنقرأ الملف الذي يشغّل فحوصات مشروعنا.

3:27

الـ workflow يصف عملية الأتمتة. وهو يتضمن jobs، وكل job يتضمن خطوات. أول workflow لدينا فيه job واحد. خطواته تجلب الكود، وتُعدّ Python، وتثبّت الاعتماديات، وتشغّل فحص المشروع.

3:43

الـ runner هو الجهاز الذي ينفّذ الـ job. في هذا المثال، يوفّر لنا GitHub runner جديدًا مستضافًا لديه، وتُنفَّذ خطوات الـ job عليه واحدة تلو الأخرى. كل خطوة إما تشغّل أمر shell أو تستخدم action. الـ action كود قابل لإعادة الاستخدام لمهمة مثل إجراء checkout للمستودع أو إعداد Python.

4:03

هذا ملف YAML. المفتاح الذي تليه نقطتان تأتي بعده قيمة أو قسم متداخل، والمسافة البادئة تبيّن ما يقع داخله. البند name يحدّد اسم الـ workflow. القسم on يحدّد الأحداث التي تبدأ تشغيله. هنا، كلمة pull request تعني أن GitHub يشغّل الـ workflow على كل pull request، قبل أن يصبح دمجه ممكنًا. وكلمة push تعني أنه يعمل أيضًا كلما أجرينا push، والبند branches يقصر ذلك على main. يجب تسجيل ملف الـ workflow في commit وإرساله مع المشروع عبر push. وكل push لاحق إلى main يبدأ تشغيلًا جديدًا.

4:39

البند permissions يمنح token المستودع، الذي يستخدمه الـ workflow، صلاحية قراءة المحتوى. تحت jobs، اسم الـ job هو checks، والبند runs-on يختار runner مستضافًا بنظام Ubuntu. داخل هذا الـ job نسرد الخطوات التي تُعدّ الجهاز وتشغّل فحوصاتنا.

4:56

والخطوات تأتي في الملف نفسه، داخل الـ job المسمّى checks. كل شَرطة تبدأ خطوة جديدة في القائمة. البند uses يحدّد action. checkout يجلب ملفات المستودع، وsetup-python يثبّت Python 3.12، وهو الإصدار الذي اخترناه للمثال المحلي أيضًا. الرقم بعد علامة @ هو إصدار الـ action نفسه، وليس إصدار Python.

5:21

البند run ينفّذ أمر shell على الـ runner. أولًا نثبّت اعتماديات التطوير من الملف requirements-dev.txt. ثم نشغّل سكربت الفحص نفسه الذي نستخدمه محليًا. إذا فشلت إحدى أدوات الفحص، ينتهي السكربت بحالة فشل. فتفشل هذه الخطوة، ويُظهر GitHub أن الـ job فشل.

5:41

الـ runner يُجري checkout للمستودع ويتّبع تعليمات الإعداد في الـ workflow. لكنه لا ينسخ مجلد العمل من حاسوبكم المحمول ولا الحزم المثبّتة عليه. فإن احتاج برنامجكم إلى data.csv الظاهر هنا، وهو غير مسجَّل في commit، فلن يكون هذا الملف موجودًا. والحزمة التي ثبّتّموها محليًا يجب أن تُضاف أيضًا إلى إعداد الـ runner.

6:03

قبل تغيير الكود، اقرؤوا ما الذي فشل. في GitHub، افتحوا تبويب Actions في المستودع، ثم التشغيل الفاشل، ثم الخطوة الفاشلة، لتروا مُخرَجاتها. في GitHub، افتحوا تبويب Actions في المستودع، ثم التشغيل الفاشل، ثم الخطوة الفاشلة، لتروا مُخرَجاتها. وأداة GitHub لسطر الأوامر تعرض المُخرَجات نفسها في الطرفية. وبهذا يستطيع الوكيل أيضًا قراءتها لكم.

6:30

وهكذا يستطيع الوكيل أيضًا أن يقرأها نيابةً عنكم. في مثالنا، شُغّل الاختبار بلا مشكلة، لكنه وجد إجابة خاطئة. مجموع 2 و3 يجب أن يكون 5، بينما أرجعت الدالة 0. نُعيد إنتاج الفشل محليًا، ونغيّر الدالة لتُرجع المجموع، ثم نشغّل الفحوصات مرة أخرى.

6:49

وراجعوا الـ diff أيضًا، لتروا ما الذي جعل الاختبار ينجح. سجّلوا التصحيح في commit وأجروا push إلى main.

6:57

هذا الـ push يبدأ تشغيلًا جديدًا للـ workflow على الكود المصحَّح. لاحظوا الترتيب هنا: GitHub يقبل الـ push أولًا، ثم يشغّل الفحوصات. التشغيل الفاشل يُبلغ عن مشكلة، لكنه لا يحذف الـ commit ولا يتراجع عن الـ push. في هذا المثال، نعالج ذلك بتقصّي سبب الفشل وإرسال تصحيح عبر push. وتشغيل الفحوصات محليًا أولًا يساعدنا

7:19

لكن الفحص المحلي متروك لكل مساهم. ولكي يبقى أي تغيير لا يجتاز الفحص بعيدًا عمّن يستخدمون المستودع، يجب أن ينجح الفحص قبل أن يصل التغيير إلى main. في GitHub، يمكن لمجموعة قواعد (ruleset) للفرع main أن تشترط pull request ونجاح فحوصات المشروع قبل الدمج. وبوجود هذه القاعدة، يُرفض أي push مباشر إلى main. فيمرّ التغيير عبر pull request، ويبقى دمجه ممنوعًا ما دام الفحص الإلزامي فاشلًا. فلا يدخل الفرع main إلا ما اجتاز الفحص، لذا يحصل كل من يستنسخه على كود اجتاز الفحوصات.

7:52

على اكتشاف الأخطاء قبل أن تصل إلى الفرع المشترك. لكن الفحص المحلي متروك لكل مساهم. ولكي يبقى التغيير الفاشل بعيدًا عمّن يستخدمون المستودع، يجب أن ينجح الفحص قبل أن يصل التغيير إلى main. في GitHub، يمكن لمجموعة قواعد (ruleset) على main أن تشترط pull request

8:09

وأن تشترط نجاح فحوصات المشروع قبل الدمج. ومع هذه القاعدة، يُرفض أي push مباشر إلى main. فيمرّ التغيير عبر pull request، ويبقى دمجه ممنوعًا ما دام الفحص الإلزامي فاشلًا. فلا يبقى في الفرع main إلا commits ناجحة، ومن يستنسخه يحصل على كود اجتاز الفحوصات.

8:28

وعلينا أيضًا أن نحافظ على ما تغطّيه هذه الفحوصات. فإذا حذف تغييرٌ اختبارًا أو أضعف سكربت الفحص، فقد ينجح الـ job دون أن يفحص شيئًا لا يزال الفريق يحتاجه. راجعوا تعديلات الـ workflow وسكربت الفحص والاختبارات، إلى جانب تعديلات كود التطبيق. الفحص المحلي يساعدكم على تصحيح الخطأ بسرعة،

8:48

والكود المعنيّ ما زال أمامكم. أما الـ workflow في GitHub فيفحص الكود المُرسَل في البيئة المعدّة له. وقد يكرّر فحوصات سبق أن شغّلتموها محليًا. وهذا التكرار مفيد، لأن النتيجة المشتركة لا تعتمد على تقرير من حاسوب محمول واحد. إلى جانب الفحوصات التي يشغّلها الوكيل،

9:09

يمكنكم تشغيل فحص محلي كلما أنشأ أحدٌ commit في Git. فـ Git لديه hooks خاصة به لعمليات كهذه. يُنفَّذ الـ pre-commit hook قبل أن ينشئ Git الـ commit، سواء كان من شغّل الأمر وكيلًا أو شخصًا. ويستطيع workflow للإطلاق أن يفرض الترتيب نفسه. فهو لا ينشر إصدارًا إلا في job يشترط نجاح الـ job المسمّى checks.

9:32

يفصل المخطط بين hooks في Git وhooks الجلسة في harness الوكيل. الأمر git commit --no-verify يتخطّى الـ pre-commit hook. ويمكن لأي شخص أو وكيل استخدام هذا الخيار.

9:46

الـ hook في جلسة الوكيل يستطيع رفض أمر يتعرّف عليه، لكنه لا يغطّي إلا تلك الجلسة. الـ runner في CI له ذاكرة سمكة ذهبية، وصرامة شاويش لا يرحم. وعند push إلى main،

10:00 of video · 1,358 words · 29 slides← Back to the video